-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Issue session token for usage with API
Some sessions may want to automate tasks against the CCM API. A session token is issued as PAT and is valid for the duration of the session.
- Loading branch information
1 parent
028a25a
commit bd122dd
Showing
22 changed files
with
318 additions
and
56 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
backend/capellacollab/alembic/versions/8731ac0b284e_add_title_to_pat.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
"""Add title to PAT | ||
Revision ID: 8731ac0b284e | ||
Revises: 7b7145600133 | ||
Create Date: 2025-02-04 16:01:41.279644 | ||
""" | ||
|
||
import sqlalchemy as sa | ||
from alembic import op | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "8731ac0b284e" | ||
down_revision = "7b7145600133" | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.add_column( | ||
"basic_auth_token", | ||
sa.Column( | ||
"title", | ||
sa.String(), | ||
nullable=False, | ||
server_default=sa.text("'Legacy Token'"), | ||
), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
|
||
import datetime | ||
|
||
from capellacollab.permissions import models as permissions_models | ||
from capellacollab.users.tokens import crud as tokens_crud | ||
|
||
from . import interface | ||
|
||
|
||
class SessionTokenIntegration(interface.HookRegistration): | ||
"""Create a PAT valid for the duration of the session.""" | ||
|
||
def configuration_hook( | ||
self, | ||
request: interface.ConfigurationHookRequest, | ||
) -> interface.ConfigurationHookResult: | ||
token, password = tokens_crud.create_token( | ||
db=request.db, | ||
scope=permissions_models.GlobalScopes( | ||
user=permissions_models.UserScopes( | ||
sessions={permissions_models.UserTokenVerb.GET} | ||
) | ||
), | ||
title=f"Session {request.session_id}", | ||
user=request.user, | ||
description=( | ||
"This PAT is managed by the Collaboration Manager." | ||
" It will be revoked when the session is terminated" | ||
" and is only valid for the duration of the session." | ||
" Manual deletion may lead to unexpected behavior." | ||
), | ||
expiration_date=datetime.date.today() | ||
+ datetime.timedelta( | ||
days=2 | ||
), # Maximum duration is until end of the next day. | ||
source="session automation", | ||
) | ||
|
||
return interface.ConfigurationHookResult( | ||
environment={"CAPELLACOLLAB_SESSION_API_TOKEN": password}, | ||
config={"session_token_id": token.id}, | ||
) | ||
|
||
def pre_session_termination_hook( | ||
self, | ||
request: interface.PreSessionTerminationHookRequest, | ||
) -> interface.PreSessionTerminationHookResult: | ||
token_id = request.session.config.get("session_token_id") | ||
if not token_id: | ||
return interface.PreSessionTerminationHookResult() | ||
|
||
if token := tokens_crud.get_token_by_user_and_id( | ||
request.db, request.session.owner.id, int(token_id) | ||
): | ||
tokens_crud.delete_token(request.db, token) | ||
|
||
return interface.PreSessionTerminationHookResult() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from sqlalchemy import orm | ||
|
||
from capellacollab.sessions.hooks import interface as sessions_hooks_interface | ||
from capellacollab.sessions.hooks import session_token | ||
from capellacollab.users import models as users_models | ||
from capellacollab.users.tokens import crud as tokens_crud | ||
|
||
|
||
def test_session_token_hook_lifecycle( | ||
user: users_models.DatabaseUser, | ||
configuration_hook_request: sessions_hooks_interface.ConfigurationHookRequest, | ||
pre_session_termination_hook_request: sessions_hooks_interface.PreSessionTerminationHookRequest, | ||
db: orm.Session, | ||
): | ||
result = session_token.SessionTokenIntegration().configuration_hook( | ||
configuration_hook_request | ||
) | ||
|
||
session_token_id = result["config"]["session_token_id"] | ||
assert isinstance(session_token_id, int) | ||
assert result["config"]["session_token_id"] | ||
assert result["environment"]["CAPELLACOLLAB_SESSION_API_TOKEN"] | ||
|
||
assert tokens_crud.get_token_by_user_and_id(db, user.id, session_token_id) | ||
|
||
pre_session_termination_hook_request.session.config["session_token_id"] = ( | ||
str(session_token_id) | ||
) | ||
|
||
session_token.SessionTokenIntegration().pre_session_termination_hook( | ||
pre_session_termination_hook_request | ||
) | ||
|
||
assert not tokens_crud.get_token_by_user_and_id( | ||
db, user.id, session_token_id | ||
) | ||
|
||
|
||
def test_termination_with_revoked_token( | ||
pre_session_termination_hook_request: sessions_hooks_interface.PreSessionTerminationHookRequest, | ||
): | ||
"""Test that a session can be terminated if the PAT was already revoked""" | ||
|
||
pre_session_termination_hook_request.session.config["session_token_id"] = ( | ||
"1" | ||
) | ||
|
||
session_token.SessionTokenIntegration().pre_session_termination_hook( | ||
pre_session_termination_hook_request | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.