import logging from django.db import router from django import forms from django.conf import settings from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.contrib.auth import update_session_auth_hash, authenticate, login, get_user_model from django.contrib.auth.decorators import login_required from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.models import Group from django.core.mail import send_mail from django.db.models import ProtectedError from django.forms import widgets from django.http import HttpResponseForbidden from django.shortcuts import render, redirect from django.template import TemplateDoesNotExist from django.urls import reverse from django.utils.encoding import force_bytes, force_text from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.translation import ugettext from basetheme_bootstrap import tokens from basetheme_bootstrap import user_preferences from basetheme_bootstrap.default_settings import is_validating_email from basetheme_bootstrap.forms import UserCreationFormWithMore, \ MyUserChangeForm, UserDeleteForm logger = logging.getLogger(__name__) def about_page(request): context = {} try: return render(request, settings.BASETHEME_BOOTSTRAP_TEMPLATE_LOCATION_PROJECT + '/about.html') except TemplateDoesNotExist: return render(request, 'basetheme_bootstrap/about.example.html') @login_required def change_password(request): if request.method == 'POST': form = PasswordChangeForm(request.user, request.POST) if form.is_valid(): user = form.save() update_session_auth_hash(request, user) # Important! messages.success(request, 'Your password was successfully updated!') return redirect('basetheme_bootstrap:account') else: messages.error(request, 'Please correct the error below.') else: form = PasswordChangeForm(request.user) return render(request, 'registration/small_form_host.html', { 'title': ugettext('Change password'), 'submit_text': ugettext('Save changes'), 'form': form }) def signup(request): if request.method == 'POST': form = UserCreationFormWithMore(request.POST) if form.is_valid(): auto_active = not is_validating_email() user = form.save() if get_user_model().objects.filter(pk__gt=1).count() == 0: user.is_superuser = True user.is_staff = True user.is_active = True Group.objects.get_or_create(name="PendingAccountUser") else: if not auto_active: g, created = Group.objects.get_or_create(name="PendingAccountUser") user.groups.add(g) user.is_active = auto_active user.save() send_account_created(request, user, auto_active=auto_active) if not auto_active and not user.is_superuser: return account_is_pending_view(request, email=request.POST['email']) username = user.username raw_password = form.cleaned_data.get('password1') user = authenticate(username=username, password=raw_password) request.user = user login(request, user) return redirect('home') else: user = get_user_model().objects.filter(groups__name="PendingAccountUser", email=request.POST['email']).first() if user is not None: send_account_created(request, user, auto_active=not is_validating_email()) return account_is_pending_view(request, email=request.POST['email']) else: if not request.user.is_anonymous: return HttpResponseForbidden() form = UserCreationFormWithMore() return render(request, 'registration/signup.html', {'form': form}) def account_is_pending_view(request, email): return render(request, 'basetheme_bootstrap/simple_message_page.html', { 'page_title': ugettext('Account activation pending'), 'message': ugettext('An email was sent with a link to validate your account, ' 'please click on the link to enable your account.'), 'sub_message': ugettext('The email has been addressed to %s.') % email, }) def send_account_created(request, user, auto_active=False): try: activation_link = request.scheme + "://" + request.get_host() activation_link += reverse('basetheme_bootstrap:activate', kwargs={ 'uidb64': urlsafe_base64_encode(force_bytes(user.pk)), 'token': tokens.account_activation_token.make_token(user) }) if auto_active: message = ugettext( 'Dear %(first_name)s %(last_name)s\n\n' 'Your account have successfully been created on %(joined)s.' '\n\n' 'Best regards') % dict( first_name=user.first_name, last_name=user.last_name, joined=str(user.date_joined), ) else: message = ugettext( 'Dear %(first_name)s %(last_name)s\n\n' 'Your account have successfully been created on %(joined)s.' '\n\n' 'Please click on the link to confirm your registration\n' '%(activation_link)s' '\n\n' 'Best regards') % dict( first_name=user.first_name, last_name=user.last_name, joined=str(user.date_joined), activation_link=activation_link, ) send_mail( subject=ugettext('Account successfully created'), message=message, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[user.email], fail_silently=False, ) except Exception as e: logging.exception("Sending email to user %i failed" % user.pk) def user_update(request): if request.method == 'POST': form = MyUserChangeForm(instance=request.user, data=request.POST) if form.is_valid(): user = form.save() update_session_auth_hash(request, user) # Important! messages.success(request, 'Your account was successfully updated!') return redirect('basetheme_bootstrap:account') else: messages.error(request, 'Please correct the error below.') else: form = MyUserChangeForm(instance=request.user) return render(request, 'registration/small_form_host.html', { 'title': ugettext('Update account'), 'submit_text': ugettext('Save changes'), 'form': form, 'medium_width': True, }) def user_delete(request): if request.method == 'POST': form = UserDeleteForm(instance=request.user, data=request.POST) if form.is_valid(): try: user = form.save() user.delete() update_session_auth_hash(request, user) # Important! messages.success(request, 'Your account was successfully deleted!') return redirect('/') except ProtectedError as e: messages.error(request, ugettext("Some data remaining in the system prevent the deletion of your " "account. Please either remove these data, or contact the " "administrator to solve the issue.\nMessage:\n" + str(e))) except Exception as e: messages.error(request, e) else: form = UserDeleteForm(instance=request.user) # Inspired from auth/admin.py#get_deleted_objects collector = NestedObjects(using=router.db_for_write(get_user_model())) collector.collect([request.user,]) return render(request, 'registration/account_deletion.html', { 'title': ugettext('Account deletion'), 'submit_text': ugettext('Delete account and all related data'), 'form': form, 'protected': collector.protected, 'medium_width': True, 'btn_classes': 'btn-lg btn-danger text-center', 'btn_container_classes': 'text-center', 'custom_css_width':' ', }) @login_required def account_detail(request): klass = user_preferences.get_user_preference_class() if klass is None: form_prefs = None else: is_posted = request.method == 'POST' pref = klass.get_for_user(user=request.user) form_prefs = forms.modelform_factory( klass, fields=list(klass.get_allowed_fields()), )(instance=pref, data=request.POST if is_posted else None) if is_posted and form_prefs.is_valid(): form_prefs.save() form_prefs = forms.modelform_factory( klass, fields=list(klass.get_allowed_fields()), )(instance=klass.get_for_user(user=request.user)) # dirty patch for time field (don't know why django doesn't express the correct type by default) for f in form_prefs.fields.values(): if isinstance(f.widget, widgets.TimeInput): f.widget.input_type = 'time' form_prefs.preferences_groups = getattr(pref, "preferences_groups", None) form_prefs.preferences_groups_descriptions = getattr(pref, "preferences_groups_descriptions", None) return render(request, 'registration/account.html', { 'form_prefs': form_prefs, 'btn_classes': 'pull-right float-right' }) def activate(request, uidb64, token): try: uid = force_text(urlsafe_base64_decode(uidb64)) user = get_user_model().objects.get(pk=uid) except(TypeError, ValueError, OverflowError, get_user_model().DoesNotExist): user = None if user is not None and user.groups.filter(name="PendingAccountUser").exists(): if tokens.account_activation_token.check_token(user, token): user.is_active = True user.groups.remove(user.groups.get(name="PendingAccountUser")) user.save() login(request, user) # return redirect('home') # return HttpResponse('Thank you for your email confirmation. Now you can login your account.') return render(request, 'basetheme_bootstrap/simple_message_page.html', { 'page_title': ugettext('Account activated'), 'message': ugettext('Thank you for your email confirmation, you account have been activated ' 'and you are now logged in.'), }) else: send_account_created(request, user) return account_is_pending_view(request, email=user.email) else: return render(request, 'basetheme_bootstrap/simple_message_page.html', { 'page_title': ugettext('Activation link is invalid!'), })