feat(share): calendar_share invite/ACL for personal and commercial.
Co-editor and deputy grants with mirror_to_default; personal out of search; list owned+shared. Refs EventHub/EventHubBack#73
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @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.
|
||||
Reference in New Issue
Block a user