| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-01-05 20:13:44 +0100 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-01-05 20:13:44 +0100 |
| commit | c29627d6826dba1be9985f9a998bea420d842aae (patch) | |
| tree | 7678c6dc4e44469fe9850e0791bfd89e0f6046db | |
| parent | 76256398ba61e47f71098b1aa6ea511473b93e44 (diff) | |
Implements most of ataxia_server's functions.
| -rw-r--r-- | src/ataxia_security.erl | 4 | ||||
| -rw-r--r-- | src/ataxia_server.erl | 377 | ||||
| -rw-r--r-- | src/ataxic.erl | 40 |
3 files changed, 369 insertions, 52 deletions
diff --git a/src/ataxia_security.erl b/src/ataxia_security.erl index e51ab3c..b1ec662 100644 --- a/src/ataxia_security.erl +++ b/src/ataxia_security.erl @@ -52,8 +52,8 @@ any () -> any. -spec admin () -> user(). admin () -> admin. --spec can_access (permission(), user()) -> boolean(). -can_access (Permission, User) -> +-spec can_access (user(), permission()) -> boolean(). +can_access (User, Permission) -> case User of admin -> true; janitor -> ordsets:is_element(User, Permission); diff --git a/src/ataxia_server.erl b/src/ataxia_server.erl index dfa2f9e..24a8e26 100644 --- a/src/ataxia_server.erl +++ b/src/ataxia_server.erl @@ -31,6 +31,7 @@ remove_all/3 ] ). +-compile([export_all]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -43,21 +44,116 @@ ataxic:meta(), ataxia_id:type() ) - -> 'ok'. + -> {'ok', ataxia_entry:type()}. update_internals (DB, User, OP, ID) -> [Entry] = mnesia:read(DB, ID), true = - ataxia_security:can_access ( - ataxia_entry:get_write_permission(Entry), - User + ataxia_lock:can_access(User, ataxia_entry:get_lock(Entry)) + and + ataxia_security:can_access + ( + User, + ataxia_entry:get_write_permission(Entry) + ) + ), + + UpdatedEntry = ataxic:apply_to(OP, Entry), + + mnesia:write(DB, UpdatedEntry, sticky_write), + + {ok, UpdatedEntry}. + +-spec update_if + ( + atom(), + ataxia_security:user(), + ataxic:meta(), + ataxia_id:type(), + ataxic:basic() + ) + -> ({'ok', ataxia_entry:type()} | no_match). +update_if (DB, User, OP, ID, Cond) -> + [Entry] = mnesia:read(DB, ID), + + true = + ( + ataxia_lock:can_access(User, ataxia_entry:get_lock(Entry)) + and + ataxia_security:can_access + ( + User, + ataxia_entry:get_write_permission(Entry) + ) + ), + + case ataxic:matches(Cond, Entry) of + true -> + UpdatedEntry = ataxic:apply_to(OP, Entry), + mnesia:write(DB, UpdatedEntry, sticky_write), + {ok, UpdatedEntry}; + + _ -> no_match + end. + +-spec remove_internals + ( + atom(), + ataxia_security:user(), + ataxia_id:type() + ) + -> 'ok'. +remove_internals (DB, User, ID) -> + [Entry] = mnesia:read(DB, ID), + + true = + ( + ataxia_lock:can_access(User, ataxia_entry:get_lock(Entry)) + and + ataxia_security:can_access + ( + User, + ataxia_entry:get_write_permission(Entry) + ) ), - mnesia:write(DB, ataxic:apply_to(OP, Entry), sticky_write), + mnesia:delete(DB, ID, sticky_write), + ataxia_id_manager:free(ID, DB), ok. +-spec remove_if + ( + atom(), + ataxia_security:user(), + ataxia_id:type(), + ataxic:basic() + ) + -> ('ok' | 'no_match'). +remove_if (DB, User, ID, Cond) -> + [Entry] = mnesia:read(DB, ID), + + true = + ( + ataxia_lock:can_access(User, ataxia_entry:get_lock(Entry)) + and + ataxia_security:can_access + ( + User, + ataxia_entry:get_write_permission(Entry) + ) + ), + + case ataxic:matches(Cond, Entry) of + true -> + mnesia:delete(DB, ID, sticky_write), + ataxia_id_manager:free(ID, DB), + ok; + + _ -> no_match + end. + -spec add_new_item (atom(), ataxia_entry:type()) -> 'ok'. add_new_item (DB, Item) -> ID = ataxia_entry:get_id(Item), @@ -67,6 +163,34 @@ add_new_item (DB, Item) -> ok. +-spec fetch_if + ( + atom(), + ataxia_security:user(), + ataxia_id:type(), + ataxic:basic() + ) + -> ({'aborted', any()} | {'ok', any()}). +fetch_if (DB, User, ID, Cond) -> + case mnesia:read(DB, ID) of + [Entry] -> + IsAllowed = + ( + ataxia_lock:can_access(User, ataxia_entry:get_lock(Entry)) + and + ataxia_security:can_access + ( + User, + ataxia_entry:get_read_permission(Entry) + ) + ), + case (IsAllowed and ataxic:matches(Cond, Entry)) of + true -> {ok, ataxia_entry:get_value(Entry)}; + _ -> {aborted, no_match} + end; + + Other -> Other + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -149,17 +273,20 @@ fetch (DB, User, ID) -> case mnesia:transaction(fun mnesia:read/2, [DB, ID]) of {atomic, []} -> {aborted, not_found}; {atomic, [Entry]} -> - true = + IsAllowed = ( ataxia_lock:can_access(User, ataxia_entry:get_lock(Entry)) and ataxia_security:can_access ( - ataxia_entry:get_read_permission(Entry), - User + User, + ataxia_entry:get_read_permission(Entry) ) ), - {ok, ataxia_entry:get_value(Entry)}; + case IsAllowed of + true -> {ok, ataxia_entry:get_value(Entry)}; + false -> {aborted, permission_denied} + end; Other -> {aborted, Other} end. @@ -171,8 +298,32 @@ fetch (DB, User, ID) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', any(), ataxia_id:type()}). -fetch_any (_DB, _User, _Cond) -> - {aborted, unimplemented}. +fetch_any (DB, User, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:foldl + ( + fun (Key, Result) -> + case Result of + {ok, _, _} -> Result; + _ -> + case + mnesia:transaction + ( + fun fetch_if/4, + [DB, User, Key, Cond] + ) + of + {atomic, {ok, Value}} -> {ok, Value, Key}; + _ -> Result + end + end + end, + {aborted, no_match}, + PotentialDBKeys + ), + + Result. -spec fetch_all ( @@ -180,9 +331,28 @@ fetch_any (_DB, _User, _Cond) -> ataxia_security:user(), ataxic:basic() ) - -> ({'aborted', any()} | {'ok', any(), ataxia_id:type()}). -fetch_all (_DB, _User, _Cond) -> - {aborted, unimplemented}. + -> ({'aborted', any()} | {'ok', list({any(), ataxia_id:type()})}). +fetch_all (DB, User, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:filtermap + ( + fun (Key) -> + case + mnesia:transaction + ( + fun fetch_if/4, + [DB, User, Key, Cond] + ) + of + {atomic, {ok, Value}} -> {true, {Value, Key}}; + _ -> false + end + end, + PotentialDBKeys + ), + + {ok, Result}. -spec update ( @@ -200,7 +370,7 @@ update (DB, User, Update, ID) -> [DB, User, Update, ID] ) of - {atomic, ok} -> ok; + {atomic, {ok, _}} -> ok; Other -> {aborted, Other} end. @@ -212,8 +382,32 @@ update (DB, User, Update, ID) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', ataxia_id:type()}). -update_any (_DB, _User, _Update, _Cond) -> - {aborted, unimplemented}. +update_any (DB, User, Update, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:foldl + ( + fun (Key, Result) -> + case Result of + {ok, _} -> Result; + _ -> + case + mnesia:transaction + ( + fun update_if/5, + [DB, User, Update, Key, Cond] + ) + of + {atomic, {ok, _}} -> {ok, Key}; + _ -> Result + end + end + end, + {aborted, no_match}, + PotentialDBKeys + ), + + Result. -spec update_all ( @@ -223,8 +417,27 @@ update_any (_DB, _User, _Update, _Cond) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', list(ataxia_id:type())}). -update_all (_DB, _User, _Update, _Cond) -> - {aborted, unimplemented}. +update_all (DB, User, Update, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:filtermap + ( + fun (Key) -> + case + mnesia:transaction + ( + fun update_if/5, + [DB, User, Update, Key, Cond] + ) + of + {atomic, {ok, _}} -> {true, Key}; + _ -> false + end + end, + PotentialDBKeys + ), + + {ok, Result}. -spec update_and_fetch ( @@ -234,8 +447,17 @@ update_all (_DB, _User, _Update, _Cond) -> ataxia_id:type() ) -> ({'aborted', any()} | {'ok', any()}). -update_and_fetch (_DB, _User, _Update, _ID) -> - {aborted, unimplemented}. +update_and_fetch (DB, User, Update, ID) -> + case + mnesia:transaction + ( + fun update_internals/4, + [DB, User, Update, ID] + ) + of + {atomic, {ok, Entry}} -> {ok, ataxia_entry:get_value(Entry)}; + Other -> {aborted, Other} + end. -spec update_and_fetch_any ( @@ -245,8 +467,34 @@ update_and_fetch (_DB, _User, _Update, _ID) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', any(), ataxia_id:type()}). -update_and_fetch_any (_DB, _User, _Update, _Cond) -> - {aborted, unimplemented}. +update_and_fetch_any (DB, User, Update, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:foldl + ( + fun (Key, Result) -> + case Result of + {ok, _} -> Result; + _ -> + case + mnesia:transaction + ( + fun update_if/5, + [DB, User, Update, Key, Cond] + ) + of + {atomic, {ok, Entry}} -> + {ok, ataxia_entry:get_value(Entry), Key}; + + _ -> Result + end + end + end, + {aborted, no_match}, + PotentialDBKeys + ), + + Result. -spec update_and_fetch_all ( @@ -256,8 +504,29 @@ update_and_fetch_any (_DB, _User, _Update, _Cond) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', list({any(), ataxia_id:type()})}). -update_and_fetch_all (_DB, _User, _Update, _Cond) -> - {aborted, unimplemented}. +update_and_fetch_all (DB, User, Update, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:filtermap + ( + fun (Key) -> + case + mnesia:transaction + ( + fun update_if/5, + [DB, User, Update, Key, Cond] + ) + of + {atomic, {ok, Entry}} -> + {true, {ataxia_entry:get_value(Entry), Key}}; + + _ -> false + end + end, + PotentialDBKeys + ), + + {ok, Result}. -spec remove ( @@ -266,8 +535,11 @@ update_and_fetch_all (_DB, _User, _Update, _Cond) -> ataxia_id:type() ) -> ({'aborted', any()} | 'ok'). -remove (_DB, _User, _ID) -> - {aborted, unimplemented}. +remove (DB, User, ID) -> + case mnesia:transaction(fun remove_internals/3, [DB, User, ID]) of + {atomic, ok} -> ok; + Other -> {aborted, Other} + end. -spec remove_any ( @@ -276,8 +548,32 @@ remove (_DB, _User, _ID) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', ataxia_id:type()}). -remove_any (_DB, _User, _Cond) -> - {aborted, unimplemented}. +remove_any (DB, User, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:foldl + ( + fun (Key, Result) -> + case Result of + {ok, _} -> Result; + _ -> + case + mnesia:transaction + ( + fun remove_if/4, + [DB, User, Key, Cond] + ) + of + {atomic, ok} -> {ok, Key}; + _ -> Result + end + end + end, + {aborted, no_match}, + PotentialDBKeys + ), + + Result. -spec remove_all ( @@ -286,5 +582,24 @@ remove_any (_DB, _User, _Cond) -> ataxic:basic() ) -> ({'aborted', any()} | {'ok', list(ataxia_id:type())}). -remove_all (_DB, _User, _Cond) -> - {aborted, unimplemented}. +remove_all (DB, User, Cond) -> + PotentialDBKeys = mnesia:dirty_all_keys(DB), + Result = + lists:filtermap + ( + fun (Key) -> + case + mnesia:transaction + ( + fun remove_if/4, + [DB, User, Key, Cond] + ) + of + {atomic, ok} -> {true, Key}; + _ -> false + end + end, + PotentialDBKeys + ), + + {ok, Result}. diff --git a/src/ataxic.erl b/src/ataxic.erl index 438cf17..6e941c4 100644 --- a/src/ataxic.erl +++ b/src/ataxic.erl @@ -113,25 +113,25 @@ basic_apply_to (#const{ value = Val }, _Val) -> basic_apply_to (#current{}, Val) -> Val; -basic_apply_to (#ge{ p0 = P0, p1 = P1 }, _Val) -> - P0 >= P1; -basic_apply_to (#gt{ p0 = P0, p1 = P1 }, _Val) -> - P0 > P1; -basic_apply_to (#le{ p0 = P0, p1 = P1 }, _Val) -> - P0 =< P1; -basic_apply_to (#lt{ p0 = P0, p1 = P1 }, _Val) -> - P0 < P1; -basic_apply_to (#eq{ p0 = P0, p1 = P1 }, _Val) -> - P0 == P1; - -basic_apply_to (#land{ params = List }, _Val) -> - lists:all(fun (E) -> E end, List); - -basic_apply_to (#lor{ params = List }, _Val) -> - lists:any(fun (E) -> E end, List); - -basic_apply_to (#neg{ param = V }, _Val) -> - not V. +basic_apply_to (#ge{ p0 = P0, p1 = P1 }, Val) -> + basic_apply_to(P0, Val) >= basic_apply_to(P1, Val); +basic_apply_to (#gt{ p0 = P0, p1 = P1 }, Val) -> + basic_apply_to(P0, Val) > basic_apply_to(P1, Val); +basic_apply_to (#le{ p0 = P0, p1 = P1 }, Val) -> + basic_apply_to(P0, Val) =< basic_apply_to(P1, Val); +basic_apply_to (#lt{ p0 = P0, p1 = P1 }, Val) -> + basic_apply_to(P0, Val) < basic_apply_to(P1, Val); +basic_apply_to (#eq{ p0 = P0, p1 = P1 }, Val) -> + basic_apply_to(P0, Val) == basic_apply_to(P1, Val); + +basic_apply_to (#land{ params = List }, Val) -> + lists:all(fun (E) -> basic_apply_to(E, Val) end, List); + +basic_apply_to (#lor{ params = List }, Val) -> + lists:any(fun (E) -> basic_apply_to(E, Val) end, List); + +basic_apply_to (#neg{ param = V }, Val) -> + not basic_apply_to(V, Val). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -227,6 +227,8 @@ apply_to (#mseq { ops = List }, Entry) -> -spec matches (basic(), ataxia_entry:type()) -> boolean(). matches (OP, Entry) -> + Result = basic_apply_to(OP, Entry), + io:format("matches test result:~p~n", [Result]), case basic_apply_to(OP, Entry) of true -> true; _ -> false |


