mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-10 09:06:21 +01:00
Restructure Alliance Auth package (#867)
* Refactor allianceauth into its own package * Add setup * Add missing default_app_config declarations * Fix timerboard namespacing * Remove obsolete future imports * Remove py2 mock support * Remove six * Add experimental 3.7 support and multiple Dj versions * Remove python_2_unicode_compatible * Add navhelper as local package * Update requirements
This commit is contained in:
151
allianceauth/authentication/views.py
Normal file
151
allianceauth/authentication/views.py
Normal file
@@ -0,0 +1,151 @@
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import login, authenticate
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.core import signing
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from esi.decorators import token_required
|
||||
from registration.backends.hmac.views import RegistrationView as BaseRegistrationView, \
|
||||
ActivationView as BaseActivationView, REGISTRATION_SALT
|
||||
from registration.signals import user_registered
|
||||
|
||||
from .models import CharacterOwnership
|
||||
from .forms import RegistrationForm
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@login_required
|
||||
@token_required(scopes=settings.LOGIN_TOKEN_SCOPES)
|
||||
def main_character_change(request, token):
|
||||
logger.debug("main_character_change called by user %s for character %s" % (request.user, token.character_name))
|
||||
try:
|
||||
co = CharacterOwnership.objects.get(character__character_id=token.character_id, user=request.user)
|
||||
except CharacterOwnership.DoesNotExist:
|
||||
if not CharacterOwnership.objects.filter(character__character_id=token.character_id).exists():
|
||||
co = CharacterOwnership.objects.create_by_token(token)
|
||||
else:
|
||||
messages.error(request, 'Cannot change main character to %(char)s: character owned by a different account.' % ({'char': token.character_name}))
|
||||
co = None
|
||||
if co:
|
||||
request.user.profile.main_character = co.character
|
||||
request.user.profile.save(update_fields=['main_character'])
|
||||
messages.success(request, _('Changed main character to %(char)s') % {"char": co.character})
|
||||
logger.info('Changed user %(user)s main character to %(char)s' % ({'user': request.user, 'char': co.character}))
|
||||
return redirect("authentication:dashboard")
|
||||
|
||||
|
||||
@token_required(new=True, scopes=settings.LOGIN_TOKEN_SCOPES)
|
||||
def add_character(request, token):
|
||||
if CharacterOwnership.objects.filter(character__character_id=token.character_id).filter(
|
||||
owner_hash=token.character_owner_hash).filter(user=request.user).exists():
|
||||
messages.success(request, _('Added %(name)s to your account.'% ({'name': token.character_name})))
|
||||
else:
|
||||
messages.error(request, _('Failed to add %(name)s to your account: they already have an account.' % ({'name': token.character_name})))
|
||||
return redirect('authentication:dashboard')
|
||||
|
||||
|
||||
"""
|
||||
Override the HMAC two-step registration view to accommodate the three-step registration required.
|
||||
Step 1: OAuth token to create user and profile.
|
||||
Step 2: Get email and send activation link (but do not save email).
|
||||
Step 3: Get link, save email and activate.
|
||||
|
||||
Step 1 is necessary to automatically assign character ownership and a main character, both of which require a saved User
|
||||
model - this means the ensuing registration form cannot create the user because it already exists.
|
||||
|
||||
Email is not saved to the user model in Step 2 as a way of differentiating users who have not yet completed registration
|
||||
(is_active=False) and users who have been disabled by an admin (is_active=False, email present).
|
||||
|
||||
Because of this, the email address needs to be assigned in Step 3 after clicking the link, which means the link must
|
||||
have the email address embedded much like the username. Key creation and decoding is overridden to support this action.
|
||||
"""
|
||||
|
||||
|
||||
# Step 1
|
||||
@token_required(new=True, scopes=settings.LOGIN_TOKEN_SCOPES)
|
||||
def sso_login(request, token):
|
||||
user = authenticate(token=token)
|
||||
if user and user.is_active:
|
||||
login(request, user)
|
||||
return redirect(request.POST.get('next', request.GET.get('next', 'authentication:dashboard')))
|
||||
elif user and not user.email:
|
||||
# Store the new user PK in the session to enable us to identify the registering user in Step 2
|
||||
request.session['registration_uid'] = user.pk
|
||||
# Go to Step 2
|
||||
return redirect('registration_register')
|
||||
else:
|
||||
messages.error(request, _('Unable to authenticate as the selected character.'))
|
||||
return redirect(settings.LOGIN_URL)
|
||||
|
||||
|
||||
# Step 2
|
||||
class RegistrationView(BaseRegistrationView):
|
||||
form_class = RegistrationForm
|
||||
success_url = 'authentication:dashboard'
|
||||
|
||||
def dispatch(self, *args, **kwargs):
|
||||
# We're storing a key in the session to pass user information from OAuth response. Make sure it's there.
|
||||
if not self.request.session.get('registration_uid', None) or not User.objects.filter(
|
||||
pk=self.request.session.get('registration_uid')).exists():
|
||||
messages.error(self.request, _('Registration token has expired.'))
|
||||
return redirect(settings.LOGIN_URL)
|
||||
return super(RegistrationView, self).dispatch(*args, **kwargs)
|
||||
|
||||
def register(self, form):
|
||||
user = User.objects.get(pk=self.request.session.get('registration_uid'))
|
||||
user.email = form.cleaned_data['email']
|
||||
user_registered.send(self.__class__, user=user, request=self.request)
|
||||
# Go to Step 3
|
||||
self.send_activation_email(user)
|
||||
return user
|
||||
|
||||
def get_activation_key(self, user):
|
||||
return signing.dumps(obj=[getattr(user, User.USERNAME_FIELD), user.email], salt=REGISTRATION_SALT)
|
||||
|
||||
def get_email_context(self, activation_key):
|
||||
context = super(RegistrationView, self).get_email_context(activation_key)
|
||||
context['url'] = context['site'].domain + reverse('registration_activate', args=[activation_key])
|
||||
return context
|
||||
|
||||
|
||||
# Step 3
|
||||
class ActivationView(BaseActivationView):
|
||||
def validate_key(self, activation_key):
|
||||
try:
|
||||
dump = signing.loads(activation_key, salt=REGISTRATION_SALT,
|
||||
max_age=settings.ACCOUNT_ACTIVATION_DAYS * 86400)
|
||||
return dump
|
||||
except signing.BadSignature:
|
||||
return None
|
||||
|
||||
def activate(self, *args, **kwargs):
|
||||
dump = self.validate_key(kwargs.get('activation_key'))
|
||||
if dump:
|
||||
user = self.get_user(dump[0])
|
||||
if user:
|
||||
user.email = dump[1]
|
||||
user.is_active = True
|
||||
user.save()
|
||||
return user
|
||||
return False
|
||||
|
||||
|
||||
def registration_complete(request):
|
||||
messages.success(request, _('Sent confirmation email. Please follow the link to confirm your email address.'))
|
||||
return redirect('authentication:login')
|
||||
|
||||
|
||||
def activation_complete(request):
|
||||
messages.success(request, _('Confirmed your email address. Please login to continue.'))
|
||||
return redirect('authentication:dashboard')
|
||||
|
||||
|
||||
def registration_closed(request):
|
||||
messages.error(request, _('Registraion of new accounts it not allowed at this time.'))
|
||||
return redirect('authentication:login')
|
||||
Reference in New Issue
Block a user