ugrás a tartalomhoz

Jogosultság kezelés

Hodicska Gergely · 2005. Feb. 2. (Sze), 08.00
Jogosultság kezelés
Egyik korábbi cikkünkben a munkamenet illetve a felhasználó kezelés rejtelmeiről volt szó. Ehhez szorosan kapcsolódik a mai témánk: a jogosultság kezelés. Ez egy mini sorozat első fejezete lesz, mely az előzetes tervek szerint két részből fog állni. Az elsőben egy alap rendszert valósítunk meg, majd a következőben megvizsgáljuk, hogy hogyan tudjuk ezt kiegészíteni összetett (attribútumokkal rendelkező) jogosultságok kezelésének képességével.

Miért van rá szükségünk

A webes alkalmazások többségénél szükségünk van arra, hogy felhasználóinkat megkülönböztethessük abból a szempontból, hogy milyen viszonyban állnak rendszerünkkel, mely funkcióit használhatják. E cél érdekében használunk jogosultság rendszert: minden egyes felhasználó esetén meghatározzuk, hogy milyen interakciókra van lehetősége alkalmazásunkkal szemben. Például egy fórum esetén egy (jogosultsággal nem rendelkező) látogató csak olvashatja a hozzászólásokat, egy regisztrált ("bejelentkezett" jogosultsággal rendelkező) tag hozzászólhat a fórum témákhoz, vagy újakat hozhat létre, míg egy adminisztrátor jogosultságokkal rendelkező felhasználó moderálhatja a többiek hozzászólásait, létrehozhat új fórum kategóriákat, stb..

Jogosultságok típusai

A jogosultságok esetén én két alapvető esetet különböztetnék meg. Vannak olyan jogosultságok, melyek esetében a puszta létük hordoz információt. Például egy cikk szerkesztő jogosultsággal rendelkező felhasználónak joga van publikálni. Általában az ilyen jogosultságok használata elegendő rugalmasságot biztosít számunkra. (De a törpök élete nem csak játék és mese.) Előfordulhatnak olyan szituációk, amikor ez kevésnek bizonyul, például szeretnénk, ha minden felhasználó csak az általa létrehozott cikkeket tudná szerkeszteni. Egy ilyen esetben a jogosultságot egy függvényként foghatjuk fel, mely az aktuális paraméterek (cikk, felhasználó azonosító) birtokában képes eldönteni, hogy a felhasználó a kívánt funkció elérésére ténylegesen jogosult-e vagy sem. Ezeket hívtam a bevezetőben összetett jogosultságoknak, és ezek támogatásáról lesz szó a következő részben.

A jogosultság rendszer felépítése

Először is vegyük sorra, hogy alap rendszerünk esetén milyen entitások kapnak szerepet: modul, jogosultság, felhasználó, csoport. Alkalmazásunk modulokból áll. A jogosultságok mindig egy modulhoz kötődnek, mindegyik modul meghatározza, hogy esetében mely jogok definiáltak. A felhasználókat csoportokba szervezhetjük a jogosultság kezelés menedzselésének egyszerűsítése végett. Ennek érdekében egy csoportba tehetjük az azonos feladatokat ellátó felhasználókat, és elegendő csak az adott csoporthoz hozzárendelni az adott feladat elvégzéséhez szükséges jogosultságokat, nem pedig egyenként, mindegyik felhasználóhoz. Természetesen egy felhasználó több csoportnak is tagja lehet. Ezenkívül az árnyaltabb kialakítás érdekében lehetőségünk van az egyes felhasználókhoz külön jogokat adni vagy elvenni a csoportjogokhoz képest. Ha alkalmazásunk rétegzettsége megkívánja, indokolt lehet annak megvalósítása is, hogy a csoportok más csoportokat is tartalmazhassanak, de ettől mi most eltekintünk.

A fenti alapján a következő logikai adatbázisterv adódik:

Logikai adatbázisterv


Az ábrán még feltüntettem a munkamenet kezeléshez szükséges táblát is, melynek majd még a jogosultságok kezelése kapcsán is szerepe lesz. A táblák nevei értelemszerűen jelölik, hogy milyen adatokat tárolunk bennük. A mezők melletti adattípusok szintén logikai adattípusok. A táblák közötti kapcsolatok jelzik, hogy azok milyen viszonyban vannak egymással. Például a felhasználó csoportokat a members kapcsolat definiálja.
A megvalósításhoz én a PostgreSQL-t választottam, mely manapság az egyik legjobb nyílt forrás kódú adatbázis kezelő rendszer, és sajnos méltatlanul van háttérbe szorítva a MySQL által, melyet mind funkcionalitásában, az SQL szabvány követésében, megbízhatóságban és konfigurálhatóságában messze leköröz. Látni fogjuk, hogy például hogyan használhatunk triggereket adatbázisunk konzisztenciájának biztosítására.

A választásból fakadóan a következő fizikai adatbázis tervet kapjuk:

Fizikai adatbázisterv


Mint láthatjuk a logikai terv kapcsolatai a számosságuktól függően külön táblákra, a logikai adattípusok pedig a megfelelő PostgreSQL adattípusra képződtek le. Ezen az ábrán a táblák közötti nyilak hivatkozási épség megszorításokat (foreign key constraint) jelölnek. Ezek használatával biztosíthatjuk, hogy például egy csoport tagja csak egy létező felhasználó lehessen (a members tábla mem_u_id oszlopába csak olyan érték szúrható be, amilyen érték szerepel a users tábla u_id oszlopában), vagy hogy egy csoportot ne lehessen addig törölni, amíg van tagja.

A fenti ábra alapján kapjuk a következő adatbázis sémát:
/*==============================================================*/
/* DBMS name:      PostgreSQL 7.3                               */
/* Created on:     2005.02.02. 03:45:03                         */
/*==============================================================*/

/*==============================================================*/
/* Table: denied_rights                                         */
/*==============================================================*/
create table denied_rights (
u_id              INT4                 not null,
rgt_id            INT4                 not null,
constraint denied_rights_pk primary key (u_id, rgt_id)
);

/*==============================================================*/
/* Table: extra_rights                                          */
/*==============================================================*/
create table extra_rights (
u_id              INT4                 not null,
rgt_id            INT4                 not null,
constraint extra_rights_pk primary key (u_id, rgt_id)
);

/*==============================================================*/
/* Table: group_rights                                          */
/*==============================================================*/
create table group_rights (
grp_id            INT4                 not null,
rgt_id            INT4                 not null,
constraint group_rights_pk primary key (grp_id, rgt_id)
);

/*==============================================================*/
/* Table: groups                                                */
/*==============================================================*/
create table groups (
id               SERIAL               not null,
name             VARCHAR(25)          not null,
dscr             VARCHAR(255)         null,
constraint groups_pk primary key (id)
);

/*==============================================================*/
/* Index: groups_dscr_uk                                        */
/*==============================================================*/
create unique index groups_name_uk on groups (
name
);

/*==============================================================*/
/* Table: members                                               */
/*==============================================================*/
create table members (
u_id             INT4                 not null,
grp_id           INT4                 not null,
constraint members_pk primary key (u_id, grp_id)
);

/*==============================================================*/
/* Table: modules                                               */
/*==============================================================*/
create table modules (
id               SERIAL               not null,
name             VARCHAR(25)          null,
constraint modules_pk primary key (id)
);

/*==============================================================*/
/* Index: modules_name_uk                                      */
/*==============================================================*/
create unique index modules_name_uk on modules (
name
);

/*==============================================================*/
/* Table: rights                                                */
/*==============================================================*/
create table rights (
id               SERIAL               not null,
name             VARCHAR(25)          not null,
mod_id           INT4                 not null,
const            VARCHAR(50)          null,
dscr             VARCHAR(255)         null,
set_act          VARCHAR(25)          null,
constraint rights_pk primary key (id)
);

/*==============================================================*/
/* Index: module_rights_fk                                      */
/*==============================================================*/
create index module_rights_fk on rights (
mod_id
);

/*==============================================================*/
/* Index: rights_name_mod_id_uk                                 */
/*==============================================================*/
create unique index rights_name_mod_id_uk on rights (
name, mod_id
);

/*==============================================================*/
/* Index: rights_name_mod_id_uk                                 */
/*==============================================================*/
create unique index rights_const_uk on rights (
const
);

/*==============================================================*/
/* Table: user_sessions                                         */
/*==============================================================*/
create table user_sessions (
id                SERIAL               not null,
session_id        VARCHAR(32)          not null,
u_id              INT4                 not null,
ip_address        VARCHAR(23)          not null,
user_agent        VARCHAR(255)         null,
referer           VARCHAR(255)         null,
created           TIMESTAMP            not null,
modified          TIMESTAMP            not null,
rights_changed    BOOL                 null,
constraint user_sessions_pk primary key (id)
);

/*==============================================================*/
/* Index: us_session_id_uk                                      */
/*==============================================================*/
create unique index user_sessions_session_id_uk on user_sessions (
session_id
);

/*==============================================================*/
/* Index: us_u_id_uk                                            */
/*==============================================================*/
create unique index user_sessions_u_id_uk on user_sessions (
u_id
);

/*==============================================================*/
/* Table: users                                                 */
/*==============================================================*/
create table users (
id                   SERIAL               not null,
forename             VARCHAR(25)          not null,
surname              VARCHAR(25)          not null,
email                VARCHAR(100)         not null,
login                VARCHAR(10)          not null,
password             VARCHAR(32)          not null,
temppass             VARCHAR(32)          null,
created              DATE                 not null,
constraint users_pk primary key (id)
);

/*==============================================================*/
/* Index: users_u_login_uk                                      */
/*==============================================================*/
create unique index users_login_uk on users (
login
);

/*==============================================================*/
/* Index: users_u_email_uk                                      */
/*==============================================================*/
create unique index users_email_uk on users (
email
);

alter table denied_rights
   add constraint fk_denied_right foreign key (rgt_id)
      references rights (id)
      on delete cascade on update restrict;

alter table denied_rights
   add constraint fk_has_denied_right foreign key (u_id)
      references users (id)
      on delete cascade on update restrict;

alter table extra_rights
   add constraint fk_extra_right foreign key (rgt_id)
      references rights (id)
      on delete cascade on update restrict;

alter table extra_rights
   add constraint fk_has_extra_right foreign key (u_id)
      references users (id)
      on delete cascade on update restrict;

alter table group_rights
   add constraint fk_group_right foreign key (rgt_id)
      references rights (id)
      on delete cascade on update restrict;

alter table group_rights
   add constraint fk_has_group_right foreign key (grp_id)
      references groups (id)
      on delete cascade on update restrict;

alter table members
   add constraint fk_is_member foreign key (u_id)
      references users (id)
      on delete cascade on update restrict;

alter table members
   add constraint fk_has_user foreign key (grp_id)
      references groups (id)
      on delete cascade on update restrict;

alter table rights
   add constraint fk_module_rights foreign key (mod_id)
      references modules (id)
      on delete cascade on update restrict;

alter table user_sessions
   add constraint fk_session_belong_to_user foreign key (u_id)
      references users (id)
      on delete cascade on update restrict;

Adatbázis konzisztencia

A fenti SQL script az ábrán szereplő elemeken kívül tartalmaz még pár egyediségre vonatkozó megszorítást (unique constraint). Ezek logikus megszorítások (például nem lehet két azonos nevű modul), melyek mind védik adatbázisunkat, hogy ne kerülhessenek bele inkonzisztens adatok.

Van még azonban egy kis disznóság, amivel nem foglalkoztunk. Mint említettem korábban, lehetőségünk van az egyes felhasználóknak extra jogokat biztosítani, illetve jogokat megvonni tőlük. Ezek tárolására szolgál az extra_rights és a denied_rights tábla. Elvileg megtehetjük, hogy egy adott jogosultságot mindkét táblában szerepeltetünk egy adott felhasználó esetén, ami nem túl szerencsés. Ennek kivédésére bővítsük ki a fenti sémát az alábbi kóddal:
 CREATE FUNCTION checkIfExtraRightExists() RETURNS TRIGGER AS '
DECLARE
    id INTEGER;
BEGIN
    SELECT INTO id u_id FROM extra_rights WHERE u_id = new.u_id AND rgt_id = new.rgt_id;
    IF FOUND THEN
        RAISE EXCEPTION ''existing_extra_right_exception'';
        RETURN null;
    ELSE
        RETURN new;
    END IF;
END;
' LANGUAGE 'plpgsql';
CREATE TRIGGER denied_rights_chk
    BEFORE INSERT OR UPDATE
    ON denied_rights
    FOR EACH ROW EXECUTE PROCEDURE checkIfExtraRightExists();
    
CREATE FUNCTION checkIfDeniedRightExists() RETURNS TRIGGER AS '
DECLARE
    id INTEGER;
BEGIN
    SELECT INTO id u_id FROM denied_rights WHERE u_id = new.u_id AND rgt_id = new.rgt_id;
    IF FOUND THEN
        RAISE EXCEPTION ''existing_denied_right_exception'';
        RETURN null;
    ELSE
        RETURN new;
    END IF;
END;
' LANGUAGE 'plpgsql';
CREATE TRIGGER extra_rights_chk
    BEFORE INSERT OR UPDATE
    ON extra_rights
    FOR EACH ROW EXECUTE PROCEDURE checkIfDeniedRightExists();
A fenti kód két triggert (http://www.postgresql.org/docs/8.0/interactive/triggers.html) definiál. Ezek a triggerek PL/pgSQL függvények, melyek a két táblán történő minden egyes INSERT és UPDATE parancs esetén meghívódnak, és a visszatérési értékük határozza meg, hogy ezek az SQL utasítások ténylegesen érvényre jutnak-e vagy sem. A függvényben ellenőrizzük, hogy a másik táblában szerepel-e ugyanazon felhasználóhoz hozzárendelve az adott jogosultság, és ha találunk ilyen sort, akkor egy kivételt váltunk ki. Az itt megadott szöveg szerepelni fog a PHP-nak visszaadott hibaüzenetben, így szükség szerint a hibát szépen le tudjuk kezelni.

Jogosultság rendszer használata

Amikor a felhasználó bejelentkezik a rendszerbe, jogosultságai felolvasásra kerülnek az adatbázisból, és a User objektumban tárolva bekerülnek a munkamenetében tárolt adatok közé. Ez a User objektum a mindenkori látogatót testesíti meg. Számunkra fontos tulajdonsága, hogy képes megmondani, hogy a felhasználó be van-e jelentkezve (isLogged()), illetve, hogy rendelkezik-e egy megadott jogosultsággal vagy sem (hasRight()).
A jogosultságokat a következő lekérdezés adja vissza:

SELECT 
	r.id
FROM
	users u
JOIN
	members m ON m.u_id = u.id
JOIN
	groups g ON g.id = m.grp_id
JOIN
	group_rights i ON i.grp_id = g.id
JOIN
	rights r ON r.id = i.rgt_id
LEFT JOIN
	denied_rights d ON (r.id = d.rgt_id AND d.u_id = '.$userId.')
WHERE
	u.id = '.$userId.' AND d.u_id is null

UNION

SELECT
	r.id
FROM
	rights r
JOIN
	extra_rights e ON r.id = e.rgt_id
WHERE
	e.u_id = '.$userId.' 
A bejelentkezés a következő képpen nézhet ki:
<?php
	$dao =& DaoFactory::get('Login');
	// Login név, jelszó ellenőrzése
	if (null !== ($userInfo =& $dao->getUserInfoByLogin($request->getParam('loginName'), $request->getParam('password')))) {
		// Beállítjuk a felhasználó adatait
		$user->setLoginState(true);
		$user->setData('userInfo', $userInfo);

		$dao =& DaoFactory::get('Rights');
		// Elmentjük a felhasználó jogosultságait
		$user->setRights($dao->getUserRights($userInfo['id']));
	} else {
		$request->setError('login', 'A megadott bejelentkezési név vagy a jelszó nem megfelelő!');
	}
?>
Ezt követően a jogosultságait nem frissítjük minden egyes oldallekéréskor, egy felesleges adatbázis műveletet végrehajtva. Ennek a módszernek azonban egy hátulütője lehet, miszerint ha egy felhasználónak a bejelentkezését követően megváltoznak a jogosultságai (az adminisztrátor éppen ezen idő alatt módosítja őket), akkor a frissítés nélkülözése miatt a munkamenetében és az adatbázisban tárolt jogai nem lesznek összhangban, a felhasználó esetleg továbbra is elérhet olyan funkciókat, melyekhez szükséges jogosultságokat már megvonták tőle.

A problémát úgy hidaltam át, hogy a munkamenet kezelésbe építettem bele egy, ezt a szituációt jelző funkciót. A munkameneteket tároló adatbázis táblába bekerült egy plusz mező (us_rights_changed), melyet true értékre állítva jelezhetjük, hogy szükséges a jogosultságok újraolvasása. Ezt a táblát úgyis szükséges minden egyes oldal kérés esetén kiolvasnunk a munkamenet ellenőrzése érdekében. Amikor az adminisztrációs felületen keresztül megváltoztatjuk a jogosultságokat, akkor az ezt érintő felhasználók azonosítója alapján lefut egy update a munkamenet táblán és beállítja ezt a mezőt.

Jogosultságok ellenőrzése

A felhasználó munkamenetében konkrétan az általa birtokolt jogosultságok (adatbázis) azonosítói kerülnek tárolásra. Ezt követően bármikor használhatjuk a User objektum hasRight() függvényét annak megállapítására, hogy a felhasználó rendelkezik-e egy joggal, vagy sem. A függvény egy jogosultság azonosítót vár paraméterül, ami ugye egy szám. Egy ilyen szám kifejező ereje viszont elég kicsi, nehezen tudnánk megjegyezni, hogy mondjuk a cikkek törlésének jogosultsága az éppen mennyi is, ezért ezen probléma orvoslására a következőt találtam ki. Amikor a jogosultságokat rögzítjük a rendszerbe, meg kell adjunk egy modul szinten egyedi szöveget (az egyediség adatbázis szinten biztosított), ami szintén tárolásra kerül. Ez alapján modulonként generálhatunk egy file-t, ami ezen szövegek, a modul neve és egy prefix (RIGHT_) alapján képzett konstans definíciókat tartalmaz, mely konstansok értéke az adott jogosultság azonosítója. Ezen file-ok generálása és includolása könnyedén automatizálható. Ezt követően például egy cikk törlésének jogosultságát a következőképpen ellenőrizhetjük:
<?php
	if ($user->hasRight(RIGHT_ARTICLE_DELETE) {
		// Cikk törlése
	} else {
		$request->setError('articleDelete', 'Sorry, nincs jogosultságod a cikk törléséhez!');
		$request->setError('articleDelete', 'És semmi légyszi, légyszi, légyszi!');
	}
?>
Persze tárolhattam volna magukat az így képzett szövegeket is a munkamenetben, és használhattam volna őket a jogosultság meglétének vizsgálatakor, de ennek két hátránya is lett volna: sok jog esetén lényeges különbség van a tárolt adatmennyiség között, de ennél is fontosabb, hogy ha egy konstans nevét írom el, akkor arról egy PHP figyelmeztetés formájában azonnal értesülök, míg ha egy szövege literált gépelek el, akkor nem, sokkal nehezebben találom meg a hibát.

Utolsó simítások ;)

Ezek után már csak annyit kell tennünk, hogy összedobunk egy kis adminisztrációs felületet, mellyel a fenti adatbázist szerkeszteni tudjuk. Igazából ebben túl nagy kihívás nincs, egy kis rabszolga munka az egész, ki-ki végezze el kedve szerint. Egy érdekesebb lekérdezést még megosztok, mellyel azokat a jogosultságokat kérdezhetjük le, melyek még nincsenek hozzárendelve egy adott felhasználóhoz (jól jöhet az adminhoz :))
SELECT
	r.id, r.name, r.mod_id, m.name as mod_name
FROM
	rights r
LEFT JOIN
	denied_rights d
	ON (r.id = d.rgt_id AND d.u_id = '.$userId.')
LEFT JOIN
	extra_rights e
	ON (r.id = e.rgt_id AND e.u_id = '.$userId.')
JOIN
	modules m
	ON r.mod_id = m.id
WHERE
	 d.u_id is null AND e.u_id is null
ORDER BY
	m.name, r.name;

Next time

Remélem a mai se volt haszontalan, legközelebb pedig terítékre kerül, hogy a cikkben említett összetett jogosultságokat hogyan tudjuk megvalósítani.
 
1

extra - denied rights

gerzson · 2005. Feb. 2. (Sze), 14.58
Van valami különösebb oka annak, hogy a külön jogokat nem egyetlen táblában tárolod, amiben a jogok mellett egy jelzőbit mutatná, h. az adott jog éppen pluszban ("allowed = TRUE") vagy mínuszban ("allowed = FALSE") van feljegyezve az adott felhasználónál?

create table extra_rights (
u_id              INT4                 not null,
rgt_id            INT4                 not null,
allowed           BOOL                 not null,
constraint extra_rights_pk primary key (u_id, rgt_id)
);
Ezzel némiképp egyszerűsödne a jogosultságokat lekérdező SQL is, és el lehetne hagyni a triggereket is.
2

Jogos

Hodicska Gergely · 2005. Feb. 2. (Sze), 15.08
Szia!

Jogos az eszrevetel. A nagy Powerdesignerosdiban nem is jutott ez eszembe. Tenyleg egyszrubb lenne igy, bar teljesitmeny szempontjabol nagyjabol mindegy.


Koszi,
Felho
3

Mikor lesz folytatás?

Dualon · 2005. Feb. 8. (K), 03.12
Kíváncsian várom a következő részt! ,)
4

Kb. 3 het

Hodicska Gergely · 2005. Feb. 8. (K), 11.07
Szia!

Elorelathatolag 2 het mulva jon a folytatas, de ez meg tobb dologtol is fugghet. ;)


Felho
5

Kösz

Dualon · 2005. Feb. 8. (K), 11.35
Köszönöm - ráérek, "csak" a kíváncsiság hajt.
6

Tűkön ülök ^^

Dualon · 2005. Már. 27. (V), 17.27
Kedves Felhobacsi (ugye?) !

Tényleg nem akarok pofátlan lenni, de igen érdekelne a cikk folytatása. Nem fogok ezzel tolakodni a jövőben, csak egy utolsó segélykiáltást hallattam... ,)
12

Folytatás?

it_sparrow · 2009. Feb. 1. (V), 19.47
Szia,

nem derült ki itt a válaszokból, hogy megjelent-e a folytatás, vagy nem.
Lehet még rá számítani?

Üdv: Sparrow
13

nem túl esélyes

Hodicska Gergely · 2009. Feb. 2. (H), 02.58
Jó régen készült ez a cikk, már nem is biztos, hogy tudnám, hogy mit is szerettem volna, akkor körvonalazódott bennem egy megoldás, de végül akkor nem csináltam meg, most meg már lehet, hogy szétnéznék a meglévő cuccok között, pl. Zend_Acl.
7

Login elötti user_id

Sweetchack · 2005. Ápr. 6. (Sze), 00.20
Sziasztok

Nem kapcsolódik szorosan a témához, de mivel megláttam az adatmodellben egy olyan problémát amivel magam is gyakran szembesülök.


create table users (
	id                   SERIAL               not null,
	constraint users_pk primary key (id)
);

create table user_sessions (
	id		SERIAL               not null,
	session_id       VARCHAR(32)          not null,
	u_id		INT4                 not null,
	constraint user_sessions_pk primary key (id)
);

alter table user_sessions
	add constraint fk_session_belong_to_user foreign key (u_id)
	references users (id)
	on delete cascade on update restrict;
 
Amíg nem jelentkezik be a felhasználó addig mit írjak a USER_SESSION.U_ID mezőbe?
Mert ügyebár a ForeginKey nem engedi üresen hagyni.
Ha a USERS táblába insertálok egy rekordod, (legyen mondjuk ez az első, tehát id=1)
akkor figyelnem kell arra, hogy ne tudjon bejelentkezni, ne küldjek neki levelet, ne számoljam a tagok közé, stb...
Ha nincsen ForeginKey akkor Trigger-rel kell figyelgetni hogy csak 0(nulla) vagy csak olyan érték legyen ami szerepel a USERS táblában.
MySQL 4.x estében úgy is programozni kell, de én is egyre jobban favorizálom a PostgreSQL-t

Eddig is megoldottam, csak gondoltam megkérdezem hátha tudtok valami jó Barba trükköt.

Szívesen veszem a javaslatokat.

Jó munkát

ui.:
Ez miért kell a USERS_SESSIONS táblába?
id SERIAL not null,

A session_id miért nem elég?
8

Adatmodell

mdombos · 2005. Júl. 1. (P), 19.40
Hali

A cikkben látható adatmodell ábrákat valami adatmodellező programmal csináltad vagy csak valami grafikaival? Ha adatmodellező akkor melyik... Esetleg más adatmodellező progikat ismertek?

Elöre is köszi:
Nova
9

PowerDesigner

Hodicska Gergely · 2005. Júl. 1. (P), 21.27
Szia!


Az ábrák a Sybase PowerDesigner nevű programjával készültek. Szerintem az egyik legjobb adatbázis tervező progi, érdemes kipróbálni. Egyetlen nagy baja az ára sajnos.

Érdemes talán megnézni az EMS termékeket, ezek már mind tartalmaznak grafikus tervező funkciót is, bár ebben a fenti cucctól erősen elmaradnak.

Aztán még van pár megoldás érdmes kicsit szétnézni.


Felhő
10

Designer

Sweetchack · 2005. Júl. 6. (Sze), 21.46
A sourceforge.org -on érdemes szétnézni.
http://sourceforge.net/projects/druid/ én ezt használom
http://sourceforge.net/projects/mogwai/
de van még néhány
11

Kérdések

mocsar · 2006. Május. 17. (Sze), 16.23
Lenne két kérdésem, hogy egy kicsit tanuljak.

1. A rights táblában mi a célod a const, set_act mezőkkel. Ezek gondolom a jogosultság tulajdonságait határozzák meg.

2. A másik kérdés nagyon alap. Hogyan kötöd ezt az egészet a kódodhoz? A modul kifejezés programmodult jelent? Végül is itt programmodulok futtatásához való jogokról van szó?
14

Észrevettem egy hibát, vagy

inf · 2013. Feb. 17. (V), 05.26
Észrevettem egy hibát, vagy inkább rossz szokást a jogosultság kezeléssel kapcsolatos adatbázisok tervezésénél. Általában több különböző módon lehet bejelentkeztetni a felhasználókat: jelszó, permanent cookie, email-ben kapott linkek. Ehhez képest alapból mindenki úgy fut neki az adatbázisnak, hogy users tábla, email, password oszlopok... Én helyette ezt a felépítést javaslom:

	access
		access_id
		user_id
		access_hash
		access_type
		access_expires
	user
		user_id
		user_email
		user_salt
		user_name
Általánosságban a hash generáláshoz meg

access_hash = sha1(sha1(access_type) + sha1(param) + user_salt)
user_salt = sha1(random)
ahol a param lehet a jelszó, vagy valamilyen random változó.

Egyébként érdekelne, hogy ki hogyan tárolja a munkameneteket, leginkább az, hogy nem e túl lassú, ha adatbázisban tárolja őket az ember. Éppen ajax-os projektet csinálok, és erősen gondolkodom rajta, hogy adatbázisba tegyem a munkameneteket fájlrendszer helyett, hogy véletlenül se legyen concurrency-vel kapcsolatos gond ...

Egyébként annyi könnyebbség van a single page js-es oldalakkal, hogy csak a jogosultságot kell tárolni munkamenetben, ezért a rights_changed flag is kihagyható az adatbázisból, és közvetlenül össze lehet kötni a rights-ot a sessions-el. Php-s szerializálásra sincs így szükség. Hát akkor tényleg ez lesz, és adatbázis szerverrel ellenőriztetek majd jogosultságot a php-s cache helyett. Amúgy ezt ugyanúgy meg lehet csinálni, ha más adat is van a session-ben, így a jogokat nem kell újra és újra szerializáltatni a php-vel...
15

Valaki leírná egybe és

RKO12 · 2013. Szep. 24. (K), 20.18
Valaki leírná egybe és felcímkézve hogy melyik -mihez tartozik pl

jogosultság.sql
/*==============================================================*/  
/* DBMS name:      PostgreSQL 7.3                               */  
/* Created on:     2005.02.02. 03:45:03                         */  
/*==============================================================*/  
  
/*==============================================================*/  
/* Table: denied_rights                                         */  
/*==============================================================*/  
create table denied_rights (  
u_id              INT4                 not null,  
rgt_id            INT4                 not null,  
constraint denied_rights_pk primary key (u_id, rgt_id)  
);  
  
/*==============================================================*/  
/* Table: extra_rights                                          */  
/*==============================================================*/  
create table extra_rights (  
u_id              INT4                 not null,  
rgt_id            INT4                 not null,  
constraint extra_rights_pk primary key (u_id, rgt_id)  
);  
  
/*==============================================================*/  
/* Table: group_rights                                          */  
/*==============================================================*/  
create table group_rights (  
grp_id            INT4                 not null,  
rgt_id            INT4                 not null,  
constraint group_rights_pk primary key (grp_id, rgt_id)  
);  
  
/*==============================================================*/  
/* Table: groups                                                */  
/*==============================================================*/  
create table groups (  
id               SERIAL               not null,  
name             VARCHAR(25)          not null,  
dscr             VARCHAR(255)         null,  
constraint groups_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: groups_dscr_uk                                        */  
/*==============================================================*/  
create unique index groups_name_uk on groups (  
name  
);  
  
/*==============================================================*/  
/* Table: members                                               */  
/*==============================================================*/  
create table members (  
u_id             INT4                 not null,  
grp_id           INT4                 not null,  
constraint members_pk primary key (u_id, grp_id)  
);  
  
/*==============================================================*/  
/* Table: modules                                               */  
/*==============================================================*/  
create table modules (  
id               SERIAL               not null,  
name             VARCHAR(25)          null,  
constraint modules_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: modules_name_uk                                      */  
/*==============================================================*/  
create unique index modules_name_uk on modules (  
name  
);  
  
/*==============================================================*/  
/* Table: rights                                                */  
/*==============================================================*/  
create table rights (  
id               SERIAL               not null,  
name             VARCHAR(25)          not null,  
mod_id           INT4                 not null,  
const            VARCHAR(50)          null,  
dscr             VARCHAR(255)         null,  
set_act          VARCHAR(25)          null,  
constraint rights_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: module_rights_fk                                      */  
/*==============================================================*/  
create index module_rights_fk on rights (  
mod_id  
);  
  
/*==============================================================*/  
/* Index: rights_name_mod_id_uk                                 */  
/*==============================================================*/  
create unique index rights_name_mod_id_uk on rights (  
name, mod_id  
);  
  
/*==============================================================*/  
/* Index: rights_name_mod_id_uk                                 */  
/*==============================================================*/  
create unique index rights_const_uk on rights (  
const  
);  
  
/*==============================================================*/  
/* Table: user_sessions                                         */  
/*==============================================================*/  
create table user_sessions (  
id                SERIAL               not null,  
session_id        VARCHAR(32)          not null,  
u_id              INT4                 not null,  
ip_address        VARCHAR(23)          not null,  
user_agent        VARCHAR(255)         null,  
referer           VARCHAR(255)         null,  
created           TIMESTAMP            not null,  
modified          TIMESTAMP            not null,  
rights_changed    BOOL                 null,  
constraint user_sessions_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: us_session_id_uk                                      */  
/*==============================================================*/  
create unique index user_sessions_session_id_uk on user_sessions (  
session_id  
);  
  
/*==============================================================*/  
/* Index: us_u_id_uk                                            */  
/*==============================================================*/  
create unique index user_sessions_u_id_uk on user_sessions (  
u_id  
);  
  
/*==============================================================*/  
/* Table: users                                                 */  
/*==============================================================*/  
create table users (  
id                   SERIAL               not null,  
forename             VARCHAR(25)          not null,  
surname              VARCHAR(25)          not null,  
email                VARCHAR(100)         not null,  
login                VARCHAR(10)          not null,  
password             VARCHAR(32)          not null,  
temppass             VARCHAR(32)          null,  
created              DATE                 not null,  
constraint users_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: users_u_login_uk                                      */  
/*==============================================================*/  
create unique index users_login_uk on users (  
login  
);  
  
/*==============================================================*/  
/* Index: users_u_email_uk                                      */  
/*==============================================================*/  
create unique index users_email_uk on users (  
email  
);  
  
alter table denied_rights  
   add constraint fk_denied_right foreign key (rgt_id)  
      references rights (id)  
      on delete cascade on update restrict;  
  
alter table denied_rights  
   add constraint fk_has_denied_right foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
  
alter table extra_rights  
   add constraint fk_extra_right foreign key (rgt_id)  
      references rights (id)  
      on delete cascade on update restrict;  
  
alter table extra_rights  
   add constraint fk_has_extra_right foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
  
alter table group_rights  
   add constraint fk_group_right foreign key (rgt_id)  
      references rights (id)  
      on delete cascade on update restrict;  
  
alter table group_rights  
   add constraint fk_has_group_right foreign key (grp_id)  
      references groups (id)  
      on delete cascade on update restrict;  
  
alter table members  
   add constraint fk_is_member foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
  
alter table members  
   add constraint fk_has_user foreign key (grp_id)  
      references groups (id)  
      on delete cascade on update restrict;  
  
alter table rights  
   add constraint fk_module_rights foreign key (mod_id)  
      references modules (id)  
      on delete cascade on update restrict;  
  
alter table user_sessions  
   add constraint fk_session_belong_to_user foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
és hogy mit kell írni az egyes fileok elejére végére közepére , hogy azt csak pl a egyes csoportok lássák (pl VIP normá felhasználó vagy tulaj/admin/moderátpr stb)????????
16

nem.

inf · 2013. Szep. 24. (K), 20.52
nem.
17

Mi ez?!

Pepita · 2013. Szep. 25. (Sze), 10.11
Látom próbáltál kódszínezőt használni, de nem ment. Erre való az előnézet.
Tegyél fel értelmes kérdést, erre nem tudunk válaszolni (én legalábbis).
18

Azt szeretném hogy egybe

RKO12 · 2013. Szep. 25. (Sze), 16.18
Azt szeretném hogy egybe leírja valaki , hogy melyik szöveg rlész melyik file-hoz tartozik

pl ezt taRTALMAZZA adatbázis.sql

SELECT   
    r.id  
FROM  
    users u  
JOIN  
    members m ON m.u_id = u.id  
JOIN  
    groups g ON g.id = m.grp_id  
JOIN  
    group_rights i ON i.grp_id = g.id  
JOIN  
    rights r ON r.id = i.rgt_id  
LEFT JOIN  
    denied_rights d ON (r.id = d.rgt_id AND d.u_id = '.$userId.')  
WHERE  
    u.id = '.$userId.' AND d.u_id is null  
  
UNION  
  
SELECT  
    r.id  
FROM  
    rights r  
JOIN  
    extra_rights e ON r.id = e.rgt_id  
WHERE  
    e.u_id = '.$userId.' 



ezt a jogosultság.sql:
   
/*==============================================================*/  
/* DBMS name:      PostgreSQL 7.3                               */  
/* Created on:     2005.02.02. 03:45:03                         */  
/*==============================================================*/  
  
/*==============================================================*/  
/* Table: denied_rights                                         */  
/*==============================================================*/  
create table denied_rights (  
u_id              INT4                 not null,  
rgt_id            INT4                 not null,  
constraint denied_rights_pk primary key (u_id, rgt_id)  
);  
  
/*==============================================================*/  
/* Table: extra_rights                                          */  
/*==============================================================*/  
create table extra_rights (  
u_id              INT4                 not null,  
rgt_id            INT4                 not null,  
constraint extra_rights_pk primary key (u_id, rgt_id)  
);  
  
/*==============================================================*/  
/* Table: group_rights                                          */  
/*==============================================================*/  
create table group_rights (  
grp_id            INT4                 not null,  
rgt_id            INT4                 not null,  
constraint group_rights_pk primary key (grp_id, rgt_id)  
);  
  
/*==============================================================*/  
/* Table: groups                                                */  
/*==============================================================*/  
create table groups (  
id               SERIAL               not null,  
name             VARCHAR(25)          not null,  
dscr             VARCHAR(255)         null,  
constraint groups_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: groups_dscr_uk                                        */  
/*==============================================================*/  
create unique index groups_name_uk on groups (  
name  
);  
  
/*==============================================================*/  
/* Table: members                                               */  
/*==============================================================*/  
create table members (  
u_id             INT4                 not null,  
grp_id           INT4                 not null,  
constraint members_pk primary key (u_id, grp_id)  
);  
  
/*==============================================================*/  
/* Table: modules                                               */  
/*==============================================================*/  
create table modules (  
id               SERIAL               not null,  
name             VARCHAR(25)          null,  
constraint modules_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: modules_name_uk                                      */  
/*==============================================================*/  
create unique index modules_name_uk on modules (  
name  
);  
  
/*==============================================================*/  
/* Table: rights                                                */  
/*==============================================================*/  
create table rights (  
id               SERIAL               not null,  
name             VARCHAR(25)          not null,  
mod_id           INT4                 not null,  
const            VARCHAR(50)          null,  
dscr             VARCHAR(255)         null,  
set_act          VARCHAR(25)          null,  
constraint rights_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: module_rights_fk                                      */  
/*==============================================================*/  
create index module_rights_fk on rights (  
mod_id  
);  
  
/*==============================================================*/  
/* Index: rights_name_mod_id_uk                                 */  
/*==============================================================*/  
create unique index rights_name_mod_id_uk on rights (  
name, mod_id  
);  
  
/*==============================================================*/  
/* Index: rights_name_mod_id_uk                                 */  
/*==============================================================*/  
create unique index rights_const_uk on rights (  
const  
);  
  
/*==============================================================*/  
/* Table: user_sessions                                         */  
/*==============================================================*/  
create table user_sessions (  
id                SERIAL               not null,  
session_id        VARCHAR(32)          not null,  
u_id              INT4                 not null,  
ip_address        VARCHAR(23)          not null,  
user_agent        VARCHAR(255)         null,  
referer           VARCHAR(255)         null,  
created           TIMESTAMP            not null,  
modified          TIMESTAMP            not null,  
rights_changed    BOOL                 null,  
constraint user_sessions_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: us_session_id_uk                                      */  
/*==============================================================*/  
create unique index user_sessions_session_id_uk on user_sessions (  
session_id  
);  
  
/*==============================================================*/  
/* Index: us_u_id_uk                                            */  
/*==============================================================*/  
create unique index user_sessions_u_id_uk on user_sessions (  
u_id  
);  
  
/*==============================================================*/  
/* Table: users                                                 */  
/*==============================================================*/  
create table users (  
id                   SERIAL               not null,  
forename             VARCHAR(25)          not null,  
surname              VARCHAR(25)          not null,  
email                VARCHAR(100)         not null,  
login                VARCHAR(10)          not null,  
password             VARCHAR(32)          not null,  
temppass             VARCHAR(32)          null,  
created              DATE                 not null,  
constraint users_pk primary key (id)  
);  
  
/*==============================================================*/  
/* Index: users_u_login_uk                                      */  
/*==============================================================*/  
create unique index users_login_uk on users (  
login  
);  
  
/*==============================================================*/  
/* Index: users_u_email_uk                                      */  
/*==============================================================*/  
create unique index users_email_uk on users (  
email  
);  
  
alter table denied_rights  
   add constraint fk_denied_right foreign key (rgt_id)  
      references rights (id)  
      on delete cascade on update restrict;  
  
alter table denied_rights  
   add constraint fk_has_denied_right foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
  
alter table extra_rights  
   add constraint fk_extra_right foreign key (rgt_id)  
      references rights (id)  
      on delete cascade on update restrict;  
  
alter table extra_rights  
   add constraint fk_has_extra_right foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
  
alter table group_rights  
   add constraint fk_group_right foreign key (rgt_id)  
      references rights (id)  
      on delete cascade on update restrict;  
  
alter table group_rights  
   add constraint fk_has_group_right foreign key (grp_id)  
      references groups (id)  
      on delete cascade on update restrict;  
  
alter table members  
   add constraint fk_is_member foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict;  
  
alter table members  
   add constraint fk_has_user foreign key (grp_id)  
      references groups (id)  
      on delete cascade on update restrict;  
  
alter table rights  
   add constraint fk_module_rights foreign key (mod_id)  
      references modules (id)  
      on delete cascade on update restrict;  
  
alter table user_sessions  
   add constraint fk_session_belong_to_user foreign key (u_id)  
      references users (id)  
      on delete cascade on update restrict; 
és hogy mit kell beírni egyes html vagy php file-okba h azt csak azok lássák például akiknek engedik pl

ezt mindenki
menü1 menü 2 menü5 stb

ezt csak aki bejelentkezik (normál felhasználó).../csoport2
menü3 menü6 menü7(+ azok a menüpontok amiket mindenki lát)

Ezt a V.I.P.-tagok:

menü7 menü8 menü9 menü10((+ azok a menüpontok amiket mindenki és a normál felhasználok látnak látnak)

Anminisztrátor(Tulaj):
mindent

Moderátor:
mindent


És senki sem látja (csak az admin) a adninisztrátor belépés menü pontot

Remélem mostmár valamennyivel érthetőbb...
19

Adatbázis

Poetro · 2013. Szep. 25. (Sze), 16.55
A fentiek adatbázis struktúrák és egy lekérdezés PostgreSQL adatbáziskezelőhöz. Semmi köze nincs se HTML-hez, se PHP-hoz. A fenti adatbázis struktúra alapján lehet írni egy PHP alkalmazást, de azt ne várd senkitől, hogy valaki megírja helyetted.