diff --git a/backend/capellacollab/core/database/__init__.py b/backend/capellacollab/core/database/__init__.py index 12fdc4be6d..581e427b21 100644 --- a/backend/capellacollab/core/database/__init__.py +++ b/backend/capellacollab/core/database/__init__.py @@ -17,7 +17,7 @@ SessionLocal = orm.sessionmaker(autocommit=False, autoflush=False, bind=engine) -class Base(orm.DeclarativeBase): +class Base(orm.MappedAsDataclass, orm.DeclarativeBase): type_annotation_map = { dict[str, str]: postgresql.JSONB, dict[str, t.Any]: postgresql.JSONB, diff --git a/backend/capellacollab/core/database/migration.py b/backend/capellacollab/core/database/migration.py index 66ddbc1491..6be39b3732 100644 --- a/backend/capellacollab/core/database/migration.py +++ b/backend/capellacollab/core/database/migration.py @@ -84,7 +84,7 @@ def migrate_db(engine, database_url: str): create_coffee_machine_model(session) -def initialize_admin_user(db): +def initialize_admin_user(db: orm.Session): LOGGER.info("Initialized adminuser %s", config["initial"]["admin"]) admin_user = users_crud.create_user( db=db, @@ -94,7 +94,7 @@ def initialize_admin_user(db): events_crud.create_user_creation_event(db, admin_user) -def initialize_default_project(db): +def initialize_default_project(db: orm.Session): LOGGER.info("Initialized project 'default'") projects_crud.create_project( db=db, @@ -104,7 +104,7 @@ def initialize_default_project(db): ) -def initialize_coffee_machine_project(db): +def initialize_coffee_machine_project(db: orm.Session): LOGGER.info("Initialize project 'Coffee Machine'") projects_crud.create_project( db=db, @@ -114,7 +114,7 @@ def initialize_coffee_machine_project(db): ) -def create_tools(db): +def create_tools(db: orm.Session): LOGGER.info("Initialized tools") registry = config["docker"]["registry"] if os.getenv("DEVELOPMENT_MODE", "").lower() in ("1", "true", "t"): @@ -131,12 +131,12 @@ def create_tools(db): ) tools_crud.create_tool(db, papyrus) - tools_crud.create_version(db, papyrus.id, "6.1") - tools_crud.create_version(db, papyrus.id, "6.0") + tools_crud.create_version(db, papyrus, "6.1") + tools_crud.create_version(db, papyrus, "6.0") - tools_crud.create_nature(db, papyrus.id, "UML 2.5") - tools_crud.create_nature(db, papyrus.id, "SysML 1.4") - tools_crud.create_nature(db, papyrus.id, "SysML 1.1") + tools_crud.create_nature(db, papyrus, "UML 2.5") + tools_crud.create_nature(db, papyrus, "SysML 1.4") + tools_crud.create_nature(db, papyrus, "SysML 1.1") else: # Use public Github images per default @@ -160,15 +160,15 @@ def create_tools(db): integrations_models.PatchToolIntegrations(jupyter=True), ) - default_version = tools_crud.create_version(db, capella.id, "6.0.0", True) - tools_crud.create_version(db, capella.id, "5.2.0") - tools_crud.create_version(db, capella.id, "5.0.0") + default_version = tools_crud.create_version(db, capella, "6.0.0", True) + tools_crud.create_version(db, capella, "5.2.0") + tools_crud.create_version(db, capella, "5.0.0") - tools_crud.create_version(db, jupyter.id, "python-3.11") - tools_crud.create_nature(db, jupyter.id, "notebooks") + tools_crud.create_version(db, jupyter, "python-3.11") + tools_crud.create_nature(db, jupyter, "notebooks") - default_nature = tools_crud.create_nature(db, capella.id, "model") - tools_crud.create_nature(db, capella.id, "library") + default_nature = tools_crud.create_nature(db, capella, "model") + tools_crud.create_nature(db, capella, "library") for model in toolmodels_crud.get_models(db): toolmodels_crud.set_tool_for_model(db, model, capella) diff --git a/backend/capellacollab/events/crud.py b/backend/capellacollab/events/crud.py index b63df31c21..12954b949f 100644 --- a/backend/capellacollab/events/crud.py +++ b/backend/capellacollab/events/crud.py @@ -26,14 +26,16 @@ def create_event( raise ValueError( f"Event type must of one of the following: {allowed_types}" ) + event = models.DatabaseUserHistoryEvent( - user_id=user.id, + user=user, event_type=event_type, execution_time=datetime.datetime.now(datetime.UTC), - executor_id=executor.id if executor else None, - project_id=project.id if project else None, + executor=executor, + project=project, reason=reason, ) + db.add(event) db.commit() diff --git a/backend/capellacollab/events/models.py b/backend/capellacollab/events/models.py index b74186bfe9..fb5ed2e10f 100644 --- a/backend/capellacollab/events/models.py +++ b/backend/capellacollab/events/models.py @@ -14,10 +14,6 @@ from capellacollab.projects import models as projects_models from capellacollab.users import models as users_models -if t.TYPE_CHECKING: - from capellacollab.projects.models import DatabaseProject - from capellacollab.users.models import DatabaseUser - class EventType(enum.Enum): CREATED_USER = "CreatedUser" @@ -55,27 +51,37 @@ class HistoryEvent(BaseHistoryEvent): class DatabaseUserHistoryEvent(database.Base): __tablename__ = "user_history_events" - id: orm.Mapped[int] = orm.mapped_column(primary_key=True, index=True) + id: orm.Mapped[int] = orm.mapped_column( + init=False, primary_key=True, index=True + ) - user_id: orm.Mapped[int] = orm.mapped_column(sa.ForeignKey("users.id")) - user: orm.Mapped["DatabaseUser"] = orm.relationship( + user_id: orm.Mapped[int] = orm.mapped_column( + sa.ForeignKey("users.id"), + init=False, + ) + user: orm.Mapped[users_models.DatabaseUser] = orm.relationship( back_populates="events", foreign_keys=[user_id] ) + event_type: orm.Mapped[EventType] + reason: orm.Mapped[str | None] = orm.mapped_column(default=None) + executor_id: orm.Mapped[int | None] = orm.mapped_column( - sa.ForeignKey("users.id") + sa.ForeignKey("users.id"), + init=False, ) - executor: orm.Mapped["DatabaseUser"] = orm.relationship( - foreign_keys=[executor_id] + executor: orm.Mapped[users_models.DatabaseUser | None] = orm.relationship( + default=None, foreign_keys=[executor_id] ) project_id: orm.Mapped[int | None] = orm.mapped_column( - sa.ForeignKey("projects.id") - ) - project: orm.Mapped["DatabaseProject"] = orm.relationship( - foreign_keys=[project_id] + sa.ForeignKey("projects.id"), + init=False, ) + project: orm.Mapped[ + projects_models.DatabaseProject | None + ] = orm.relationship(default=None, foreign_keys=[project_id]) - execution_time: orm.Mapped[datetime.datetime] - event_type: orm.Mapped[EventType] - reason: orm.Mapped[str | None] + execution_time: orm.Mapped[datetime.datetime] = orm.mapped_column( + default=datetime.datetime.now(datetime.UTC) + ) diff --git a/backend/capellacollab/notices/models.py b/backend/capellacollab/notices/models.py index ef38002985..e454a21f6a 100644 --- a/backend/capellacollab/notices/models.py +++ b/backend/capellacollab/notices/models.py @@ -34,7 +34,9 @@ class NoticeResponse(CreateNoticeRequest): class DatabaseNotice(database.Base): __tablename__ = "notices" - id: orm.Mapped[int] = orm.mapped_column(primary_key=True, index=True) + id: orm.Mapped[int] = orm.mapped_column( + init=False, primary_key=True, index=True + ) title: orm.Mapped[str] message: orm.Mapped[str] level: orm.Mapped[NoticeLevel] diff --git a/backend/capellacollab/projects/models.py b/backend/capellacollab/projects/models.py index be808655c6..675f3caa02 100644 --- a/backend/capellacollab/projects/models.py +++ b/backend/capellacollab/projects/models.py @@ -105,20 +105,25 @@ class DatabaseProject(database.Base): __tablename__ = "projects" id: orm.Mapped[int] = orm.mapped_column( - unique=True, primary_key=True, index=True + init=False, unique=True, primary_key=True, index=True ) name: orm.Mapped[str] = orm.mapped_column(unique=True, index=True) slug: orm.Mapped[str] = orm.mapped_column(unique=True, index=True) - description: orm.Mapped[str | None] - visibility: orm.Mapped[Visibility] - type: orm.Mapped[ProjectType] + + description: orm.Mapped[str | None] = orm.mapped_column(default=None) + visibility: orm.Mapped[Visibility] = orm.mapped_column( + default=Visibility.PRIVATE + ) + type: orm.Mapped[ProjectType] = orm.mapped_column( + default=ProjectType.GENERAL + ) users: orm.Mapped[list[ProjectUserAssociation]] = orm.relationship( - back_populates="project" + default_factory=list, back_populates="project" ) models: orm.Mapped[list[DatabaseCapellaModel]] = orm.relationship( - back_populates="project" + default_factory=list, back_populates="project" ) is_archived: orm.Mapped[bool] = orm.mapped_column(default=False) diff --git a/backend/capellacollab/projects/toolmodels/backups/models.py b/backend/capellacollab/projects/toolmodels/backups/models.py index 356010a270..1efd3e9429 100644 --- a/backend/capellacollab/projects/toolmodels/backups/models.py +++ b/backend/capellacollab/projects/toolmodels/backups/models.py @@ -51,7 +51,7 @@ class Backup(pydantic.BaseModel): class DatabaseBackup(database.Base): __tablename__ = "backups" id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, autoincrement=True + init=False, primary_key=True, index=True, autoincrement=True ) created_by: orm.Mapped[str] diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/models.py b/backend/capellacollab/projects/toolmodels/backups/runs/models.py index 21204aa43e..b5007b6dfd 100644 --- a/backend/capellacollab/projects/toolmodels/backups/runs/models.py +++ b/backend/capellacollab/projects/toolmodels/backups/runs/models.py @@ -28,7 +28,7 @@ class PipelineRunStatus(enum.Enum): class DatabasePipelineRun(Base): __tablename__ = "pipeline_run" id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, autoincrement=True + init=False, primary_key=True, index=True, autoincrement=True ) reference_id: orm.Mapped[str | None] diff --git a/backend/capellacollab/projects/toolmodels/models.py b/backend/capellacollab/projects/toolmodels/models.py index 0ab55fd171..66120c0cb7 100644 --- a/backend/capellacollab/projects/toolmodels/models.py +++ b/backend/capellacollab/projects/toolmodels/models.py @@ -67,7 +67,7 @@ class DatabaseCapellaModel(database.Base): __table_args__ = (sa.UniqueConstraint("project_id", "slug"),) id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, unique=True + init=False, primary_key=True, index=True, unique=True ) name: orm.Mapped[str] = orm.mapped_column(index=True) diff --git a/backend/capellacollab/projects/toolmodels/modelsources/t4c/models.py b/backend/capellacollab/projects/toolmodels/modelsources/t4c/models.py index 7fc1f740ae..3c08629fbf 100644 --- a/backend/capellacollab/projects/toolmodels/modelsources/t4c/models.py +++ b/backend/capellacollab/projects/toolmodels/modelsources/t4c/models.py @@ -28,7 +28,7 @@ class DatabaseT4CModel(database.Base): ) id: orm.Mapped[int] = orm.mapped_column( - unique=True, primary_key=True, index=True + init=False, unique=True, primary_key=True, index=True ) name: orm.Mapped[str] = orm.mapped_column(index=True) diff --git a/backend/capellacollab/projects/toolmodels/restrictions/models.py b/backend/capellacollab/projects/toolmodels/restrictions/models.py index e2d93d2a07..544e3f76fc 100644 --- a/backend/capellacollab/projects/toolmodels/restrictions/models.py +++ b/backend/capellacollab/projects/toolmodels/restrictions/models.py @@ -28,7 +28,7 @@ class DatabaseToolModelRestrictions(database.Base): __tablename__ = "model_restrictions" id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, unique=True + init=False, primary_key=True, index=True, unique=True ) model_id: orm.Mapped[int] = orm.mapped_column(sa.ForeignKey("models.id")) diff --git a/backend/capellacollab/settings/configuration/models.py b/backend/capellacollab/settings/configuration/models.py index 829395a052..ea554bfcf1 100644 --- a/backend/capellacollab/settings/configuration/models.py +++ b/backend/capellacollab/settings/configuration/models.py @@ -14,7 +14,7 @@ class DatabaseConfiguration(database.Base): __tablename__ = "configuration" id: orm.Mapped[int] = orm.mapped_column( - unique=True, primary_key=True, index=True + init=False, unique=True, primary_key=True, index=True ) name: orm.Mapped[str] = orm.mapped_column(unique=True, index=True) diff --git a/backend/capellacollab/settings/integrations/purevariants/models.py b/backend/capellacollab/settings/integrations/purevariants/models.py index bae5c84238..da77d1ad2b 100644 --- a/backend/capellacollab/settings/integrations/purevariants/models.py +++ b/backend/capellacollab/settings/integrations/purevariants/models.py @@ -28,7 +28,9 @@ def validate_license_url(value: str | None): class DatabasePureVariantsLicenses(database.Base): __tablename__ = "pure_variants" - id: orm.Mapped[int] = orm.mapped_column(primary_key=True, index=True) + id: orm.Mapped[int] = orm.mapped_column( + init=False, primary_key=True, index=True + ) license_server_url: orm.Mapped[str | None] license_key_filename: orm.Mapped[str | None] diff --git a/backend/capellacollab/settings/modelsources/git/models.py b/backend/capellacollab/settings/modelsources/git/models.py index fa47081460..f408c60673 100644 --- a/backend/capellacollab/settings/modelsources/git/models.py +++ b/backend/capellacollab/settings/modelsources/git/models.py @@ -34,7 +34,7 @@ class DatabaseGitInstance(database.Base): __tablename__ = "git_instances" id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, autoincrement=True + init=False, primary_key=True, index=True, autoincrement=True ) name: orm.Mapped[str] diff --git a/backend/capellacollab/settings/modelsources/t4c/models.py b/backend/capellacollab/settings/modelsources/t4c/models.py index 91ad5d6586..546e55439e 100644 --- a/backend/capellacollab/settings/modelsources/t4c/models.py +++ b/backend/capellacollab/settings/modelsources/t4c/models.py @@ -46,20 +46,14 @@ class DatabaseT4CInstance(database.Base): __tablename__ = "t4c_instances" id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, autoincrement=True + init=False, primary_key=True, index=True, autoincrement=True ) name: orm.Mapped[str] = orm.mapped_column(unique=True) license: orm.Mapped[str] host: orm.Mapped[str] - port: orm.Mapped[int] = orm.mapped_column( - sa.CheckConstraint("port >= 0 AND port <= 65535"), default=2036 - ) - cdo_port: orm.Mapped[int] = orm.mapped_column( - sa.CheckConstraint("cdo_port >= 0 AND cdo_port <= 65535"), - default=12036, - ) + http_port: orm.Mapped[int | None] = orm.mapped_column( sa.CheckConstraint("http_port >= 0 AND http_port <= 65535"), ) @@ -68,8 +62,6 @@ class DatabaseT4CInstance(database.Base): username: orm.Mapped[str] password: orm.Mapped[str] - protocol: orm.Mapped[Protocol] = orm.mapped_column(default=Protocol.tcp) - version_id: orm.Mapped[int] = orm.mapped_column( sa.ForeignKey("versions.id") ) @@ -79,6 +71,15 @@ class DatabaseT4CInstance(database.Base): back_populates="instance", cascade="all, delete" ) + port: orm.Mapped[int] = orm.mapped_column( + sa.CheckConstraint("port >= 0 AND port <= 65535"), default=2036 + ) + cdo_port: orm.Mapped[int] = orm.mapped_column( + sa.CheckConstraint("cdo_port >= 0 AND cdo_port <= 65535"), + default=12036, + ) + protocol: orm.Mapped[Protocol] = orm.mapped_column(default=Protocol.tcp) + is_archived: orm.Mapped[bool] = orm.mapped_column(default=False) diff --git a/backend/capellacollab/settings/modelsources/t4c/repositories/models.py b/backend/capellacollab/settings/modelsources/t4c/repositories/models.py index 2786d71f15..cad2ff8214 100644 --- a/backend/capellacollab/settings/modelsources/t4c/repositories/models.py +++ b/backend/capellacollab/settings/modelsources/t4c/repositories/models.py @@ -27,7 +27,11 @@ class DatabaseT4CRepository(database.Base): __table_args__ = (sa.UniqueConstraint("instance_id", "name"),) id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, autoincrement=True, unique=True + init=False, + primary_key=True, + index=True, + autoincrement=True, + unique=True, ) name: orm.Mapped[str] diff --git a/backend/capellacollab/tools/crud.py b/backend/capellacollab/tools/crud.py index 9692e9b8ec..044820ead9 100644 --- a/backend/capellacollab/tools/crud.py +++ b/backend/capellacollab/tools/crud.py @@ -38,7 +38,7 @@ def create_tool( db: orm.Session, tool: models.DatabaseTool ) -> models.DatabaseTool: tool.integrations = integrations_models.DatabaseToolIntegrations( - pure_variants=False, t4c=False, jupyter=False + tool=tool, pure_variants=False, t4c=False, jupyter=False ) db.add(tool) db.commit() @@ -151,7 +151,7 @@ def update_version( def create_version( db: orm.Session, - tool_id: int, + tool: models.DatabaseTool, name: str, is_recommended: bool = False, is_deprecated: bool = False, @@ -160,7 +160,7 @@ def create_version( name=name, is_recommended=is_recommended, is_deprecated=is_deprecated, - tool_id=tool_id, + tool=tool, ) db.add(version) db.commit() @@ -223,9 +223,9 @@ def get_natures_by_tool_id( def create_nature( - db: orm.Session, tool_id: int, name: str + db: orm.Session, tool: models.DatabaseTool, name: str ) -> models.DatabaseNature: - nature = models.DatabaseNature(name=name, tool_id=tool_id) + nature = models.DatabaseNature(name=name, tool=tool) db.add(nature) db.commit() return nature diff --git a/backend/capellacollab/tools/integrations/models.py b/backend/capellacollab/tools/integrations/models.py index 9615d5663b..937885194e 100644 --- a/backend/capellacollab/tools/integrations/models.py +++ b/backend/capellacollab/tools/integrations/models.py @@ -32,9 +32,11 @@ class PatchToolIntegrations(pydantic.BaseModel): class DatabaseToolIntegrations(database.Base): __tablename__ = "tool_integrations" - id: orm.Mapped[int] = orm.mapped_column(primary_key=True) + id: orm.Mapped[int] = orm.mapped_column(init=False, primary_key=True) - tool_id: orm.Mapped[int] = orm.mapped_column(sa.ForeignKey("tools.id")) + tool_id: orm.Mapped[int] = orm.mapped_column( + sa.ForeignKey("tools.id"), init=False + ) tool: orm.Mapped[DatabaseTool] = orm.relationship( back_populates="integrations" ) diff --git a/backend/capellacollab/tools/models.py b/backend/capellacollab/tools/models.py index ec682ad095..07016ef2af 100644 --- a/backend/capellacollab/tools/models.py +++ b/backend/capellacollab/tools/models.py @@ -20,22 +20,30 @@ class DatabaseTool(database.Base): __tablename__ = "tools" - id: orm.Mapped[int] = orm.mapped_column(primary_key=True) + id: orm.Mapped[int] = orm.mapped_column(init=False, primary_key=True) name: orm.Mapped[str] docker_image_template: orm.Mapped[str] - docker_image_backup_template: orm.Mapped[str | None] - readonly_docker_image_template: orm.Mapped[str | None] + docker_image_backup_template: orm.Mapped[str | None] = orm.mapped_column( + default=None + ) + readonly_docker_image_template: orm.Mapped[str | None] = orm.mapped_column( + default=None + ) + + integrations: orm.Mapped[ + DatabaseToolIntegrations | None + ] = orm.relationship( + default=None, + back_populates="tool", + uselist=False, + ) versions: orm.Mapped[list[DatabaseVersion]] = orm.relationship( - back_populates="tool" + default_factory=list, back_populates="tool" ) natures: orm.Mapped[list[DatabaseNature]] = orm.relationship( - back_populates="tool" - ) - - integrations: orm.Mapped[DatabaseToolIntegrations] = orm.relationship( - back_populates="tool", uselist=False + default_factory=list, back_populates="tool" ) @@ -43,14 +51,15 @@ class DatabaseVersion(database.Base): __tablename__ = "versions" __table_args__ = (sa.UniqueConstraint("tool_id", "name"),) - id: orm.Mapped[int] = orm.mapped_column(primary_key=True) + id: orm.Mapped[int] = orm.mapped_column(init=False, primary_key=True) name: orm.Mapped[str] is_recommended: orm.Mapped[bool] is_deprecated: orm.Mapped[bool] tool_id: orm.Mapped[int | None] = orm.mapped_column( - sa.ForeignKey("tools.id") + sa.ForeignKey("tools.id"), + init=False, ) tool: orm.Mapped[DatabaseTool] = orm.relationship( back_populates="versions" @@ -61,7 +70,7 @@ class DatabaseNature(database.Base): __tablename__ = "types" __table_args__ = (sa.UniqueConstraint("tool_id", "name"),) - id: orm.Mapped[int] = orm.mapped_column(primary_key=True) + id: orm.Mapped[int] = orm.mapped_column(init=False, primary_key=True) name: orm.Mapped[str] tool_id: orm.Mapped[int | None] = orm.mapped_column( diff --git a/backend/capellacollab/tools/routes.py b/backend/capellacollab/tools/routes.py index 0b89b32072..668310a58a 100644 --- a/backend/capellacollab/tools/routes.py +++ b/backend/capellacollab/tools/routes.py @@ -130,7 +130,7 @@ def create_tool_version( tool: models.DatabaseTool = fastapi.Depends(injectables.get_existing_tool), db: orm.Session = fastapi.Depends(database.get_db), ) -> models.DatabaseVersion: - return crud.create_version(db, tool.id, body.name) + return crud.create_version(db, tool, body.name) @router.patch( @@ -194,11 +194,11 @@ def get_tool_natures( ], ) def create_tool_nature( - tool_id: int, body: models.CreateToolNature, + tool: models.DatabaseTool = fastapi.Depends(injectables.get_existing_tool), db: orm.Session = fastapi.Depends(database.get_db), ) -> models.DatabaseNature: - return crud.create_nature(db, tool_id, body.name) + return crud.create_nature(db, tool, body.name) @router.delete( diff --git a/backend/capellacollab/users/models.py b/backend/capellacollab/users/models.py index d1ffef652e..a4431c886e 100644 --- a/backend/capellacollab/users/models.py +++ b/backend/capellacollab/users/models.py @@ -8,7 +8,7 @@ import typing as t import pydantic -from sqlalchemy import orm +from sqlalchemy import func, orm from capellacollab.core import database from capellacollab.core import pydantic as core_pydantic @@ -59,23 +59,34 @@ class PostUser(pydantic.BaseModel): class DatabaseUser(database.Base): __tablename__ = "users" - id: orm.Mapped[int] = orm.mapped_column(primary_key=True, index=True) + id: orm.Mapped[int] = orm.mapped_column( + init=False, primary_key=True, index=True + ) name: orm.Mapped[str] = orm.mapped_column(unique=True, index=True) role: orm.Mapped[Role] - created: orm.Mapped[datetime.datetime | None] - last_login: orm.Mapped[datetime.datetime | None] + created: orm.Mapped[datetime.datetime | None] = orm.mapped_column( + default=datetime.datetime.now(datetime.UTC) + ) projects: orm.Mapped[list[ProjectUserAssociation]] = orm.relationship( - back_populates="user" + default_factory=list, back_populates="user" ) sessions: orm.Mapped[list[DatabaseSession]] = orm.relationship( - back_populates="owner" + default_factory=list, back_populates="owner" ) events: orm.Mapped[list[DatabaseUserHistoryEvent]] = orm.relationship( - back_populates="user", foreign_keys="DatabaseUserHistoryEvent.user_id" + default_factory=list, + back_populates="user", + foreign_keys="DatabaseUserHistoryEvent.user_id", ) tokens: orm.Mapped[list[DatabaseUserToken]] = orm.relationship( - back_populates="user", cascade="all, delete-orphan" + default_factory=list, + back_populates="user", + cascade="all, delete-orphan", + ) + + last_login: orm.Mapped[datetime.datetime | None] = orm.mapped_column( + default=None ) diff --git a/backend/capellacollab/users/tokens/models.py b/backend/capellacollab/users/tokens/models.py index 38345a8403..7f3cee2128 100644 --- a/backend/capellacollab/users/tokens/models.py +++ b/backend/capellacollab/users/tokens/models.py @@ -38,7 +38,7 @@ class DatabaseUserToken(database.Base): __tablename__ = "basic_auth_token" id: orm.Mapped[int] = orm.mapped_column( - primary_key=True, index=True, autoincrement=True + init=False, primary_key=True, index=True, autoincrement=True ) user_id: orm.Mapped[int] = orm.mapped_column(sa.ForeignKey("users.id")) user: orm.Mapped["DatabaseUser"] = orm.relationship( diff --git a/backend/tests/sessions/test_sessions_routes.py b/backend/tests/sessions/test_sessions_routes.py index 695c6b906d..cfdec31752 100644 --- a/backend/tests/sessions/test_sessions_routes.py +++ b/backend/tests/sessions/test_sessions_routes.py @@ -34,14 +34,8 @@ ) from capellacollab.sessions.operators import get_operator from capellacollab.sessions.operators import models as operators_models +from capellacollab.tools import crud as tools_crud from capellacollab.tools import models as tools_models -from capellacollab.tools.crud import ( - create_tool, - create_tool_with_name, - create_version, - get_natures, - get_versions, -) from capellacollab.tools.integrations.crud import update_integrations from capellacollab.tools.integrations.models import PatchToolIntegrations from capellacollab.users.crud import create_user @@ -179,7 +173,7 @@ def test_create_readonly_session_as_user( ): _, version = next( (v.tool, v) - for v in get_versions(db) + for v in tools_crud.get_versions(db) if v.tool.name == "Capella" and v.name == "5.0.0" ) @@ -217,8 +211,8 @@ def test_create_readonly_session_as_user( def test_no_readonly_session_as_user(client, db, user, kubernetes): - tool = create_tool_with_name(db, "Test") - version = create_version(db, tool.id, "test") + tool = tools_crud.create_tool_with_name(db, "Test") + version = tools_crud.create_version(db, tool, "test") model, git_model = setup_git_model_for_user(db, user, version) @@ -249,7 +243,7 @@ def test_one_readonly_sessions_as_user_per_tool_version( ): version = next( v - for v in get_versions(db) + for v in tools_crud.get_versions(db) if v.tool.name == "Capella" and v.name == "5.0.0" ) @@ -276,7 +270,7 @@ def test_one_readonly_sessions_as_user_per_tool_version( def setup_git_model_for_user(db, user, version): project = create_project(db, name=str(uuid1())) - nature = get_natures(db)[0] + nature = tools_crud.get_natures(db)[0] add_user_to_project( db, project, @@ -357,7 +351,7 @@ def test_create_read_only_session_as_user( ): version = next( v - for v in get_versions(db) + for v in tools_crud.get_versions(db) if v.tool.name == "Capella" and v.name == "6.0.0" ) @@ -377,7 +371,6 @@ def test_create_read_only_session_as_user( }, ) out = response.json() - print(out) session = get_session_by_id(db, out["id"]) assert response.status_code == 200 @@ -393,7 +386,7 @@ def test_create_read_only_session_as_user( def test_create_persistent_jupyter_session(client, db, user, kubernetes): - jupyter = create_tool( + jupyter = tools_crud.create_tool( db, tools_models.DatabaseTool( name="jupyter", @@ -404,8 +397,8 @@ def test_create_persistent_jupyter_session(client, db, user, kubernetes): db, jupyter.integrations, PatchToolIntegrations(jupyter=True) ) - jupyter_version = create_version( - db, name="python-3.10.8", tool_id=jupyter.id + jupyter_version = tools_crud.create_version( + db, name="python-3.10.8", tool=jupyter ) response = client.post( diff --git a/backend/tests/settings/conftest.py b/backend/tests/settings/conftest.py index d0aa936b11..e27b2bd9ae 100644 --- a/backend/tests/settings/conftest.py +++ b/backend/tests/settings/conftest.py @@ -15,7 +15,7 @@ @pytest.fixture(name="test_tool_version") def fixture_test_tool_version(db: orm.Session) -> tools_models.DatabaseVersion: tool = tools_crud.create_tool_with_name(db, "Test") - return tools_crud.create_version(db, tool.id, "test") + return tools_crud.create_version(db, tool, "test") @pytest.fixture(name="admin_user")