Skip to content

Commit

Permalink
Merge pull request #1899 from DSD-DBS/license-indicator
Browse files Browse the repository at this point in the history
feat: Add indicator to warn when most T4C licenses are being used
  • Loading branch information
MoritzWeber0 authored Oct 24, 2024
2 parents 9f017c0 + 6d0dc05 commit 5cb85b9
Show file tree
Hide file tree
Showing 12 changed files with 402 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,18 @@ class T4CLicenseServer(T4CLicenseServerBase):
usage: interface.T4CLicenseServerUsage | None = None
warnings: list[core_models.Message] = []
instances: list[t4c_instance_models2.SimpleT4CInstance] = []
anonymized: bool = pydantic.Field(default=False, exclude=True)

def anonymize(self):
self.usage_api = ""
self.license_key = ""
self.anonymized = True

@pydantic.model_validator(mode="after")
def add_from_api(self) -> t.Any:
if self.anonymized:
return self

self.license_server_version = interface.get_t4c_license_server_version(
self.usage_api
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

from collections import abc

import fastapi
from sqlalchemy import orm

from capellacollab.core import database
from capellacollab.core.authentication import injectables as auth_injectables
from capellacollab.users import injectables as users_injectables
from capellacollab.users import models as users_models

from . import crud, exceptions, injectables, interface, models
Expand All @@ -25,11 +24,23 @@
router = fastapi.APIRouter()


@admin_router.get("", response_model=list[models.T4CLicenseServer])
@router.get("")
def get_t4c_license_servers(
db: orm.Session = fastapi.Depends(database.get_db),
) -> abc.Sequence[models.DatabaseT4CLicenseServer]:
return crud.get_t4c_license_servers(db)
user: users_models.DatabaseUser = fastapi.Depends(
users_injectables.get_own_user
),
) -> list[models.T4CLicenseServer]:
license_servers = [
models.T4CLicenseServer.model_validate(license_server)
for license_server in crud.get_t4c_license_servers(db)
]

if user.role != users_models.Role.ADMIN:
for license_server in license_servers:
license_server.anonymize()

return license_servers


@admin_router.get(
Expand Down Expand Up @@ -99,7 +110,7 @@ def delete_t4c_license_server(
"/{t4c_license_server_id}/usage",
response_model=interface.T4CLicenseServerUsage,
)
def fetch_t4c_license_server_licenses(
def get_t4c_license_server_usage(
license_server: models.DatabaseT4CLicenseServer = fastapi.Depends(
injectables.get_existing_license_server
),
Expand Down
5 changes: 3 additions & 2 deletions backend/capellacollab/settings/modelsources/t4c/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
)

router.include_router(
settings_t4c_license_server_routes.admin_router,
settings_t4c_license_server_routes.router,
prefix="/license-servers",
tags=["Settings - Modelsources - T4C - License Servers"],
)


router.include_router(
settings_t4c_license_server_routes.router,
settings_t4c_license_server_routes.admin_router,
prefix="/license-servers",
tags=["Settings - Modelsources - T4C - License Servers"],
)
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def test_create_t4c_license_server_already_existing_name(


@pytest.mark.usefixtures("t4c_license_server")
def test_get_t4c_license_servers(
def test_get_t4c_license_servers_admin(
client: testclient.TestClient,
db: orm.Session,
executor_name: str,
Expand All @@ -79,6 +79,29 @@ def test_get_t4c_license_servers(
assert len(response.json()) == 2

assert response.json()[1]["name"] == "test license server"
assert response.json()[1]["license_key"] == "test key"
assert response.json()[1]["usage_api"] == "http://localhost:8086"


@pytest.mark.usefixtures("t4c_license_server")
def test_get_t4c_license_servers(
client: testclient.TestClient,
db: orm.Session,
executor_name: str,
):
users_crud.create_user(
db, executor_name, executor_name, None, users_models.Role.USER
)

response = client.get(
"/api/v1/settings/modelsources/t4c/license-servers",
)

assert len(response.json()) == 2

assert response.json()[1]["name"] == "test license server"
assert response.json()[1]["license_key"] == ""
assert response.json()[1]["usage_api"] == ""


def test_get_t4c_license_server(
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!--
~ SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
~ SPDX-License-Identifier: Apache-2.0
-->

<div
class="max-h-0 overflow-hidden transition-all duration-700"
[ngClass]="{
'max-h-[100vh]':
((licenseUsageWrapperService.licenseServerUsage$ | async)?.length ?? -1) >
0,
}"
>
@if ((licenseUsageWrapperService.licenseServerUsage$ | async) !== undefined) {
@for (
licenseServer of licenseUsageWrapperService.licenseServerUsage$ | async;
track licenseServer.id
) {
@if (licenseServer.usage) {
<div
class="mt-2 flex items-center gap-2 rounded border p-2 text-sm shadow"
[class]="getLevel(licenseServer.usage)?.classes"
>
<mat-icon class="shrink-0">{{
getLevel(licenseServer.usage)?.icon
}}</mat-icon>
<span>{{ getLevel(licenseServer.usage)?.text }}</span>
</div>
}
}
}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { AsyncPipe, NgClass } from '@angular/common';
import { Component } from '@angular/core';
import { MatIcon } from '@angular/material/icon';
import { T4CLicenseServerUsage } from '../../openapi';
import { LicenseUsageWrapperService } from './license-usage.service';

@Component({
selector: 'app-license-indicator',
standalone: true,
imports: [MatIcon, AsyncPipe, NgClass],
templateUrl: './license-indicator.component.html',
})
export class LicenseIndicatorComponent {
constructor(public licenseUsageWrapperService: LicenseUsageWrapperService) {}

getLevel(usage: T4CLicenseServerUsage) {
const usagePercentage = (usage.total - usage.free) / usage.total;
return this.levels.find(
(level) => usagePercentage * 100 >= level.percentage,
);
}

levels = [
{
percentage: 100,
text: 'All TeamForCapella licenses are currently in use. You can start new sessions, but may encounter the error "Invalid license" when trying to use TeamForCapella. Please make sure to terminate your sessions after use.',
icon: 'error',
classes: 'bg-red-500 text-white',
},
{
percentage: 75,
text: 'Most TeamForCapella licenses are currently in use. Please make sure to terminate your sessions after use.',
icon: 'warning',
classes: 'bg-yellow-300',
},
{
percentage: 0,
text: 'TeamForCapella licenses are available. We do not expect any license issues in the session.',
icon: 'check_circle',
classes: '',
},
];
}
Loading

0 comments on commit 5cb85b9

Please sign in to comment.