Sari la conținut

DB Schema — GStorage (v1)

Acest conținut nu este încă disponibil în limba selectată.

Schema derivată din ../gstorage.jdl pentru verificare manuală înainte de jhipster jdl ../gstorage.jdl --force.

Tipuri de date: PostgreSQL (profil prod). H2 (dev) folosește mapări echivalente generate de Liquibase. Toate tabelele moștenesc 4 câmpuri de audit de la AbstractAuditingEntity (created_by, created_date, last_modified_by, last_modified_date — omise din DDL-urile de mai jos, vezi §6). Numele coloanelor sunt snake_case (convenția JHipster); enum-urile se stochează ca varchar (numele constantei).

Toate tabelele aparțin microserviciului gstorage (schema proprie de DB). Binarele nu se stochează în DB — trăiesc în object-store (MinIO/S3); obiect_stocat ține doar metadatele + cheia.

erDiagram
BUCKET ||--o{ OBIECT_STOCAT : "conține"
BUCKET ||--o{ SESIUNE_TRANSFER : ""
OBIECT_STOCAT ||--o{ SESIUNE_TRANSFER : "→ obiect rezultat"
ORGANIZATIE ||--o{ DATASET : "deține"
DATASET ||--o{ RESURSA : "are resurse"
OBIECT_STOCAT ||--o{ RESURSA : "referă blob"
DATASET }o--o{ GRUP : "clasificat în"
GRUP ||--o{ GRUP : "parinte"
ORGANIZATIE ||--o{ API_CLIENT : ""
BUCKET ||--o{ API_CLIENT : "restricționat la"
ORGANIZATIE ||--o{ APP_USER : "membru"
APP_USER ||--o{ PERMISIUNE : "beneficiar"
API_CLIENT ||--o{ PERMISIUNE : "beneficiar mașină"
BUCKET ||--o{ PERMISIUNE : "resursă"
DATASET ||--o{ PERMISIUNE : "resursă"
ORGANIZATIE ||--o{ ALARMA : ""
BUCKET ||--o{ ALARMA : ""
BUCKET ||--o{ ARHIVA : ""
OBIECT_STOCAT ||--o{ ARHIVA : "obiect arhivă"
CREATE TABLE bucket (
id BIGSERIAL PRIMARY KEY,
nume VARCHAR(63) NOT NULL UNIQUE, -- convenție S3 (3–63)
descriere VARCHAR(512),
tenant VARCHAR(64) NOT NULL,
regiune VARCHAR(64),
backend VARCHAR(32), -- id driver: minio | s3
versionare_activa BOOLEAN NOT NULL,
nivel_acces VARCHAR(16) NOT NULL, -- enum NivelAcces
clasa_implicita VARCHAR(16) NOT NULL, -- enum ClasaStocare
replica_count INTEGER,
dimensiune_totala BIGINT,
numar_obiecte INTEGER
);
CREATE INDEX idx_bucket_tenant ON bucket(tenant);

2.2 obiect_stocat — metadatele unui obiect (binarul în object-store)

Section titled “2.2 obiect_stocat — metadatele unui obiect (binarul în object-store)”
CREATE TABLE obiect_stocat (
id BIGSERIAL PRIMARY KEY,
cheie VARCHAR(1024) NOT NULL, -- calea/cheia în bucket
dimensiune BIGINT NOT NULL, -- octeți
content_type VARCHAR(255),
hash_sha256 VARCHAR(64), -- integritate
etag VARCHAR(64),
versiune VARCHAR(64), -- id versiune (driver)
clasa_stocare VARCHAR(16) NOT NULL, -- enum ClasaStocare
statut VARCHAR(16) NOT NULL, -- enum StatutObiect
nivel_acces VARCHAR(16) NOT NULL, -- enum NivelAcces
replica_count INTEGER,
sters_la TIMESTAMP, -- tombstone (soft-delete)
text_indexat TEXT, -- text extras (Tika → ES)
metadate TEXT, -- JSON (jsonb amânat)
bucket_id BIGINT NOT NULL REFERENCES bucket(id)
);
-- Unicitatea logică (bucket, cheie, versiune) — changelog dedicat, vezi §4.
CREATE INDEX idx_obiect_bucket ON obiect_stocat(bucket_id);
CREATE INDEX idx_obiect_cheie ON obiect_stocat(bucket_id, cheie);
CREATE INDEX idx_obiect_statut ON obiect_stocat(statut);

2.3 sesiune_transfer — încărcare reluabilă (multipart)

Section titled “2.3 sesiune_transfer — încărcare reluabilă (multipart)”
CREATE TABLE sesiune_transfer (
id BIGSERIAL PRIMARY KEY,
upload_id VARCHAR(128) NOT NULL UNIQUE, -- id sesiune (MinIO multipart)
cheie VARCHAR(1024) NOT NULL,
dimensiune_totala BIGINT,
octeti_incarcati BIGINT,
numar_parti INTEGER,
marime_parte INTEGER,
hash_sha256 VARCHAR(64),
statut VARCHAR(16) NOT NULL, -- enum StatutTransfer
initiat_de VARCHAR(64),
expira_la TIMESTAMP,
bucket_id BIGINT NOT NULL REFERENCES bucket(id),
obiect_id BIGINT REFERENCES obiect_stocat(id) -- obiectul rezultat la complete
);
CREATE INDEX idx_transfer_statut ON sesiune_transfer(statut);
CREATE TABLE organizatie (
id BIGSERIAL PRIMARY KEY,
denumire VARCHAR(255) NOT NULL,
slug VARCHAR(128) NOT NULL UNIQUE, -- /organization/<slug>
idno VARCHAR(13),
tip VARCHAR(32), -- gov | company | ngo
domeniu_web VARCHAR(255),
tenant VARCHAR(64) NOT NULL,
sigla_uri VARCHAR(512),
descriere TEXT,
activ BOOLEAN NOT NULL
);

3.2 grup — temă/domeniu (ierarhic opțional)

Section titled “3.2 grup — temă/domeniu (ierarhic opțional)”
CREATE TABLE grup (
id BIGSERIAL PRIMARY KEY,
denumire VARCHAR(128) NOT NULL,
slug VARCHAR(128) NOT NULL UNIQUE,
descriere VARCHAR(512),
icon_uri VARCHAR(512),
parinte_id BIGINT REFERENCES grup(id)
);
CREATE TABLE dataset (
id BIGSERIAL PRIMARY KEY,
titlu VARCHAR(255) NOT NULL,
slug VARCHAR(160) NOT NULL UNIQUE,
descriere TEXT,
licenta VARCHAR(128),
frecventa VARCHAR(16), -- enum Frecventa
nivel_acces VARCHAR(16) NOT NULL, -- enum NivelAcces
statut VARCHAR(16) NOT NULL, -- enum StatutDataset
data_publicare TIMESTAMP,
etichete TEXT, -- JSON keywords (jsonb amânat)
metadate TEXT, -- JSON (jsonb amânat)
organizatie_id BIGINT NOT NULL REFERENCES organizatie(id)
);
CREATE INDEX idx_dataset_org ON dataset(organizatie_id);
CREATE INDEX idx_dataset_statut ON dataset(statut, nivel_acces);

3.4 resursa — fișier al unui dataset (referă un obiect)

Section titled “3.4 resursa — fișier al unui dataset (referă un obiect)”
CREATE TABLE resursa (
id BIGSERIAL PRIMARY KEY,
denumire VARCHAR(255) NOT NULL,
format VARCHAR(16) NOT NULL, -- enum FormatResursa
dimensiune BIGINT,
descriere VARCHAR(512),
ordine INTEGER,
dataset_id BIGINT NOT NULL REFERENCES dataset(id),
obiect_id BIGINT NOT NULL REFERENCES obiect_stocat(id)
);
CREATE INDEX idx_resursa_dataset ON resursa(dataset_id);

3.5 dataset_grup — join ManyToMany (dataset ↔ grup)

Section titled “3.5 dataset_grup — join ManyToMany (dataset ↔ grup)”
CREATE TABLE dataset_grup (
dataset_id BIGINT NOT NULL REFERENCES dataset(id),
grup_id BIGINT NOT NULL REFERENCES grup(id),
PRIMARY KEY (dataset_id, grup_id)
);

4. Tabele — acces / clienți / utilizatori

Section titled “4. Tabele — acces / clienți / utilizatori”

4.1 api_client — client mașină-mașină

Section titled “4.1 api_client — client mașină-mașină”
CREATE TABLE api_client (
id BIGSERIAL PRIMARY KEY,
denumire VARCHAR(128) NOT NULL,
tip VARCHAR(16) NOT NULL, -- enum TipClient (KEYCLOAK|API_KEY)
client_id VARCHAR(128), -- client Keycloak sau id cheie
api_key_hash VARCHAR(255), -- secret hash-uit (doar API_KEY)
scopes VARCHAR(255), -- "storage:read storage:write"
tenant VARCHAR(64) NOT NULL,
activ BOOLEAN NOT NULL,
expira_la TIMESTAMP,
ultima_utilizare TIMESTAMP,
organizatie_id BIGINT REFERENCES organizatie(id),
bucket_id BIGINT REFERENCES bucket(id) -- restricție opțională
);
CREATE INDEX idx_apiclient_tenant ON api_client(tenant);

4.2 permisiune — grant de acces (subiect → resursă)

Section titled “4.2 permisiune — grant de acces (subiect → resursă)”
CREATE TABLE permisiune (
id BIGSERIAL PRIMARY KEY,
drept VARCHAR(16) NOT NULL, -- enum DreptAcces
acordat_de VARCHAR(64),
data_acordare TIMESTAMP NOT NULL,
expira_la TIMESTAMP,
motiv VARCHAR(512),
beneficiar_id BIGINT REFERENCES app_user(id), -- uman (exact unul din
beneficiar_client_id BIGINT REFERENCES api_client(id), -- mașină cele două)
bucket_id BIGINT REFERENCES bucket(id), -- resursă (exact una din
dataset_id BIGINT REFERENCES dataset(id) -- cele două)
);
-- CHECK „exact un beneficiar + exact o resursă" impus la nivel aplicație (+ opțional trigger).
CREATE INDEX idx_permisiune_bucket ON permisiune(bucket_id);
CREATE INDEX idx_permisiune_dataset ON permisiune(dataset_id);

4.3 app_user — operator/utilizator de business (≠ jhi_user)

Section titled “4.3 app_user — operator/utilizator de business (≠ jhi_user)”
CREATE TABLE app_user (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
email VARCHAR(255),
rol VARCHAR(16) NOT NULL, -- enum RolUser
statut VARCHAR(16) NOT NULL, -- enum StatutUser
id_sec_local VARCHAR(64),
organizatie_id BIGINT REFERENCES organizatie(id)
);

5. Tabele — operațional (alarme / audit / arhivă)

Section titled “5. Tabele — operațional (alarme / audit / arhivă)”

5.1 alarma — regulă de alarmă parametrizabilă

Section titled “5.1 alarma — regulă de alarmă parametrizabilă”
CREATE TABLE alarma (
id BIGSERIAL PRIMARY KEY,
denumire VARCHAR(128) NOT NULL,
tip VARCHAR(24) NOT NULL, -- enum TipAlarma
prag BIGINT,
canal VARCHAR(16) NOT NULL, -- enum CanalAlarma
destinatar VARCHAR(255),
parametri TEXT, -- JSON (jsonb amânat)
activ BOOLEAN NOT NULL,
ultima_declansare TIMESTAMP,
organizatie_id BIGINT REFERENCES organizatie(id),
bucket_id BIGINT REFERENCES bucket(id)
);

5.2 eveniment — jurnal de audit APPEND-ONLY

Section titled “5.2 eveniment — jurnal de audit APPEND-ONLY”
CREATE TABLE eveniment (
id BIGSERIAL PRIMARY KEY,
tip VARCHAR(24) NOT NULL, -- enum TipEveniment
actor VARCHAR(64) NOT NULL,
tenant VARCHAR(64),
resursa_tip VARCHAR(16), -- BUCKET|OBIECT|DATASET|TRANSFER
resursa_id VARCHAR(64),
ip_adresa VARCHAR(64),
data TIMESTAMP NOT NULL,
payload TEXT -- JSON (jsonb amânat)
);
CREATE INDEX idx_eveniment_data ON eveniment(data);
CREATE INDEX idx_eveniment_tenant ON eveniment(tenant, tip);
-- Append-only: UPDATE/DELETE interzise la repository (AppendOnlyAuditGuard) + trigger, vezi §4 din §8.
CREATE TABLE arhiva (
id BIGSERIAL PRIMARY KEY,
denumire VARCHAR(255) NOT NULL,
cheie VARCHAR(1024), -- cheia obiectului arhivă rezultat
dimensiune BIGINT,
numar_obiecte INTEGER,
statut VARCHAR(16) NOT NULL, -- enum StatutJob
creat_la TIMESTAMP NOT NULL,
finalizat_la TIMESTAMP,
bucket_id BIGINT NOT NULL REFERENCES bucket(id),
obiect_id BIGINT REFERENCES obiect_stocat(id)
);

6. Coloane de audit (moștenite din AbstractAuditingEntity)

Section titled “6. Coloane de audit (moștenite din AbstractAuditingEntity)”

Fiecare tabel de mai sus include (generat de JHipster, omis din DDL pentru lizibilitate):

created_by VARCHAR(50) NOT NULL,
created_date TIMESTAMP,
last_modified_by VARCHAR(50),
last_modified_date TIMESTAMP

7. Note JSONB (conversie amânată — pas de hardening)

Section titled “7. Note JSONB (conversie amânată — pas de hardening)”

TextBlob → @Lob text în demo. Câmpurile care conțin JSON și beneficiază de jsonb real (interogare + index GIN) sunt: obiect_stocat.metadate, dataset.etichete, dataset.metadate, alarma.parametri, eveniment.payload. Conversia = changelog Liquibase dedicat (ALTER TABLE … TYPE jsonb USING …::jsonb)

  • @JdbcTypeCode(SqlTypes.JSON) pe câmp + index GIN. JDL nu are tip jsonb nativ. La runtime în demo fațetele vin din Elasticsearch, nu din interogări în DB pe aceste coloane — de aceea conversia nu blochează demo-ul.

8. Checklist pre-regenerare (decizii de rezolvat)

Section titled “8. Checklist pre-regenerare (decizii de rezolvat)”
  1. Unicitate obiect_stocat (bucket_id, cheie, versiune) — changelog dedicat (ADD CONSTRAINT uq_obiect UNIQUE), JDL nu suportă unique compus.
  2. permisiune exact-un-beneficiar + exact-o-resursă — validare la aplicație (opțional CHECK/trigger).
  3. eveniment append-only — AppendOnlyAuditGuard (listener Hibernate care vetează UPDATE/DELETE) + trigger DB BEFORE UPDATE/DELETE → RAISE.
  4. Retenția tombstone (soft-delete sters_la) + fereastra de restaurare (implicit 30 zile) → job @Scheduled de purjare.
  5. Expirarea sesiunilor de transfer (expira_la) → job de curățare + abortMultipart pe driver.
  6. Index-uri ES pentru obiect_stocat / dataset / resursa — hand-wired.
  7. Auto-provisioning organizație/bucket/api_client la conectare PaaS.