From dd639d829e3e3d1bb476fe782d447f4b515941e3 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 14 Jun 2021 23:30:01 +0200
Subject: [PATCH] Implement OAuth2 scopes based on permissions

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 apps/permission/scopes.py  | 36 ++++++++++++++++++++++++++++++++++++
 note_kfet/settings/base.py |  5 +++++
 2 files changed, 41 insertions(+)
 create mode 100644 apps/permission/scopes.py

diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py
new file mode 100644
index 00000000..4abca5a1
--- /dev/null
+++ b/apps/permission/scopes.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from oauth2_provider.scopes import BaseScopes
+
+from member.models import Club
+
+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):
+        return {f"{p.id}_{club.id}": f"{p.description} (club {club.name})"
+                for p in Permission.objects.all() for club in Club.objects.all()}
+
+    def get_available_scopes(self, application=None, request=None, *args, **kwargs):
+        if not application:
+            return []
+        user = application.user
+        return [f"{p.id}_{p.membership.club.id}"
+                for t in Permission.PERMISSION_TYPES
+                for p in PermissionBackend.get_raw_permissions(user, t[0])]
+
+    def get_default_scopes(self, application=None, request=None, *args, **kwargs):
+        if not application:
+            return []
+        user = application.user
+        return [f"{p.id}_{p.membership.club.id}"
+                for p in PermissionBackend.get_raw_permissions(user, 'view')]
diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py
index 6cb068a5..a0ece715 100644
--- a/note_kfet/settings/base.py
+++ b/note_kfet/settings/base.py
@@ -245,6 +245,11 @@ REST_FRAMEWORK = {
     'PAGE_SIZE': 20,
 }
 
+# OAuth2 Provider
+OAUTH2_PROVIDER = {
+    'SCOPES_BACKEND_CLASS': 'permission.scopes.PermissionScopes',
+}
+
 # Take control on how widget templates are sourced
 # See https://docs.djangoproject.com/en/2.2/ref/forms/renderers/#templatessetting
 FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
-- 
GitLab