From 09c2330e9e8279f6c9fd391a736435ceb4705873 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Tue, 7 Mar 2023 05:49:21 +0300 Subject: auth: user_by_id: Return a user or raise an exception Fetching the user by id should return the user, or raise an exception. We get rid of the Maybe monad here since it is leading to some weird code flows - probably the wrong monad to use here. --- .../authentication/oauth2/models/oauth2client.py | 12 +++++++--- .../authentication/oauth2/models/oauth2token.py | 14 +++++++---- gn3/auth/authentication/users.py | 7 +++--- gn3/auth/authorisation/groups/models.py | 27 +++++++++++----------- 4 files changed, 35 insertions(+), 25 deletions(-) (limited to 'gn3') diff --git a/gn3/auth/authentication/oauth2/models/oauth2client.py b/gn3/auth/authentication/oauth2/models/oauth2client.py index 70b8f59..14f4d5d 100644 --- a/gn3/auth/authentication/oauth2/models/oauth2client.py +++ b/gn3/auth/authentication/oauth2/models/oauth2client.py @@ -9,6 +9,8 @@ from pymonad.maybe import Just, Maybe, Nothing from gn3.auth import db from gn3.auth.authentication.users import User, user_by_id +from gn3.auth.authorisation.errors import NotFoundError + class OAuth2Client(NamedTuple): """ Client to the OAuth2 Server. @@ -134,8 +136,12 @@ def client(conn: db.DbConnection, client_id: uuid.UUID, cursor.execute( "SELECT * FROM oauth2_clients WHERE client_id=?", (str(client_id),)) result = cursor.fetchone() - the_user = user or user_by_id(conn, result["user_id"]).maybe( - None, lambda usr: usr)# type: ignore + the_user = user + if not bool(the_user): + try: + the_user = user_by_id(conn, result["user_id"]) + except NotFoundError as _nfe: + the_user = None if result: return Just( OAuth2Client(uuid.UUID(result["client_id"]), @@ -145,6 +151,6 @@ def client(conn: db.DbConnection, client_id: uuid.UUID, datetime.datetime.fromtimestamp( result["client_secret_expires_at"]), json.loads(result["client_metadata"]), - the_user)) + the_user))# type: ignore[arg-type] return Nothing diff --git a/gn3/auth/authentication/oauth2/models/oauth2token.py b/gn3/auth/authentication/oauth2/models/oauth2token.py index c1fcafb..72e20cc 100644 --- a/gn3/auth/authentication/oauth2/models/oauth2token.py +++ b/gn3/auth/authentication/oauth2/models/oauth2token.py @@ -8,6 +8,8 @@ from pymonad.maybe import Just, Maybe, Nothing from gn3.auth import db from gn3.auth.authentication.users import User, user_by_id +from gn3.auth.authorisation.errors import NotFoundError + from .oauth2client import client, OAuth2Client class OAuth2Token(NamedTuple): @@ -50,11 +52,13 @@ class OAuth2Token(NamedTuple): def __token_from_resultset__(conn: db.DbConnection, rset) -> Maybe: __identity__ = lambda val: val - the_user = user_by_id(conn, uuid.UUID(rset["user_id"])) - the_client = client(conn, uuid.UUID(rset["client_id"]), - the_user.maybe(None, __identity__)) + try: + the_user = user_by_id(conn, uuid.UUID(rset["user_id"])) + except NotFoundError as _nfe: + the_user = None + the_client = client(conn, uuid.UUID(rset["client_id"]), the_user) - if the_client.is_just() and the_user.is_just(): + if the_client.is_just() and bool(the_user): return Just(OAuth2Token(token_id=uuid.UUID(rset["token_id"]), client=the_client.maybe(None, __identity__), token_type=rset["token_type"], @@ -65,7 +69,7 @@ def __token_from_resultset__(conn: db.DbConnection, rset) -> Maybe: issued_at=datetime.datetime.fromtimestamp( rset["issued_at"]), expires_in=rset["expires_in"], - user=the_user.maybe(None, __identity__))) + user=the_user))# type: ignore[arg-type] return Nothing diff --git a/gn3/auth/authentication/users.py b/gn3/auth/authentication/users.py index e65938e..54838a3 100644 --- a/gn3/auth/authentication/users.py +++ b/gn3/auth/authentication/users.py @@ -3,7 +3,6 @@ from uuid import UUID, uuid4 from typing import Any, Tuple, NamedTuple import bcrypt -from pymonad.maybe import Just, Maybe, Nothing from gn3.auth import db from gn3.auth.authorisation.errors import NotFoundError @@ -37,16 +36,16 @@ def user_by_email(conn: db.DbConnection, email: str) -> User: raise NotFoundError(f"Could not find user with email {email}") -def user_by_id(conn: db.DbConnection, user_id: UUID) -> Maybe: +def user_by_id(conn: db.DbConnection, user_id: UUID) -> User: """Retrieve user from database by their user id""" with db.cursor(conn) as cursor: cursor.execute("SELECT * FROM users WHERE user_id=?", (str(user_id),)) row = cursor.fetchone() if row: - return Just(User(UUID(row["user_id"]), row["email"], row["name"])) + return User(UUID(row["user_id"]), row["email"], row["name"]) - return Nothing + raise NotFoundError(f"Could not find user with ID {user_id}") def valid_login(conn: db.DbConnection, user: User, password: str) -> bool: """Check the validity of the provided credentials for login.""" diff --git a/gn3/auth/authorisation/groups/models.py b/gn3/auth/authorisation/groups/models.py index 777e2d0..b1f307f 100644 --- a/gn3/auth/authorisation/groups/models.py +++ b/gn3/auth/authorisation/groups/models.py @@ -9,7 +9,7 @@ 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, user_by_id, DUMMY_USER +from gn3.auth.authentication.users import User, user_by_id from ..checks import authorised_p from ..privileges import Privilege @@ -286,19 +286,20 @@ def accept_reject_join_request( row = cursor.fetchone() if row: if group.group_id == UUID(row["group_id"]): - the_user = user_by_id(conn, UUID(row["requester_id"])).maybe(# type: ignore[misc] - DUMMY_USER, lambda usr: usr) - if the_user == DUMMY_USER: + try: + the_user = user_by_id(conn, UUID(row["requester_id"])) + if status == "ACCEPTED": + add_user_to_group(cursor, group, the_user) + revoke_user_role_by_name(cursor, the_user, "group-creator") + cursor.execute( + "UPDATE group_join_requests SET status=? " + "WHERE request_id=?", + (status, str(request_id))) + return {"request_id": request_id, "status": status} + except NotFoundError as nfe: raise InconsistencyError( - "Could not find user associated with join request.") - if status == "ACCEPTED": - add_user_to_group(cursor, group, the_user) - revoke_user_role_by_name(cursor, the_user, "group-creator") - cursor.execute( - "UPDATE group_join_requests SET status=? " - "WHERE request_id=?", - (status, str(request_id))) - return {"request_id": request_id, "status": status} + "Could not find user associated with join request." + ) from nfe raise AuthorisationError( "You cannot act on other groups join requests") raise NotFoundError(f"Could not find request with ID '{request_id}'") -- cgit v1.2.3