ublog

Знайомство з n2o - 5 (2)

programming [33]erlang [32]n2o [17]postgresql [9]

Вітаю!

Існує така штука як RBAC https://en.wikipedia.org/wiki/Role-based_access_control
І зараз ми реалізуємо цей спосіб в ерлангу, з використанням hstore.

Зберігатимемо наші ключі-значення в полі з іменем security_attributes та типом hstore
(напевно у тій же таблиці, де і id-login-password наших користувачів)

в окремий ерланг-модуль hm.erl додамо функції
(назва не важлива, це скорочення від helping module)

has_access(Security_Attributes2, Page) ->
  Not_Banned = not(?MODULE:has_access4(Security_Attributes2, <<"banned">>)),
  ?MODULE:has_access3(Security_Attributes2, Not_Banned, Page).

has_access2(Security_Attributes) ->
  Map1 = #{<<"banned">> => <<"0">>,
    <<"is_user">> => <<"0">>,
    <<"is_moderator">> => <<"0">>,
    <<"is_admin">> => <<"0">>},
  maps:merge(Map1,maps:from_list(Security_Attributes)).

%banned
has_access3(_, false, _) -> false;
%not banned
has_access3(Security_Attributes2, _, <<"mypage1">>) ->
  ?MODULE:has_access4(Security_Attributes2, <<"is_user">>);
has_access3(Security_Attributes2, _, <<"mypage2">>) ->
  ?MODULE:has_access4(Security_Attributes2, <<"is_moderator">>);
has_access3(Security_Attributes2, _, <<"adminka">>) ->
  ?MODULE:has_access4(Security_Attributes2, <<"is_admin">>);
has_access3(_,_,_) -> false.

%get value by key and return bool
has_access4(Security_Attributes2, Key) ->
  case maps:get(Key, Security_Attributes2, undefined) of
    <<"1">> -> true;
    _ -> false
  end.


Пояснення -

Порядок дій
1) отримане з бд значення перетворюємо (proplist -> map) та об'єднуємо зі значеннями по-замовчанню,
значення з бд перезаписують значення по-замовчанню
(в тій же функції has_access2 в 1й map ми і дописуємо групи та додаткові права цієї групи, або ж просто окремі набори прав для кожного нашого користувача, в залежності від потреби)

Security_access2 = hm:has_access2(Security_access),


2) перевіряємо чи має користувач доступ до певної сторінки,
далі виводимо користувачу повідомлення про відсутність доступу|переадресовуємо його на іншу сторінку чи показуємо вибрану сторінку

Access = hm:has_access(Security_access2, <<"mypage1">>),
case Access of
  false ->
    wf:redirect("/login/");
  true ->
    %show mypage1 here
end.


Деталі функцій -
1) has_access2(Security_Attributes) --
отримайний список-proplist з бд перетворюється в map та обєднується зі списком значень по-замовчанню

inputs - отримані з бд Security_Attributes у вигляді proplist
outputs - Security_Attributes2 у вигляді map, включає у себе значення з Security_Attributes та значення по-замовчанню для відсутніх в попередньому списку ключів

2) has_access(Security_Attributes2, Page) --
отримуємо відповідь на запитання "чи забанений користувач" та викликаємо функцію перевірки права доступу до даної сторінки

inputs - Security_Attributes2 - map, Page - binary string (цільова сторінка),
outputs - результат роботи функції has_access3/3, bool

3) has_access3(Security_Attributes2, Not_Banned, Page) --
отримуємо відповідь на запитання "чи має користувач право доступу до цієї сторінки",
якщо користувач забанений - відповідь завжди false

inputs - Security_Attributes2 - map (результат роботи функції has_access2(Security_Attributes) ), Page - binary string (цільова сторінка)
outputs - bool

4) has_access4(Security_Attributes2, Key) --
ця функція просто повертає bool-значення для даного ключа Key з map Security_Attributes2
(<<"1">> -> true, <<"0">> -> false, undefined -> false)


Далі буде)