Skip to content

Commit

Permalink
Merge pull request #459 from DSD-DBS/fix-t4c-user-deletion
Browse files Browse the repository at this point in the history
Use routes for session termination
  • Loading branch information
MoritzWeber0 authored Dec 16, 2022
2 parents e662df6 + e093887 commit f105dc9
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
ProjectUserPermission,
ProjectUserRole,
)
from capellacollab.sessions.database import get_session_by_id
from capellacollab.sessions.crud import get_session_by_id
from capellacollab.settings.modelsources.git import crud
from capellacollab.users.crud import get_user_by_name
from capellacollab.users.models import Role
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion backend/capellacollab/sessions/files/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from capellacollab.core.authentication.helper import get_username
from capellacollab.core.authentication.jwt_bearer import JWTBearer
from capellacollab.core.database import get_db
from capellacollab.sessions.database import get_session_by_id
from capellacollab.sessions.crud import get_session_by_id
from capellacollab.sessions.operators import OPERATOR
from capellacollab.sessions.schema import FileTree

Expand Down
12 changes: 9 additions & 3 deletions backend/capellacollab/sessions/idletimeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

from capellacollab.config import config
from capellacollab.core import database
from capellacollab.sessions.database import delete_session, get_session_by_id
from capellacollab.sessions import util
from capellacollab.sessions.crud import get_session_by_id
from capellacollab.sessions.operators import OPERATOR

log = logging.getLogger(__name__)
Expand All @@ -31,10 +32,15 @@ def terminate_idle_session():
for metric in response.json()["data"]["result"]:
if session_id := metric.get("metric", {}).get("app"):
log.info("Terminating idle session %s", session_id)
OPERATOR.kill_session(session_id)
with database.SessionLocal() as db:
if session := get_session_by_id(db, session_id):
delete_session(db, session)
util.terminate_session(session, db, OPERATOR)
else:
log.error(
"Session was not found in our database. Terminating idle session %s",
session_id,
)
OPERATOR.kill_session(session_id)


async def terminate_idle_sessions_in_background(interval=60):
Expand Down
4 changes: 2 additions & 2 deletions backend/capellacollab/sessions/injectables.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from capellacollab.core.database import get_db
from capellacollab.users.models import Role

from . import database
from . import crud
from .models import DatabaseSession


Expand All @@ -21,7 +21,7 @@ def get_existing_session(
token: JWTBearer = Depends(JWTBearer()),
) -> DatabaseSession:
try:
session: DatabaseSession = database.get_session_by_id(db, session_id)
session: DatabaseSession = crud.get_session_by_id(db, session_id)
except NoResultFound as e:
raise HTTPException(
404,
Expand Down
39 changes: 8 additions & 31 deletions backend/capellacollab/sessions/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
from requests.exceptions import RequestException
from sqlalchemy.orm import Session

import capellacollab.projects.toolmodels.modelsources.git.crud as git_models_crud
from capellacollab.config import config
from capellacollab.core.authentication.database import (
ProjectRoleVerification,
RoleVerification,
verify_project_role,
)
from capellacollab.core.authentication.helper import get_username
from capellacollab.core.authentication.jwt_bearer import JWTBearer
Expand All @@ -34,13 +32,12 @@
DatabaseGitModel,
)
from capellacollab.projects.users.crud import ProjectUserRole
from capellacollab.sessions import database, guacamole
from capellacollab.sessions import crud, guacamole
from capellacollab.sessions.files import routes as files
from capellacollab.sessions.models import DatabaseSession
from capellacollab.sessions.operators import get_operator
from capellacollab.sessions.operators.k8s import KubernetesOperator
from capellacollab.sessions.schema import (
DepthType,
GetSessionsResponse,
GuacamoleAuthentication,
PostPersistentSessionRequest,
Expand All @@ -53,7 +50,6 @@
)
from capellacollab.settings.modelsources.t4c.repositories.interface import (
add_user_to_repository,
remove_user_from_repository,
)
from capellacollab.tools.crud import (
get_image_for_tool_version,
Expand All @@ -67,6 +63,7 @@
from capellacollab.users.injectables import get_own_user
from capellacollab.users.models import DatabaseUser, Role

from . import util
from .injectables import get_existing_session

router = APIRouter(
Expand All @@ -87,7 +84,7 @@ def get_current_sessions(
token=Depends(JWTBearer()),
):
if RoleVerification(required_role=Role.ADMIN, verify=False)(token, db):
return inject_attrs_in_sessions(database.get_all_sessions(db))
return inject_attrs_in_sessions(crud.get_all_sessions(db))

if not any(
project_user.role == ProjectUserRole.MANAGER
Expand All @@ -103,7 +100,7 @@ def get_current_sessions(
list(
itertools.chain.from_iterable(
[
database.get_sessions_for_repository(db, project)
crud.get_sessions_for_repository(db, project)
for project in [
p.name
for p in db_user.projects
Expand Down Expand Up @@ -212,7 +209,7 @@ def request_persistent_session(

log.info("Starting persistent session for user %s", owner)

existing_user_sessions = database.get_sessions_for_user(db, owner)
existing_user_sessions = crud.get_sessions_for_user(db, owner)

if WorkspaceType.PERSISTENT in [
session.type for session in existing_user_sessions
Expand Down Expand Up @@ -350,7 +347,7 @@ def create_database_and_guacamole_session(
version=version,
**session,
)
response = database.create_session(db=db, session=database_model)
response = crud.create_session(db=db, session=database_model)
response.state = "New"
response.last_seen = "UNKNOWN"
return response
Expand All @@ -362,27 +359,7 @@ def end_session(
db: Session = Depends(get_db),
operator: KubernetesOperator = Depends(get_operator),
):
if (
session.tool.name == "Capella"
and session.type == WorkspaceType.PERSISTENT
):
for repository in get_user_t4c_repositories(
db, session.tool, session.version, session.owner
):
try:
remove_user_from_repository(
repository.instance,
repository.name,
username=session.owner.name,
)
except RequestException:
log.exception(
"Could not delete user from repository '%s' of instance '%s'. Please delete the user manually.",
exc_info=True,
)

database.delete_session(db, session)
operator.kill_session(session.id)
util.terminate_session(db, session, operator)


@router.post(
Expand All @@ -394,7 +371,7 @@ def create_guacamole_token(
db: Session = Depends(get_db),
token=Depends(JWTBearer()),
):
session = database.get_session_by_id(db, id)
session = crud.get_session_by_id(db, id)
if session.owner_name != get_username(token):
raise HTTPException(
status_code=403,
Expand Down
51 changes: 51 additions & 0 deletions backend/capellacollab/sessions/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors
# SPDX-License-Identifier: Apache-2.0

import logging

from requests.exceptions import RequestException
from sqlalchemy.orm import Session

from capellacollab.sessions.models import DatabaseSession
from capellacollab.sessions.operators.k8s import KubernetesOperator
from capellacollab.sessions.schema import WorkspaceType
from capellacollab.settings.modelsources.t4c.repositories.crud import (
get_user_t4c_repositories,
)
from capellacollab.settings.modelsources.t4c.repositories.interface import (
remove_user_from_repository,
)

from . import crud

log = logging.getLogger(__name__)


def terminate_session(
db_session: Session, session: DatabaseSession, operator: KubernetesOperator
):
if (
session.tool.name == "Capella"
and session.type == WorkspaceType.PERSISTENT
):
revoke_session_tokens(db_session, session)

crud.delete_session(db_session, session)
operator.kill_session(session.id)


def revoke_session_tokens(db_session: Session, session: DatabaseSession):
for repository in get_user_t4c_repositories(
db_session, session.tool, session.version, session.owner
):
try:
remove_user_from_repository(
repository.instance,
repository.name,
username=session.owner.name,
)
except RequestException:
log.exception(
"Could not delete user from repository '%s' of instance '%s'. Please delete the user manually.",
exc_info=True,
)
4 changes: 3 additions & 1 deletion backend/tests/test_sessions_idletimeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ def test_no_idle_sessions(monkeypatch):
terminate_idle_session()


def test_no_idle_sessions(monkeypatch, db):
def test_idle_sessions(monkeypatch, db):
# db fixture is needed to start the database

operator = MockOperator()
monkeypatch.setattr(
requests,
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/test_sessions_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
ProjectUserPermission,
ProjectUserRole,
)
from capellacollab.sessions.database import (
from capellacollab.sessions.crud import (
get_session_by_id,
get_sessions_for_user,
)
Expand Down

0 comments on commit f105dc9

Please sign in to comment.