Preimenovanje: dal-license-server -> licence-server (+ debrendiranje)

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>
This commit is contained in:
Nenad Djukic 2026-07-25 07:55:26 +02:00
parent 74d52e05c1
commit 1abe7176ec
46 changed files with 129 additions and 111 deletions

View File

@ -1,8 +1,8 @@
{ {
"name": "dal-license-server", "name": "licence-server",
"description": "Univerzalni licencni server za sve DAL proizvode (ESIR, ARV, Light-Ticket).", "description": "Univerzalni licencni server za vise proizvoda i klijenata (ESIR, ARV, Light-Ticket).",
"binary": "dal-license-server", "binary": "licence-server",
"start_cmd": "", "start_cmd": "",
"work_dir": "/root/projects/dal-license-server", "work_dir": "/root/projects/licence-server",
"ports": {} "ports": {}
} }

View File

@ -3,7 +3,7 @@ APP_ENV=development
DB_HOST=localhost DB_HOST=localhost
DB_PORT=3306 DB_PORT=3306
DB_NAME=dal_license_db DB_NAME=licence_db
DB_USER=license DB_USER=license
DB_PASS=OBAVEZNO-PROMENITI DB_PASS=OBAVEZNO-PROMENITI

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
.env .env
*.exe *.exe
dal-license-server licence-server
crypto/private.pem crypto/private.pem
log/*.log log/*.log
data/ data/

2
API.md
View File

@ -1,4 +1,4 @@
# DAL License Server — API Dokumentacija # Licence Server — API Dokumentacija
Bazni URL: `http://localhost:8090` Bazni URL: `http://localhost:8090`

View File

@ -1,14 +1,14 @@
# DAL License Server — CLAUDE.md # Licence Server — CLAUDE.md
## Pregled ## Pregled
Univerzalni licencni server za **sve DAL proizvode**: ESIR, ARV, Light-Ticket, i buduće aplikacije. Univerzalni licencni server za **ve proizvoda i klijenata**: ESIR, ARV, Light-Ticket, i buduće aplikacije.
Zamenjuje stari `esir-license-server` (koji niko ne koristi u produkciji). Arhitektura prema ARV licencnoj dokumentaciji (`/root/projects/arv/TASKS/Licenciranje-Starter.md`), ali univerzalna — podržava N proizvoda. Zamenjuje stari `esir-license-server` (koji niko ne koristi u produkciji). Arhitektura prema ARV licencnoj dokumentaciji (`/root/projects/arv/TASKS/Licenciranje-Starter.md`), ali univerzalna — podržava N proizvoda.
**Princip:** License Server je jedini koji ima RSA private key. Klijentske aplikacije imaju samo public key. Server potpisuje licence, klijenti verifikuju potpis. Niko osim servera ne može da kreira validnu licencu. **Princip:** Licence Server je jedini koji ima RSA private key. Klijentske aplikacije imaju samo public key. Server potpisuje licence, klijenti verifikuju potpis. Niko osim servera ne može da kreira validnu licencu.
**KRITIČNO — Testiranje:** Ova aplikacija je osnova budućeg poslovanja DAL-a. Mora biti **rigorozno testirana** svim poznatim tipovima testova: **KRITIČNO — Testiranje:** Ova aplikacija je osnova budućeg poslovanja. Mora biti **rigorozno testirana** svim poznatim tipovima testova:
- **Unit testovi** — svaki servis, model, helper, middleware - **Unit testovi** — svaki servis, model, helper, middleware
- **Integration testovi** — kompletni API flow-ovi (activate → validate → deactivate → re-activate) - **Integration testovi** — kompletni API flow-ovi (activate → validate → deactivate → re-activate)
- **Security testovi** — SQL injection, brute force, API key bypass, tampered signatures, invalid inputs - **Security testovi** — SQL injection, brute force, API key bypass, tampered signatures, invalid inputs
@ -23,7 +23,7 @@ Zamenjuje stari `esir-license-server` (koji niko ne koristi u produkciji). Arhit
``` ```
┌─────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────┐
DAL LICENSE SERVER LICENCE SERVER
│ port: 8090 │ │ port: 8090 │
│ │ │ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
@ -114,7 +114,7 @@ Jednom dnevno (ako ima internet):
## Go struktura projekta ## Go struktura projekta
``` ```
dal-license-server/ licence-server/
├── cmd/ ├── cmd/
│ └── server/ │ └── server/
│ └── main.go │ └── main.go
@ -496,7 +496,7 @@ Primeri:
Pošto stari server niko ne koristi u produkciji, migracija je jednostavna: Pošto stari server niko ne koristi u produkciji, migracija je jednostavna:
1. Kreiraj novi `dal-license-server` projekat 1. Kreiraj novi `licence-server` projekat
2. Kopiraj korisnu logiku iz `esir-license-server` (keygen, verify flow, helpers) 2. Kopiraj korisnu logiku iz `esir-license-server` (keygen, verify flow, helpers)
3. Proširi model (product, features, limits, RSA) 3. Proširi model (product, features, limits, RSA)
4. Zameni port 8090 (isti port, drop-in replacement) 4. Zameni port 8090 (isti port, drop-in replacement)
@ -578,7 +578,7 @@ APP_ENV=development
# MySQL # MySQL
DB_HOST=localhost DB_HOST=localhost
DB_PORT=3306 DB_PORT=3306
DB_NAME=dal_license_db DB_NAME=licence_db
DB_USER=license DB_USER=license
DB_PASS=OBAVEZNO-PROMENITI DB_PASS=OBAVEZNO-PROMENITI
@ -632,7 +632,7 @@ LOG_FILE=./log/server.log
### Implementirano ### Implementirano
- ✅ Go projekat inicijalizovan (go.mod, go.sum) - ✅ Go projekat inicijalizovan (go.mod, go.sum)
- ✅ MySQL baza `dal_license_db` kreirana, user `license` - ✅ MySQL baza `licence_db` kreirana, user `license`
- ✅ Migracije (001_create_tables.sql, 002_seed_products.sql) - ✅ Migracije (001_create_tables.sql, 002_seed_products.sql)
- ✅ RSA-2048 ključevi generisani (crypto/private.pem, crypto/public.pem) - ✅ RSA-2048 ključevi generisani (crypto/private.pem, crypto/public.pem)
- ✅ Seed podaci: 3 proizvoda (ESIR, ARV, LIGHT_TICKET) - ✅ Seed podaci: 3 proizvoda (ESIR, ARV, LIGHT_TICKET)
@ -695,7 +695,7 @@ crypto/public.pem — RSA javni ključ
``` ```
APP_PORT=8090 APP_PORT=8090
DB_HOST=localhost / DB_PORT=3306 DB_HOST=localhost / DB_PORT=3306
DB_NAME=dal_license_db DB_NAME=licence_db
DB_USER=license / DB_PASS=license_pass_2026 DB_USER=license / DB_PASS=license_pass_2026
ADMIN_API_KEY=dal-admin-key-2026-supersecret-change-me ADMIN_API_KEY=dal-admin-key-2026-supersecret-change-me
ADMIN_PASSWORD=DalAdmin2026! ADMIN_PASSWORD=DalAdmin2026!
@ -790,4 +790,6 @@ sudare; `devices.license_id` referencira licencu iz tog paketa.
*Kreirano: mart 2026* *Kreirano: mart 2026*
*Ažurirano: 04.03.2026 — Kompletna implementacija, 22/22 testova* *Ažurirano: 04.03.2026 — Kompletna implementacija, 22/22 testova*
*Autor: Nenad Đukić / DAL d.o.o.* *Autor: Nenad Đukić*
*Preimenovano 2026-07-25: dal-license-server → licence-server (samostalan
proizvod, izlazi iz DAL priče); baza `dal_license_db``licence_db`.*

View File

@ -1,6 +1,6 @@
# DAL License Server # Licence Server
Univerzalni licencni server za sve DAL proizvode (ESIR, ARV, Light-Ticket). Univerzalni licencni server za ve proizvoda i klijenata (ESIR, ARV, Light-Ticket).
## Funkcionalnosti ## Funkcionalnosti
@ -27,9 +27,9 @@ cp .env.example .env
# Uredi .env sa pravim vrednostima # Uredi .env sa pravim vrednostima
# 2. Kreiraj MySQL bazu # 2. Kreiraj MySQL bazu
mysql -u root -e "CREATE DATABASE dal_license_db CHARACTER SET utf8mb4;" mysql -u root -e "CREATE DATABASE licence_db CHARACTER SET utf8mb4;"
mysql -u root -e "CREATE USER 'license'@'localhost' IDENTIFIED BY 'TVOJA_LOZINKA';" mysql -u root -e "CREATE USER 'license'@'localhost' IDENTIFIED BY 'TVOJA_LOZINKA';"
mysql -u root -e "GRANT ALL ON dal_license_db.* TO 'license'@'localhost';" mysql -u root -e "GRANT ALL ON licence_db.* TO 'license'@'localhost';"
# 3. Generiši RSA ključeve (ako ne postoje) # 3. Generiši RSA ključeve (ako ne postoje)
openssl genrsa -out crypto/private.pem 2048 openssl genrsa -out crypto/private.pem 2048
@ -55,4 +55,4 @@ Server radi na portu **8090** (konfigurisano u `.env`).
--- ---
*DAL d.o.o. | Mart 2026* *Nenad Đukić | Mart 2026*

View File

@ -1,4 +1,4 @@
# DAL License Server — Test Checklista # Licence Server — Test Checklista
## Ukupno testova: 182 ## Ukupno testova: 182
- Go unit testovi: 46 - Go unit testovi: 46

View File

@ -1,12 +1,12 @@
package main package main
import ( import (
"dal-license-server/internal/config" "licence-server/internal/config"
"dal-license-server/internal/handler" "licence-server/internal/handler"
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/repository" "licence-server/internal/repository"
"dal-license-server/internal/router" "licence-server/internal/router"
"dal-license-server/internal/service" "licence-server/internal/service"
"database/sql" "database/sql"
"fmt" "fmt"
"log" "log"

View File

@ -1,10 +1,10 @@
# DAL License Server — Arhitektura # Licence Server — Arhitektura
## Dijagram sistema ## Dijagram sistema
``` ```
┌─────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────┐
DAL LICENSE SERVER LICENCE SERVER
│ port: 8090 │ │ port: 8090 │
│ │ │ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
@ -16,7 +16,7 @@
│ │ │ │ │ │
│ ┌────────┴────────┐ │ │ ┌────────┴────────┐ │
│ │ MySQL baza │ │ │ │ MySQL baza │ │
│ │ dal_license_db │ │ │ │ licence_db │ │
│ └─────────────────┘ │ │ └─────────────────┘ │
│ │ │ │
│ RSA-2048 Private Key (samo ovde, nikad ne izlazi) │ │ RSA-2048 Private Key (samo ovde, nikad ne izlazi) │
@ -33,7 +33,7 @@
## Struktura projekta ## Struktura projekta
``` ```
dal-license-server/ licence-server/
├── cmd/server/main.go — Entry point, MySQL konekcija, migracije ├── cmd/server/main.go — Entry point, MySQL konekcija, migracije
├── internal/ ├── internal/
│ ├── config/config.go — .env loading, DSN builder │ ├── config/config.go — .env loading, DSN builder

View File

@ -1,4 +1,4 @@
# DAL License Server — Setup i Deployment # Licence Server — Setup i Deployment
## Preduslovi ## Preduslovi
@ -12,8 +12,8 @@
```bash ```bash
cd /root/projects cd /root/projects
git clone http://localhost:3000/dal/dal-license-server.git git clone https://git.terminia.net/djuka/licence-server.git
cd dal-license-server cd licence-server
``` ```
### 2. Instaliraj Go zavisnosti ### 2. Instaliraj Go zavisnosti
@ -25,9 +25,9 @@ go mod download
### 3. Kreiraj MySQL bazu ### 3. Kreiraj MySQL bazu
```sql ```sql
CREATE DATABASE dal_license_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE licence_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'license'@'localhost' IDENTIFIED BY 'TVOJA_LOZINKA'; CREATE USER 'license'@'localhost' IDENTIFIED BY 'TVOJA_LOZINKA';
GRANT ALL PRIVILEGES ON dal_license_db.* TO 'license'@'localhost'; GRANT ALL PRIVILEGES ON licence_db.* TO 'license'@'localhost';
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
``` ```
@ -56,7 +56,7 @@ APP_ENV=production
DB_HOST=localhost DB_HOST=localhost
DB_PORT=3306 DB_PORT=3306
DB_NAME=dal_license_db DB_NAME=licence_db
DB_USER=license DB_USER=license
DB_PASS=tvoja_lozinka DB_PASS=tvoja_lozinka
@ -85,26 +85,34 @@ Server se pokrece na `http://localhost:8090`. Migracije se izvrsavaju automatski
### Build ### Build
```bash ```bash
go build -o dal-license-server cmd/server/main.go go build -o licence-server cmd/server/main.go
``` ```
### Systemd servis ### Systemd servis
Kreiraj `/etc/systemd/system/dal-license-server.service`: Kreiraj `/etc/systemd/system/licence-server.service` (obrazac po `terminia.service`
na 151 — journal log + graceful shutdown, ne stariji minimalni predložak):
```ini ```ini
[Unit] [Unit]
Description=DAL License Server Description=Licence Server
After=network.target mysql.service After=network.target mysql.service
Wants=mysql.service
[Service] [Service]
Type=simple Type=simple
User=root User=root
WorkingDirectory=/root/projects/dal-license-server WorkingDirectory=/root/projects/licence-server
ExecStart=/root/projects/dal-license-server/dal-license-server ExecStart=/root/projects/licence-server/licence-server
EnvironmentFile=/root/projects/licence-server/.env
Restart=always Restart=always
RestartSec=5 RestartSec=5
EnvironmentFile=/root/projects/dal-license-server/.env StandardOutput=journal
StandardError=journal
SyslogIdentifier=licence-server
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=15
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
@ -112,18 +120,26 @@ WantedBy=multi-user.target
```bash ```bash
systemctl daemon-reload systemctl daemon-reload
systemctl enable dal-license-server systemctl enable --now licence-server
systemctl start dal-license-server journalctl -u licence-server -f
``` ```
### HTTPS (reverse proxy) ### HTTPS (reverse proxy)
Preporuceno: Caddy ili Nginx kao reverse proxy sa TLS: Nginx kao reverse proxy sa TLS (Let's Encrypt/Certbot) — primer sa produkcije:
``` ```
# Caddy primer # licenca.terminia.net -> licence-server (127.0.0.1:8090)
license.dal.rs { server {
reverse_proxy localhost:8090 server_name licenca.terminia.net;
location / {
proxy_pass http://127.0.0.1:8090/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
listen 443 ssl; # managed by Certbot
} }
``` ```
@ -132,7 +148,7 @@ license.dal.rs {
### MySQL backup ### MySQL backup
```bash ```bash
mysqldump -u license -p dal_license_db > backup_$(date +%Y%m%d).sql mysqldump -u license -p licence_db > backup_$(date +%Y%m%d).sql
``` ```
### RSA kljucevi ### RSA kljucevi

View File

@ -1,8 +1,8 @@
# DAL License Server — Specifikacija # Licence Server — Specifikacija
## Cilj ## Cilj
Univerzalni licencni server koji zamenjuje stari `esir-license-server` i podržava sve DAL proizvode: ESIR, ARV, Light-Ticket, i buduće aplikacije. Univerzalni licencni server koji zamenjuje stari `esir-license-server` i podržava više proizvoda: ESIR, ARV, Light-Ticket, i buduće aplikacije.
## Principi ## Principi

View File

@ -10,9 +10,9 @@
- Gitea; - Gitea;
- ESIR backend (fiskalizacija). - ESIR backend (fiskalizacija).
## 2. `dal-license-server` (naš deo) ## 2. `licence-server` (naš deo)
- **Kod:** `/root/projects/dal-license-server` — Go, bez frameworka, MySQL. - **Kod:** `/root/projects/licence-server` — Go, bez frameworka, MySQL.
- **Port:** 8090 lokalno; javno preko nginx sajta **`arv`**. - **Port:** 8090 lokalno; javno preko nginx sajta **`arv`**.
- **Javni URL (ovo firmware već koristi):** `https://157.180.119.151/license/api/v1/` - **Javni URL (ovo firmware već koristi):** `https://157.180.119.151/license/api/v1/`
- HTTPS 443, cert `/etc/nginx/ssl/arv.crt`, `server_name` = IP → **self-signed** - HTTPS 443, cert `/etc/nginx/ssl/arv.crt`, `server_name` = IP → **self-signed**

View File

@ -1,7 +1,7 @@
# ASP-Terminia — licenciranje (radni paket) # ASP-Terminia — licenciranje (radni paket)
> **Misija:** dovesti licenciranje ASPTerminia terminala do produkcije na > **Misija:** dovesti licenciranje ASPTerminia terminala do produkcije na
> postojećem `dal-license-server`-u (server 151), bez lomljenja ijednog > postojećem `licence-server`-u (server 151), bez lomljenja ijednog
> postojećeg klijenta (ESIR/ARV/LIGHT_TICKET su ŽIVI u produkciji). > postojećeg klijenta (ESIR/ARV/LIGHT_TICKET su ŽIVI u produkciji).
> >
> **Jezik projekta:** srpski (ekavica), latinica. Kod/komentari na serveru su Go — > **Jezik projekta:** srpski (ekavica), latinica. Kod/komentari na serveru su Go —
@ -27,7 +27,7 @@
1. **Šta se licencira:** ESP32S3 terminal za kontrolu prolaza (bazeni/spa), proizvod 1. **Šta se licencira:** ESP32S3 terminal za kontrolu prolaza (bazeni/spa), proizvod
**„ASPTerminia"** (Autonomni Sistem Prolaza). Licenca je vezana za **MAC** čipa **„ASPTerminia"** (Autonomni Sistem Prolaza). Licenca je vezana za **MAC** čipa
(eFuse, nepromenljiv) preko `machine_fingerprint`. (eFuse, nepromenljiv) preko `machine_fingerprint`.
2. **Server već postoji:** `dal-license-server` (Go, MySQL, RSA2048/SHA256) na 2. **Server već postoji:** `licence-server` (Go, MySQL, RSA2048/SHA256) na
`157.180.119.151`, u produkciji sa 3 proizvoda / ~140 licenci / ~19 aktivacija. `157.180.119.151`, u produkciji sa 3 proizvoda / ~140 licenci / ~19 aktivacija.
3. **Firmware klijent je GOTOV** (modul `licenca.h/.cpp` u firmveru, od verzije 0.10.0): 3. **Firmware klijent je GOTOV** (modul `licenca.h/.cpp` u firmveru, od verzije 0.10.0):
aktivacija, offline verifikacija potpisa javnim ključem, UI. Čeka samo proizvod aktivacija, offline verifikacija potpisa javnim ključem, UI. Čeka samo proizvod

View File

@ -31,7 +31,7 @@ Za sada **najosnovnije**, sa dve tvrde odrednice od vlasnika:
parking, garderoba…) — modul zna koji proizvod/verzija ide na koji uređaj i parking, garderoba…) — modul zna koji proizvod/verzija ide na koji uređaj i
omogućava podešavanje/dodelu FW (naslanja se na katalog `fw.terminia.net`, omogućava podešavanje/dodelu FW (naslanja se na katalog `fw.terminia.net`,
vidi `03-provisioning-i-fw-katalog.md`). vidi `03-provisioning-i-fw-katalog.md`).
2. **Direktno vezan za licencni server** (`dal-license-server`): modul 2. **Direktno vezan za licencni server** (`licence-server`): modul
komunicira sa njim (proizvodi, licence po MAC-u, entitlements) — NE gradi komunicira sa njim (proizvodi, licence po MAC-u, entitlements) — NE gradi
svoju paralelnu evidenciju licenci. Vidi paket [`docs/asp-terminia/`](../asp-terminia/README.md). svoju paralelnu evidenciju licenci. Vidi paket [`docs/asp-terminia/`](../asp-terminia/README.md).

View File

@ -1,7 +1,7 @@
# Pravila rada — PROČITATI PRE PRVOG SSH-a # Pravila rada — PROČITATI PRE PRVOG SSH-a
> Server 151 (`157.180.119.151`, SSH `root@`, ključ `~/.ssh/id_ed25519`) je > Server 151 (`157.180.119.151`, SSH `root@`, ključ `~/.ssh/id_ed25519`) je
> **PRODUKCIJA**: dal-license-server (3 proizvoda, ~140 licenci), terminia SaaS > **PRODUKCIJA**: licence-server (3 proizvoda, ~140 licenci), terminia SaaS
> (8091/8092), ESIR, Gitea. Greška košta prave korisnike. > (8091/8092), ESIR, Gitea. Greška košta prave korisnike.
## Tvrda pravila (identična paketu [`docs/asp-terminia/04-pravila-rada.md`](../asp-terminia/04-pravila-rada.md)) ## Tvrda pravila (identična paketu [`docs/asp-terminia/04-pravila-rada.md`](../asp-terminia/04-pravila-rada.md))

View File

@ -2,7 +2,7 @@
> **Misija:** izgraditi serversku kontrolnu ravan za flote terminala — RBAC stablo > **Misija:** izgraditi serversku kontrolnu ravan za flote terminala — RBAC stablo
> organizacija, uređaji + heartbeat, servisni grantovi, provisioning i katalog > organizacija, uređaji + heartbeat, servisni grantovi, provisioning i katalog
> firmvera — kao **proširenje postojećeg `dal-license-server`-a** (server 151). > firmvera — kao **proširenje postojećeg `licence-server`-a** (server 151).
> Jedan backend, **dva lica**: `terminia.net` = vendor (licence/fw), > Jedan backend, **dva lica**: `terminia.net` = vendor (licence/fw),
> **`loggerservice.com` = serviserski brend** (isti mozak, drugi izgled). > **`loggerservice.com` = serviserski brend** (isti mozak, drugi izgled).
> >
@ -34,7 +34,7 @@
**DAL = KUPAC** (org pod Terminijom) — ne vendor. **DAL = KUPAC** (org pod Terminijom) — ne vendor.
3. **Serviseri NISU nivo u stablu** nego **grant preko stabla** (razdvaja 3. **Serviseri NISU nivo u stablu** nego **grant preko stabla** (razdvaja
vlasništvo od servisnog pristupa) — detalji u 01. vlasništvo od servisnog pristupa) — detalji u 01.
4. **Server:** isti `dal-license-server` (Go/MySQL, produkcija!) — RBAC se DODAJE 4. **Server:** isti `licence-server` (Go/MySQL, produkcija!) — RBAC se DODAJE
migracijama; koordinacija sa paketom [`docs/asp-terminia/`](../asp-terminia/README.md) (deli bazu i admin sloj). migracijama; koordinacija sa paketom [`docs/asp-terminia/`](../asp-terminia/README.md) (deli bazu i admin sloj).
5. **Uređaj već emituje:** LAN discovery (UDP 46464, upit `TERMINIA?` → JSON 5. **Uređaj već emituje:** LAN discovery (UDP 46464, upit `TERMINIA?` → JSON
identitet), heartbeat (UDP JSON na podesiv interval), dbg dnevnik (UDP) — identitet), heartbeat (UDP JSON na podesiv interval), dbg dnevnik (UDP) —

2
go.mod
View File

@ -1,4 +1,4 @@
module dal-license-server module licence-server
go 1.24.0 go 1.24.0

View File

@ -31,7 +31,7 @@ func Load() *Config {
Env: getEnv("APP_ENV", "development"), Env: getEnv("APP_ENV", "development"),
DBHost: getEnv("DB_HOST", "localhost"), DBHost: getEnv("DB_HOST", "localhost"),
DBPort: getEnv("DB_PORT", "3306"), DBPort: getEnv("DB_PORT", "3306"),
DBName: getEnv("DB_NAME", "dal_license_db"), DBName: getEnv("DB_NAME", "licence_db"),
DBUser: getEnv("DB_USER", "license"), DBUser: getEnv("DB_USER", "license"),
DBPass: getEnv("DB_PASS", ""), DBPass: getEnv("DB_PASS", ""),
AdminAPIKey: getEnv("ADMIN_API_KEY", ""), AdminAPIKey: getEnv("ADMIN_API_KEY", ""),

View File

@ -38,8 +38,8 @@ func TestLoad_Defaults(t *testing.T) {
if cfg.DBPort != "3306" { if cfg.DBPort != "3306" {
t.Errorf("DBPort default: ocekivano '3306', dobijeno %q", cfg.DBPort) t.Errorf("DBPort default: ocekivano '3306', dobijeno %q", cfg.DBPort)
} }
if cfg.DBName != "dal_license_db" { if cfg.DBName != "licence_db" {
t.Errorf("DBName default: ocekivano 'dal_license_db', dobijeno %q", cfg.DBName) t.Errorf("DBName default: ocekivano 'licence_db', dobijeno %q", cfg.DBName)
} }
if cfg.DBUser != "license" { if cfg.DBUser != "license" {
t.Errorf("DBUser default: ocekivano 'license', dobijeno %q", cfg.DBUser) t.Errorf("DBUser default: ocekivano 'license', dobijeno %q", cfg.DBUser)

View File

@ -1,9 +1,9 @@
package handler package handler
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/repository" "licence-server/internal/repository"
"dal-license-server/internal/service" "licence-server/internal/service"
"encoding/json" "encoding/json"
"net/http" "net/http"
"strconv" "strconv"

View File

@ -1,8 +1,8 @@
package handler package handler
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/service" "licence-server/internal/service"
"encoding/json" "encoding/json"
"net/http" "net/http"
) )

View File

@ -2,9 +2,9 @@ package handler
import ( import (
"crypto/rand" "crypto/rand"
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/repository" "licence-server/internal/repository"
"dal-license-server/internal/service" "licence-server/internal/service"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"html/template" "html/template"

View File

@ -1,8 +1,8 @@
package handler package handler
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/service" "licence-server/internal/service"
"encoding/json" "encoding/json"
"net/http" "net/http"
) )

View File

@ -1,8 +1,8 @@
package handler package handler
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/service" "licence-server/internal/service"
"encoding/json" "encoding/json"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"

View File

@ -1,7 +1,7 @@
package repository package repository
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"database/sql" "database/sql"
"fmt" "fmt"
) )

View File

@ -1,7 +1,7 @@
package repository package repository
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
package repository package repository
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"database/sql" "database/sql"
"fmt" "fmt"
) )

View File

@ -1,7 +1,7 @@
package repository package repository
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"database/sql" "database/sql"
"fmt" "fmt"
) )

View File

@ -1,8 +1,8 @@
package router package router
import ( import (
"dal-license-server/internal/handler" "licence-server/internal/handler"
"dal-license-server/internal/middleware" "licence-server/internal/middleware"
"net/http" "net/http"
"strconv" "strconv"
) )

View File

@ -1,8 +1,8 @@
package service package service
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/repository" "licence-server/internal/repository"
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"

View File

@ -1,8 +1,8 @@
package service package service
import ( import (
"dal-license-server/internal/model" "licence-server/internal/model"
"dal-license-server/internal/repository" "licence-server/internal/repository"
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"

4
package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "dal-license-server", "name": "licence-server",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "dal-license-server", "name": "licence-server",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {

View File

@ -1,7 +1,7 @@
{ {
"name": "dal-license-server", "name": "licence-server",
"version": "1.0.0", "version": "1.0.0",
"description": "Univerzalni licencni server za sve DAL proizvode (ESIR, ARV, Light-Ticket).", "description": "Univerzalni licencni server za vise proizvoda i klijenata (ESIR, ARV, Light-Ticket).",
"main": "index.js", "main": "index.js",
"directories": { "directories": {
"doc": "docs" "doc": "docs"
@ -11,7 +11,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "http://djuka:dzabulan1@localhost:3000/djuka/dal-license-server.git" "url": "https://git.terminia.net/djuka/licence-server.git"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",

View File

@ -3,14 +3,14 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{block "page-title" .}}DAL License Server{{end}}</title> <title>{{block "page-title" .}}Licence Server{{end}}</title>
<link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg"> <link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg">
<link rel="stylesheet" href="/static/css/style.css"> <link rel="stylesheet" href="/static/css/style.css">
<script src="/static/js/htmx.min.js"></script> <script src="/static/js/htmx.min.js"></script>
</head> </head>
<body> <body>
<nav class="navbar"> <nav class="navbar">
<div class="nav-brand"><img src="/static/img/logo.svg" alt="" class="nav-logo">DAL License Server</div> <div class="nav-brand"><img src="/static/img/logo.svg" alt="" class="nav-logo">Licence Server</div>
<div class="nav-links"> <div class="nav-links">
<a href="/dashboard" class="{{if eq .ActivePage "dashboard"}}active{{end}}">Dashboard</a> <a href="/dashboard" class="{{if eq .ActivePage "dashboard"}}active{{end}}">Dashboard</a>
<a href="/licenses" class="{{if eq .ActivePage "licenses"}}active{{end}}">Licence</a> <a href="/licenses" class="{{if eq .ActivePage "licenses"}}active{{end}}">Licence</a>

View File

@ -1,5 +1,5 @@
{{define "audit.html"}}{{template "app" .}}{{end}} {{define "audit.html"}}{{template "app" .}}{{end}}
{{define "page-title"}}Audit Log - DAL License Server{{end}} {{define "page-title"}}Audit Log - Licence Server{{end}}
{{define "page-content"}} {{define "page-content"}}
<h1>Audit Log</h1> <h1>Audit Log</h1>

View File

@ -1,5 +1,5 @@
{{define "dashboard.html"}}{{template "app" .}}{{end}} {{define "dashboard.html"}}{{template "app" .}}{{end}}
{{define "page-title"}}Dashboard - DAL License Server{{end}} {{define "page-title"}}Dashboard - Licence Server{{end}}
{{define "page-content"}} {{define "page-content"}}
<h1>Dashboard</h1> <h1>Dashboard</h1>

View File

@ -1,5 +1,5 @@
{{define "license-detail.html"}}{{template "app" .}}{{end}} {{define "license-detail.html"}}{{template "app" .}}{{end}}
{{define "page-title"}}Licenca {{.License.LicenseKey}} - DAL License Server{{end}} {{define "page-title"}}Licenca {{.License.LicenseKey}} - Licence Server{{end}}
{{define "page-content"}} {{define "page-content"}}
<div class="page-header"> <div class="page-header">
<h1>Licenca: <code>{{.License.LicenseKey}}</code></h1> <h1>Licenca: <code>{{.License.LicenseKey}}</code></h1>

View File

@ -1,5 +1,5 @@
{{define "license-new.html"}}{{template "app" .}}{{end}} {{define "license-new.html"}}{{template "app" .}}{{end}}
{{define "page-title"}}Nova licenca - DAL License Server{{end}} {{define "page-title"}}Nova licenca - Licence Server{{end}}
{{define "page-content"}} {{define "page-content"}}
<h1>Nova licenca</h1> <h1>Nova licenca</h1>

View File

@ -1,5 +1,5 @@
{{define "licenses.html"}}{{template "app" .}}{{end}} {{define "licenses.html"}}{{template "app" .}}{{end}}
{{define "page-title"}}Licence - DAL License Server{{end}} {{define "page-title"}}Licence - Licence Server{{end}}
{{define "page-content"}} {{define "page-content"}}
<div class="page-header"> <div class="page-header">
<h1>Licence</h1> <h1>Licence</h1>

View File

@ -3,13 +3,13 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prijava - DAL License Server</title> <title>Prijava - Licence Server</title>
<link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg"> <link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg">
<link rel="stylesheet" href="/static/css/style.css"> <link rel="stylesheet" href="/static/css/style.css">
</head> </head>
<body> <body>
<div class="login-container"> <div class="login-container">
<h1><img src="/static/img/logo.svg" alt="" class="login-logo">DAL License Server</h1> <h1><img src="/static/img/logo.svg" alt="" class="login-logo">Licence Server</h1>
<form method="POST" action="/login" class="login-form"> <form method="POST" action="/login" class="login-form">
{{if .Error}}<div class="alert alert-error">{{.Error}}</div>{{end}} {{if .Error}}<div class="alert alert-error">{{.Error}}</div>{{end}}
<div class="form-group"> <div class="form-group">

View File

@ -23,7 +23,7 @@ test.describe('Audit Log stranica', () => {
test('ima ispravan title', async ({ page }) => { test('ima ispravan title', async ({ page }) => {
await page.goto('/audit'); await page.goto('/audit');
await expect(page).toHaveTitle('Audit Log - DAL License Server'); await expect(page).toHaveTitle('Audit Log - Licence Server');
}); });
test('prikazuje tabelu', async ({ page }) => { test('prikazuje tabelu', async ({ page }) => {

View File

@ -59,7 +59,7 @@ test.describe('Dashboard stranica', () => {
}); });
test('navbar prikazuje brend', async ({ page }) => { test('navbar prikazuje brend', async ({ page }) => {
await expect(page.locator('.nav-brand')).toHaveText('DAL License Server'); await expect(page.locator('.nav-brand')).toHaveText('Licence Server');
}); });
test('navbar ima link na dashboard (aktivan)', async ({ page }) => { test('navbar ima link na dashboard (aktivan)', async ({ page }) => {
@ -109,7 +109,7 @@ test.describe('Dashboard stranica', () => {
}); });
test('dashboard ima ispravan title', async ({ page }) => { test('dashboard ima ispravan title', async ({ page }) => {
await expect(page).toHaveTitle('Dashboard - DAL License Server'); await expect(page).toHaveTitle('Dashboard - Licence Server');
}); });
test('htmx je ucitan', async ({ page }) => { test('htmx je ucitan', async ({ page }) => {

View File

@ -32,7 +32,7 @@ test.describe('Forma za novu licencu', () => {
}); });
test('ima ispravan title', async ({ page }) => { test('ima ispravan title', async ({ page }) => {
await expect(page).toHaveTitle('Nova licenca - DAL License Server'); await expect(page).toHaveTitle('Nova licenca - Licence Server');
}); });
test('prikazuje sva polja forme', async ({ page }) => { test('prikazuje sva polja forme', async ({ page }) => {

View File

@ -88,7 +88,7 @@ test.describe('Detalji licence — informacije', () => {
await createLicense(page, 'Title Check'); await createLicense(page, 'Title Check');
const title = await page.title(); const title = await page.title();
expect(title).toContain('LT-'); expect(title).toContain('LT-');
expect(title).toContain('DAL License Server'); expect(title).toContain('Licence Server');
}); });
}); });

View File

@ -20,7 +20,7 @@ test.describe('Lista licenci — stranica', () => {
test('ima ispravan title', async ({ page }) => { test('ima ispravan title', async ({ page }) => {
await page.goto('/licenses'); await page.goto('/licenses');
await expect(page).toHaveTitle('Licence - DAL License Server'); await expect(page).toHaveTitle('Licence - Licence Server');
}); });
test('prikazuje tabelu sa ispravnim kolonama', async ({ page }) => { test('prikazuje tabelu sa ispravnim kolonama', async ({ page }) => {

View File

@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test';
test.describe('Login stranica', () => { test.describe('Login stranica', () => {
test('prikazuje login formu sa svim elementima', async ({ page }) => { test('prikazuje login formu sa svim elementima', async ({ page }) => {
await page.goto('/login'); await page.goto('/login');
await expect(page.locator('h1')).toHaveText('DAL License Server'); await expect(page.locator('h1')).toHaveText('Licence Server');
await expect(page.locator('input[name="username"]')).toBeVisible(); await expect(page.locator('input[name="username"]')).toBeVisible();
await expect(page.locator('input[name="username"]')).toHaveAttribute('required', ''); await expect(page.locator('input[name="username"]')).toHaveAttribute('required', '');
await expect(page.locator('input[name="password"]')).toBeVisible(); await expect(page.locator('input[name="password"]')).toBeVisible();
@ -105,7 +105,7 @@ test.describe('Login stranica', () => {
test('login stranica ima ispravan title', async ({ page }) => { test('login stranica ima ispravan title', async ({ page }) => {
await page.goto('/login'); await page.goto('/login');
await expect(page).toHaveTitle('Prijava - DAL License Server'); await expect(page).toHaveTitle('Prijava - Licence Server');
}); });
test('visestruki logini kreiraju razlicite sesije', async ({ page, context }) => { test('visestruki logini kreiraju razlicite sesije', async ({ page, context }) => {