Skip to content

Commit 35ca87b

Browse files
UpstreamDatab-rowan
authored andcommitted
Allow denying specific permissions.
Using the `!` prefix will deny permissions for a route, and takes precedence over allowing permissions. If you wanted to allow reading but deny software access, you could use `["*.read", "!software"]`.
1 parent 02e6c73 commit 35ca87b

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

goosebit/auth/__init__.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import logging
4-
from typing import Annotated
4+
from typing import Annotated, Iterable
55

66
from argon2.exceptions import VerifyMismatchError
77
from fastapi import Depends, HTTPException
@@ -116,16 +116,20 @@ def validate_user_permissions(
116116
return connection
117117

118118

119-
def compare_permissions(scopes: list[str] | None, permissions: set[str]) -> bool:
119+
def compare_permissions(scopes: Iterable[str] | None, permissions: Iterable[str]) -> bool:
120+
deny_permissions = [p.lstrip("!") for p in permissions if p.startswith("!")]
121+
allow_permissions = [p for p in permissions if not p.startswith("!")]
120122
if scopes is None:
121123
return True
122124
for scope in scopes:
123-
if not any([compare_permission(scope, permission) for permission in permissions]):
125+
if any([compare_permission(scope, permission) for permission in deny_permissions]):
126+
return False
127+
if not any([compare_permission(scope, permission) for permission in allow_permissions]):
124128
return False
125129
return True
126130

127131

128-
def compare_permission(scope: str, permission: str):
132+
def compare_permission(scope: str, permission: str) -> bool:
129133
split_scope = scope.split(".")
130134
for idx, permission in enumerate(permission.split(".")):
131135
if permission == "*":

0 commit comments

Comments
 (0)