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.
1. ER diagram
Section titled “1. ER diagram”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ă"2. Tabele — strat FIZIC (object-store)
Section titled “2. Tabele — strat FIZIC (object-store)”2.1 bucket — container/spațiu de nume
Section titled “2.1 bucket — container/spațiu de nume”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);3. Tabele — strat CATALOG (open-data)
Section titled “3. Tabele — strat CATALOG (open-data)”3.1 organizatie — emitentul de date
Section titled “3.1 organizatie — emitentul de date”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));3.3 dataset — set de date publicabil
Section titled “3.3 dataset — set de date publicabil”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.5.3 arhiva — job de arhivare/comprimare
Section titled “5.3 arhiva — job de arhivare/comprimare”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 TIMESTAMP7. 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 tipjsonbnativ. 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)”- Unicitate
obiect_stocat (bucket_id, cheie, versiune)— changelog dedicat (ADD CONSTRAINT uq_obiect UNIQUE), JDL nu suportă unique compus. permisiuneexact-un-beneficiar + exact-o-resursă — validare la aplicație (opțional CHECK/trigger).evenimentappend-only —AppendOnlyAuditGuard(listener Hibernate care vetează UPDATE/DELETE) + trigger DBBEFORE UPDATE/DELETE → RAISE.- Retenția tombstone (soft-delete
sters_la) + fereastra de restaurare (implicit 30 zile) → job@Scheduledde purjare. - Expirarea sesiunilor de transfer (
expira_la) → job de curățare +abortMultipartpe driver. - Index-uri ES pentru
obiect_stocat/dataset/resursa— hand-wired. - Auto-provisioning organizație/bucket/api_client la conectare PaaS.