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>
273 lines
4.9 KiB
Markdown
273 lines
4.9 KiB
Markdown
# Licence Server — API Dokumentacija
|
|
|
|
Bazni URL: `http://localhost:8090`
|
|
|
|
## Health
|
|
|
|
### GET /api/v1/health
|
|
|
|
Provera da li server radi.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{"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:**
|
|
```json
|
|
{
|
|
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
|
|
"machine_fingerprint": "sha256:a1b2c3d4e5f6...",
|
|
"app_version": "1.0.0",
|
|
"os": "windows",
|
|
"hostname": "FIRMA-PC"
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
|
|
"machine_fingerprint": "sha256:a1b2c3d4e5f6..."
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"message": "Licenca uspešno deaktivirana",
|
|
"can_reactivate": true
|
|
}
|
|
```
|
|
|
|
### POST /api/v1/validate
|
|
|
|
Opciona online provera validnosti licence.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"license_key": "LT-K7M2-9P4N-R3W8-J6T1",
|
|
"machine_fingerprint": "sha256:a1b2c3d4e5f6..."
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
[
|
|
{
|
|
"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:**
|
|
```json
|
|
[
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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*
|