Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP] Projekt systemu ACL
Forum PHP.pl > Forum > Przedszkole
mentoos
Chciałbym napisać swój system ACL. Zastanawiam się jak go zaprojektować by był elastyczny. Bazę danych chcę zaprojektować tak:

acl_resources - zasoby
id | resource

acl_roles -> role
id | role_name

acl_permissions - tabela wiążąca 2 poprzednie, w permission określany jest dostęp lub nie
id | resource_id | role_id | permission

i jeszcze tabela users normalnie wykorzystywana do logowania

Co powinien mieć dobry system ACL?
Czy powinien mieć też możliwość przypisywania uprawnień konkretnemu użytkownikowi?
erix
Cytat
Czy powinien mieć też możliwość przypisywania uprawnień konkretnemu użytkownikowi?

Oczywiście. Rzadko, ale się przydaje; nie ma sensu tworzenia osobnej grupy dla zmiany tylko jednego uprawnienia.
mentoos
W takim razie zrobię też obsługę uprawnień dla konkretnego użytkownika.

Czy struktura bazy, którą dałem pod taki system jest prawidłowa?
Co polecałbyś dorzucić jeszcze?
phpion
Ja w swoim systemie ACL mam 3-poziomowe sprawdzanie uprawnień. Uprawnienia przypisuję na poziomie zasobu, roli użytkownika oraz samego użytkownika. Mam napisaną funkcję w plsql, która dla podanego ID użytkownika zwraca mi listę uprawnień/zakazów. Jeżeli określenie uprawnienia występuje na kilku poziomach (np. dla roli jest odebrane, ale dla samego użytkownika przyznane) to, nadając priorytety uprawnieniom, zwraca wartość końcową (tj. w opisanym przypadku nadanie uprawnienia).

Co jeszcze byłoby przydatne? "Przestrzenie nazw" - tak to nazwałem - czyli po prostu typy zasobów. U mnie generalnie występują 3 typy: action (dla akcji, czyli kliknięcia), field (pozwala/zabrania modyfikacji pola w formularzu oraz w bazie danych - za jednym zamachem) oraz image (wyświetlanie obrazka).

Mając zdefiniowane wspomniane typy zasobów możesz zrobić fajny myk. Ja osobiście pracuję z frameworkiem Kohana i wstrzyknąłem się bezpośrednio w helpery do budowy linków oraz tworzenia formularzy. Dzięki temu już podczas tworzenia linku (helperem html::anchor()) sprawdzam czy użytkownik ma uprawnienia do danej akcji. Jeśli tak - tworzę link, jeśli nie - wyświetlam go jako span class="access_denied". Do tego mam plugin w jQuery, który wszystkie elementy o klasie access_denied wyszarza tj. np. obrazki przekształca do skali szarości. W całości daje to bardzo fajny efekt.
mentoos
@phpion

Extra masz zrobiony system ACL. Sam używam Kohan'y, tyle że v3.0 smile.gif. Zastanawiam się też czy nie napisać systemu ACL dla Kohana, ale jest już chyba wersja Kohana ACL dla wersji v3.0.

Jak wygląda struktura bazy danych w Twoim systemie ACL? Podobna do tej co pokazałem?
phpion
Poniżej zrzuty tabel (w kolejności alfabetycznej, nie zakładania - powycinałem ze zrzutu bazy):
  1. CREATE TABLE acl_resource_groups (
  2. id integer NOT NULL,
  3. name character varying(50) NOT NULL,
  4. description text,
  5. priority smallint DEFAULT 0 NOT NULL
  6. );
  7. CREATE TABLE acl_resource_groups_acl_resources (
  8. acl_resource_group_id integer NOT NULL,
  9. acl_resource_id integer NOT NULL,
  10. permission BOOLEAN DEFAULT false NOT NULL
  11. );
  12.  
  13. CREATE TABLE acl_resource_groups_acl_roles (
  14. acl_resource_group_id integer NOT NULL,
  15. acl_role_id integer NOT NULL
  16. );
  17.  
  18. CREATE TABLE acl_resource_groups_auth_users (
  19. acl_resource_group_id integer NOT NULL,
  20. auth_user_id integer NOT NULL
  21. );
  22.  
  23. CREATE TABLE acl_resource_namespaces (
  24. id integer NOT NULL,
  25. name character varying(255) NOT NULL
  26. );
  27.  
  28. CREATE TABLE acl_resources (
  29. id integer NOT NULL,
  30. name character varying(255) NOT NULL,
  31. acl_resource_namespace_id integer NOT NULL,
  32. permission BOOLEAN DEFAULT false NOT NULL
  33. );
  34.  
  35. CREATE TABLE acl_resources_acl_roles (
  36. acl_resource_id integer NOT NULL,
  37. acl_role_id integer NOT NULL,
  38. permission BOOLEAN DEFAULT false NOT NULL
  39. );
  40.  
  41. CREATE TABLE acl_resources_auth_users (
  42. acl_resource_id integer NOT NULL,
  43. auth_user_id integer NOT NULL,
  44. permission BOOLEAN DEFAULT false NOT NULL
  45. );
  46.  
  47. CREATE TABLE acl_roles (
  48. id integer NOT NULL,
  49. name character varying(25) NOT NULL,
  50. priority smallint DEFAULT 0 NOT NULL
  51. );
  52.  
  53. CREATE TABLE acl_roles_auth_users (
  54. auth_user_id integer NOT NULL,
  55. acl_role_id integer NOT NULL
  56. );

Do tego wspomniana funkcja, a do niej potrzebny nowy typ danych:
  1. CREATE TYPE acl_user_resurces_permissions AS (
  2. resource_id integer,
  3. permission BOOLEAN,
  4. level integer
  5. );
  6.  
  7. CREATE FUNCTION f_get_acl_user_resources_permissions(_user_id integer) RETURNS SETOF acl_user_resurces_permissions
  8. AS $$
  9. DECLARE
  10. row record;
  11. BEGIN
  12. FOR row IN
  13. SELECT
  14. DISTINCT ON (resource_id) resource_id, permission, level
  15. FROM
  16. (
  17. -- Pobranie uprawnien przypisanych bezposrednio do uzytkownika (priorytet = 5)
  18. (SELECT
  19. acl_resource_id AS resource_id, permission AS permission, 5 AS level
  20. FROM
  21. acl_resources_auth_users
  22. WHERE
  23. auth_user_id=_user_id)
  24. UNION
  25. -- Pobranie uprawnien przypisanych do grupy ACL uzytkownika (priorytet = 4)
  26. (SELECT
  27. DISTINCT ON (resource_id) b.acl_resource_id AS resource_id, permission AS permission, 4 AS level
  28. FROM
  29. acl_resource_groups_auth_users AS a
  30. JOIN acl_resource_groups_acl_resources b USING (acl_resource_group_id)
  31. JOIN acl_resource_groups c ON (c.id = b.acl_resource_group_id)
  32. WHERE
  33. a.auth_user_id=_user_id
  34. GROUP BY
  35. resource_id, permission, level, priority
  36. ORDER BY
  37. resource_id ASC, c.priority DESC)
  38. UNION
  39. -- Pobranie uprawnien przypisanych do rol uzytkownika (priorytet = 3)
  40. (SELECT
  41. DISTINCT ON (resource_id) b.acl_resource_id AS resource_id, permission AS permission, 3 AS level
  42. FROM
  43. acl_roles_auth_users AS a
  44. JOIN acl_resources_acl_roles b USING (acl_role_id)
  45. JOIN acl_roles c ON (c.id = b.acl_role_id)
  46. WHERE
  47. a.auth_user_id=_user_id
  48. GROUP BY
  49. resource_id, permission, level, priority
  50. ORDER BY
  51. resource_id ASC, c.priority DESC)
  52. UNION
  53. -- Pobranie uprawnien przypisanych do roli ACL uzytkownika (priorytet = 2)
  54. (SELECT
  55. DISTINCT ON (resource_id) c.acl_resource_id AS resource_id, permission AS permission, 2 AS level
  56. FROM
  57. acl_roles_auth_users AS a
  58. JOIN acl_resource_groups_acl_roles AS b USING (acl_role_id)
  59. JOIN acl_resource_groups_acl_resources AS c USING (acl_resource_group_id )
  60. JOIN acl_resource_groups d ON (d.id = b.acl_resource_group_id)
  61. WHERE
  62. a.auth_user_id=_user_id
  63. GROUP BY
  64. resource_id, permission, level, priority
  65. ORDER BY
  66. resource_id ASC, d.priority DESC)
  67. UNION
  68. -- Pobranie uprawnien przypisanych bezposrednio do zasobow (priorytet = 1)
  69. (SELECT
  70. id AS resource_id, permission AS permission, 1 AS level
  71. FROM
  72. acl_resources)
  73. ) AS t
  74. GROUP BY
  75. resource_id, permission, level
  76. ORDER BY
  77. resource_id ASC, level DESC
  78. LOOP
  79. RETURN NEXT row;
  80. END LOOP;
  81. END;
  82. $$
  83. LANGUAGE plpgsql;

smile.gif

PS: Okazuje się jednak, że działa to na 5, a nie 3 poziomach smile.gif hehehe.
mentoos
Dzięki. Wezmę się za robotę systemu, bo się bardzo przydaje ogólnie.
phpowiec84
w jaki sposób należy zmodyfikowac zapytanie do bazy aby działała na MYSQL ?
gothye
phpion

do czego służy tabela : acl_resource_namespaces , skoro nie jet wykorzystana w zapytaniu SQL
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.