Implement optional scopes : clients can request scopes, but they are not guaranteed to get them

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
Yohann D'ANELLO 2021-12-23 21:59:37 +01:00
parent 132afc3d15
commit 18a1282773
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 27 additions and 1 deletions

View File

@ -1,6 +1,6 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from oauth2_provider.oauth2_validators import OAuth2Validator
from oauth2_provider.scopes import BaseScopes from oauth2_provider.scopes import BaseScopes
from member.models import Club from member.models import Club
from note_kfet.middlewares import get_current_request from note_kfet.middlewares import get_current_request
@ -32,3 +32,26 @@ class PermissionScopes(BaseScopes):
return [] return []
return [f"{p.id}_{p.membership.club.id}" return [f"{p.id}_{p.membership.club.id}"
for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')] for p in PermissionBackend.get_raw_permissions(get_current_request(), 'view')]
class PermissionOAuth2Validator(OAuth2Validator):
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)
request.scopes = valid_scopes
return valid_scopes

View File

@ -7,6 +7,8 @@
import os import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
from datetime import timedelta
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
@ -248,6 +250,7 @@ REST_FRAMEWORK = {
# OAuth2 Provider # OAuth2 Provider
OAUTH2_PROVIDER = { OAUTH2_PROVIDER = {
'SCOPES_BACKEND_CLASS': 'permission.scopes.PermissionScopes', 'SCOPES_BACKEND_CLASS': 'permission.scopes.PermissionScopes',
'OAUTH2_VALIDATOR_CLASS': "permission.scopes.PermissionOAuth2Validator",
} }
# Take control on how widget templates are sourced # Take control on how widget templates are sourced