Знайомство з Erlang [5-2]

Продовжуємо роботу в erlang з postgresql - hstore

Існує така штука як 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),
  1. перевіряємо чи має користувач доступ до певної сторінки,
    далі виводимо користувачу повідомлення про відсутність доступу|переадресовуємо його на іншу сторінку чи показуємо вибрану сторінку
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 та значення по-замовчанню для відсутніх в попередньому списку ключів

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

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

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

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

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

Продовження

Посилання

https://en.wikipedia.org/wiki/Role-based_access_control