Files
EventHubBack/src/core/core_push_subscription.erl
T
aleksey 12274f9ed0
CI / test (push) Successful in 7m43s
CI / deploy-ift (push) Successful in 3m33s
CI / e2e-ift (push) Successful in 1m28s
CI / deploy-stage (push) Failing after 3m40s
CI / e2e-stage (push) Has been skipped
feat(notify): Web Push subscriptions and email/push prefs.
Prefs in user.preferences; push_subscription table; VAPID send on
reminder/waitlist. Refs EventHub/EventHubBack#75
2026-08-15 20:19:44 +03:00

74 lines
2.4 KiB
Erlang

%%%-------------------------------------------------------------------
%%% @doc Web Push subscriptions (Back#75).
%%% @end
%%%-------------------------------------------------------------------
-module(core_push_subscription).
-export([upsert/4, list_by_user/1, delete_by_endpoint/2, delete_by_id/1,
get_by_endpoint/1]).
-include("records.hrl").
-spec upsert(binary(), binary(), binary(), binary()) ->
{ok, #push_subscription{}} | {error, term()}.
upsert(UserId, Endpoint, P256dh, Auth) ->
Now = calendar:universal_time(),
case get_by_endpoint(Endpoint) of
{ok, #push_subscription{} = Existing} ->
Rec = Existing#push_subscription{
user_id = UserId,
p256dh = P256dh,
auth = Auth,
created_at = Now
},
case mnesia:transaction(fun() -> mnesia:write(Rec) end) of
{atomic, ok} -> {ok, Rec};
{aborted, Reason} -> {error, Reason}
end;
{error, not_found} ->
Rec = #push_subscription{
id = infra_utils:generate_id(16),
user_id = UserId,
endpoint = Endpoint,
p256dh = P256dh,
auth = Auth,
created_at = Now
},
case mnesia:transaction(fun() -> mnesia:write(Rec) end) of
{atomic, ok} -> {ok, Rec};
{aborted, Reason} -> {error, Reason}
end
end.
-spec list_by_user(binary()) -> [#push_subscription{}].
list_by_user(UserId) ->
mnesia:dirty_match_object(#push_subscription{user_id = UserId, _ = '_'}).
-spec get_by_endpoint(binary()) -> {ok, #push_subscription{}} | {error, not_found}.
get_by_endpoint(Endpoint) ->
case mnesia:dirty_index_read(push_subscription, Endpoint, #push_subscription.endpoint) of
[Rec | _] -> {ok, Rec};
[] ->
case mnesia:dirty_match_object(#push_subscription{endpoint = Endpoint, _ = '_'}) of
[Rec | _] -> {ok, Rec};
[] -> {error, not_found}
end
end.
-spec delete_by_endpoint(binary(), binary()) -> ok | {error, not_found | forbidden}.
delete_by_endpoint(UserId, Endpoint) ->
case get_by_endpoint(Endpoint) of
{ok, #push_subscription{id = Id, user_id = UserId}} ->
delete_by_id(Id);
{ok, #push_subscription{}} ->
{error, forbidden};
{error, not_found} ->
{error, not_found}
end.
-spec delete_by_id(binary()) -> ok | {error, term()}.
delete_by_id(Id) ->
case mnesia:transaction(fun() -> mnesia:delete({push_subscription, Id}) end) of
{atomic, ok} -> ok;
{aborted, Reason} -> {error, Reason}
end.