about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gn3/auth/authentication/users.py6
-rw-r--r--gn3/auth/authorisation/groups.py18
-rw-r--r--gn3/auth/authorisation/privileges.py9
-rw-r--r--gn3/auth/authorisation/resources.py20
-rw-r--r--gn3/auth/authorisation/roles.py9
-rw-r--r--gn3/auth/dictify.py19
6 files changed, 61 insertions, 20 deletions
diff --git a/gn3/auth/authentication/users.py b/gn3/auth/authentication/users.py
index ee3b5c2..b2d8d53 100644
--- a/gn3/auth/authentication/users.py
+++ b/gn3/auth/authentication/users.py
@@ -1,6 +1,6 @@
 """User-specific code and data structures."""
 from uuid import UUID, uuid4
-from typing import Tuple, NamedTuple
+from typing import Any, Tuple, NamedTuple
 
 import bcrypt
 from pymonad.maybe import Just, Maybe, Nothing
@@ -17,6 +17,10 @@ class User(NamedTuple):
         """Return the user's UUID. Mostly for use with Authlib."""
         return self.user_id
 
+    def dictify(self) -> dict[str, Any]:
+        """Return a dict representation of `User` objects."""
+        return {"user_id": self.user_id, "email": self.email, "name": self.name}
+
 def user_by_email(conn: db.DbConnection, email: str) -> Maybe:
     """Retrieve user from database by their email address"""
     with db.cursor(conn) as cursor:
diff --git a/gn3/auth/authorisation/groups.py b/gn3/auth/authorisation/groups.py
index 6d1b1a3..9dd5b71 100644
--- a/gn3/auth/authorisation/groups.py
+++ b/gn3/auth/authorisation/groups.py
@@ -7,8 +7,8 @@ from flask import g
 from pymonad.maybe import Just, Maybe, Nothing
 
 from gn3.auth import db
+from gn3.auth.dictify import dictify
 from gn3.auth.authentication.users import User
-from gn3.auth.dictify import register_dictifier
 from gn3.auth.authentication.checks import authenticated_p
 
 from .checks import authorised_p
@@ -23,9 +23,12 @@ class Group(NamedTuple):
     group_name: str
     group_metadata: dict[str, Any]
 
-register_dictifier(Group, lambda grp: {
-    "group_id": grp.group_id, "group_name": grp.group_name,
-    "group_metadata": grp.group_metadata})
+    def dictify(self):
+        """Return a dict representation of `Group` objects."""
+        return {
+            "group_id": self.group_id, "group_name": self.group_name,
+            "group_metadata": self.group_metadata
+        }
 
 class GroupRole(NamedTuple):
     """Class representing a role tied/belonging to a group."""
@@ -33,6 +36,13 @@ class GroupRole(NamedTuple):
     group: Group
     role: Role
 
+    def dictify(self) -> dict[str, Any]:
+        """Return a dict representation of `GroupRole` objects."""
+        return {
+            "group_role_id": self.group_role_id, "group": dictify(self.group),
+            "role": dictify(self.role)
+        }
+
 class GroupCreationError(AuthorisationError):
     """Raised whenever a group creation fails"""
 
diff --git a/gn3/auth/authorisation/privileges.py b/gn3/auth/authorisation/privileges.py
index 6cfd1d8..ae4ed88 100644
--- a/gn3/auth/authorisation/privileges.py
+++ b/gn3/auth/authorisation/privileges.py
@@ -1,5 +1,5 @@
 """Handle privileges"""
-from typing import Iterable, NamedTuple
+from typing import Any, Iterable, NamedTuple
 
 from gn3.auth import db
 from gn3.auth.authentication.users import User
@@ -9,6 +9,13 @@ class Privilege(NamedTuple):
     privilege_id: str
     privilege_description: str
 
+    def dictify(self) -> dict[str, Any]:
+        """Return a dict representation of `Privilege` objects."""
+        return {
+            "privilege_id": self.privilege_id,
+            "privilege_description": self.privilege_description
+        }
+
 def user_privileges(conn: db.DbConnection, user: User) -> Iterable[Privilege]:
     """Fetch the user's privileges from the database."""
     with db.cursor(conn) as cursor:
diff --git a/gn3/auth/authorisation/resources.py b/gn3/auth/authorisation/resources.py
index 29e50bf..1e37d7a 100644
--- a/gn3/auth/authorisation/resources.py
+++ b/gn3/auth/authorisation/resources.py
@@ -1,9 +1,10 @@
 """Handle the management of resources."""
 import json
 from uuid import UUID, uuid4
-from typing import Dict, Sequence, NamedTuple
+from typing import Any, Dict, Sequence, NamedTuple
 
 from gn3.auth import db
+from gn3.auth.dictify import dictify
 from gn3.auth.authentication.users import User
 
 from .checks import authorised_p
@@ -19,6 +20,14 @@ class ResourceCategory(NamedTuple):
     resource_category_key: str
     resource_category_description: str
 
+    def dictify(self) -> dict[str, Any]:
+        """Return a dict representation of `ResourceCategory` objects."""
+        return {
+            "resource_category_id": self.resource_category_id,
+            "resource_category_key": self.resource_category_key,
+            "resource_category_description": self.resource_category_description
+        }
+
 class Resource(NamedTuple):
     """Class representing a resource."""
     group: Group
@@ -27,6 +36,15 @@ class Resource(NamedTuple):
     resource_category: ResourceCategory
     public: bool
 
+    def dictify(self) -> dict[str, Any]:
+        """Return a dict representation of `Resource` objects."""
+        return {
+            "group": dictify(self.group), "resource_id": self.resource_id,
+            "resource_name": self.resource_name,
+            "resource_category": dictify(self.resource_category),
+            "public": self.public
+        }
+
 @authorised_p(("group:resource:create-resource",),
               error_message="Could not create resource")
 def create_resource(
diff --git a/gn3/auth/authorisation/roles.py b/gn3/auth/authorisation/roles.py
index cd59a36..86759b1 100644
--- a/gn3/auth/authorisation/roles.py
+++ b/gn3/auth/authorisation/roles.py
@@ -1,11 +1,12 @@
 """Handle management of roles"""
 from uuid import UUID, uuid4
 from functools import reduce
-from typing import Sequence, Iterable, NamedTuple
+from typing import Any, Sequence, Iterable, NamedTuple
 
 from pymonad.maybe import Just, Maybe, Nothing
 
 from gn3.auth import db
+from gn3.auth.dictify import dictify
 from gn3.auth.authentication.users import User
 from gn3.auth.authentication.checks import authenticated_p
 
@@ -18,6 +19,12 @@ class Role(NamedTuple):
     role_name: str
     privileges: Iterable[Privilege]
 
+    def dictify(self) -> dict[str, Any]:
+        """Return a dict representation of `Role` objects."""
+        return {
+            "role_id": self.role_id, "role_name": self.role_name,
+            "privileges": tuple(dictify(priv) for priv in self.privileges)
+        }
 @authenticated_p
 @authorised_p(("group:role:create-role",), error_message="Could not create role")
 def create_role(
diff --git a/gn3/auth/dictify.py b/gn3/auth/dictify.py
index 274ebb0..f9337f6 100644
--- a/gn3/auth/dictify.py
+++ b/gn3/auth/dictify.py
@@ -1,17 +1,12 @@
 """Module for dictifying objects"""
 
-from typing import Any
+from typing import Any, Protocol
 
-# TYPE = TypeVar("TYPE")
+class Dictifiable(Protocol):# pylint: disable=[too-few-public-methods]
+    """Type annotation for generic object with a `dictify` method."""
+    def dictify(self):
+        """Convert the object to a dict"""
 
-__dictifiers__ = {}#: dict[TYPE, Callable[[TYPE], dict[str, Any]]] = {}
-
-# def register_dictifier(obj_type: TYPE, dictifier: Callable[[TYPE], dict[str, Any]]):
-def register_dictifier(obj_type, dictifier):
-    """Register a new dictifier function"""
-    global __dictifiers__ # pylint: disable=[global-variable-not-assigned]
-    __dictifiers__[obj_type] = dictifier
-
-def dictify(obj: Any) -> dict[str, Any]:
+def dictify(obj: Dictifiable) -> dict[str, Any]:
     """Turn `obj` to a dict representation."""
-    return __dictifiers__[type(obj)](obj)
+    return obj.dictify()