mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
OAuth: Add profile-only access
This commit is contained in:
@@ -84,3 +84,15 @@ class EventCRUDPermission(EventPermission):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ProfilePermission(BasePermission):
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if isinstance(request.auth, OAuthAccessToken):
|
||||
if not (request.auth.allow_scopes(['read']) or request.auth.allow_scopes(['profile'])) and request.method in SAFE_METHODS:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -9,7 +9,7 @@ from oauth2_provider.settings import oauth2_settings
|
||||
class Validator(OAuth2Validator):
|
||||
|
||||
def save_authorization_code(self, client_id, code, request, *args, **kwargs):
|
||||
if not getattr(request, 'organizers', None):
|
||||
if not getattr(request, 'organizers', None) and request.scopes != ['profile']:
|
||||
raise FatalClientError('No organizers selected.')
|
||||
|
||||
expires = timezone.now() + timedelta(
|
||||
@@ -18,7 +18,8 @@ class Validator(OAuth2Validator):
|
||||
expires=expires, redirect_uri=request.redirect_uri,
|
||||
scope=" ".join(request.scopes))
|
||||
g.save()
|
||||
g.organizers.add(*request.organizers.all())
|
||||
if request.scopes != ['profile']:
|
||||
g.organizers.add(*request.organizers.all())
|
||||
|
||||
def validate_code(self, client_id, code, client, request, *args, **kwargs):
|
||||
try:
|
||||
@@ -34,12 +35,14 @@ class Validator(OAuth2Validator):
|
||||
return False
|
||||
|
||||
def _create_access_token(self, expires, request, token, source_refresh_token=None):
|
||||
if not getattr(request, 'organizers', None) and not getattr(source_refresh_token, 'access_token'):
|
||||
if not getattr(request, 'organizers', None) and not getattr(source_refresh_token, 'access_token', None) and token["scope"] != 'profile':
|
||||
raise FatalClientError('No organizers selected.')
|
||||
if hasattr(request, 'organizers'):
|
||||
orgs = list(request.organizers.all())
|
||||
else:
|
||||
orgs = list(source_refresh_token.access_token.organizers.all())
|
||||
if token['scope'] != 'profile':
|
||||
if hasattr(request, 'organizers'):
|
||||
orgs = list(request.organizers.all())
|
||||
else:
|
||||
orgs = list(source_refresh_token.access_token.organizers.all())
|
||||
access_token = super()._create_access_token(expires, request, token, source_refresh_token=None)
|
||||
access_token.organizers.add(*orgs)
|
||||
if token['scope'] != 'profile':
|
||||
access_token.organizers.add(*orgs)
|
||||
return access_token
|
||||
|
||||
@@ -3,8 +3,9 @@ import logging
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
from oauth2_provider.exceptions import OAuthToolkitError
|
||||
from oauth2_provider.exceptions import OAuthToolkitError, FatalClientError
|
||||
from oauth2_provider.forms import AllowForm
|
||||
from oauth2_provider.settings import oauth2_settings
|
||||
from oauth2_provider.views import (
|
||||
AuthorizationView as BaseAuthorizationView,
|
||||
RevokeTokenView as BaseRevokeTokenView, TokenView as BaseTokenView,
|
||||
@@ -24,9 +25,12 @@ class OAuthAllowForm(AllowForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
user = kwargs.pop('user')
|
||||
scope = kwargs.pop('scope')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['organizers'].queryset = Organizer.objects.filter(
|
||||
pk__in=user.teams.values_list('organizer', flat=True))
|
||||
if scope == 'profile':
|
||||
del self.fields['organizers']
|
||||
|
||||
|
||||
class AuthorizationView(BaseAuthorizationView):
|
||||
@@ -36,6 +40,7 @@ class AuthorizationView(BaseAuthorizationView):
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['user'] = self.request.user
|
||||
kwargs['scope'] = self.request.GET.get('scope')
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@@ -43,8 +48,14 @@ class AuthorizationView(BaseAuthorizationView):
|
||||
ctx['settings'] = settings
|
||||
return ctx
|
||||
|
||||
def create_authorization_response(self, request, scopes, credentials, allow, organizers):
|
||||
credentials["organizers"] = organizers
|
||||
def validate_authorization_request(self, request):
|
||||
require_approval = request.GET.get("approval_prompt", oauth2_settings.REQUEST_APPROVAL_PROMPT)
|
||||
if require_approval != 'force' and request.GET.get('scope') != 'profile':
|
||||
raise FatalClientError('Combnination of require_approval and scope values not allowed.')
|
||||
return super().validate_authorization_request(request)
|
||||
|
||||
def create_authorization_response(self, request, scopes, credentials, allow, organizers=None):
|
||||
credentials["organizers"] = organizers or []
|
||||
return super().create_authorization_response(request, scopes, credentials, allow)
|
||||
|
||||
def form_valid(self, form):
|
||||
|
||||
@@ -3,14 +3,18 @@ from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from pretix.api.auth.permission import ProfilePermission
|
||||
|
||||
|
||||
class MeView(APIView):
|
||||
authentication_classes = (SessionAuthentication, OAuth2Authentication)
|
||||
permission_classes = (ProfilePermission,)
|
||||
|
||||
def get(self, request, format=None):
|
||||
return Response({
|
||||
'email': request.user.email,
|
||||
'fullname': request.user.fullname,
|
||||
'locale': request.user.locale,
|
||||
'is_staff': request.user.is_staff,
|
||||
'timezone': request.user.timezone
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user