summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-01-05 20:13:44 +0100
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-01-05 20:13:44 +0100
commitc29627d6826dba1be9985f9a998bea420d842aae (patch)
tree7678c6dc4e44469fe9850e0791bfd89e0f6046db
parent76256398ba61e47f71098b1aa6ea511473b93e44 (diff)
Implements most of ataxia_server's functions.
-rw-r--r--src/ataxia_security.erl4
-rw-r--r--src/ataxia_server.erl377
-rw-r--r--src/ataxic.erl40
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