[ ultraKeen @ 29.09.2004. 14:28 ] @
Sistemska tabela RDB$USER_PRIVILEGES ima izmedju ostalih kao prvu i kolonu RDB$USER, ciji su sadrzaji imena svih "user-a" kojima su dodeljene privilegije iz kolone RDB$PRIVILEGE (dakle ako je "user-u" dodeljeno VISE privilegija, postoji VISE redova sa ISTIM sadrzajem u koloni RDB$USER, tj. imenonom TOG "user-a", a razlicitim sadrzajem u koloni RDB$PRIVILEGE).

*

ne bitno za ono sto se zeli reci, ali bitno kao opste saznanje: sadrzaj kolone RDB$PRIVILEGE su jednoslovni karakteri (iako? je ista/kolona dimenzije CHAR(6)): A, S, D, I, U, R, M, koji respektivno prezentuju vrstu privilegije njenim prvim slovom: ALL, SELECT, DELETE, INSERT, UPDATE, REFERENCE, MEMEBER OF (for roles)

jos nesto ne bitno za ono sto se zeli reci, ali bitno kao opet opste saznanje: posle samog formiranja baze, dakle fajla u kome ce TEK da budu radne tabele tj. u kome su za'sad SAMO sistemske tabele (one sto sve pocinju sa RDB$...), sadrzaj sistemske tabele RDB$USER_PRIVILEGES za zivo cudo NIJE prazan: u njoj je (automatski! pri kreiranju baze/fajla) INSERT-ovano 6 redova u kojima owner baze, imenovan u koloni RDB$GRANTOR, dodeljuje ustvari sam sebi (!) 'S', 'I', 'U', 'D', 'R' privilegije nad sistemskom tabelom 'RDB$ROLES' imenovanom u koloni RDB$RELATION_NAME, i u zadnjem redu takodje owner kao imenovani iz kolone RDB$GRANTOR, daje 'S' privilegiju nad tabelom 'RDB$ROLES' iz kolone RDB$RELATION_NAME specijalnom user-u sa imenom 'PUBLIC'... sve receno u ovom pasusu ne bi bilo mnogo bitno, da se taj automatizam formiranja tih 6 redova ne bi mogao iskoristiti da se jednom dopisanom/korisnickom procedurom dodje da imena ownera baze, sto nam FireBird (a i InterBase) NE omogucavaju kroz svoje kontekst varijable (kao sto su na primer CURRENT_USER i CURRENT_ROLE); dakle MOZE se sasvim regularnom SQL procedurom naci i ko je owner baze - ali uz samo ipak ;) jedan "mali uslov": u bazi se NE SMEJU koristiti role, jer onda potrebni SELECT-i ne bi vracali jedan red... :((( ... pa ko voli nek' (tako) izvoli...

*

Na pocetku je pod navodnike stavljeno "user" - ne bez razloga, jer iako kolona zaista ima naziv RDB$USER, njen sadrzaj ne moraju biti samo registrovani/zivi user-i iz tabele security.fdb, vec - i kojesta drugo ! ... Nadju se tu pored zaista pravih user-a i imena procedura, imena trigera, i svega drugog cemu se moze GRANT-ovati neko pravo/privilegija, sto nas navodi na to da je "user" shvacen u SIREM smislu, da to nije samo onaj zivi covek iz tabele security.fdb vec i bilo koji drugi entitet...

E sad', ima jedna mala zvrcka od fenomena :) oko toga...

Neka je regularno (u security.fdb) registrovan jedan user kome nisu data NIKAKVA prava nad NICIM iz neke baze. Ako je ta baza SKROZ prazna, tj. ako nema NI JEDNU tabelu (ili neki drugi entitet kome je inace potrebno GRANT-ovati pravo/privilegiju pristupa), tada taj user MOZE pristupiti takvoj/praznoj bazi, MOZE se (u)konektovati na nju - ali, ako baza NIJE prazna, ako ima bilo cega u njoj cemu JESTE potrebno GRANT-ovanjem dodeliti prava/privilegije pristupa, a doticni user to nema - tj. njegovog imena UOPSTE i NEMA u koloni RDB$USER tabele RDB$USER_PRIVILEGES - tada takvom user-u nece biti dozvoljeno ni da primirise doticnoj bazi: problemi ce se javiti ODMAH pri samoj konekciji na nju: ispisace se kojekakve poruke i cak error-i da nesto ne valja... a sve to naravno ne vazi za user-e koji se pojavljuju makar u jednom redu tabele RDB$USER_PRIVILEGES: on IMA razloga do zaviruje u bazu...

NAPOMENA: Celu tu lepu pricu kvare onih 6 redova koji se automatski generisu pri formiranju baze: kada postoje SAMO oni, onaj registrovani user koji nema razloga da pristupa bazi - IPAK moze da se konektuje IAKO ga TADA TAKODjE nema ni u jednom redu tabele RDB$USER_PRIVILEGE u koloni RDB$USER ... a cim se formira neki koristan/radni enitet za koga je potrebno GRANT-ovanje, onaj user koji nema sta da trazi u takvoj bazi, odbija se vec na ulazu u nju, pri konekciji, dok bukvalno tek "otkljucava vrata ulaza"...

ZAKLjUCAK: "tako (i) treba..."
[ Dejan Topalovic @ 04.10.2004. 01:38 ] @
Hmmm, procitao sam ovu poruku barem 10 puta proteklih dana, ali mi stvarno nije jasno sta si zelio reci ovime? :) Da FireBird ima mana ili da nema? Malo su ti recenicni sklopovi poteski za citanje, sorry ...
[ ultraKeen @ 28.10.2004. 03:56 ] @
:) zeleo sam da posavetujem pre svega korisnike FireBird-a kako se moze u SQL koodu naci ime vlasnika tabele jer doticna baza nema kontekst (environment) varijablu koja bi se recimo zvala CURRENT_OWNER kao sto ima recimo CURRENT_USER i CURRENT_ROLE... dakle pomalo :) kritikujem i samu bazu, ali pokusavam i da nadjem resenje onim sto su mi dali u ruke...

izvinjavam sa na teskom stilu recenice: on je posledica kontradiktorne teznje ka 2 cilja: biti sto apstraktniji (i time/zato sveobuhvatniji), a istovremeno biti i sto precizniji, ne dovoditi u dileme... (i biti sto koncizniji, naravno)

naravno, uz moj tezak tekst, pred ocima treba imati sistemsku tabelu RDB$USER_PRIVILEGES sasvim novo-formirane baze; onda ce sve biti jasnije

inace, kood procedure za nalazenje owner-a baze (iz pomenuto ogranicenje iz teksta) je:

/*----------------------------------------------------------------------------*/
/* dobavljanje kreatora/vlasnika baze/tabela */
/* koriscenjem (interne/NE!zvanicne) osobine da novo-kreirana/prazna baza */
/* AUTOMATSKI dobija odredjene redove u sistemskoj tabeli RDB$USER_PRIVILEGES */
/*-----___________________________--------------------------------------------*/
CREATE PROCEDURE API_owner_of_base RETURNS (its_owner CHAR(31))
AS
DECLARE VARIABLE owner_S CHAR(31);
DECLARE VARIABLE owner_I CHAR(31);
DECLARE VARIABLE owner_U CHAR(31);
DECLARE VARIABLE owner_D CHAR(31);
DECLARE VARIABLE owner_R CHAR(31);
/* */
DECLARE VARIABLE owner_pom CHAR(31);
BEGIN
/* privilegija SELECT */
SELECT "RDB$USER"
FROM "RDB$USER_PRIVILEGES"
WHERE "RDB$USER_PRIVILEGES"."RDB$USER" = "RDB$USER_PRIVILEGES"."RDB$GRANTOR" AND
"RDB$USER_PRIVILEGES"."RDB$PRIVILEGE" = 'S' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$GRANT_OPTION" = 1 AND
"RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" = 'RDB$ROLES' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$FIELD_NAME" IS NULL AND
"RDB$USER_PRIVILEGES"."RDB$USER_TYPE" = 8 AND
"RDB$USER_PRIVILEGES"."RDB$OBJECT_TYPE" = 0
INTO :owner_S;
/* privilegija INSERT */
SELECT "RDB$USER"
FROM "RDB$USER_PRIVILEGES"
WHERE "RDB$USER_PRIVILEGES"."RDB$USER" = "RDB$USER_PRIVILEGES"."RDB$GRANTOR" AND
"RDB$USER_PRIVILEGES"."RDB$PRIVILEGE" = 'I' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$GRANT_OPTION" = 1 AND
"RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" = 'RDB$ROLES' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$FIELD_NAME" IS NULL AND
"RDB$USER_PRIVILEGES"."RDB$USER_TYPE" = 8 AND
"RDB$USER_PRIVILEGES"."RDB$OBJECT_TYPE" = 0
INTO :owner_I;
/* privilegija UPDATE */
SELECT "RDB$USER"
FROM "RDB$USER_PRIVILEGES"
WHERE "RDB$USER_PRIVILEGES"."RDB$USER" = "RDB$USER_PRIVILEGES"."RDB$GRANTOR" AND
"RDB$USER_PRIVILEGES"."RDB$PRIVILEGE" = 'U' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$GRANT_OPTION" = 1 AND
"RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" = 'RDB$ROLES' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$FIELD_NAME" IS NULL AND
"RDB$USER_PRIVILEGES"."RDB$USER_TYPE" = 8 AND
"RDB$USER_PRIVILEGES"."RDB$OBJECT_TYPE" = 0
INTO :owner_U;
/* privilegija DELETE */
SELECT "RDB$USER"
FROM "RDB$USER_PRIVILEGES"
WHERE "RDB$USER_PRIVILEGES"."RDB$USER" = "RDB$USER_PRIVILEGES"."RDB$GRANTOR" AND
"RDB$USER_PRIVILEGES"."RDB$PRIVILEGE" = 'D' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$GRANT_OPTION" = 1 AND
"RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" = 'RDB$ROLES' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$FIELD_NAME" IS NULL AND
"RDB$USER_PRIVILEGES"."RDB$USER_TYPE" = 8 AND
"RDB$USER_PRIVILEGES"."RDB$OBJECT_TYPE" = 0
INTO :owner_D;
/* privilegija REFERENCES */
SELECT "RDB$USER"
FROM "RDB$USER_PRIVILEGES"
WHERE "RDB$USER_PRIVILEGES"."RDB$USER" = "RDB$USER_PRIVILEGES"."RDB$GRANTOR" AND
"RDB$USER_PRIVILEGES"."RDB$PRIVILEGE" = 'R' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$GRANT_OPTION" = 1 AND
"RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" = 'RDB$ROLES' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$FIELD_NAME" IS NULL AND
"RDB$USER_PRIVILEGES"."RDB$USER_TYPE" = 8 AND
"RDB$USER_PRIVILEGES"."RDB$OBJECT_TYPE" = 0
INTO :owner_R;

its_owner = NULL; IF ( owner_S = owner_I AND
owner_S = owner_U AND
owner_S = owner_D AND
owner_S = owner_R ) THEN
BEGIN
SELECT "RDB$GRANTOR"
FROM "RDB$USER_PRIVILEGES"
WHERE "RDB$USER_PRIVILEGES"."RDB$USER" = 'PUBLIC' AND
"RDB$USER_PRIVILEGES"."RDB$GRANTOR" = :owner_S AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$PRIVILEGE" = 'S' AND
"RDB$USER_PRIVILEGES"."RDB$GRANT_OPTION" = 0 AND
"RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" = 'RDB$ROLES' AND /* kljucni uslov */
"RDB$USER_PRIVILEGES"."RDB$FIELD_NAME" IS NULL AND
"RDB$USER_PRIVILEGES"."RDB$USER_TYPE" = 8 AND
"RDB$USER_PRIVILEGES"."RDB$OBJECT_TYPE" = 0
INTO :owner_pom;
/**/
IF ( owner_pom = owner_S ) THEN its_owner = owner_pom;
END

/* za its_owner = NULL znaci da se owner tabela/baze */
/* NE MOZE naci ovim primitivnim nacinom */
END^
/* mogucnost upotrebe ove/gornje PROCEDURE API_owner_of_base */
/* se dobrim/sustinskim delom zasniva i na tome da se u tekucem resenju */
/* NE koriste ROLES, tj. da se u koloni "RDB$USER_PRIVILEGES"."RDB$RELATION_NAME" */
/* 'RDB$ROLES' kao vrednost pojavljuje SAMO u redovima koji su */
/* posledica inicijalizacije baze, a kada se ROLES koriste - NE BI MOGLO... */