mirror of
https://github.com/bec-project/bec_atlas.git
synced 2025-07-14 07:01:48 +02:00
feat(sessions): added session router
This commit is contained in:
@ -114,7 +114,12 @@ class MongoDBDatasource:
|
||||
return UserCredentials(**out)
|
||||
|
||||
def find_one(
|
||||
self, collection: str, query_filter: dict, dtype: Type[T], user: User | None = None
|
||||
self,
|
||||
collection: str,
|
||||
query_filter: dict,
|
||||
dtype: Type[T],
|
||||
fields: list[str] = None,
|
||||
user: User | None = None,
|
||||
) -> T | None:
|
||||
"""
|
||||
Find one document in the collection.
|
||||
@ -130,7 +135,7 @@ class MongoDBDatasource:
|
||||
"""
|
||||
if user is not None:
|
||||
query_filter = self.add_user_filter(user, query_filter)
|
||||
out = self.db[collection].find_one(query_filter)
|
||||
out = self.db[collection].find_one(query_filter, projection=fields)
|
||||
if out is None:
|
||||
return None
|
||||
return dtype(**out)
|
||||
@ -143,6 +148,7 @@ class MongoDBDatasource:
|
||||
limit: int = 0,
|
||||
offset: int = 0,
|
||||
fields: list[str] = None,
|
||||
sort: list[str] = None,
|
||||
user: User | None = None,
|
||||
) -> list[T]:
|
||||
"""
|
||||
@ -159,7 +165,9 @@ class MongoDBDatasource:
|
||||
"""
|
||||
if user is not None:
|
||||
query_filter = self.add_user_filter(user, query_filter)
|
||||
out = self.db[collection].find(query_filter, limit=limit, skip=offset, projection=fields)
|
||||
out = self.db[collection].find(
|
||||
query_filter, limit=limit, skip=offset, projection=fields, sort=sort
|
||||
)
|
||||
return [dtype(**x) for x in out]
|
||||
|
||||
def post(self, collection: str, data: dict, dtype: Type[T], user: User | None = None) -> T:
|
||||
|
@ -10,6 +10,7 @@ from bec_atlas.router.deployments_router import DeploymentsRouter
|
||||
from bec_atlas.router.realm_router import RealmRouter
|
||||
from bec_atlas.router.redis_router import RedisRouter, RedisWebsocket
|
||||
from bec_atlas.router.scan_router import ScanRouter
|
||||
from bec_atlas.router.session_router import SessionRouter
|
||||
from bec_atlas.router.user_router import UserRouter
|
||||
|
||||
CONFIG = {
|
||||
@ -54,15 +55,20 @@ class AtlasApp:
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
if not self.datasources.datasources:
|
||||
raise ValueError("Datasources not loaded")
|
||||
self.scan_router = ScanRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.scan_router.router, tags=["Scan"])
|
||||
|
||||
# User
|
||||
self.user_router = UserRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.user_router.router, tags=["User"])
|
||||
|
||||
# Realm
|
||||
self.realm_router = RealmRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.realm_router.router, tags=["Realm"])
|
||||
|
||||
# Deployment
|
||||
self.deployment_router = DeploymentsRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.deployment_router.router, tags=["Deployment"])
|
||||
|
||||
# Deployment Credentials
|
||||
self.deployment_credentials_router = DeploymentCredentialsRouter(
|
||||
prefix=self.prefix, datasources=self.datasources
|
||||
)
|
||||
@ -70,17 +76,25 @@ class AtlasApp:
|
||||
self.deployment_credentials_router.router, tags=["Deployment Credentials"]
|
||||
)
|
||||
|
||||
# Deployment Access
|
||||
self.deployment_access_router = DeploymentAccessRouter(
|
||||
prefix=self.prefix, datasources=self.datasources
|
||||
)
|
||||
self.app.include_router(self.deployment_access_router.router, tags=["Deployment Access"])
|
||||
|
||||
# BEC Access
|
||||
self.bec_access_router = BECAccessRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.bec_access_router.router, tags=["BEC Access"])
|
||||
|
||||
self.realm_router = RealmRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.realm_router.router, tags=["Realm"])
|
||||
# Session
|
||||
self.session_router = SessionRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.session_router.router, tags=["Session"])
|
||||
|
||||
# Scan
|
||||
self.scan_router = ScanRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.scan_router.router, tags=["Scan"])
|
||||
|
||||
# Redis
|
||||
self.redis_router = RedisRouter(prefix=self.prefix, datasources=self.datasources)
|
||||
self.app.include_router(self.redis_router.router, tags=["Redis"])
|
||||
|
||||
|
@ -70,14 +70,14 @@ class UserInfo(BaseModel):
|
||||
|
||||
|
||||
class Deployments(MongoBaseModel, AccessProfile):
|
||||
realm_id: str | ObjectId
|
||||
realm_id: str
|
||||
name: str
|
||||
active_session_id: str | ObjectId | None = None
|
||||
config_templates: list[str | ObjectId] = []
|
||||
|
||||
|
||||
class DeploymentsPartial(MongoBaseModel, AccessProfilePartial):
|
||||
realm_id: str | ObjectId | None = None
|
||||
realm_id: str | None = None
|
||||
name: str | None = None
|
||||
active_session_id: str | ObjectId | None = None
|
||||
config_templates: list[str | ObjectId] | None = None
|
||||
@ -120,7 +120,7 @@ class BECAccessProfile(MongoBaseModel, AccessProfile):
|
||||
|
||||
"""
|
||||
|
||||
deployment_id: str | ObjectId
|
||||
deployment_id: str
|
||||
username: str
|
||||
passwords: dict[str, str] = {}
|
||||
categories: list[str] = []
|
||||
@ -167,10 +167,13 @@ class State(AccessProfile):
|
||||
|
||||
|
||||
class Session(MongoBaseModel, AccessProfile):
|
||||
deployment_id: str | ObjectId
|
||||
deployment_id: str
|
||||
name: str
|
||||
|
||||
|
||||
SessionPartial = make_all_fields_optional(Session, "SessionPartial")
|
||||
|
||||
|
||||
class Datasets(AccessProfile):
|
||||
realm_id: str
|
||||
dataset_id: str
|
||||
@ -214,8 +217,8 @@ class SignalData(AccessProfile, MongoBaseModel):
|
||||
min, and max values for the signal.
|
||||
"""
|
||||
|
||||
scan_id: str | ObjectId | None = None
|
||||
device_id: str | ObjectId
|
||||
scan_id: str | None = None
|
||||
device_id: str
|
||||
signal_name: str
|
||||
data: list[Any]
|
||||
timestamps: list[float]
|
||||
@ -227,9 +230,9 @@ class SignalData(AccessProfile, MongoBaseModel):
|
||||
|
||||
|
||||
class DeviceData(AccessProfile, MongoBaseModel):
|
||||
scan_id: str | ObjectId | None = None
|
||||
scan_id: str | None = None
|
||||
name: str
|
||||
device_config_id: str | ObjectId
|
||||
device_config_id: str
|
||||
signals: list[SignalData]
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ class BECAccessRouter(BaseRouter):
|
||||
user = current_user.email
|
||||
out = self.db.find_one(
|
||||
"bec_access_profiles",
|
||||
{"deployment_id": ObjectId(deployment_id), "username": user},
|
||||
{"deployment_id": deployment_id, "username": user},
|
||||
BECAccessProfile,
|
||||
user=current_user,
|
||||
)
|
||||
|
@ -153,7 +153,9 @@ class DeploymentAccessRouter(BaseRouter):
|
||||
redis: RedisDatasource = self.datasources.datasources.get("redis")
|
||||
db: MongoDBDatasource = self.datasources.datasources.get("mongodb")
|
||||
profiles = db.find(
|
||||
"bec_access_profiles", {"deployment_id": ObjectId(deployment_id)}, BECAccessProfile
|
||||
collection="bec_access_profiles",
|
||||
query_filter={"deployment_id": deployment_id},
|
||||
dtype=BECAccessProfile,
|
||||
)
|
||||
profiles = [profile.model_dump(exclude_none=True) for profile in profiles]
|
||||
for profile in profiles:
|
||||
|
@ -44,6 +44,7 @@ class ScanRouter(BaseRouter):
|
||||
fields: list[str] = Query(default=None),
|
||||
offset: int = 0,
|
||||
limit: int = 100,
|
||||
sort: str | None = None,
|
||||
current_user: UserInfo = Depends(get_current_user),
|
||||
) -> list[ScanStatusPartial]:
|
||||
"""
|
||||
@ -51,6 +52,17 @@ class ScanRouter(BaseRouter):
|
||||
|
||||
Args:
|
||||
session_id (str): The session id
|
||||
filter (str): JSON filter for the query, e.g. '{"name": "test"}'
|
||||
fields (list[str]): List of fields to return, e.g ["name", "description"]
|
||||
offset (int): Offset for the query
|
||||
limit (int): Limit for the query
|
||||
sort (str): Sort order for the query, e.g. '{"name": 1}' for ascending order,
|
||||
'{"name": -1}' for descending order. Multiple fields can be sorted by
|
||||
separating them with a comma, e.g. '{"name": 1, "description": -1}'
|
||||
current_user (UserInfo): The current user
|
||||
|
||||
Returns:
|
||||
list[ScanStatusPartial]: List of scans
|
||||
"""
|
||||
|
||||
if fields:
|
||||
@ -72,16 +84,14 @@ class ScanRouter(BaseRouter):
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
fields=fields,
|
||||
sort=sort,
|
||||
user=current_user,
|
||||
)
|
||||
|
||||
async def scans_with_id(
|
||||
self,
|
||||
scan_id: str,
|
||||
filter: str | None = None,
|
||||
fields: list[str] = Query(default=None),
|
||||
offset: int = 0,
|
||||
limit: int = 100,
|
||||
current_user: UserInfo = Depends(get_current_user),
|
||||
):
|
||||
"""
|
||||
@ -90,7 +100,18 @@ class ScanRouter(BaseRouter):
|
||||
Args:
|
||||
scan_id (str): The scan id
|
||||
"""
|
||||
return self.db.find_one("scans", {"_id": scan_id}, ScanStatusPartial, user=current_user)
|
||||
if fields:
|
||||
fields = {
|
||||
field: 1
|
||||
for field in fields
|
||||
if field in ScanStatusPartial.model_json_schema()["properties"].keys()
|
||||
}
|
||||
return self.db.find_one(
|
||||
collection="scans",
|
||||
query_filter={"_id": scan_id},
|
||||
dtype=ScanStatusPartial,
|
||||
user=current_user,
|
||||
)
|
||||
|
||||
async def update_scan_user_data(
|
||||
self,
|
||||
|
99
backend/bec_atlas/router/session_router.py
Normal file
99
backend/bec_atlas/router/session_router.py
Normal file
@ -0,0 +1,99 @@
|
||||
import json
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from pydantic import BaseModel
|
||||
|
||||
from bec_atlas.authentication import create_access_token, get_current_user, verify_password
|
||||
from bec_atlas.datasources.mongodb.mongodb import MongoDBDatasource
|
||||
from bec_atlas.model import UserInfo
|
||||
from bec_atlas.model.model import Session
|
||||
from bec_atlas.router.base_router import BaseRouter
|
||||
|
||||
|
||||
class SessionRouter(BaseRouter):
|
||||
def __init__(self, prefix="/api/v1", datasources=None):
|
||||
super().__init__(prefix, datasources)
|
||||
self.db: MongoDBDatasource = self.datasources.datasources.get("mongodb")
|
||||
self.router = APIRouter(prefix=prefix)
|
||||
self.router.add_api_route(
|
||||
"/sessions",
|
||||
self.sessions,
|
||||
methods=["GET"],
|
||||
description="Get all sessions",
|
||||
response_model=list[Session],
|
||||
response_model_exclude_none=True,
|
||||
)
|
||||
self.router.add_api_route(
|
||||
"/sessions/realm",
|
||||
self.sessions_by_realm,
|
||||
methods=["GET"],
|
||||
description="Get all sessions for a realm",
|
||||
response_model=list[Session],
|
||||
response_model_exclude_none=True,
|
||||
)
|
||||
|
||||
async def sessions(
|
||||
self,
|
||||
filter: str | None = None,
|
||||
fields: list[str] = Query(default=None),
|
||||
offset: int = 0,
|
||||
limit: int = 100,
|
||||
sort: str | None = None,
|
||||
current_user: UserInfo = Depends(get_current_user),
|
||||
) -> list[Session]:
|
||||
"""
|
||||
Get all sessions.
|
||||
|
||||
Args:
|
||||
filter (str): JSON filter for the query, e.g. '{"name": "test"}'
|
||||
fields (list[str]): List of fields to return, e.g ["name", "description"]
|
||||
offset (int): Offset for the query
|
||||
limit (int): Limit for the query
|
||||
sort (str): Sort order for the query, e.g. '{"name": 1}' for ascending order,
|
||||
'{"name": -1}' for descending order. Multiple fields can be sorted by
|
||||
separating them with a comma, e.g. '{"name": 1, "description": -1}'
|
||||
current_user (UserInfo): The current user
|
||||
|
||||
Returns:
|
||||
list[Sessions]: List of sessions
|
||||
|
||||
"""
|
||||
if fields:
|
||||
fields = {
|
||||
field: 1
|
||||
for field in fields
|
||||
if field in Session.model_json_schema()["properties"].keys()
|
||||
}
|
||||
return self.db.find(
|
||||
"sessions",
|
||||
filter,
|
||||
Session,
|
||||
fields=fields,
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
sort=sort,
|
||||
user=current_user,
|
||||
)
|
||||
|
||||
async def sessions_by_realm(
|
||||
self,
|
||||
realm_id: str,
|
||||
filter: str | None = None,
|
||||
fields: list[str] = Query(default=None),
|
||||
offset: int = 0,
|
||||
limit: int = 100,
|
||||
sort: str | None = None,
|
||||
current_user: UserInfo = Depends(get_current_user),
|
||||
) -> list[Session]:
|
||||
"""
|
||||
Get all sessions for a realm.
|
||||
"""
|
||||
filters = {"realm_id": realm_id}
|
||||
if filter:
|
||||
filter = json.loads(filter)
|
||||
filters.update(filter)
|
||||
out = await self.sessions(filter, fields, offset, limit, sort, current_user)
|
||||
return out
|
Reference in New Issue
Block a user