| summaryrefslogtreecommitdiff | 
diff options
| -rw-r--r-- | src/ataxia_client.erl | 139 | ||||
| -rw-r--r-- | src/ataxia_lock.erl | 62 | ||||
| -rw-r--r-- | src/ataxia_security.erl | 40 | 
3 files changed, 149 insertions, 92 deletions
| diff --git a/src/ataxia_client.erl b/src/ataxia_client.erl index a2e47a8..4703b9f 100644 --- a/src/ataxia_client.erl +++ b/src/ataxia_client.erl @@ -14,19 +14,19 @@        add_at/5,        reserve/3, -      fetch/4, +      fetch/3,        update/4, -      lock/4, +      update_and_fetch/4,        remove/3, -      fetch_any/4, +      fetch_any/3,        update_any/4, -      lock_any/4, +      update_and_fetch_any/4,        remove_any/3, -      fetch_all/4, +      fetch_all/3,        update_all/4, -      lock_all/4, +      update_and_fetch_all/4,        remove_all/3     ]  ). @@ -64,7 +64,7 @@ add_at (DB, ID, ReadPerm, WritePerm, Value) ->        rpc:call        (           DBNode, -         atexia_server, +         ataxia_server,           add_at,           [DB, ID, ReadPerm, WritePerm, Value]        ), @@ -89,7 +89,7 @@ add (DB, ReadPerm, WritePerm, Value) ->     DBNode = get_random_db_node(),     Reply = -      rpc:call(DBNode, atexia_server, add, [DB, ReadPerm, WritePerm, Value]), +      rpc:call(DBNode, ataxia_server, add, [DB, ReadPerm, WritePerm, Value]),     io:format     ( @@ -109,7 +109,7 @@ add (DB, ReadPerm, WritePerm, Value) ->  reserve (DB, User, ID) ->     DBNode = get_db_node_for(ID), -   Reply = rpc:call(DBNode, atexia_server, reserve, [DB, User, ID]), +   Reply = rpc:call(DBNode, ataxia_server, reserve, [DB, User, ID]),     io:format     ( @@ -125,19 +125,18 @@ reserve (DB, User, ID) ->     (        atom(),        ataxia_security:user(), -      ataxic:type(),        ataxia_id:type()     )     -> ({'ok', any()} | 'not_found'). -fetch (DB, User, Selector, ID) -> +fetch (DB, User, ID) ->     DBNode = get_db_node_for(ID), -   Reply = rpc:call(DBNode, atexia_server, fetch, [DB, User, Selector, ID]), +   Reply = rpc:call(DBNode, ataxia_server, fetch, [DB, User, ID]),     io:format     (        "~nataxia_client:fetch(~p) ! ~p -> ~p.~n", -      [{DB, User, Selector, ID}, DBNode, Reply] +      [{DB, User, ID}, DBNode, Reply]     ),     Reply. @@ -146,14 +145,14 @@ fetch (DB, User, Selector, ID) ->     (        atom(),        ataxia_security:user(), -      ataxiac:meta(), +      ataxic:meta(),        ataxia_id:type()     )     -> ('ok' | 'not_found').  update (DB, User, Op, ID) ->     DBNode = get_db_node_for(ID), -   Reply = rpc:call(DBNode, atexia_server, update, [DB, User, Op, ID]), +   Reply = rpc:call(DBNode, ataxia_server, update, [DB, User, Op, ID]),     io:format     ( @@ -163,23 +162,24 @@ update (DB, User, Op, ID) ->     Reply. --spec lock +-spec update_and_fetch     (        atom(),        ataxia_security:user(), -      ataxia_time:type(), +      ataxic:meta(),        ataxia_id:type()     ) -   -> ('ok' | 'not_found'). -lock (DB, User, Duration, ID) -> +   -> ({'ok', any()} | 'not_found'). +update_and_fetch (DB, User, Op, ID) ->     DBNode = get_db_node_for(ID), -   Reply = rpc:call(DBNode, atexia_server, lock, [DB, User, Duration, ID]), +   Reply = +      rpc:call(DBNode, ataxia_server, update_and_fetch, [DB, User, Op, ID]),     io:format     ( -      "~nataxia_client:lock(~p) ! ~p -> ~p.~n", -      [{DB, User, Duration, ID}, DBNode, Reply] +      "~nataxia_client:update_and_fetch(~p) ! ~p -> ~p.~n", +      [{DB, User, Op, ID}, DBNode, Reply]     ),     Reply. @@ -195,7 +195,7 @@ lock (DB, User, Duration, ID) ->  remove (DB, User, ID) ->     DBNode = get_db_node_for(ID), -   Reply = rpc:call(DBNode, atexia_server, remove, [DB, User, ID]), +   Reply = rpc:call(DBNode, ataxia_server, remove, [DB, User, ID]),     io:format     ( @@ -210,27 +210,19 @@ remove (DB, User, ID) ->     (        atom(),        ataxia_security:user(), -      ataxic:type(), -      ataxic:meta() +      ataxic:basic()     )     -> ({'ok', ataxia_id:type(), any()} | 'not_found'). -fetch_any (DB, User, Selector, Condition) -> +fetch_any (DB, User, Condition) ->     % TODO: Try all nodes one by one until one is found.     DBNode = get_db_node_for(<<"">>), -   Reply = -      rpc:call -      ( -         DBNode, -         atexia_server, -         fetch_any, -         [DB, User, Selector, Condition] -      ), +   Reply = rpc:call(DBNode, ataxia_server, fetch_any, [DB, User, Condition]),     io:format     (        "~nataxia_client:fetch_any(~p) ! ~p -> ~p.~n", -      [{DB, User, Selector, Condition}, DBNode, Reply] +      [{DB, User, Condition}, DBNode, Reply]     ),     Reply. @@ -239,8 +231,8 @@ fetch_any (DB, User, Selector, Condition) ->     (        atom(),        ataxia_security:user(), -      ataxiac:meta(), -      ataxiac:meta() +      ataxic:meta(), +      ataxic:basic()     )     -> ({'ok', ataxia_id:type()} | 'not_found').  update_any (DB, User, Op, Condition) -> @@ -248,7 +240,7 @@ update_any (DB, User, Op, Condition) ->     DBNode = get_db_node_for(<<"">>),     Reply = -      rpc:call(DBNode, atexia_server, update_any, [DB, User, Op, Condition]), +      rpc:call(DBNode, ataxia_server, update_any, [DB, User, Op, Condition]),     io:format     ( @@ -258,15 +250,15 @@ update_any (DB, User, Op, Condition) ->     Reply. --spec lock_any +-spec update_and_fetch_any     (        atom(),        ataxia_security:user(), -      ataxia_time:type(), -      ataxic:meta() +      ataxic:meta(), +      ataxic:basic()     ) -   -> ({'ok', ataxia_id:type()} | 'not_found'). -lock_any (DB, User, Duration, Condition) -> +   -> ({'ok', any(), ataxia_id:type()} | 'not_found'). +update_and_fetch_any (DB, User, Op, Condition) ->     % TODO: Try all nodes one by one until one is found.     DBNode = get_db_node_for(<<"">>), @@ -274,31 +266,32 @@ lock_any (DB, User, Duration, Condition) ->        rpc:call        (           DBNode, -         atexia_server, -         lock_any, -         [DB, User, Duration, Condition] +         ataxia_server, +         update_and_fetch_any, +         [DB, User, Op, Condition]        ),     io:format     ( -      "~nataxia_client:lock_any(~p) ! ~p -> ~p.~n", -      [{DB, User, Duration, Condition}, DBNode, Reply] +      "~nataxia_client:update_and_fetch(~p) ! ~p -> ~p.~n", +      [{DB, User, Op, Condition}, DBNode, Reply]     ),     Reply. +  -spec remove_any     (        atom(),        ataxia_security:user(), -      ataxic:meta() +      ataxic:basic()     )     -> ({'ok', ataxia_id:type()} | 'not_found').  remove_any (DB, User, Condition) ->     % TODO: Try all nodes one by one until one is found.     DBNode = get_db_node_for(<<"">>), -   Reply = rpc:call(DBNode, atexia_server, remove_any, [DB, User, Condition]), +   Reply = rpc:call(DBNode, ataxia_server, remove_any, [DB, User, Condition]),     io:format     ( @@ -313,27 +306,19 @@ remove_any (DB, User, Condition) ->     (        atom(),        ataxia_security:user(), -      ataxic:type(), -      ataxic:meta() +      ataxic:basic()     )     -> ({'ok', list({ataxia_id:type(), any()})}). -fetch_all (DB, User, Selector, Condition) -> +fetch_all (DB, User, Condition) ->     % TODO: Try all nodes one by one, apply to all they matching items.     DBNode = get_db_node_for(<<"">>), -   Reply = -      rpc:call -      ( -         DBNode, -         atexia_server, -         fetch_all, -         [DB, User, Selector, Condition] -      ), +   Reply = rpc:call ( DBNode, ataxia_server, fetch_all, [DB, User, Condition]),     io:format     (        "~nataxia_client:fetch_all(~p) ! ~p -> ~p.~n", -      [{DB, User, Selector, Condition}, DBNode, Reply] +      [{DB, User, Condition}, DBNode, Reply]     ),     Reply. @@ -342,8 +327,8 @@ fetch_all (DB, User, Selector, Condition) ->     (        atom(),        ataxia_security:user(), -      ataxiac:meta(), -      ataxiac:meta() +      ataxic:meta(), +      ataxic:basic()     )     -> {'ok', list(ataxia_id:type())}.  update_all (DB, User, Op, Condition) -> @@ -351,7 +336,7 @@ update_all (DB, User, Op, Condition) ->     DBNode = get_db_node_for(<<"">>),     Reply = -      rpc:call(DBNode, atexia_server, update_all, [DB, User, Op, Condition]), +      rpc:call(DBNode, ataxia_server, update_all, [DB, User, Op, Condition]),     io:format     ( @@ -361,15 +346,15 @@ update_all (DB, User, Op, Condition) ->     Reply. --spec lock_all +-spec update_and_fetch_all     (        atom(),        ataxia_security:user(), -      ataxia_time:type(), -      ataxic:meta() +      ataxic:meta(), +      ataxic:basic()     ) -   -> {'ok', list(ataxia_id:type())}. -lock_all (DB, User, Duration, Condition) -> +   -> {'ok', list({any(), ataxia_id:type()})}. +update_and_fetch_all (DB, User, Op, Condition) ->     % TODO: Try all nodes one by one, apply to all they matching items.     DBNode = get_db_node_for(<<"">>), @@ -377,15 +362,15 @@ lock_all (DB, User, Duration, Condition) ->        rpc:call        (           DBNode, -         atexia_server, -         lock_all, -         [DB, User, Duration, Condition] +         ataxia_server, +         update_and_fetch_all, +         [DB, User, Op, Condition]        ),     io:format     ( -      "~nataxia_client:lock_all(~p) ! ~p -> ~p.~n", -      [{DB, User, Duration, Condition}, DBNode, Reply] +      "~nataxia_client:update_and_fetch(~p) ! ~p -> ~p.~n", +      [{DB, User, Op, Condition}, DBNode, Reply]     ),     Reply. @@ -394,14 +379,14 @@ lock_all (DB, User, Duration, Condition) ->     (        atom(),        ataxia_security:user(), -      ataxic:meta() +      ataxic:basic()     )     -> {'ok', list(ataxia_id:type())}.  remove_all (DB, User, Condition) ->     % TODO: Try all nodes one by one, apply to all they matching items.     DBNode = get_db_node_for(<<"">>), -   Reply = rpc:call(DBNode, atexia_server, remove_all, [DB, User, Condition]), +   Reply = rpc:call(DBNode, ataxia_server, remove_all, [DB, User, Condition]),     io:format     ( diff --git a/src/ataxia_lock.erl b/src/ataxia_lock.erl new file mode 100644 index 0000000..b6ce2c6 --- /dev/null +++ b/src/ataxia_lock.erl @@ -0,0 +1,62 @@ +-module(ataxia_lock). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type status() :: none | locked. + +-record +( +   lock, +   { +      status :: status(), +      permission :: ataxia_security:permission(), +      time :: ataxia_time:type() +   } +). + +-type type() :: #lock{}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export_type([type/0]). + +-export([locked/2, unlocked/0, allows/2]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec locked (ataxia_security:user(), ataxia_time:type()) -> type(). +locked (User, Time) -> +   #lock +   { +      status = locked, +      permission = ataxia_security:allow_only(User), +      time = ataxia_time:add(ataxia_time:now(), Time) +   }. + +-spec unlocked () -> type(). +unlocked () -> +   #lock +   { +      status = none, +      permission = ataxia_security:allow_only(ataxia_security:any()), +      time = ataxia_time:now() +   }. + +-spec allows (ataxia_security:user(), type()) -> boolean(). +allows (User, Lock) -> +   case Lock#lock.status of +      none -> true; +      locked -> +         ( +            ataxia_security:can_access(Lock#lock.permission, User) +            or ataxia_time:is_past(Lock#lock.time) +         ) +   end. + diff --git a/src/ataxia_security.erl b/src/ataxia_security.erl index 192171f..7654384 100644 --- a/src/ataxia_security.erl +++ b/src/ataxia_security.erl @@ -5,16 +5,17 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  -type named_user() :: {'user', any()}.  -type user() :: (named_user() | 'admin' | 'any' | 'janitor'). --type permission() :: (list(named_user()) | 'any' | 'janitor'). +-type permission() :: ordset:ordset(user()).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  -export_type([user/0, permission/0]). --export([can_access/2]).  -export([janitor/0, any/0, admin/0, user_from_id/1]). --export([unlocked/0]). + +-export([add_access/2, remove_access/2, allow_only/1]). +-export([can_access/2]).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23,6 +24,18 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec add_access (user(), permission()) -> permission(). +add_access (User, Permission) -> +   ordset:add_element(User, Permission). + +-spec remove_access (user(), permission()) -> permission(). +remove_access (User, Permission) -> +   ordset:del_element(User, Permission). + +-spec allow_only (user()) -> permission(). +allow_only (User) -> +   ordset:add_element(User, ordset:new()). +  -spec user_from_id (any()) -> user().  user_from_id (ID) -> {user, ID}. @@ -35,16 +48,13 @@ any () -> any.  -spec admin () -> user().  admin () -> admin. --spec unlocked () -> atom(). -unlocked () -> none. -  -spec can_access (permission(), user()) -> boolean(). -can_access (_, admin) -> true; -can_access (any, _) -> true; -can_access (janitor, janitor) -> true; -can_access (List, {user, User}) -> -   lists:member({user, User}, List); -can_access (List, janitor) -> -   lists:member(janitor, List); -can_access (List, User) -> -   can_access(List, {user, User}). +can_access (Permission, User) -> +   case User of +      admin -> true; +      _ -> +         ( +            ordset:is_element(any, Permission) +            or ordset:is_element(User, Permission) +         ) +   end. | 


