Version 2.8.38: eine Rechnung fuer die Resttage, Module benannt
This commit is contained in:
1 parent
50b212caec
commit
68bda48d72
7 files changed
+53
-7
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm-license"
|
||||
version = "2.8.18"
|
||||
version = "2.8.19"
|
||||
description = "TESM-Lizenzserver -- Kunden, Tickets, Lizenzen, Aktivierung"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
@@ -779,6 +779,11 @@ def display_state(row: dict[str, Any], *, now: datetime | None = None) -> dict[s
|
||||
|
||||
Grenzen: mehr als 90 Tage = gruen, 30 bis 90 Tage = orange, unter 30 Tage
|
||||
(auch abgelaufen) = rot. Unbefristete Lizenzen sind immer gruen.
|
||||
|
||||
Gezaehlt wird in **angefangenen** Tagen (``lic.tage_bis``) -- dieselbe
|
||||
Rechnung, die auch der Client meldet. Die Vergleiche sind darauf
|
||||
abgestimmt: 90 volle Tage und eine Stunde sind "mehr als 90" und damit
|
||||
gruen, 29 Tage und eine Stunde sind "unter 30" und damit rot.
|
||||
"""
|
||||
moment = now or datetime.now(timezone.utc)
|
||||
result = {
|
||||
@@ -802,11 +807,18 @@ def display_state(row: dict[str, Any], *, now: datetime | None = None) -> dict[s
|
||||
return {**result, "color": "red"}
|
||||
|
||||
delta = expires - moment
|
||||
days_left = int(delta.total_seconds() // 86400)
|
||||
# Dieselbe Rechnung wie im Client -- nicht eine zweite daneben. Hier stand
|
||||
# eine abgerundete, und damit zeigte dieselbe Lizenz auf dieser Seite
|
||||
# "21 Tage", waehrend der Abruf beim Kunden "22" meldete.
|
||||
days_left = lic.tage_bis(expires, now=moment)
|
||||
expired = delta.total_seconds() <= 0
|
||||
if expired:
|
||||
color = "red"
|
||||
elif days_left < RED_BELOW_DAYS:
|
||||
elif days_left <= RED_BELOW_DAYS:
|
||||
# "<=", weil ``days_left`` **angefangene** Tage zaehlt: eine Lizenz mit
|
||||
# 29 Tagen und einer Stunde steht als 30 da und liegt trotzdem unter
|
||||
# der Schwelle von 30 vollen Tagen. Mit "<" waere sie orange -- die
|
||||
# Warnung kaeme einen Tag zu spaet, und zwar genau am kritischen Rand.
|
||||
color = "red"
|
||||
elif days_left <= GREEN_ABOVE_DAYS:
|
||||
color = "orange"
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm-core"
|
||||
version = "2.8.19"
|
||||
version = "2.8.20"
|
||||
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
@@ -193,7 +193,18 @@ def zustand_als_auskunft(state: "LicenseState") -> dict[str, Any]:
|
||||
"days_left": (status.days_left if status and not status.lifetime else None),
|
||||
"expiring_soon": bool(status.expiring_soon) if status else False,
|
||||
"grace_active": bool(status.grace_active) if status else False,
|
||||
"modules": sorted(state.modules_in_use),
|
||||
# Drei Angaben, weil zwei davon verschieden sein koennen und die
|
||||
# Verwechslung teuer ist: "modules" ist, was die **Lizenz** freigibt --
|
||||
# dieselbe Liste, die der Lizenzserver zeigt. Was davon vor Ort
|
||||
# abgeschaltet wurde, steht daneben.
|
||||
#
|
||||
# Vorher stand hier allein das Laufende. Beim Kunden fehlte darin
|
||||
# "dhcp", waehrend die Lizenzseite es auswies -- es war lediglich unter
|
||||
# Verwaltung -> System abgeschaltet. Aus der Antwort ging das nicht
|
||||
# hervor, und damit sah es nach einem Lizenzproblem aus.
|
||||
"modules": sorted(state.modules),
|
||||
"modules_active": sorted(state.modules_in_use),
|
||||
"modules_off": sorted(state.modules_off),
|
||||
"customer": state.customer_name,
|
||||
"last_heartbeat_at": state.last_heartbeat_at,
|
||||
"error": state.error,
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm-licensing"
|
||||
version = "2.7.7"
|
||||
version = "2.7.8"
|
||||
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = ["cryptography>=42"]
|
||||
|
||||
@@ -46,6 +46,7 @@ from .license import (
|
||||
key_id,
|
||||
license_status,
|
||||
parse_iso,
|
||||
tage_bis,
|
||||
split_bundle,
|
||||
utcnow,
|
||||
verify_license,
|
||||
@@ -103,6 +104,7 @@ __all__ = [
|
||||
"machine_identity",
|
||||
"new_nonce",
|
||||
"parse_iso",
|
||||
"tage_bis",
|
||||
"sign",
|
||||
"split_bundle",
|
||||
"system_fingerprint",
|
||||
|
||||
@@ -221,6 +221,27 @@ def verify_license(
|
||||
)
|
||||
|
||||
|
||||
def tage_bis(expires_at: datetime, *, now: datetime | None = None) -> int:
|
||||
"""Restlaufzeit in **angefangenen** Tagen.
|
||||
|
||||
Aufgerundet, und das ist eine Entscheidung: eine Lizenz, die in zwei
|
||||
Stunden ablaeuft, hat "1 Tag" und nicht "0". Null bedeutet hier
|
||||
ausschliesslich *abgelaufen* -- eine gueltige Lizenz, die mit "0 Tage"
|
||||
dasteht, liest sich wie eine tote.
|
||||
|
||||
**Es gibt genau diese eine Rechnung.** Der Lizenzserver hatte eine zweite,
|
||||
abgerundete: dieselbe Lizenz zeigte in seiner Oberflaeche "21 Tage" und im
|
||||
Abruf beim Kunden "22". Zwei Zahlen fuer dieselbe Frage sind schlimmer als
|
||||
eine ungenaue -- sie kosten jemanden einen Nachmittag mit der Suche nach
|
||||
einem Fehler, den es nicht gibt.
|
||||
"""
|
||||
moment = now or utcnow()
|
||||
sekunden = int((expires_at - moment).total_seconds())
|
||||
if sekunden <= 0:
|
||||
return 0
|
||||
return -(-sekunden // 86400)
|
||||
|
||||
|
||||
def license_status(
|
||||
document: Mapping[str, Any],
|
||||
*,
|
||||
@@ -278,7 +299,7 @@ def license_status(
|
||||
days_left = 0
|
||||
days_since_expiry = int((moment - expires_at).total_seconds() // 86400)
|
||||
else:
|
||||
days_left = -(-int(delta.total_seconds()) // 86400)
|
||||
days_left = tage_bis(expires_at, now=moment)
|
||||
days_since_expiry = None
|
||||
|
||||
grace_active = bool(
|
||||
|
||||
Reference in new issue
Block a user