123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- import json
- from django.core.exceptions import ValidationError
- from django.utils.translation import gettext as _
- from rest_framework import status
- from rest_framework.response import Response
- from misago.conf import settings
- from misago.core.decorators import require_dict_data
- from misago.core.utils import format_plaintext_for_html
- from misago.users import avatars
- from misago.users.models import AvatarGallery
- from misago.users.serializers import ModerateAvatarSerializer
- @require_dict_data
- def avatar_endpoint(request, pk=None):
- if request.user.is_avatar_locked:
- if request.user.avatar_lock_user_message:
- reason = format_plaintext_for_html(request.user.avatar_lock_user_message)
- else:
- reason = None
- return Response(
- {
- "detail": _("Your avatar is locked. You can't change it."),
- "reason": reason,
- },
- status=status.HTTP_403_FORBIDDEN,
- )
- avatar_options = get_avatar_options(request, request.user)
- if request.method == "POST":
- return avatar_post(request, avatar_options)
- else:
- return Response(avatar_options)
- def get_avatar_options(request, user):
- options = {
- "avatars": user.avatars,
- "generated": True,
- "gravatar": False,
- "crop_src": False,
- "crop_tmp": False,
- "upload": False,
- "galleries": False,
- }
- # Allow existing galleries
- if avatars.gallery.galleries_exist():
- options["galleries"] = []
- for gallery in avatars.gallery.get_available_galleries():
- gallery_images = []
- for image in gallery["images"]:
- gallery_images.append({"id": image.id, "url": image.url})
- options["galleries"].append(
- {"name": gallery["name"], "images": gallery_images}
- )
- # Can't have custom avatar?
- if not request.settings.allow_custom_avatars:
- return options
- # Allow Gravatar download
- options["gravatar"] = True
- # Allow crop if we have uploaded temporary avatar
- if avatars.uploaded.has_source_avatar(user):
- try:
- options["crop_src"] = {
- "url": user.avatar_src.url,
- "crop": json.loads(user.avatar_crop),
- "size": max(settings.MISAGO_AVATARS_SIZES),
- }
- except (TypeError, ValueError):
- pass
- # Allow crop of uploaded avatar
- if avatars.uploaded.has_temporary_avatar(user):
- options["crop_tmp"] = {
- "url": user.avatar_tmp.url,
- "size": max(settings.MISAGO_AVATARS_SIZES),
- }
- # Allow upload conditions
- options["upload"] = {
- "limit": request.settings.avatar_upload_limit * 1024,
- "allowed_extensions": avatars.uploaded.ALLOWED_EXTENSIONS,
- "allowed_mime_types": avatars.uploaded.ALLOWED_MIME_TYPES,
- }
- return options
- class AvatarError(Exception):
- pass
- def avatar_post(request, options):
- user = request.user
- data = request.data
- avatar_type = data.get("avatar", "nope")
- try:
- type_options = options[avatar_type]
- if not type_options:
- return Response(
- {"detail": _("This avatar type is not allowed.")},
- status=status.HTTP_400_BAD_REQUEST,
- )
- avatar_strategy = AVATAR_TYPES[avatar_type]
- except KeyError:
- return Response(
- {"detail": _("Unknown avatar type.")}, status=status.HTTP_400_BAD_REQUEST
- )
- try:
- if avatar_type == "upload":
- # avatar_upload strategy requires access to request.settings
- response_dict = {"detail": avatar_upload(request, user, data)}
- else:
- response_dict = {"detail": avatar_strategy(user, data)}
- except AvatarError as e:
- return Response({"detail": e.args[0]}, status=status.HTTP_400_BAD_REQUEST)
- user.save()
- updated_options = get_avatar_options(request, user)
- response_dict.update(updated_options)
- return Response(response_dict)
- def avatar_generate(user, data):
- avatars.dynamic.set_avatar(user)
- return _("New avatar based on your account was set.")
- def avatar_gravatar(user, data):
- try:
- avatars.gravatar.set_avatar(user)
- return _("Gravatar was downloaded and set as new avatar.")
- except avatars.gravatar.NoGravatarAvailable:
- raise AvatarError(_("No Gravatar is associated with your e-mail address."))
- except avatars.gravatar.GravatarError:
- raise AvatarError(_("Failed to connect to Gravatar servers."))
- def avatar_gallery(user, data):
- try:
- image_pk = int(data.get("image"))
- image = AvatarGallery.objects.get(pk=image_pk)
- if image.gallery == "__default__":
- raise ValueError()
- avatars.gallery.set_avatar(user, image)
- return _("Avatar from gallery was set.")
- except (TypeError, ValueError, AvatarGallery.DoesNotExist):
- raise AvatarError(_("Incorrect image."))
- def avatar_upload(request, user, data):
- new_avatar = data.get("image")
- if not new_avatar:
- raise AvatarError(_("No file was sent."))
- try:
- avatars.uploaded.handle_uploaded_file(request, user, new_avatar)
- except ValidationError as e:
- raise AvatarError(e.args[0])
- # send back url for temp image
- return user.avatar_tmp.url
- def avatar_crop_src(user, data):
- avatar_crop(user, data, "src")
- return _("Avatar was re-cropped.")
- def avatar_crop_tmp(user, data):
- avatar_crop(user, data, "tmp")
- return _("Uploaded avatar was set.")
- def avatar_crop(user, data, suffix):
- try:
- crop = avatars.uploaded.crop_source_image(user, suffix, data.get("crop", {}))
- user.avatar_crop = json.dumps(crop)
- except ValidationError as e:
- raise AvatarError(e.args[0])
- AVATAR_TYPES = {
- "generated": avatar_generate,
- "gravatar": avatar_gravatar,
- "galleries": avatar_gallery,
- "upload": avatar_upload,
- "crop_src": avatar_crop_src,
- "crop_tmp": avatar_crop_tmp,
- }
- def moderate_avatar_endpoint(request, profile):
- if request.method == "POST":
- is_avatar_locked = profile.is_avatar_locked
- serializer = ModerateAvatarSerializer(profile, data=request.data)
- if serializer.is_valid():
- if serializer.validated_data["is_avatar_locked"] and not is_avatar_locked:
- avatars.dynamic.set_avatar(profile)
- serializer.save()
- return Response(
- {
- "avatars": profile.avatars,
- "is_avatar_locked": int(profile.is_avatar_locked),
- "avatar_lock_user_message": profile.avatar_lock_user_message,
- "avatar_lock_staff_message": profile.avatar_lock_staff_message,
- }
- )
- else:
- return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- else:
- return Response(
- {
- "is_avatar_locked": int(profile.is_avatar_locked),
- "avatar_lock_user_message": profile.avatar_lock_user_message,
- "avatar_lock_staff_message": profile.avatar_lock_staff_message,
- }
- )
|