%%%------------------------------------------------------------------- %%% @doc Grants calendar_share: list / revoke / rights / mirror. %%% @end %%%------------------------------------------------------------------- -module(logic_calendar_share). -include("records.hrl"). -export([ list/2, revoke/3, update_rights/4, update_my_mirror/3, get_rights/2, can_manage_shares/2, to_json/1 ]). -spec list(ActorId :: binary(), CalendarId :: binary()) -> {ok, [#calendar_share{}]} | {error, not_found | access_denied}. list(ActorId, CalendarId) -> case require_can_view_shares(ActorId, CalendarId) of {ok, _} -> {ok, core_calendar_share:list_by_calendar(CalendarId)}; Error -> Error end. -spec revoke(ActorId :: binary(), CalendarId :: binary(), TargetUserId :: binary()) -> ok | {error, not_found | access_denied | term()}. revoke(ActorId, CalendarId, TargetUserId) -> case require_can_manage(ActorId, CalendarId) of {ok, _} -> case core_calendar_share:delete(CalendarId, TargetUserId) of ok -> ok; {error, _} = E -> E end; Error -> Error end. -spec update_rights(ActorId :: binary(), CalendarId :: binary(), TargetUserId :: binary(), Rights :: read | write | admin) -> {ok, #calendar_share{}} | {error, not_found | access_denied | bad_request | term()}. update_rights(ActorId, CalendarId, TargetUserId, Rights) -> case valid_rights(Rights) of false -> {error, bad_request}; true -> case require_can_manage(ActorId, CalendarId) of {ok, _} -> core_calendar_share:update_rights(CalendarId, TargetUserId, Rights); Error -> Error end end. %% Invitee updates own mirror preference (personal shares only meaningful). -spec update_my_mirror(UserId :: binary(), CalendarId :: binary(), Mirror :: boolean()) -> {ok, #calendar_share{}} | {error, not_found | access_denied | term()}. update_my_mirror(UserId, CalendarId, Mirror) when is_boolean(Mirror) -> case core_calendar_share:get(CalendarId, UserId) of {ok, _} -> core_calendar_share:update_mirror(CalendarId, UserId, Mirror); {error, not_found} -> {error, not_found} end; update_my_mirror(_, _, _) -> {error, bad_request}. -spec get_rights(UserId :: binary(), CalendarId :: binary()) -> none | read | write | admin. get_rights(UserId, CalendarId) -> case core_calendar_share:get(CalendarId, UserId) of {ok, #calendar_share{rights = R}} -> R; {error, not_found} -> none end. -spec can_manage_shares(UserId :: binary(), #calendar{}) -> boolean(). can_manage_shares(UserId, #calendar{owner_id = UserId, status = active}) -> true; can_manage_shares(UserId, #calendar{id = CalId, status = active}) -> get_rights(UserId, CalId) =:= admin; can_manage_shares(_, _) -> false. -spec to_json(#calendar_share{}) -> map(). to_json(S) -> #{ id => S#calendar_share.id, calendar_id => S#calendar_share.calendar_id, user_id => S#calendar_share.user_id, rights => S#calendar_share.rights, mirror_to_default => S#calendar_share.mirror_to_default }. %%%=================================================================== %%% Internal %%%=================================================================== require_can_view_shares(ActorId, CalendarId) -> case core_calendar:get_by_id(CalendarId) of {ok, #calendar{status = active} = Cal} -> case can_manage_shares(ActorId, Cal) orelse Cal#calendar.owner_id =:= ActorId orelse get_rights(ActorId, CalendarId) =/= none of true -> {ok, Cal}; false -> {error, access_denied} end; {ok, _} -> {error, not_found}; Error -> Error end. require_can_manage(ActorId, CalendarId) -> case core_calendar:get_by_id(CalendarId) of {ok, #calendar{status = active} = Cal} -> case can_manage_shares(ActorId, Cal) of true -> {ok, Cal}; false -> {error, access_denied} end; {ok, _} -> {error, not_found}; Error -> Error end. valid_rights(read) -> true; valid_rights(write) -> true; valid_rights(admin) -> true; valid_rights(_) -> false.