123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- from django.contrib import messages
- from django.contrib.auth import update_session_auth_hash
- from django.core.exceptions import ValidationError
- from django.core.urlresolvers import reverse
- from django.db import IntegrityError, transaction
- from django.http import Http404, JsonResponse
- from django.shortcuts import redirect, render as django_render
- from django.utils.translation import ugettext as _
- from django.views.decorators.debug import sensitive_post_parameters
- from misago.conf import settings
- from misago.core.decorators import ajax_only, require_POST
- from misago.core.exceptions import AjaxError
- from misago.core.mail import mail_user
- from misago.markup import Editor
- from misago.users import avatars
- from misago.users.decorators import deny_guests
- from misago.users.forms.rename import ChangeUsernameForm
- from misago.users.forms.usercp import (ChangeForumOptionsForm,
- EditSignatureForm,
- ChangeEmailPasswordForm)
- from misago.users.signatures import set_user_signature
- from misago.users.sites import usercp
- from misago.users.changedcredentials import (cache_new_credentials,
- get_new_credentials)
- from misago.users.namechanges import UsernameChanges
- def render(request, template, context=None):
- context = context or {}
- context['pages'] = usercp.get_pages(request)
- for page in context['pages']:
- if page['is_active']:
- context['active_page'] = page
- break
- return django_render(request, template, context)
- @deny_guests
- def change_forum_options(request):
- form = ChangeForumOptionsForm(instance=request.user)
- if request.method == 'POST':
- form = ChangeForumOptionsForm(request.POST, instance=request.user)
- if form.is_valid():
- form.save()
- message = _("Your forum options have been changed.")
- messages.success(request, message)
- return redirect('misago:usercp_change_forum_options')
- return render(request, 'misago/usercp/change_forum_options.html',
- {'form': form})
- @deny_guests
- def change_avatar(request):
- avatar_size = max(settings.MISAGO_AVATARS_SIZES)
- if not request.user.is_avatar_banned and request.method == 'POST':
- if 'dl-gravatar' in request.POST and settings.allow_custom_avatars:
- try:
- avatars.gravatar.set_avatar(request.user)
- message = _("Gravatar was downloaded and set as new avatar.")
- messages.success(request, message)
- except avatars.gravatar.GravatarError:
- message = _("Failed to connect to Gravatar servers.")
- messages.info(request, message)
- except avatars.gravatar.NoGravatarAvailable:
- message = _("No Gravatar is associated "
- "with your e-mail address.")
- messages.info(request, message)
- elif 'set-dynamic' in request.POST:
- avatars.dynamic.set_avatar(request.user)
- message = _("New avatar based on your account was set.")
- messages.success(request, message)
- return redirect('misago:usercp_change_avatar')
- return render(request, 'misago/usercp/change_avatar.html', {
- 'avatar_size': avatar_size,
- 'galleries_exist': avatars.gallery.galleries_exist(),
- 'has_source_image': avatars.uploaded.has_original_avatar(request.user)
- })
- def avatar_not_banned(f):
- def decorator(request, *args, **kwargs):
- if request.user.is_avatar_banned:
- message = _("You don't have permission to change your avatar.")
- messages.info(request, message)
- return redirect('misago:usercp_change_avatar')
- else:
- return f(request, *args, **kwargs)
- return decorator
- @deny_guests
- @avatar_not_banned
- def upload_avatar(request):
- if not settings.allow_custom_avatars:
- messages.info(request, _("Avatar uploads are currently disabled."))
- return redirect('misago:usercp_change_avatar')
- return render(request, 'misago/usercp/upload_avatar.html', {
- 'upload_limit': settings.avatar_upload_limit * 1024,
- 'upload_limit_mb': settings.avatar_upload_limit / 1024.0,
- 'allowed_extensions': avatars.uploaded.ALLOWED_EXTENSIONS,
- 'allowed_mime_types': avatars.uploaded.ALLOWED_MIME_TYPES,
- })
- @ajax_only
- @deny_guests
- @require_POST
- @avatar_not_banned
- def upload_avatar_handler(request):
- if not settings.allow_custom_avatars:
- raise AjaxError(_("Avatar uploads are currently disabled."))
- new_avatar = request.FILES.get('new-avatar');
- if not new_avatar:
- raise AjaxError(_("No file was sent."))
- try:
- avatars.uploaded.handle_uploaded_file(request.user, new_avatar)
- except ValidationError as e:
- raise AjaxError(e.args[0])
- return JsonResponse({'is_error': 0, 'message': 'Image has been uploaded.'})
- @deny_guests
- @avatar_not_banned
- def crop_avatar(request, use_tmp_avatar):
- if use_tmp_avatar:
- if not avatars.uploaded.has_temporary_avatar(request.user):
- messages.error(request, _("Upload image that you want to crop."))
- return redirect('misago:usercp_change_avatar')
- else:
- if not avatars.uploaded.has_original_avatar(request.user):
- messages.error(request, _("You don't have uploaded image to crop."))
- return redirect('misago:usercp_change_avatar')
- if use_tmp_avatar:
- token = avatars.uploaded.avatar_source_token(request.user, 'tmp')
- avatar_url = reverse('misago:user_avatar_tmp', kwargs={
- 'user_id': request.user.pk, 'token': token
- })
- else:
- token = avatars.uploaded.avatar_source_token(request.user, 'org')
- avatar_url = reverse('misago:user_avatar_org', kwargs={
- 'user_id': request.user.pk, 'token': token
- })
- if request.method == 'POST':
- crop = request.POST.get('crop')
- try:
- if use_tmp_avatar:
- avatars.uploaded.crop_source_image(request.user, 'tmp', crop)
- else:
- avatars.uploaded.crop_source_image(request.user, 'org', crop)
- request.user.avatar_crop = crop
- request.user.save(update_fields=['avatar_crop'])
- if use_tmp_avatar:
- messages.success(request, _("Uploaded avatar was set."))
- else:
- messages.success(request, _("Avatar was cropped."))
- return redirect('misago:usercp_change_avatar')
- except ValidationError as e:
- messages.error(request, e.args[0])
- if not use_tmp_avatar and request.user.avatar_crop:
- user_crop = request.user.avatar_crop.split(',')
- current_crop = {
- 'image_width': user_crop[0],
- 'selection_len': user_crop[3],
- 'start_x': user_crop[4],
- 'start_y': user_crop[6],
- }
- else:
- current_crop = None
- return render(request, 'misago/usercp/crop_avatar.html', {
- 'avatar_url': avatar_url,
- 'crop': current_crop
- })
- @deny_guests
- @avatar_not_banned
- def avatar_galleries(request):
- if not avatars.gallery.galleries_exist():
- messages.info(request, _("No avatars galleries exist."))
- return redirect('misago:usercp_change_avatar')
- if request.method == 'POST':
- new_image = request.POST.get('new-image')
- if new_image:
- if avatars.gallery.is_avatar_from_gallery(new_image):
- avatars.gallery.set_avatar(request.user, new_image)
- messages.success(request, _("Avatar from gallery was set."))
- return redirect('misago:usercp_change_avatar')
- else:
- messages.error(request, _("Incorrect image."))
- return render(request, 'misago/usercp/avatar_galleries.html', {
- 'galleries': avatars.gallery.get_available_galleries()
- })
- @deny_guests
- def edit_signature(request):
- if not request.user.acl['can_have_signature']:
- raise Http404()
- form = EditSignatureForm(instance=request.user)
- if not request.user.is_signature_banned and request.method == 'POST':
- form = EditSignatureForm(request.POST, instance=request.user)
- if form.is_valid():
- set_user_signature(request.user, form.cleaned_data['signature'])
- request.user.save(update_fields=['signature', 'signature_parsed',
- 'signature_checksum'])
- if form.cleaned_data['signature']:
- messages.success(request, _("Your signature has been edited."))
- else:
- message = _("Your signature has been cleared.")
- messages.success(request, message)
- return redirect('misago:usercp_edit_signature')
- acl = request.user.acl
- editor = Editor(form['signature'],
- allow_blocks=acl['allow_signature_blocks'],
- allow_links=acl['allow_signature_links'],
- allow_images=acl['allow_signature_images'])
- return render(request, 'misago/usercp/edit_signature.html',
- {'form': form, 'editor': editor})
- @deny_guests
- @transaction.atomic()
- def change_username(request):
- namechanges = UsernameChanges(request.user)
- form = ChangeUsernameForm()
- if request.method == 'POST' and namechanges.left:
- form = ChangeUsernameForm(request.POST, user=request.user)
- if form.is_valid():
- try:
- form.change_username(changed_by=request.user)
- message = _("Your username has been changed.")
- messages.success(request, message)
- return redirect('misago:usercp_change_username')
- except IntegrityError:
- message = _("Error changing username. Please try again.")
- messages.error(request, message)
- return render(request, 'misago/usercp/change_username.html', {
- 'form': form,
- 'changes_left': namechanges.left,
- 'next_change_on': namechanges.next_on
- })
- @sensitive_post_parameters()
- @deny_guests
- def change_email_password(request):
- form = ChangeEmailPasswordForm()
- if request.method == 'POST':
- form = ChangeEmailPasswordForm(request.POST, user=request.user)
- if form.is_valid():
- new_email = ''
- new_password = ''
- # Store original data
- old_email = request.user.email
- old_password = request.user.password
- # Assign new creds to user temporarily
- if form.cleaned_data['new_email']:
- request.user.set_email(form.cleaned_data['new_email'])
- new_email = request.user.email
- if form.cleaned_data['new_password']:
- request.user.set_password(form.cleaned_data['new_password'])
- new_password = request.user.password
- request.user.email = old_email
- request.user.password = old_password
- credentials_token = cache_new_credentials(
- request.user, new_email, new_password)
- mail_subject = _("Confirm changes to %(username)s account "
- "on %(forum_title)s forums")
- subject_formats = {'username': request.user.username,
- 'forum_title': settings.forum_name}
- mail_subject = mail_subject % subject_formats
- if new_email:
- # finally override email before sending message
- request.user.email = new_email
- mail_user(request, request.user, mail_subject,
- 'misago/emails/change_email_password',
- {'credentials_token': credentials_token})
- message = _("E-mail was sent to %(email)s with a link that "
- "you have to click to confirm changes.")
- messages.info(request, message % {'email': request.user.email})
- return redirect('misago:usercp_change_email_password')
- return render(request, 'misago/usercp/change_email_password.html',
- {'form': form})
- @deny_guests
- def confirm_email_password_change(request, token):
- new_credentials = get_new_credentials(request.user, token)
- if not new_credentials:
- messages.error(request, _("Confirmation link is invalid."))
- else:
- changes_made = []
- if new_credentials['email']:
- request.user.set_email(new_credentials['email'])
- changes_made.extend(['email', 'email_hash'])
- if new_credentials['password']:
- request.user.password = new_credentials['password']
- update_session_auth_hash(request, request.user)
- changes_made.append('password')
- try:
- request.user.save(update_fields=changes_made)
- message = _("Changes in e-mail and password have been saved.")
- messages.success(request, message)
- except IntegrityError:
- messages.error(request, _("Confirmation link is invalid."))
- return redirect('misago:usercp_change_email_password')
|