-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat!: Add support for global configuration
The global configuration is now defined in the yaml format in the frontend. We use the `monaco` editor. This is a breaking change. The following configuration options have to be configured manually after the update: - privacy policy URL - imprint URL - provider - authentication provider (Only the display name in the frontend) - environment (Only the display name in the frontend)
- Loading branch information
1 parent
c8fe2e4
commit 2dbdade
Showing
34 changed files
with
9,250 additions
and
8,681 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
backend/capellacollab/alembic/versions/86ab7d4d1684_add_configuration_table.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
"""Add configuration table | ||
Revision ID: 86ab7d4d1684 | ||
Revises: f55b41e32223 | ||
Create Date: 2023-10-27 14:54:40.452599 | ||
""" | ||
import sqlalchemy as sa | ||
from alembic import op | ||
from sqlalchemy.dialects import postgresql | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "86ab7d4d1684" | ||
down_revision = "f55b41e32223" | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.create_table( | ||
"configuration", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("name", sa.String(), nullable=False), | ||
sa.Column( | ||
"configuration", | ||
postgresql.JSONB(astext_type=sa.Text()), | ||
nullable=False, | ||
), | ||
sa.PrimaryKeyConstraint("id"), | ||
) | ||
op.create_index( | ||
op.f("ix_configuration_id"), "configuration", ["id"], unique=True | ||
) | ||
op.create_index( | ||
op.f("ix_configuration_name"), "configuration", ["name"], unique=True | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from sqlalchemy import orm | ||
|
||
from . import crud, models | ||
|
||
|
||
def get_config(db: orm.Session, name: str) -> models.ConfigurationBase: | ||
"""Get a configuration by name.""" | ||
configuration = crud.get_configuration_by_name(db, name) | ||
model_type = models.NAME_TO_MODEL_TYPE_MAPPING[name] | ||
if configuration: | ||
return model_type().model_validate(configuration.configuration) | ||
return model_type().model_validate({}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import typing as t | ||
|
||
import sqlalchemy as sa | ||
from sqlalchemy import orm | ||
|
||
from . import models | ||
|
||
|
||
def get_configuration_by_name( | ||
db: orm.Session, name: str | ||
) -> None | models.DatabaseConfiguration: | ||
return db.execute( | ||
sa.select(models.DatabaseConfiguration).where( | ||
models.DatabaseConfiguration.name == name | ||
) | ||
).scalar_one_or_none() | ||
|
||
|
||
def get_pydantic_configuration_by_name( | ||
db: orm.Session, pydantic_model: models.ConfigurationBase | ||
): | ||
return pydantic_model.model_validate( | ||
get_configuration_by_name(db, pydantic_model._name) | ||
) | ||
|
||
|
||
def create_configuration( | ||
db: orm.Session, | ||
name: str, | ||
configuration: dict[str, t.Any], | ||
) -> models.DatabaseConfiguration: | ||
db_configuration = models.DatabaseConfiguration( | ||
name=name, configuration=configuration | ||
) | ||
db.add(db_configuration) | ||
db.commit() | ||
return db_configuration | ||
|
||
|
||
def update_configuration( | ||
db: orm.Session, | ||
db_configuration: models.DatabaseConfiguration, | ||
configuration: dict[str, t.Any], | ||
) -> models.DatabaseConfiguration: | ||
db_configuration.configuration = configuration | ||
db.commit() | ||
return db_configuration | ||
|
||
|
||
def delete_configuration( | ||
db: orm.Session, db_configuration: models.DatabaseConfiguration | ||
): | ||
db.delete(db_configuration) | ||
db.commit() | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import abc | ||
import typing as t | ||
|
||
import pydantic | ||
from sqlalchemy import orm | ||
|
||
from capellacollab.core import database | ||
|
||
|
||
class DatabaseConfiguration(database.Base): | ||
__tablename__ = "configuration" | ||
|
||
id: orm.Mapped[int] = orm.mapped_column( | ||
unique=True, primary_key=True, index=True | ||
) | ||
|
||
name: orm.Mapped[str] = orm.mapped_column(unique=True, index=True) | ||
configuration: orm.Mapped[dict[str, t.Any]] | ||
|
||
|
||
class MetadataConfiguration(pydantic.BaseModel): | ||
model_config = pydantic.ConfigDict(extra="forbid") | ||
|
||
privacy_policy_url: str = pydantic.Field( | ||
default="https://example.com/privacy" | ||
) | ||
imprint_url: str = pydantic.Field(default="https://example.com/imprint") | ||
provider: str = pydantic.Field( | ||
default="Systems Engineering Toolchain team" | ||
) | ||
authentication_provider: str = pydantic.Field( | ||
default="OAuth2", | ||
description="Authentication provides which is displayed in the frontend.", | ||
) | ||
environment: str = pydantic.Field(default="-", description="general") | ||
|
||
|
||
class ConfigurationBase(pydantic.BaseModel, abc.ABC): | ||
""" | ||
Base class for configuration models. Can be used to define new configurations | ||
in the future. | ||
""" | ||
|
||
model_config = pydantic.ConfigDict(extra="forbid") | ||
|
||
_name: t.ClassVar[str] | ||
|
||
|
||
class GlobalConfiguration(ConfigurationBase): | ||
"""Global application configuration.""" | ||
|
||
_name: t.ClassVar[t.Literal["global"]] = "global" | ||
|
||
metadata: MetadataConfiguration = pydantic.Field( | ||
default_factory=MetadataConfiguration | ||
) | ||
|
||
|
||
# All subclasses of ConfigurationBase are automatically registered using this dict. | ||
NAME_TO_MODEL_TYPE_MAPPING: dict[str, t.Type[ConfigurationBase]] = { | ||
model()._name: model for model in ConfigurationBase.__subclasses__() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import typing as t | ||
|
||
import fastapi | ||
from sqlalchemy import orm | ||
|
||
from capellacollab.core import database | ||
from capellacollab.core.authentication import injectables as auth_injectables | ||
from capellacollab.users import models as users_models | ||
|
||
from . import core, crud, models | ||
|
||
router = fastapi.APIRouter( | ||
dependencies=[ | ||
fastapi.Depends( | ||
auth_injectables.RoleVerification( | ||
required_role=users_models.Role.ADMIN | ||
) | ||
) | ||
] | ||
) | ||
|
||
schema_router = fastapi.APIRouter(dependencies=[]) | ||
|
||
|
||
@router.get( | ||
f"/{models.GlobalConfiguration._name}", | ||
response_model=models.GlobalConfiguration, | ||
) | ||
async def get_configuration( | ||
db: orm.Session = fastapi.Depends(database.get_db), | ||
): | ||
return core.get_config(db, models.GlobalConfiguration._name) | ||
|
||
|
||
@router.put( | ||
f"/{models.GlobalConfiguration._name}", | ||
response_model=models.GlobalConfiguration, | ||
) | ||
async def update_configuration( | ||
body: models.GlobalConfiguration, | ||
db: orm.Session = fastapi.Depends(database.get_db), | ||
): | ||
configuration = crud.get_configuration_by_name( | ||
db, models.GlobalConfiguration._name | ||
) | ||
|
||
if configuration: | ||
return crud.update_configuration( | ||
db, configuration, body.model_dump() | ||
).configuration | ||
return crud.create_configuration( | ||
db, | ||
name=models.GlobalConfiguration._name, | ||
configuration=body.model_dump(), | ||
).configuration | ||
|
||
|
||
@schema_router.get( | ||
f"/{models.GlobalConfiguration._name}/schema", response_model=t.Any | ||
) | ||
async def get_json_schema(): | ||
return models.GlobalConfiguration.model_json_schema() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.