routers.sessions

Endpoint for sessions.

--- config: mirrorActors: false --- sequenceDiagram title Session Creation actor User box ./routers participant sessions.py@{ "type" : "boundary" } end box ./internal/database participant database.py end box ./internal/auth participant middleware.py participant token.py participant security.py end box ./internal/queries participant tq as token.py participant uq as user.py end participant database@{ "type" : "database" } User->>sessions.py: create session activate sessions.py sessions.py->>middleware.py: basic_auth() activate middleware.py database.py->>middleware.py: yield connection activate database.py middleware.py->>uq: get_user_login() activate uq uq->>database: select user activate database database-->>uq: found user deactivate database uq-->>middleware.py: found user deactivate uq middleware.py-->>sessions.py: user and role middleware.py-->>database.py: return connection deactivate middleware.py deactivate database.py database.py->>sessions.py: yield connection activate database.py sessions.py->>token.py: await create_token() activate token.py token.py->>security.py: generate_token() activate security.py security.py-->>token.py: generated token deactivate security.py token.py->>tq: Querier.create_token() activate tq tq->>database: insert token activate database database-->>tq: inserted token deactivate database tq-->>token.py: inserted token deactivate tq token.py-->>sessions.py: inserted token deactivate token.py sessions.py-->>User: 201 OK + token sessions.py-->>database.py: return connection deactivate database.py deactivate sessions.py
--- config: mirrorActors: false --- sequenceDiagram title Session Deletion actor User box ./routers participant sessions.py@{ "type" : "boundary" } end box ./internal/database participant database.py end box ./internal/auth participant middleware.py participant token.py end box ./internal/queries participant tq as token.py end participant database@{ "type" : "database" } User->>sessions.py: delete session activate sessions.py sessions.py->>middleware.py: bearer_auth() activate middleware.py database.py->>middleware.py: yield connection activate database.py middleware.py->>tq: get_session_by_token() activate tq tq->>database: select token activate database database-->>tq: found token deactivate database tq-->>middleware.py: found token deactivate tq middleware.py-->>sessions.py: found token middleware.py-->>database.py: return connection deactivate middleware.py deactivate database.py database.py->>sessions.py: yield connection activate database.py sessions.py->>token.py: await delete_token() activate token.py token.py->>tq: Querier.delete_token() activate tq tq->>database: delete token activate database database-->>tq: deleted token deactivate database tq-->>token.py: deleted token deactivate tq token.py-->>sessions.py: deleted token deactivate token.py sessions.py-->>User: 200 OK sessions.py-->>database.py: return connection deactivate sessions.py deactivate database.py
  1"""Endpoint for sessions.
  2
  3```mermaid
  4---
  5config:
  6  mirrorActors: false
  7---
  8sequenceDiagram
  9    title Session Creation
 10    actor User
 11    box ./routers
 12    participant sessions.py@{ "type" : "boundary" }
 13    end
 14    box ./internal/database
 15    participant database.py
 16    end
 17    box ./internal/auth
 18    participant middleware.py
 19    participant token.py
 20    participant security.py
 21    end
 22    box ./internal/queries
 23    participant tq as token.py
 24    participant uq as user.py
 25    end
 26    participant database@{ "type" : "database" }
 27
 28    User->>sessions.py: create session
 29    activate sessions.py
 30    sessions.py->>middleware.py: basic_auth()
 31    activate middleware.py
 32    database.py->>middleware.py: yield connection
 33    activate database.py
 34    middleware.py->>uq: get_user_login()
 35    activate uq
 36    uq->>database: select user
 37    activate database
 38    database-->>uq: found user
 39    deactivate database
 40    uq-->>middleware.py: found user
 41    deactivate uq
 42    middleware.py-->>sessions.py: user and role
 43    middleware.py-->>database.py: return connection
 44    deactivate middleware.py
 45    deactivate database.py
 46    database.py->>sessions.py: yield connection
 47    activate database.py
 48    sessions.py->>token.py: await create_token()
 49    activate token.py
 50    token.py->>security.py: generate_token()
 51    activate security.py
 52    security.py-->>token.py: generated token
 53    deactivate security.py
 54    token.py->>tq: Querier.create_token()
 55    activate tq
 56    tq->>database: insert token
 57    activate database
 58    database-->>tq: inserted token
 59    deactivate database
 60    tq-->>token.py: inserted token
 61    deactivate tq
 62    token.py-->>sessions.py: inserted token
 63    deactivate token.py
 64    sessions.py-->>User: 201 OK + token
 65    sessions.py-->>database.py: return connection
 66    deactivate database.py
 67    deactivate sessions.py
 68```
 69
 70```mermaid
 71---
 72config:
 73  mirrorActors: false
 74---
 75sequenceDiagram
 76    title Session Deletion
 77    actor User
 78    box ./routers
 79    participant sessions.py@{ "type" : "boundary" }
 80    end
 81    box ./internal/database
 82    participant database.py
 83    end
 84    box ./internal/auth
 85    participant middleware.py
 86    participant token.py
 87    end
 88    box ./internal/queries
 89    participant tq as token.py
 90    end
 91    participant database@{ "type" : "database" }
 92
 93    User->>sessions.py: delete session
 94    activate sessions.py
 95    sessions.py->>middleware.py: bearer_auth()
 96    activate middleware.py
 97    database.py->>middleware.py: yield connection
 98    activate database.py
 99    middleware.py->>tq: get_session_by_token()
100    activate tq
101    tq->>database: select token
102    activate database
103    database-->>tq: found token
104    deactivate database
105    tq-->>middleware.py: found token
106    deactivate tq
107    middleware.py-->>sessions.py: found token
108    middleware.py-->>database.py: return connection
109    deactivate middleware.py
110    deactivate database.py
111    database.py->>sessions.py: yield connection
112    activate database.py
113    sessions.py->>token.py: await delete_token()
114    activate token.py
115    token.py->>tq: Querier.delete_token()
116    activate tq
117    tq->>database: delete token
118    activate database
119    database-->>tq: deleted token
120    deactivate database
121    tq-->>token.py: deleted token
122    deactivate tq
123    token.py-->>sessions.py: deleted token
124    deactivate token.py
125    sessions.py-->>User: 200 OK
126    sessions.py-->>database.py: return connection
127    deactivate sessions.py
128    deactivate database.py
129```
130"""
131
132from datetime import datetime
133
134from fastapi import APIRouter, status
135from internal.auth.middleware import BasicAuthDep, BearerAuthDep
136from internal.auth.token import create_token, delete_token
137from internal.database.dependency import database_dependency
138from internal.queries.models import UserRole
139from pydantic import BaseModel
140
141router = APIRouter(prefix="/sessions", tags=["sessions"])
142
143
144class TokenResponseModel(BaseModel):
145    """Response on session creation."""
146
147    token: str
148    expires_at: datetime
149    role: UserRole
150
151
152@router.post(
153    "",
154    response_model=TokenResponseModel,
155    status_code=status.HTTP_201_CREATED,
156    summary="Create session",
157    description="Authenticates a user and creates a new session token.",
158)
159async def create_session(
160    conn: database_dependency, user: BasicAuthDep
161) -> TokenResponseModel:
162    """Create session if user exists.
163
164    Args:
165      conn: database connection
166      user: user information if authorised
167
168    Returns:
169      user session information
170    """
171    token = await create_token(user.user_id, conn)
172    return TokenResponseModel(
173        token=token.token, expires_at=token.expires_at, role=user.role
174    )
175
176
177@router.delete(
178    "",
179    status_code=status.HTTP_200_OK,
180    summary="Delete session",
181    description="Deletes the current authenticated session token.",
182)
183async def delete_session(conn: database_dependency, session: BearerAuthDep) -> None:
184    """Delete session from database.
185
186    Args:
187      conn: database connection
188      session: authorised users information
189    """
190    await delete_token(session.token, conn)
router = <fastapi.routing.APIRouter object>
class TokenResponseModel(pydantic.main.BaseModel):
145class TokenResponseModel(BaseModel):
146    """Response on session creation."""
147
148    token: str
149    expires_at: datetime
150    role: UserRole

Response on session creation.

token: str = PydanticUndefined
expires_at: datetime.datetime = PydanticUndefined
role: internal.queries.models.UserRole = PydanticUndefined
@router.post('', response_model=TokenResponseModel, status_code=status.HTTP_201_CREATED, summary='Create session', description='Authenticates a user and creates a new session token.')
async def create_session( conn: Annotated[sqlalchemy.ext.asyncio.engine.AsyncConnection, Depends(dependency=<bound method DatabaseManager.get_connection of <internal.database.manager.DatabaseManager object>>, use_cache=True, scope=None)], user: Annotated[internal.auth.middleware.BasicAuthResponse, Security(dependency=<function basic_auth>, use_cache=True, scope=None, scopes=None)]) -> TokenResponseModel:
153@router.post(
154    "",
155    response_model=TokenResponseModel,
156    status_code=status.HTTP_201_CREATED,
157    summary="Create session",
158    description="Authenticates a user and creates a new session token.",
159)
160async def create_session(
161    conn: database_dependency, user: BasicAuthDep
162) -> TokenResponseModel:
163    """Create session if user exists.
164
165    Args:
166      conn: database connection
167      user: user information if authorised
168
169    Returns:
170      user session information
171    """
172    token = await create_token(user.user_id, conn)
173    return TokenResponseModel(
174        token=token.token, expires_at=token.expires_at, role=user.role
175    )

Create session if user exists.

Arguments:
  • conn: database connection
  • user: user information if authorised
Returns:

user session information

@router.delete('', status_code=status.HTTP_200_OK, summary='Delete session', description='Deletes the current authenticated session token.')
async def delete_session( conn: Annotated[sqlalchemy.ext.asyncio.engine.AsyncConnection, Depends(dependency=<bound method DatabaseManager.get_connection of <internal.database.manager.DatabaseManager object>>, use_cache=True, scope=None)], session: Annotated[internal.queries.token.GetSessionByTokenRow, Security(dependency=<function bearer_auth>, use_cache=True, scope=None, scopes=None)]) -> None:
178@router.delete(
179    "",
180    status_code=status.HTTP_200_OK,
181    summary="Delete session",
182    description="Deletes the current authenticated session token.",
183)
184async def delete_session(conn: database_dependency, session: BearerAuthDep) -> None:
185    """Delete session from database.
186
187    Args:
188      conn: database connection
189      session: authorised users information
190    """
191    await delete_token(session.token, conn)

Delete session from database.

Arguments:
  • conn: database connection
  • session: authorised users information