api: properly compute authorization based on ccchh role

This commit is contained in:
lilly 2026-05-14 16:41:16 +02:00
commit bf0c085739
Signed by: lilly
SSH key fingerprint: SHA256:y9T5GFw2A20WVklhetIxG1+kcg/Ce0shnQmbu1LQ37g
3 changed files with 10 additions and 8 deletions

View file

@ -19,7 +19,7 @@ def main():
) )
argp.add_argument( argp.add_argument(
"--openid-scope", "--openid-scope",
default=os.environ.get("DOORIS_OPENID_SCOPE", "openid profile"), default=os.environ.get("DOORIS_OPENID_SCOPE", "openid profile ccchh-roles"),
help="The Keycloak OpenID isser to use for authentication", help="The Keycloak OpenID isser to use for authentication",
) )
argp.add_argument( argp.add_argument(

View file

@ -71,6 +71,7 @@ async def get_user_info(
current_user.id_token.exp, UTC current_user.id_token.exp, UTC
), ),
username=current_user.id_token.preferred_username, username=current_user.id_token.preferred_username,
ccchh_roles=current_user.ccchh_roles,
) )
@ -117,7 +118,7 @@ async def login_init(
response_class=RedirectResponse, response_class=RedirectResponse,
status_code=302, status_code=302,
) )
async def login_callback(req: Request, resp: Response, oidc_client: deps.OpenidClient): async def login_callback(req: Request, resp: Response, oidc_client: deps.OpenidClient) -> str:
# check that the user is currently in an authenticating state # check that the user is currently in an authenticating state
# these cookies are set by the login_init() view # these cookies are set by the login_init() view
if ( if (
@ -167,7 +168,7 @@ async def login_callback(req: Request, resp: Response, oidc_client: deps.OpenidC
) )
async def logout( async def logout(
resp: Response, oidc_client: deps.OpenidClient, current_user: deps.CurrentUser resp: Response, oidc_client: deps.OpenidClient, current_user: deps.CurrentUser
): ) -> str:
deps.clear_auth_state(resp) deps.clear_auth_state(resp)
return oidc_client.initiate_logout( return oidc_client.initiate_logout(
RpInitiatedLogoutRequest( RpInitiatedLogoutRequest(
@ -253,7 +254,7 @@ async def operate_lock(
) -> None: ) -> None:
if not current_user.may_operate_locks: if not current_user.may_operate_locks:
raise exceptions.HttpProblemException.forbidden_to_operate(req.url) raise exceptions.HttpProblemException.forbidden_to_operate(req.url)
# TODO: Validate that the user is authorized
# find appropriate lock from ccujack # find appropriate lock from ccujack
for i_lock, lock_channels in ccujack.locks: for i_lock, lock_channels in ccujack.locks:
if i_lock.identifier == lock_id: if i_lock.identifier == lock_id:

View file

@ -33,17 +33,18 @@ class CurrentUser(BaseModel):
@property @property
def ccchh_roles(self) -> List[str]: def ccchh_roles(self) -> List[str]:
return [] return getattr(self.id_token, "ccchh-roles", [])
@property @property
def may_operate_locks(self) -> bool: def may_operate_locks(self) -> bool:
return True return "intern@" in self.ccchh_roles
class UserStatus(BaseModel): class UserStatus(BaseModel):
is_authorized: bool is_authorized: bool
guaranteed_session_until: Optional[datetime] guaranteed_session_until: datetime
username: Optional[str] username: str
ccchh_roles: List[str]
class LockStatus(BaseModel): class LockStatus(BaseModel):