From 25b3f31c8a451044459d104a3a36f919557b8d20 Mon Sep 17 00:00:00 2001 From: nsensfel Date: Mon, 4 Jun 2018 17:39:23 +0200 Subject: Analysis of 'db' -> crash. Always a good sign... --- src/db/include/db_item.hrl | 15 +++++++ src/db/include/db_query.hrl | 10 ++--- src/db/include/db_user.hrl | 7 +++ src/db/src/logic/storage_access.erl | 46 +++++++++++++++++++ src/db/src/storage_access.erl | 46 ------------------- src/db/src/storage_query.erl | 90 ------------------------------------- src/db/src/struct/db_item.erl | 64 ++++++++++++++++++++++++++ src/db/src/struct/db_query.erl | 90 +++++++++++++++++++++++++++++++++++++ src/db/src/struct/db_user.erl | 28 ++++++++++++ 9 files changed, 254 insertions(+), 142 deletions(-) create mode 100644 src/db/include/db_item.hrl create mode 100644 src/db/include/db_user.hrl create mode 100644 src/db/src/logic/storage_access.erl delete mode 100644 src/db/src/storage_access.erl delete mode 100644 src/db/src/storage_query.erl create mode 100644 src/db/src/struct/db_item.erl create mode 100644 src/db/src/struct/db_query.erl create mode 100644 src/db/src/struct/db_user.erl diff --git a/src/db/include/db_item.hrl b/src/db/include/db_item.hrl new file mode 100644 index 0000000..86d5863 --- /dev/null +++ b/src/db/include/db_item.hrl @@ -0,0 +1,15 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-record +( + db_item, + { + id :: any(), + perm :: db_user:permission(), + val :: any() + } +). + +-type db_item() :: #db_item{}. + diff --git a/src/db/include/db_query.hrl b/src/db/include/db_query.hrl index 45c040b..ac7745a 100644 --- a/src/db/include/db_query.hrl +++ b/src/db/include/db_query.hrl @@ -1,8 +1,6 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --type db_user() :: ({'user', any()} | 'admin' | 'any'). - -record ( set_field, @@ -34,9 +32,9 @@ -record ( - set_user, + set_perm, { - user :: db_user() + perm :: db_user:permission() } ). @@ -46,12 +44,12 @@ { db :: atom(), id :: any(), - user :: db_user(), + user :: db_user:user(), ops :: list(db_query_master_op()) } ). -type db_query_op() :: (#set_field{} | #add_to_field{} | #update_indexed{}). --type db_query_master_op() :: (db_query_op() | #set_user{}). +-type db_query_master_op() :: (db_query_op() | #set_perm{}). -type db_query() :: #db_query{}. diff --git a/src/db/include/db_user.hrl b/src/db/include/db_user.hrl new file mode 100644 index 0000000..c5b033e --- /dev/null +++ b/src/db/include/db_user.hrl @@ -0,0 +1,7 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type db_named_user() :: {'user', any()}. +-type db_user() :: (db_named_user() | 'admin' | 'any'). +-type db_permission() :: (list(db_named_user()) | 'any'). + diff --git a/src/db/src/logic/storage_access.erl b/src/db/src/logic/storage_access.erl new file mode 100644 index 0000000..c58f26d --- /dev/null +++ b/src/db/src/logic/storage_access.erl @@ -0,0 +1,46 @@ +-module(storage_access). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-record(regval, {id, owner, val}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + read/2, + insert/4, + update/3 + ] +). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +get_value ([]) -> not_found; +get_value ([Regval]) -> {ok, Regval}. + +get_value(DB, ID) -> get_value(mnesia:read(DB, ID)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +read (DB, ID) -> + get_value(mnesia:read(DB, ID)). + +insert (DB, ID, Owner, Value) -> + StoredItem = #regval{ id = ID, owner = Owner, val = Value }, + % FIXME: handle return value, mnesia:write -> (transaction abort | ok). + % FIXME: is this an atomic OP? Is the lock freed afterwards? + mnesia:write(DB, StoredItem, sticky_write), + ok. + +update (DB, ID, Query) -> + {ok, Item} = get_value(DB, ID), + {ok, UpdatedItem} = db_query:apply_to(Query, Item), + % FIXME: handle return value, mnesia:write -> (transaction abort | ok). + % FIXME: is this an atomic OP? Is the lock freed afterwards? + mnesia:write(DB, UpdatedItem, sticky_write), + ok. diff --git a/src/db/src/storage_access.erl b/src/db/src/storage_access.erl deleted file mode 100644 index c58f26d..0000000 --- a/src/db/src/storage_access.erl +++ /dev/null @@ -1,46 +0,0 @@ --module(storage_access). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --record(regval, {id, owner, val}). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - read/2, - insert/4, - update/3 - ] -). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_value ([]) -> not_found; -get_value ([Regval]) -> {ok, Regval}. - -get_value(DB, ID) -> get_value(mnesia:read(DB, ID)). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -read (DB, ID) -> - get_value(mnesia:read(DB, ID)). - -insert (DB, ID, Owner, Value) -> - StoredItem = #regval{ id = ID, owner = Owner, val = Value }, - % FIXME: handle return value, mnesia:write -> (transaction abort | ok). - % FIXME: is this an atomic OP? Is the lock freed afterwards? - mnesia:write(DB, StoredItem, sticky_write), - ok. - -update (DB, ID, Query) -> - {ok, Item} = get_value(DB, ID), - {ok, UpdatedItem} = db_query:apply_to(Query, Item), - % FIXME: handle return value, mnesia:write -> (transaction abort | ok). - % FIXME: is this an atomic OP? Is the lock freed afterwards? - mnesia:write(DB, UpdatedItem, sticky_write), - ok. diff --git a/src/db/src/storage_query.erl b/src/db/src/storage_query.erl deleted file mode 100644 index 5b37f2d..0000000 --- a/src/db/src/storage_query.erl +++ /dev/null @@ -1,90 +0,0 @@ --module(storage_query). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --include("../include/db_query.hrl"). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([apply_to/2]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec get_user (db_query()) -> db_user(). -get_user (#db_query{ user = Result }) -> Result. - --spec apply_update_indexed (#update_indexed{}, any()) -> any(). -apply_update_indexed (Op, Elem) -> - FieldNumber = Op#update_indexed.field, - IX = Op#update_indexed.ix, - Ops = Op#update_indexed.ops, - - IndexedFieldValue = element(FieldNumber, Elem), - ArrayValue = array:get(IX, IndexedFieldValue), - UpdatedArrayValue = lists:foldl(fun apply_op_to/2, ArrayValue, Ops), - UpdatedIndexedFieldValue = array:set(IX, UpdatedArrayValue), - - setelement(FieldNumber, Elem, UpdatedIndexedFieldValue). - --spec apply_add_to_field (#add_to_field{}, any()) -> any(). -apply_add_to_field (Op, Elem) -> - FieldNumber = Op#add_to_field.field, - NewValues = Op#add_to_field.values, - AddToHead = Op#add_to_field.head, - - CurrentValues = element(FieldNumber, Elem), - UpdatedValues = - case AddToHead of - true -> (NewValues ++ CurrentValues); - _ -> (CurrentValues ++ NewValues) - end, - - setelement(FieldNumber, Elem, UpdatedValues). - --spec apply_set_field (#set_field{}, any()) -> any(). -apply_set_field (Op, Elem) -> - FieldNumber = Op#set_field.field, - NewValue = Op#set_field.value, - - setelement(FieldNumber, Elem, NewValue). - --spec apply_op_to (db_query_op(), any()) -> any(). -apply_op_to (Op, Elem) when is_record(Elem, set_field) -> - apply_set_field(Op, Elem); -apply_op_to (Op, Elem) when is_record(Elem, add_to_field) -> - apply_add_to_field(Op, Elem); -apply_op_to (Op, Elem) when is_record(Elem, update_indexed) -> - apply_update_indexed(Op, Elem). - --spec apply_master_op_to - ( - db_query_master_op(), - db_item:type() - ) - -> db_item:type(). -apply_master_op_to (MOp, Elem) when is_record(MOp, set_user) -> - NewUser = MOp#set_user.user, - - db_item:set_user(NewUser, Elem); -apply_master_op_to (MOp, Elem) -> - OldValue = db_item:get_value(Elem), - NewValue = apply_op_to(MOp, OldValue), - - db_item:set_value(NewValue, Elem). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec apply_to - ( - db_query(), - db_item:type() - ) - -> ({'ok', db_item:type()} | 'error'). -apply_to (DBQuery, DBItem) -> - true = db_user:has_permission(db_item:get_user(DBItem), get_user(DBQuery)), - {ok, apply_master_op_to(DBQuery, DBItem)}. - diff --git a/src/db/src/struct/db_item.erl b/src/db/src/struct/db_item.erl new file mode 100644 index 0000000..6ec79d0 --- /dev/null +++ b/src/db/src/struct/db_item.erl @@ -0,0 +1,64 @@ +-module(db_item). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-include("../../include/db_item.hrl"). + +-type type() :: db_item(). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export_type([type/0]). + +-export +( + [ + new/3, + + get_id/1, + get_permission/1, + get_value/1, + + set_permission/2, + set_value/2, + + get_id_field/0 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec new (any(), db_user:permission(), any()) -> type(). +new (ID, Permission, Value) -> + #db_item + { + id = ID, + perm = Permission, + val = Value + }. + +-spec get_id (type()) -> any(). +get_id (#db_item { id = Result }) -> Result. + +-spec get_permission (type()) -> db_user:permission(). +get_permission (#db_item { perm = Result }) -> Result. + +-spec get_value (type()) -> any(). +get_value (#db_item { val = Result }) -> Result. + +-spec set_permission (db_user:permission(), type()) -> type(). +set_permission (Perm, Item) -> Item#db_item{ perm = Perm }. + +-spec set_value (any(), type()) -> type(). +set_value (Value, Item) -> Item#db_item{ val = Value }. + +-spec get_id_field () -> non_neg_integer(). +get_id_field () -> #db_item.id. + diff --git a/src/db/src/struct/db_query.erl b/src/db/src/struct/db_query.erl new file mode 100644 index 0000000..18d0a12 --- /dev/null +++ b/src/db/src/struct/db_query.erl @@ -0,0 +1,90 @@ +-module(db_query). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-include("../../include/db_query.hrl"). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([apply_to/2]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_user (db_query()) -> db_user:user(). +get_user (#db_query{ user = Result }) -> Result. + +-spec apply_update_indexed (#update_indexed{}, any()) -> any(). +apply_update_indexed (Op, Elem) -> + FieldNumber = Op#update_indexed.field, + IX = Op#update_indexed.ix, + Ops = Op#update_indexed.ops, + + IndexedFieldValue = element(FieldNumber, Elem), + ArrayValue = array:get(IX, IndexedFieldValue), + UpdatedArrayValue = lists:foldl(fun apply_op_to/2, ArrayValue, Ops), + UpdatedIndexedFieldValue = array:set(IX, UpdatedArrayValue), + + setelement(FieldNumber, Elem, UpdatedIndexedFieldValue). + +-spec apply_add_to_field (#add_to_field{}, any()) -> any(). +apply_add_to_field (Op, Elem) -> + FieldNumber = Op#add_to_field.field, + NewValues = Op#add_to_field.values, + AddToHead = Op#add_to_field.head, + + CurrentValues = element(FieldNumber, Elem), + UpdatedValues = + case AddToHead of + true -> (NewValues ++ CurrentValues); + _ -> (CurrentValues ++ NewValues) + end, + + setelement(FieldNumber, Elem, UpdatedValues). + +-spec apply_set_field (#set_field{}, any()) -> any(). +apply_set_field (Op, Elem) -> + FieldNumber = Op#set_field.field, + NewValue = Op#set_field.value, + + setelement(FieldNumber, Elem, NewValue). + +-spec apply_op_to (db_query_op(), any()) -> any(). +apply_op_to (Op, Elem) when is_record(Elem, set_field) -> + apply_set_field(Op, Elem); +apply_op_to (Op, Elem) when is_record(Elem, add_to_field) -> + apply_add_to_field(Op, Elem); +apply_op_to (Op, Elem) when is_record(Elem, update_indexed) -> + apply_update_indexed(Op, Elem). + +-spec apply_master_op_to + ( + db_query_master_op(), + db_item:type() + ) + -> db_item:type(). +apply_master_op_to (MOp, Elem) when is_record(MOp, set_perm) -> + NewPerm = MOp#set_perm.perm, + + db_item:set_perm(NewPerm, Elem); +apply_master_op_to (MOp, Elem) -> + OldValue = db_item:get_value(Elem), + NewValue = apply_op_to(MOp, OldValue), + + db_item:set_value(NewValue, Elem). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec apply_to + ( + db_query(), + db_item:type() + ) + -> ({'ok', db_item:type()} | 'error'). +apply_to (DBQuery, DBItem) -> + true = db_user:can_access(db_item:get_permission(DBItem), get_user(DBQuery)), + {ok, apply_master_op_to(DBQuery, DBItem)}. + diff --git a/src/db/src/struct/db_user.erl b/src/db/src/struct/db_user.erl new file mode 100644 index 0000000..983013c --- /dev/null +++ b/src/db/src/struct/db_user.erl @@ -0,0 +1,28 @@ +-module(db_user). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-include("../../include/db_user.hrl"). + +-type user() :: db_user(). +-type permission() :: db_permission(). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export_type([user/0, permission/0]). + +-export([can_access/2]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec can_access (permission(), user()) -> boolean(). +can_access (_, admin) -> true; +can_access (any, _) -> true; +can_access (List, {'user', User}) -> + lists:member(User, List). -- cgit v1.2.3-70-g09d2