Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Unify various API endpoints related to config #2034

Merged
merged 1 commit into from
Dec 6, 2024
Merged
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
18 changes: 1 addition & 17 deletions backend/capellacollab/feedback/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@
import fastapi
from sqlalchemy import orm

from capellacollab.config import config
from capellacollab.core import database
from capellacollab.core import logging as log
from capellacollab.core.authentication import injectables as auth_injectables
from capellacollab.settings.configuration import core as config_core
from capellacollab.settings.configuration import models as config_models
from capellacollab.users import injectables as user_injectables
from capellacollab.users import models as users_models

Expand All @@ -23,21 +20,8 @@
router = fastapi.APIRouter()


@router.get(
"/configurations/feedback",
response_model=config_models.FeedbackConfiguration,
)
def get_feedback_configuration(
db: orm.Session = fastapi.Depends(database.get_db),
):
feedback = config_core.get_global_configuration(db).feedback
if not (config.smtp and config.smtp.enabled):
util.disable_feedback(feedback)
return feedback


@router.post(
"/feedback",
"",
status_code=204,
dependencies=[
fastapi.Depends(
Expand Down
45 changes: 0 additions & 45 deletions backend/capellacollab/metadata/routes.py

This file was deleted.

23 changes: 0 additions & 23 deletions backend/capellacollab/navbar/routes.py

This file was deleted.

8 changes: 3 additions & 5 deletions backend/capellacollab/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
from capellacollab.events import routes as events_router
from capellacollab.feedback import routes as feedback_routes
from capellacollab.health import routes as health_routes
from capellacollab.metadata import routes as core_metadata
from capellacollab.navbar import routes as navbar_routes
from capellacollab.notices import routes as notices_routes
from capellacollab.projects import routes as projects_routes
from capellacollab.sessions import routes as sessions_routes
Expand All @@ -30,9 +28,9 @@
responses=auth_responses.api_exceptions(include_authentication=True),
tags=["Health"],
)
router.include_router(core_metadata.router, tags=["Metadata"])
router.include_router(navbar_routes.router, tags=["Navbar"])
router.include_router(feedback_routes.router, tags=["Feedback"])
router.include_router(
feedback_routes.router, prefix="/feedback", tags=["Feedback"]
)
router.include_router(
sessions_routes.router,
prefix="/sessions",
Expand Down
20 changes: 20 additions & 0 deletions backend/capellacollab/settings/configuration/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,23 @@ class GlobalConfiguration(ConfigurationBase):
NAME_TO_MODEL_TYPE_MAPPING: dict[str, t.Type[ConfigurationBase]] = {
model()._name: model for model in ConfigurationBase.__subclasses__()
}


class Metadata(core_pydantic.BaseModel):
version: str
privacy_policy_url: str | None
imprint_url: str | None
provider: str | None
authentication_provider: str | None
environment: str | None

host: str | None
port: str | None
protocol: str | None


class UnifiedConfig(core_pydantic.BaseModel):
metadata: Metadata
feedback: FeedbackConfiguration
navbar: NavbarConfiguration
beta: BetaConfiguration
39 changes: 31 additions & 8 deletions backend/capellacollab/settings/configuration/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,41 @@
from capellacollab.users import crud as users_crud
from capellacollab.users import models as users_models

from . import core, crud, models
from . import core, crud, models, util

router = fastapi.APIRouter(
dependencies=[
fastapi.Depends(
auth_injectables.RoleVerification(
required_role=users_models.Role.ADMIN
)
)
],
tags=["Configuration"],
)

schema_router = fastapi.APIRouter(dependencies=[], tags=["Configuration"])


@router.get(
"/unified",
)
def get_unified_config(
db: orm.Session = fastapi.Depends(database.get_db),
) -> models.UnifiedConfig:
cfg = core.get_global_configuration(db)

return models.UnifiedConfig(
metadata=util.get_metadata(cfg),
feedback=util.get_feedback(cfg),
beta=cfg.beta,
navbar=cfg.navbar,
)


@router.get(
f"/{models.GlobalConfiguration._name}",
response_model=models.GlobalConfiguration,
dependencies=[
fastapi.Depends(
auth_injectables.RoleVerification(
required_role=users_models.Role.ADMIN
)
)
],
)
async def get_configuration(
db: orm.Session = fastapi.Depends(database.get_db),
Expand All @@ -41,6 +57,13 @@ async def get_configuration(
@router.put(
f"/{models.GlobalConfiguration._name}",
response_model=models.GlobalConfiguration,
dependencies=[
fastapi.Depends(
auth_injectables.RoleVerification(
required_role=users_models.Role.ADMIN
)
)
],
)
async def update_configuration(
body: models.GlobalConfiguration,
Expand Down
34 changes: 34 additions & 0 deletions backend/capellacollab/settings/configuration/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import capellacollab
from capellacollab.config import config
from capellacollab.settings.configuration import models


def get_metadata(
global_config: models.GlobalConfiguration,
) -> models.Metadata:
return models.Metadata.model_validate(
global_config.metadata.model_dump()
| {
"version": capellacollab.__version__,
"host": config.general.host,
"port": str(config.general.port),
"protocol": config.general.scheme,
}
)


def get_feedback(
global_config: models.GlobalConfiguration,
) -> models.FeedbackConfiguration:
feedback = global_config.feedback
if not (config.smtp and config.smtp.enabled):
feedback.enabled = False
feedback.after_session = False
feedback.on_footer = False
feedback.on_session_card = False
feedback.interval.enabled = False

return feedback
13 changes: 0 additions & 13 deletions backend/capellacollab/users/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from capellacollab.projects.users import crud as projects_users_crud
from capellacollab.sessions import routes as session_routes
from capellacollab.settings.configuration import core as config_core
from capellacollab.settings.configuration import models as config_models
from capellacollab.users import injectables as users_injectables
from capellacollab.users import models as users_models
from capellacollab.users.tokens import routes as tokens_routes
Expand All @@ -41,18 +40,6 @@ def get_current_user(
return user


@router.get(
"/beta",
response_model=config_models.BetaConfiguration,
)
def get_beta_config(db: orm.Session = fastapi.Depends(database.get_db)):
cfg = config_core.get_global_configuration(db)

return config_models.BetaConfiguration.model_validate(
cfg.beta.model_dump()
)


@router.get(
"/{user_id}",
response_model=models.User,
Expand Down
8 changes: 4 additions & 4 deletions backend/tests/settings/test_global_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ def test_metadata_is_updated(

assert response.status_code == 200

response = client.get("/api/v1/metadata")
response = client.get("/api/v1/settings/configurations/unified")
assert response.status_code == 200
assert response.json()["environment"] == "test"
assert response.json()["metadata"]["environment"] == "test"


@pytest.mark.usefixtures("admin")
Expand All @@ -154,9 +154,9 @@ def test_navbar_is_updated(

assert response.status_code == 200

response = client.get("/api/v1/navbar")
response = client.get("/api/v1/settings/configurations/unified")
assert response.status_code == 200
assert response.json()["external_links"][0] == {
assert response.json()["navbar"]["external_links"][0] == {
"name": "Example",
"href": "https://example.com",
"role": "user",
Expand Down
8 changes: 4 additions & 4 deletions backend/tests/test_feedback.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ def test_feedback_is_updated(

assert response.status_code == 200

response = client.get("/api/v1/configurations/feedback")
response = client.get("/api/v1/settings/configurations/unified")
assert response.status_code == 200
assert response.json() == {
assert response.json()["feedback"] == {
"enabled": True,
"after_session": True,
"on_footer": True,
Expand Down Expand Up @@ -262,9 +262,9 @@ def test_activate_feedback_without_recipients(

@pytest.mark.usefixtures("user", "smtp_config_not_set", "feedback_enabled")
def test_feedback_is_disabled_without_smtp(client: testclient.TestClient):
response = client.get("/api/v1/configurations/feedback")
response = client.get("/api/v1/settings/configurations/unified")
assert response.status_code == 200
assert response.json()["enabled"] is False
assert response.json()["feedback"]["enabled"] is False


def test_feedback_metric(db: orm.Session):
Expand Down
24 changes: 7 additions & 17 deletions frontend/src/app/general/metadata/metadata.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { BehaviorSubject, Observable, tap } from 'rxjs';
import {
Metadata,
MetadataService as OpenAPIMetadataService,
} from 'src/app/openapi';
import { map } from 'rxjs';
import { UnifiedConfigWrapperService } from '../../services/unified-config-wrapper/unified-config-wrapper.service';

@Injectable({
providedIn: 'root',
Expand All @@ -18,19 +15,18 @@ export class MetadataService {
constructor(
private httpClient: HttpClient,
public dialog: MatDialog,
private metadataService: OpenAPIMetadataService,
private unifiedConfigWrapperService: UnifiedConfigWrapperService,
) {
this.loadVersion();
this.loadBackendMetadata().subscribe();
}

public version: Version | undefined;
public oldVersion: string | undefined;

private _backendMetadata = new BehaviorSubject<Metadata | undefined>(
undefined,
);
readonly backendMetadata = this._backendMetadata.asObservable();
readonly backendMetadata =
this.unifiedConfigWrapperService.unifiedConfig$.pipe(
map((unifiedConfig) => unifiedConfig?.metadata),
);

loadVersion(): void {
if (!this.version) {
Expand All @@ -42,12 +38,6 @@ export class MetadataService {
}
}

loadBackendMetadata(): Observable<Metadata> {
return this.metadataService
.getMetadata()
.pipe(tap((metadata: Metadata) => this._backendMetadata.next(metadata)));
}

get changedVersion(): boolean {
const currentVersion = localStorage.getItem('version');

Expand Down
Loading
Loading