Vlasnik izlazi iz DAL price za ovaj projekat - postaje samostalan proizvod. Preimenovanje je mehanicko (import putanje, imena fajlova/baze/UI naslova), NIJEDNA linija poslovne logike u internal/handler ili internal/service nije dirana - go build, go vet i go test ./... prolaze cisto pod novim imenom. - go.mod: module dal-license-server -> licence-server; 28 import linija u 13 .go fajlova usaglaseno - internal/config/config.go (+test): default DB_NAME licence_db - HTML sabloni (7 stranica) + 7 Playwright e2e spec fajlova: "DAL License Server" -> "Licence Server" u title/nav-brand, testovi usaglaseni u istom prolazu (nista ne moze da se razdvoji) - package.json/package-lock.json/.gitignore/.claude/project.json: ime projekta/binarnog fajla/work_dir - Usput: package.json je u repository.url nosio OTVORENU Gitea lozinku u cistom tekstu - uklonjena (URL sad bez kredencijala). Lozinka je i dalje u staroj git istoriji - preporuka: rotirati je posebno. - CLAUDE.md/README/API/TESTING/docs/SPEC/ARCHITECTURE/SETUP: naslovi, ASCII dijagrami, git clone URL, mysqldump primer, systemd predlozak u SETUP.md zamenjen stvarnim (obrazac terminia.service - journal log + graceful shutdown, ne stari minimalni predlozak) - Debrendiranje: "Univerzalni licencni server za sve DAL proizvode" -> "za vise proizvoda i klijenata"; potpis "Nenad Djukic / DAL d.o.o." -> "Nenad Djukic". NE dirano: nazivi ESIR/ARV/LIGHT_TICKET (tudji proizvodi, ne DAL brend), "DAL" kao stvaran naziv org-a u RBAC modelu (docs/loggerservice/README.md) - to je podatak, ne branding ovog servera. - docs/asp-terminia/, docs/loggerservice/: prozni pomeni imena servera Baza (dal_license_db -> licence_db) i deploy na 151 idu u posebnom koraku, posle preimenovanja Gitea repoa - vidi CLAUDE.md istorijsku belesku na dnu. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4.9 KiB
Licence Server — API Dokumentacija
Bazni URL: http://localhost:8090
Health
GET /api/v1/health
Provera da li server radi.
Response 200:
{"status": "ok"}
Klijentski API
Endpointi za klijentske aplikacije (ESIR, ARV, Light-Ticket). Bez autentifikacije, zastiteni rate limiting-om.
POST /api/v1/activate
Aktivacija licence na konkretnom racunaru.
Request:
{
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
"machine_fingerprint": "sha256:a1b2c3d4e5f6...",
"app_version": "1.0.0",
"os": "windows",
"hostname": "FIRMA-PC"
}
Response 200:
{
"license": {
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
"product": "LIGHT_TICKET",
"license_type": "MONTHLY",
"issued_at": "2026-03-01T00:00:00Z",
"expires_at": "2026-04-01T00:00:00Z",
"activated_at": "2026-03-03T10:00:00Z",
"machine_fingerprint": "sha256:a1b2c3d4e5f6...",
"grace_days": 30,
"limits": {
"max_operators": 3
},
"features": ["TICKET_VALIDATION", "REPORTS", "EXCEL_EXPORT", "LIVE_FEED"],
"customer": {
"name": "Firma DOO",
"email": "admin@firma.rs"
}
},
"signature": "RSA-SHA256:base64encodedSignature..."
}
Error kodovi:
| Kod | Opis |
|---|---|
| INVALID_KEY | Licencni kljuc ne postoji |
| ALREADY_ACTIVATED | Licenca vec aktivirana na drugom racunaru |
| KEY_EXPIRED | Licenca istekla |
| KEY_REVOKED | Licenca opozvana |
| PRODUCT_MISMATCH | Proizvod ne odgovara |
Error response 400:
{
"error": {
"code": "ALREADY_ACTIVATED",
"message": "Licenca je već aktivirana na drugom računaru",
"details": {
"activated_on": "DRUGA-PC",
"activated_at": "2026-02-15T08:00:00Z"
}
}
}
POST /api/v1/deactivate
Deaktivacija licence (za transfer na drugi racunar).
Request:
{
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
"machine_fingerprint": "sha256:a1b2c3d4e5f6..."
}
Response 200:
{
"message": "Licenca uspešno deaktivirana",
"can_reactivate": true
}
POST /api/v1/validate
Opciona online provera validnosti licence.
Request:
{
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
"machine_fingerprint": "sha256:a1b2c3d4e5f6..."
}
Response 200:
{
"valid": true,
"expires_at": "2026-04-01T00:00:00Z",
"revoked": false
}
Admin API
Svi admin endpointi zahtevaju X-API-Key header.
X-API-Key: vas-api-kljuc
GET /api/v1/admin/products
Lista svih proizvoda.
Response 200:
[
{
"id": 1,
"code": "ESIR",
"name": "ESIR Fiskalizacija",
"key_prefix": "ESIR-",
"default_limits": {"max_installations": 1},
"available_features": ["FISCALIZATION", "REPORTS"],
"active": true
}
]
GET /api/v1/admin/licenses
Lista licenci. Podrzava filter po proizvodu.
Query parametri:
product— Filter po product code (ESIR, ARV, LIGHT_TICKET)
Response 200:
[
{
"id": 1,
"product_code": "LIGHT_TICKET",
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
"license_type": "MONTHLY",
"customer_name": "Firma DOO",
"expires_at": "2026-04-01T00:00:00Z",
"active": true,
"revoked": false
}
]
POST /api/v1/admin/licenses
Kreiranje nove licence.
Request:
{
"product_code": "LIGHT_TICKET",
"license_type": "MONTHLY",
"customer_name": "Firma DOO",
"customer_pib": "123456789",
"customer_email": "admin@firma.rs",
"limits": {"max_operators": 10},
"features": ["TICKET_VALIDATION", "REPORTS", "EXCEL_EXPORT", "LIVE_FEED"],
"grace_days": 30,
"notes": "Pro paket"
}
Response 201:
{
"id": 1,
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
"message": "Licenca kreirana"
}
GET /api/v1/admin/licenses/{id}
Detalji jedne licence.
PUT /api/v1/admin/licenses/{id}
Izmena licence.
POST /api/v1/admin/licenses/{id}/revoke
Opozivanje licence.
Request:
{
"reason": "Klijent nije platio"
}
POST /api/v1/admin/licenses/{id}/release
Force release aktivacije (kada je racunar klijenta nedostupan).
GET /api/v1/admin/licenses/{id}/activations
Lista aktivacija za licencu.
GET /api/v1/admin/audit
Audit log. Lista svih akcija.
GET /api/v1/admin/stats
Statistike po proizvodima.
Dashboard rute (htmx)
| Metoda | Putanja | Opis |
|---|---|---|
| GET | /login | Login stranica |
| POST | /login | Login submit |
| POST | /logout | Logout |
| GET | /dashboard | Pocetna — statistike |
| GET | /licenses | Lista licenci |
| GET | /licenses/new | Forma za novu licencu |
| POST | /licenses | Kreiranje licence |
| GET | /licenses/{id} | Detalji licence |
| POST | /licenses/{id}/revoke | Opozivanje |
| POST | /licenses/{id}/release | Force release |
| GET | /audit | Audit log |
Rate limiting
| Endpoint | Limit |
|---|---|
| POST /api/v1/activate | 10 req/min per IP |
| POST /api/v1/deactivate | 10 req/min per IP |
| POST /api/v1/validate | 60 req/min per IP |
Mart 2026