about summary refs log tree commit diff
path: root/gn3/auth
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2023-01-30 03:00:27 +0300
committerFrederick Muriuki Muriithi2023-01-30 03:00:27 +0300
commit5d21e8195d1a51a633608b20baa8dbee01d51a7c (patch)
treeec6ef38ff3b0615827ec7d9b5b8287b4925bd629 /gn3/auth
parent786c6f61c0dc635f908175a369fdd3e89ba7d7b2 (diff)
downloadgenenetwork3-5d21e8195d1a51a633608b20baa8dbee01d51a7c.tar.gz
auth: API: Retrieve a user's group
Add endpoint to retrieve the group in which the user is a member.
Diffstat (limited to 'gn3/auth')
-rw-r--r--gn3/auth/authorisation/errors.py4
-rw-r--r--gn3/auth/authorisation/groups.py9
-rw-r--r--gn3/auth/authorisation/roles.py8
-rw-r--r--gn3/auth/authorisation/views.py20
4 files changed, 30 insertions, 11 deletions
diff --git a/gn3/auth/authorisation/errors.py b/gn3/auth/authorisation/errors.py
index 89c5983..e1fb1a0 100644
--- a/gn3/auth/authorisation/errors.py
+++ b/gn3/auth/authorisation/errors.py
@@ -10,3 +10,7 @@ class AuthorisationError(Exception):
 
 class UserRegistrationError(AuthorisationError):
     """Raised whenever a user registration fails"""
+
+class NotFoundError(AuthorisationError):
+    """Raised whenever we try fetching (a/an) object(s) that do(es) not exist."""
+    error_code: int = 404
diff --git a/gn3/auth/authorisation/groups.py b/gn3/auth/authorisation/groups.py
index 9dd5b71..cd7e034 100644
--- a/gn3/auth/authorisation/groups.py
+++ b/gn3/auth/authorisation/groups.py
@@ -4,6 +4,7 @@ from uuid import UUID, uuid4
 from typing import Any, Sequence, Iterable, Optional, NamedTuple
 
 from flask import g
+from pymonad.either import Left, Right, Either
 from pymonad.maybe import Just, Maybe, Nothing
 
 from gn3.auth import db
@@ -13,7 +14,7 @@ from gn3.auth.authentication.checks import authenticated_p
 
 from .checks import authorised_p
 from .privileges import Privilege
-from .errors import AuthorisationError
+from .errors import NotFoundError, AuthorisationError
 from .roles import (
     Role, create_role, revoke_user_role_by_name, assign_user_role_by_name)
 
@@ -140,7 +141,7 @@ def authenticated_user_group(conn) -> Maybe:
 
     return Nothing
 
-def user_group(cursor: db.DbCursor, user: User) -> Maybe[Group]:
+def user_group(cursor: db.DbCursor, user: User) -> Either:
     """Returns the given user's group"""
     cursor.execute(
         ("SELECT groups.group_id, groups.group_name, groups.group_metadata "
@@ -156,9 +157,9 @@ def user_group(cursor: db.DbCursor, user: User) -> Maybe[Group]:
         raise MembershipError(user, groups)
 
     if len(groups) == 1:
-        return Just(groups[0])
+        return Right(groups[0])
 
-    return Nothing
+    return Left(NotFoundError("User is not in any group."))
 
 def is_group_leader(cursor: db.DbCursor, user: User, group: Group):
     """Check whether the given `user` is the leader of `group`."""
diff --git a/gn3/auth/authorisation/roles.py b/gn3/auth/authorisation/roles.py
index e75163d..23b74cc 100644
--- a/gn3/auth/authorisation/roles.py
+++ b/gn3/auth/authorisation/roles.py
@@ -13,7 +13,7 @@ from gn3.auth.authentication.checks import authenticated_p
 
 from .checks import authorised_p
 from .privileges import Privilege
-from .errors import AuthorisationError
+from .errors import NotFoundError, AuthorisationError
 
 class Role(NamedTuple):
     """Class representing a role: creates immutable objects."""
@@ -28,10 +28,6 @@ class Role(NamedTuple):
             "privileges": tuple(dictify(priv) for priv in self.privileges)
         }
 
-class RoleNotFoundError(AuthorisationError):
-    """Raised whenever we try fetching (a) role(s) that do(es) not exist."""
-    error_code: int = 404
-
 @authenticated_p
 @authorised_p(("group:role:create-role",), error_message="Could not create role")
 def create_role(
@@ -115,7 +111,7 @@ def user_role(conn: db.DbConnection, user: User, role_id: UUID) -> Either:
         if results:
             return Right(tuple(
                 reduce(__organise_privileges__, results, {}).values())[0])
-        return Left(RoleNotFoundError(
+        return Left(NotFoundError(
             f"Could not find role with id '{role_id}'",))
 
 def assign_default_roles(cursor: db.DbCursor, user: User):
diff --git a/gn3/auth/authorisation/views.py b/gn3/auth/authorisation/views.py
index 6c6e5e3..33ac95b 100644
--- a/gn3/auth/authorisation/views.py
+++ b/gn3/auth/authorisation/views.py
@@ -19,6 +19,10 @@ from ..authentication.oauth2.resource_server import require_oauth
 from ..authentication.users import save_user, set_user_password
 from ..authentication.oauth2.models.oauth2token import token_by_access_token
 
+def __raise_error__(exc):
+    current_app.logger.error(exc)
+    raise exc
+
 @oauth2.route("/user", methods=["GET"])
 @require_oauth("profile")
 def user_details():
@@ -28,11 +32,16 @@ def user_details():
         with db.connection(current_app.config["AUTH_DB"]) as conn, db.cursor(conn) as cursor:
             group = user_group(cursor, user)
 
+        def __raise__(exc):
+            if type(exc) == NotFoundError:
+                return False
+            raise exc
+
         return jsonify({
             "user_id": user.user_id,
             "email": user.email,
             "name": user.name,
-            "group": group.maybe(False, dictify)
+            "group": group.either(__raise__, dictify)
         })
 
 @oauth2.route("/user-roles", methods=["GET"])
@@ -159,3 +168,12 @@ def role(role_id: uuid.UUID) -> Response:
             the_role = user_role(conn, the_token.user, role_id)
             return the_role.either(
                 __error__, lambda a_role: jsonify(dictify(a_role)))
+
+@oauth2.route("/user-group", methods=["GET"])
+@require_oauth("group")
+def users_group():
+    with require_oauth.acquire("profile group") as the_token:
+        db_uri = current_app.config["AUTH_DB"]
+        with db.connection(db_uri) as conn, db.cursor(conn) as cursor:
+            return user_group(cursor, the_token.user).either(
+                __raise_error__, lambda grp: jsonify(dictify(grp)))