async def create_session_token(self, user_info: TokenUserInfo, *, scopes: List[str], ip_address: str) -> Token: """Create a new session token. Parameters ---------- user_info : `gafaelfawr.models.token.TokenUserInfo` The user information to associate with the token. scopes : List[`str`] The scopes of the token. ip_address : `str` The IP address from which the request came. Returns ------- token : `gafaelfawr.models.token.Token` The newly-created token. Raises ------ gafaelfawr.exceptions.PermissionDeniedError If the provided username is invalid. """ self._validate_username(user_info.username) scopes = sorted(scopes) token = Token() created = current_datetime() expires = created + self._config.token_lifetime data = TokenData( token=token, token_type=TokenType.session, scopes=scopes, created=created, expires=expires, **user_info.dict(), ) history_entry = TokenChangeHistoryEntry( token=token.key, username=data.username, token_type=TokenType.session, scopes=scopes, expires=expires, actor=data.username, action=TokenChange.create, ip_address=ip_address, event_time=created, ) await self._token_redis_store.store_data(data) with self._transaction_manager.transaction(): self._token_db_store.add(data) self._token_change_store.add(history_entry) return token
async def add_expired_session_token( user_info: TokenUserInfo, *, scopes: List[str], ip_address: str, session: AsyncSession, ) -> None: """Add an expired session token to the database. This requires going beneath the service layer, since the service layer rejects creation of expired tokens (since apart from testing this isn't a sensible thing to want to do). This does not add the token to Redis, since Redis will refuse to add it with a negative expiration time, so can only be used for tests that exclusively use the database. Parameters ---------- user_info : `gafaelfawr.models.token.TokenUserInfo` The user information to associate with the token. scopes : List[`str`] The scopes of the token. ip_address : `str` The IP address from which the request came. session : `sqlalchemy.ext.asyncio.AsyncSession` The database session. """ token_db_store = TokenDatabaseStore(session) token_change_store = TokenChangeHistoryStore(session) token = Token() created = current_datetime() expires = created - timedelta(minutes=10) data = TokenData( token=token, token_type=TokenType.session, scopes=scopes, created=created, expires=expires, **user_info.dict(), ) history_entry = TokenChangeHistoryEntry( token=token.key, username=data.username, token_type=TokenType.session, scopes=scopes, expires=expires, actor=data.username, action=TokenChange.create, ip_address=ip_address, event_time=created, ) await token_db_store.add(data) await token_change_store.add(history_entry)