Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/fmu_settings_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class APISettings(BaseModel):

API_V1_PREFIX: str = Field(default="/api/v1", frozen=True)
SESSION_COOKIE_KEY: str = Field(default="fmu_settings_session", frozen=True)
SESSION_EXPIRE_SECONDS: int = Field(default=1200, frozen=True) # 20 minutes
SESSION_EXPIRE_SECONDS: int = Field(default=31556926, frozen=True) # 1 year
RMS_SESSION_EXPIRE_SECONDS: int = Field(default=3600, frozen=True) # 60 minutes
APP_NAME: str = Field(default="fmu-settings-api", frozen=True)
APP_VERSION: str = Field(default=__version__, frozen=True)
TOKEN: str = Field(
Expand Down
8 changes: 0 additions & 8 deletions src/fmu_settings_api/deps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@
from .resource import ResourceServiceDep
from .session import (
ProjectSessionDep,
ProjectSessionNoExtendDep,
ProjectSessionServiceDep,
ProjectSessionServiceNoExtendDep,
ProjectSmdaSessionDep,
SessionDep,
SessionNoExtendDep,
SessionServiceDep,
SessionServiceNoExtendDep,
get_session,
get_smda_session,
)
Expand All @@ -31,13 +27,9 @@
"UserFMUDirDep",
"get_session",
"SessionDep",
"SessionNoExtendDep",
"SessionServiceDep",
"SessionServiceNoExtendDep",
"ProjectSessionDep",
"ProjectSessionNoExtendDep",
"ProjectSessionServiceDep",
"ProjectSessionServiceNoExtendDep",
"RefreshLockDep",
"get_smda_session",
"ProjectSmdaSessionDep",
Expand Down
99 changes: 20 additions & 79 deletions src/fmu_settings_api/deps/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,30 @@
ProjectSession,
Session,
SessionNotFoundError,
session_manager,
destroy_fmu_session_if_expired,
get_fmu_session,
)


async def get_session(
async def destroy_session_if_expired(
fmu_settings_session: Annotated[str | None, Cookie()] = None,
) -> Session:
"""Gets a session from the session manager."""
if not fmu_settings_session:
raise HTTPException(
status_code=401,
detail="No active session found",
headers={
HttpHeader.WWW_AUTHENTICATE_KEY: HttpHeader.WWW_AUTHENTICATE_COOKIE
},
)
try:
return await session_manager.get_session(fmu_settings_session)
except SessionNotFoundError as e:
raise HTTPException(
status_code=401,
detail="Invalid or expired session",
headers={
HttpHeader.WWW_AUTHENTICATE_KEY: HttpHeader.WWW_AUTHENTICATE_COOKIE
},
) from e
except Exception as e:
raise HTTPException(status_code=500, detail=f"Session error: {e}") from e
) -> None:
"""Destroys a session from the session manager if it has expired."""
return (
await destroy_fmu_session_if_expired(fmu_settings_session)
if fmu_settings_session
else None
)


SessionDep = Annotated[Session, Depends(get_session)]
DestroySessionIfExpiredDep = Annotated[None, Depends(destroy_session_if_expired)]


async def get_session_no_extend(
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these no_extend functions could now be removed as session_manager.get_session()does no longer extend the session expiration time.

async def get_session(
expired_session_dep: DestroySessionIfExpiredDep,
fmu_settings_session: Annotated[str | None, Cookie()] = None,
) -> Session:
"""Gets a session from the session manager without extending expiration."""
"""Gets an active session from the session manager."""
if not fmu_settings_session:
raise HTTPException(
status_code=401,
Expand All @@ -56,13 +43,11 @@ async def get_session_no_extend(
},
)
try:
return await session_manager.get_session(
fmu_settings_session, extend_expiration=False
)
return await get_fmu_session(fmu_settings_session)
Copy link
Copy Markdown
Collaborator Author

@slangeveld slangeveld Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functionality for removing/destroying sessions where kindoff hidden inside the session_manager.get_session() function. This has now been moved out to a separate dependency DestroySessionIfExpiredDep which is injected into the get_session dependency.

except SessionNotFoundError as e:
raise HTTPException(
status_code=401,
detail="Invalid or expired session",
detail="No active session found",
headers={
HttpHeader.WWW_AUTHENTICATE_KEY: HttpHeader.WWW_AUTHENTICATE_COOKIE
},
Expand All @@ -71,14 +56,14 @@ async def get_session_no_extend(
raise HTTPException(status_code=500, detail=f"Session error: {e}") from e


SessionNoExtendDep = Annotated[Session, Depends(get_session_no_extend)]
SessionDep = Annotated[Session, Depends(get_session)]


async def get_project_session(
session: SessionDep,
Copy link
Copy Markdown
Collaborator Author

@slangeveld slangeveld Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather inject the depedency then call the get_session function directly

fmu_settings_session: str | None = Cookie(None),
) -> ProjectSession:
"""Gets a session with an FMU Project opened from the session manager."""
session = await get_session(fmu_settings_session)
if not isinstance(session, ProjectSession):
raise HTTPException(
status_code=401,
Expand All @@ -96,30 +81,6 @@ async def get_project_session(
ProjectSessionDep = Annotated[ProjectSession, Depends(get_project_session)]


async def get_project_session_no_extend(
fmu_settings_session: str | None = Cookie(None),
) -> ProjectSession:
"""Gets a session with an FMU Project opened from the session manager."""
session = await get_session_no_extend(fmu_settings_session)
if not isinstance(session, ProjectSession):
raise HTTPException(
status_code=401,
detail="No FMU project directory open",
)

if not session.project_fmu_directory.path.exists():
raise HTTPException(
status_code=404,
detail="Project .fmu directory not found. It may have been deleted.",
)
return session


ProjectSessionNoExtendDep = Annotated[
ProjectSession, Depends(get_project_session_no_extend)
]


async def ensure_smda_session(session: Session) -> None:
"""Raises exceptions if a session is not SMDA-query capable."""
if (
Expand All @@ -140,19 +101,19 @@ async def ensure_smda_session(session: Session) -> None:


async def get_smda_session(
session: SessionDep,
fmu_settings_session: str | None = Cookie(None),
) -> Session:
"""Gets a session capable of querying SMDA from the session manager."""
session = await get_session(fmu_settings_session)
await ensure_smda_session(session)
return session


async def get_project_smda_session(
session: ProjectSessionDep,
fmu_settings_session: str | None = Cookie(None),
) -> ProjectSession:
"""Returns a project .fmu session that is SMDA-querying capable."""
session = await get_project_session(fmu_settings_session)
await ensure_smda_session(session)
return session

Expand All @@ -167,17 +128,7 @@ async def get_session_service(
return SessionService(session)


async def get_session_service_no_extend(
session: SessionNoExtendDep,
) -> SessionService:
"""Returns a SessionService instance without extending session expiration."""
return SessionService(session)


SessionServiceDep = Annotated[SessionService, Depends(get_session_service)]
SessionServiceNoExtendDep = Annotated[
SessionService, Depends(get_session_service_no_extend)
]


async def get_project_session_service(
Expand All @@ -187,16 +138,6 @@ async def get_project_session_service(
return SessionService(session)


async def get_project_session_service_no_extend(
session: ProjectSessionNoExtendDep,
) -> SessionService:
"""Returns a SessionService for a project session without extending expiration."""
return SessionService(session)


ProjectSessionServiceDep = Annotated[
SessionService, Depends(get_project_session_service)
]
ProjectSessionServiceNoExtendDep = Annotated[
SessionService, Depends(get_project_session_service_no_extend)
]
3 changes: 3 additions & 0 deletions src/fmu_settings_api/models/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ class SessionResponse(BaseResponseModel):
expires_at: datetime
"""Timestamp when the session will expire."""

rms_expires_at: datetime | None
Copy link
Copy Markdown
Collaborator Author

@slangeveld slangeveld Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to also return this to the client so that it can keep track of when the RMS session will expire.

"""Timestamp when the rms session will expire."""

last_accessed: datetime
"""Timestamp when the session was last accessed."""
4 changes: 3 additions & 1 deletion src/fmu_settings_api/services/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
add_access_token_to_session as add_token_to_session_manager,
add_fmu_project_to_session,
add_rms_project_to_session,
get_rms_session_expiration,
release_project_lock,
remove_fmu_project_from_session,
remove_rms_project_from_session,
Expand All @@ -35,12 +36,13 @@ def __init__(self, session: Session | ProjectSession) -> None:
"""Initialize the service with a session."""
self._session = session

def get_session_response(self) -> SessionResponse:
async def get_session_response(self) -> SessionResponse:
"""Get the session data in a serializable format."""
return SessionResponse(
id=self._session.id,
created_at=self._session.created_at,
expires_at=self._session.expires_at,
rms_expires_at=await get_rms_session_expiration(self._session.id),
last_accessed=self._session.last_accessed,
)

Expand Down
Loading
Loading