From 18a1282773ace97b50475d73195ca6bff46f32b4 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Thu, 23 Dec 2021 21:59:37 +0100 Subject: [PATCH] Implement optional scopes : clients can request scopes, but they are not guaranteed to get them Signed-off-by: Yohann D'ANELLO --- apps/permission/scopes.py | 25 ++++++++++++++++++++++++- note_kfet/settings/base.py | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py index bf74cb81..65242804 100644 --- a/apps/permission/scopes.py +++ b/apps/permission/scopes.py @@ -1,6 +1,6 @@ # Copyright (C) 2018-2021 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_kfet.middlewares import get_current_request @@ -32,3 +32,26 @@ class PermissionScopes(BaseScopes): return [] return [f"{p.id}_{p.membership.club.id}" 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 diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index a0ece715..72194d62 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -7,6 +7,8 @@ import os # 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__)))) # Quick-start development settings - unsuitable for production @@ -248,6 +250,7 @@ REST_FRAMEWORK = { # OAuth2 Provider OAUTH2_PROVIDER = { 'SCOPES_BACKEND_CLASS': 'permission.scopes.PermissionScopes', + 'OAUTH2_VALIDATOR_CLASS': "permission.scopes.PermissionOAuth2Validator", } # Take control on how widget templates are sourced