mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| from oauth2_provider.oauth2_validators import OAuth2Validator
 | |
| from oauth2_provider.scopes import BaseScopes
 | |
| from member.models import Club
 | |
| from note.models import Alias
 | |
| from note_kfet.middlewares import get_current_request
 | |
| 
 | |
| from .backends import PermissionBackend
 | |
| from .models import Permission
 | |
| 
 | |
| 
 | |
| class PermissionScopes(BaseScopes):
 | |
|     """
 | |
|     An OAuth2 scope is defined by a permission object and a club.
 | |
|     A token will have a subset of permissions from the owner of the application,
 | |
|     and can be useful to make queries through the API with limited privileges.
 | |
|     """
 | |
| 
 | |
|     def get_all_scopes(self, **kwargs):
 | |
|         scopes = {}
 | |
|         if 'scopes' in kwargs:
 | |
|             for scope in kwargs['scopes']:
 | |
|                 if scope == 'openid':
 | |
|                     scopes['openid'] = "OpenID Connect"
 | |
|                 else:
 | |
|                     p = Permission.objects.get(id=scope.split('_')[0])
 | |
|                     club = Club.objects.get(id=scope.split('_')[1])
 | |
|                     scopes[scope] = f"{p.description} (club {club.name})"
 | |
|             return scopes
 | |
| 
 | |
|         scopes = {f"{p.id}_{club.id}": f"{p.description} (club {club.name})"
 | |
|                   for p in Permission.objects.all() for club in Club.objects.all()}
 | |
|         scopes['openid'] = "OpenID Connect"
 | |
|         return scopes
 | |
| 
 | |
|     def get_available_scopes(self, application=None, request=None, *args, **kwargs):
 | |
|         if not application:
 | |
|             return []
 | |
|         scopes = [f"{p.id}_{p.membership.club.id}"
 | |
|                   for t in Permission.PERMISSION_TYPES
 | |
|                   for p in PermissionBackend.get_raw_permissions(get_current_request(), t[0])]
 | |
|         scopes.append('openid')
 | |
|         return scopes
 | |
| 
 | |
|     def get_default_scopes(self, application=None, request=None, *args, **kwargs):
 | |
|         if not application:
 | |
|             return []
 | |
|         scopes = [f"{p.id}_{p.membership.club.id}"
 | |
|                   for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')]
 | |
|         scopes.append('openid')
 | |
|         return scopes
 | |
| 
 | |
| 
 | |
| class PermissionOAuth2Validator(OAuth2Validator):
 | |
|     oidc_claim_scope = OAuth2Validator.oidc_claim_scope
 | |
|     oidc_claim_scope.update({"name": 'openid',
 | |
|                              "normalized_name": 'openid',
 | |
|                              "email": 'openid',
 | |
|                              })
 | |
| 
 | |
|     def get_additional_claims(self, request):
 | |
|         return {
 | |
|             "name": request.user.username,
 | |
|             "normalized_name": Alias.normalize(request.user.username),
 | |
|             "email": request.user.email,
 | |
|         }
 | |
| 
 | |
|     def get_discovery_claims(self, request):
 | |
|         claims = super().get_discovery_claims(self)
 | |
|         return claims + ["name", "normalized_name", "email"]
 | |
| 
 | |
|     def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs):
 | |
|         """
 | |
|         User can request as many scope as he wants, including invalid scopes,
 | |
|         but it will have only the permissions he has.
 | |
| 
 | |
|         This allows clients to request more permission to get finally a
 | |
|         subset of permissions.
 | |
|         """
 | |
| 
 | |
|         valid_scopes = set()
 | |
| 
 | |
|         for t in Permission.PERMISSION_TYPES:
 | |
|             for p in PermissionBackend.get_raw_permissions(get_current_request(), t[0]):
 | |
|                 scope = f"{p.id}_{p.membership.club.id}"
 | |
|                 if scope in scopes:
 | |
|                     valid_scopes.add(scope)
 | |
| 
 | |
|         if 'openid' in scopes:
 | |
|             valid_scopes.add('openid')
 | |
| 
 | |
|         request.scopes = valid_scopes
 | |
|         return valid_scopes
 |