diff options
| author | Claude | 2026-09-01 15:36:34 +0000 |
|---|---|---|
| committer | Frederick Muriuki Muriithi | 2026-09-01 10:39:53 -0500 |
| commit | aab9408e8c1641c0552e51e1c9f6ebd8804f00cc (patch) | |
| tree | b12aa8275db4242d24f16e69e95d73030c4606a1 | |
| parent | 7f5a53035b8c39cc4c0821cc6e6a7c4ca7fcd293 (diff) | |
| download | gn-auth-aab9408e8c1641c0552e51e1c9f6ebd8804f00cc.tar.gz | |
fix(auth): check system:user:list against system resource in resource_users
The HACK block in resource_users() was checking the system:user:list privilege against the requested resource_id rather than the system resource. This made the sysadmin branch a dead leg: sysadmins hold system:user:list on the system resource, not on individual data resources. Fix: pass system_resource(conn).resource_id for the system-level check. Also restructure to early-return on auth failure (cleaner control flow). Reviewed-By: Frederick M. Muriithi <fredmanglis@gmail.com>
| -rw-r--r-- | gn_auth/auth/authorisation/resources/views.py | 93 |
1 files changed, 43 insertions, 50 deletions
diff --git a/gn_auth/auth/authorisation/resources/views.py b/gn_auth/auth/authorisation/resources/views.py index 06645db..bdcc803 100644 --- a/gn_auth/auth/authorisation/resources/views.py +++ b/gn_auth/auth/authorisation/resources/views.py @@ -255,57 +255,50 @@ def resource_users(resource_id: UUID): """Retrieve all users with access to the given resource.""" with require_oauth.acquire("profile group resource") as the_token: def __the_users__(conn: db.DbConnection): - ########## BEGIN: HACK ########## - # This hack gets the UI to work, but needs replacing. - # It resolves (albeit, temporarily) the bug introduced after a - # refactor that made the system itself, and the groups into - # resources. - grouplevelauth = authorised_for_spec( - conn, - the_token.user.user_id, - resource_id, - "group:resource:view-resource") - systemlevelauth = authorised_for_spec( - conn, - the_token.user.user_id, - resource_id, - "system:user:list") - ########## END: HACK ########## - if grouplevelauth or systemlevelauth: - with db.cursor(conn) as cursor: - def __organise_users_n_roles__(users_n_roles, row): - user_id = UUID(row["user_id"]) - user = users_n_roles.get(user_id, {}).get( - "user", User.from_sqlite3_row(row)) - role = Role( - UUID(row["role_id"]), row["role_name"], - bool(int(row["user_editable"])), tuple()) - return { - **users_n_roles, - user_id: { - "user": user, - "user_group": ( - Group(UUID(row["group_id"]), - row["group_name"], - json.loads(row["group_metadata"])) - if bool(row["group_id"]) else False) , - "roles": users_n_roles.get( - user_id, {}).get("roles", tuple()) + (role,) - } + if not (authorised_for_spec( + conn, + the_token.user.user_id, + resource_id, + "group:resource:view-resource") + or authorised_for_spec( + conn, + the_token.user.user_id, + system_resource(conn).resource_id, + "system:user:list")): + raise AuthorisationError( + "You do not have sufficient privileges to view the resource " + "users.") + with db.cursor(conn) as cursor: + def __organise_users_n_roles__(users_n_roles, row): + user_id = UUID(row["user_id"]) + user = users_n_roles.get(user_id, {}).get( + "user", User.from_sqlite3_row(row)) + role = Role( + UUID(row["role_id"]), row["role_name"], + bool(int(row["user_editable"])), tuple()) + return { + **users_n_roles, + user_id: { + "user": user, + "user_group": ( + Group(UUID(row["group_id"]), + row["group_name"], + json.loads(row["group_metadata"])) + if bool(row["group_id"]) else False) , + "roles": users_n_roles.get( + user_id, {}).get("roles", tuple()) + (role,) } - cursor.execute( - "SELECT g.*, u.*, r.* " - "FROM groups AS g INNER JOIN group_users AS gu " - "ON g.group_id=gu.group_id RIGHT JOIN users AS u " - "ON gu.user_id=u.user_id INNER JOIN user_roles AS ur " - "ON u.user_id=ur.user_id INNER JOIN roles AS r " - "ON ur.role_id=r.role_id " - "WHERE ur.resource_id=?", - (str(resource_id),)) - return reduce(__organise_users_n_roles__, cursor.fetchall(), {}) - raise AuthorisationError( - "You do not have sufficient privileges to view the resource " - "users.") + } + cursor.execute( + "SELECT g.*, u.*, r.* " + "FROM groups AS g INNER JOIN group_users AS gu " + "ON g.group_id=gu.group_id RIGHT JOIN users AS u " + "ON gu.user_id=u.user_id INNER JOIN user_roles AS ur " + "ON u.user_id=ur.user_id INNER JOIN roles AS r " + "ON ur.role_id=r.role_id " + "WHERE ur.resource_id=?", + (str(resource_id),)) + return reduce(__organise_users_n_roles__, cursor.fetchall(), {}) results = ( { "user": asdict(row["user"]), |
