mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-10 04:50:16 +02:00
* Add service access permissions and migration `ENABLE_AUTH_<servicename> = True` will have the new permission applied to the settings configured `DEFAULT_AUTH_GROUP` group or `Member` if none is configured. `ENABLE_BLUE_<servicename> = True` will have the new permission applied to the settings configured `DEFAULT_BLUE_GROUP` group or `Blue` if none is configured. * Move views and hooks to permissions based access * Remove access restriction to services view Hypothetically non-member/blues could be granted permission to access services manually as desired now. A user that has no permissions to access any services will see a blank services list. * Remove obsolete service settings * Remove references to obsolete settings * Adjusted tests to support permissions based access * Fix incorrectly named permissions * Add simple get_services generator function * Added signals for user and groups perm changes * Update validate_services to support permissions deactivate_services removed as its surplus to requirements. * Removed state parameter from validate_services calls * Update tests to support signals changes * Fix incorrect call to validate_services task * Fix validate_services and test * Add validate_user to changed user groups signal * Added tests for new signals * Remove unnecessary post_add signals * Added documentation for service permissions * Added detection for members with service active If there are any service users in the Member or Blue groups active, then the permission will be added to the respective Member or Blue group. This means its no longer necessary to maintain the service enablesettings to migrate to permissions based service. Remove obsolete state based status checking
116 lines
3.7 KiB
Python
116 lines
3.7 KiB
Python
from __future__ import unicode_literals
|
|
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.shortcuts import render, redirect
|
|
from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE
|
|
from eveonline.models import EveCharacter
|
|
from eveonline.managers import EveManager
|
|
from authentication.models import AuthServicesInfo
|
|
|
|
from .manager import DiscourseManager
|
|
from .tasks import DiscourseTasks
|
|
from .models import DiscourseUser
|
|
|
|
import base64
|
|
import hmac
|
|
import hashlib
|
|
|
|
try:
|
|
from urllib import unquote, urlencode
|
|
except ImportError: #py3
|
|
from urllib.parse import unquote, urlencode
|
|
try:
|
|
from urlparse import parse_qs
|
|
except ImportError: #py3
|
|
from urllib.parse import parse_qs
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
ACCESS_PERM = 'discourse.access_discourse'
|
|
|
|
|
|
@login_required
|
|
def discourse_sso(request):
|
|
|
|
## Check if user has access
|
|
|
|
auth = AuthServicesInfo.objects.get(user=request.user)
|
|
if not request.user.has_perm(ACCESS_PERM):
|
|
messages.error(request, 'You are not authorized to access Discourse.')
|
|
return redirect('auth_dashboard')
|
|
|
|
if not auth.main_char_id:
|
|
messages.error(request, "You must have a main character set to access Discourse.")
|
|
return redirect('auth_characters')
|
|
|
|
main_char = EveManager.get_main_character(request.user)
|
|
if main_char is None:
|
|
messages.error(request, "Your main character is missing a database model. Please select a new one.")
|
|
return redirect('auth_characters')
|
|
|
|
payload = request.GET.get('sso')
|
|
signature = request.GET.get('sig')
|
|
|
|
if None in [payload, signature]:
|
|
messages.error(request, 'No SSO payload or signature. Please contact support if this problem persists.')
|
|
return redirect('auth_dashboard')
|
|
|
|
## Validate the payload
|
|
|
|
try:
|
|
payload = unquote(payload).encode('utf-8')
|
|
decoded = base64.decodestring(payload).decode('utf-8')
|
|
assert 'nonce' in decoded
|
|
assert len(payload) > 0
|
|
except AssertionError:
|
|
messages.error(request, 'Invalid payload. Please contact support if this problem persists.')
|
|
return redirect('auth_dashboard')
|
|
|
|
key = str(settings.DISCOURSE_SSO_SECRET).encode('utf-8')
|
|
h = hmac.new(key, payload, digestmod=hashlib.sha256)
|
|
this_signature = h.hexdigest()
|
|
|
|
if this_signature != signature:
|
|
messages.error(request, 'Invalid payload. Please contact support if this problem persists.')
|
|
return redirect('auth_dashboard')
|
|
|
|
## Build the return payload
|
|
|
|
username = DiscourseManager._sanitize_username(main_char.character_name)
|
|
|
|
qs = parse_qs(decoded)
|
|
params = {
|
|
'nonce': qs['nonce'][0],
|
|
'email': request.user.email,
|
|
'external_id': request.user.pk,
|
|
'username': username,
|
|
'name': username,
|
|
}
|
|
|
|
if auth.main_char_id:
|
|
params['avatar_url'] = 'https://image.eveonline.com/Character/%s_256.jpg' % auth.main_char_id
|
|
|
|
return_payload = base64.encodestring(urlencode(params).encode('utf-8'))
|
|
h = hmac.new(key, return_payload, digestmod=hashlib.sha256)
|
|
query_string = urlencode({'sso': return_payload, 'sig': h.hexdigest()})
|
|
|
|
## Record activation and queue group sync
|
|
|
|
if not DiscourseTasks.has_account(request.user):
|
|
discourse_user = DiscourseUser()
|
|
discourse_user.user = request.user
|
|
discourse_user.enabled = True
|
|
discourse_user.save()
|
|
DiscourseTasks.update_groups.apply_async(args=[request.user.pk], countdown=30) # wait 30s for new user creation on Discourse
|
|
|
|
## Redirect back to Discourse
|
|
|
|
url = '%s/session/sso_login' % settings.DISCOURSE_URL
|
|
return redirect('%s?%s' % (url, query_string))
|
|
|