Select Git revision
Forked from
hub / hub
4056 commits behind the upstream repository.

HeJ authored
This is intended for troubleshooting authentication issues - primarily in the backoffice but might be used for other parts of the system as well.
auth.py 5.26 KiB
import logging
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import views as auth_views
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMessage
from django.http import JsonResponse
from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.views.generic import FormView, TemplateView, View
from django.urls import reverse, reverse_lazy
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from core.models import PlatformUser, UserCommunicationChannel
from ..forms import SignUpForm
from ..tokens import channel_activation_token
from .mixins import ConferenceMixin
logger = logging.getLogger(__name__)
class LoginView(auth_views.LoginView):
template_name = 'backoffice/login.html'
def get_success_url(self):
return reverse('backoffice:index')
class LogoutView(auth_views.LogoutView):
next_page = reverse_lazy('backoffice:index')
class SignupView(FormView):
form_class = SignUpForm
template_name = 'registration/signup.html'
def form_valid(self, form):
user = form.save(commit=False)
user.is_active = False
user.save()
channel = user.communication_channels.create(
channel=UserCommunicationChannel.Channel.MAIL,
address=form.cleaned_data['email'],
)
channel.save()
try:
subject = 'Activate Your RC3 Platform Account'
body = render_to_string('registration/account_activation_email.txt', {
'user': user,
'domain': get_current_site(self.request).domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'cid': channel.id,
'token': channel_activation_token.make_token(channel),
})
message = EmailMessage(
to=[user.email],
subject=subject,
body=body,
reply_to=settings.MAIL_REPLY_TO,
)
result = message.send()
logger.info('Sent account activation mail to "' + user.email + '" for ' + user.username + ' = ' + str(result))
return redirect('backoffice:account_activation_sent')
except Exception as err:
print('MIMIMI', err)
logger.exception('sending account activation mail failed')
user.delete()
messages.error(self.request, 'Could not send mail, please try again :(')
return self.get(self.request)
class SignupDoneView(ConferenceMixin, TemplateView):
template_name = 'registration/signup_done.html'
def signup_activate(request, uidb64, channel_id, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = PlatformUser.objects.get(pk=uid)
channel = user.communication_channels.get(id=channel_id)
except Exception as err:
messages.warning(request, 'Invalid activation code.')
logger.warning(f'Account activation failed (user={user}, uidb64={uidb64}, channel={channel_id}, token={token}): {err}')
return redirect('backoffice:signup')
if not channel_activation_token.check_token(channel, token):
messages.warning(request, 'Invalid activation code.')
logger.warning(f'Account activation failed (user={user}, uidb64={uidb64}, channel={channel_id}, token={token}) due to invalid token.')
return redirect('backoffice:signup')
if channel.channel != UserCommunicationChannel.Channel.MAIL or user.email is None or user.email != channel.address:
messages.warning(request, 'Not an account registration.')
logger.warning(f'Account activation failed for non-registration-channel (user={user}, uidb64={uidb64}, channel={channel_id}, token={token})')
return redirect('backoffice:signup')
# first time registration: user.email was still set to the mail communication channel's address
user.is_active = True
user.email = ''
channel.is_verified = True
user.save()
channel.save()
messages.success(request, 'Activation code OK')
logger.info(f'Account activated successfully: {user.username}')
return redirect('backoffice:index')
class AuthDebugView(LoginRequiredMixin, ConferenceMixin, View):
def get(self, *args, **kwargs):
u = self.request.user
result = {}
result['conference'] = self.conference.slug
result['global'] = {
'username': u.username,
'active': u.is_active,
'flags': [],
'groups': list(u.groups.values_list('name', flat=True)),
}
if u.is_superuser:
result['global']['flags'].append('superuser')
if u.is_staff:
result['global']['flags'].append('staff')
if (member := self.conferencemember) is not None:
result['member'] = {
'staff': member.is_staff,
'active_angel': member.active_angel,
'pages': member.static_page_groups,
'groups': list(member.permission_groups.values_list('name', flat=True)),
}
else:
result['member'] = False
return JsonResponse(result)