./ct_report/coverage/mod_last_api.COVER.html

1 %% @doc Provide an interface for frontends (like graphql or ctl) to manage last activity.
2 -module(mod_last_api).
3
4 -export([get_last/1, set_last/3, count_active_users/2]).
5
6 -export([list_old_users/1, list_old_users/2,
7 remove_old_users/1, remove_old_users/2]).
8
9 -include("jlib.hrl").
10 -include("mongoose.hrl").
11
12 -type old_user() :: {jid:jid(), null | timestamp()}.
13 -type info() :: #{timestamp := mod_last:timestamp(), status := mod_last:status()}.
14 -type timestamp() :: mod_last:timestamp().
15 -type status() :: mod_last:status().
16 -type host_type() :: mongooseim:host_type().
17
18 -define(USER_NOT_FOUND_RESULT(User, Server),
19 {user_does_not_exist, io_lib:format("User ~s@~s does not exist", [User, Server])}).
20 -define(DOMAIN_NOT_FOUND_RESULT, {domain_not_found, <<"Domain not found">>}).
21
22 -spec set_last(jid:jid(), timestamp(), status()) -> {ok, info()} | {user_does_not_exist, iolist()}.
23 set_last(#jid{luser = User, lserver = Server} = JID, Timestamp, Status) ->
24 22 case ejabberd_auth:does_user_exist(JID) of
25 true ->
26 21 {ok, HostType} = mongoose_domain_api:get_host_type(Server),
27 21 ok = mod_last:store_last_info(HostType, User, Server, Timestamp, Status),
28 21 {ok, #{timestamp => Timestamp, status => Status}};
29 false ->
30 1 ?USER_NOT_FOUND_RESULT(User, Server)
31 end.
32
33 -spec get_last(jid:jid()) ->
34 {ok, info()} | {last_not_found | user_does_not_exist, iodata()}.
35 get_last(#jid{luser = User, lserver = Server} = JID) ->
36 5 case ejabberd_auth:does_user_exist(JID) of
37 true ->
38 4 {ok, HostType} = mongoose_domain_api:get_host_type(Server),
39 4 case mod_last:get_last_info(HostType, User, Server) of
40 {ok, Timestamp, Status} ->
41 3 {ok, #{timestamp => Timestamp, status => Status}};
42 not_found ->
43 1 {last_not_found, <<"Given user's last info not found">>}
44 end;
45 false ->
46 1 ?USER_NOT_FOUND_RESULT(User, Server)
47 end.
48
49 -spec count_active_users(jid:server(), timestamp()) ->
50 {ok, non_neg_integer()} | {domain_not_found, binary()}.
51 count_active_users(Domain, Timestamp) ->
52 5 LDomain = jid:nameprep(Domain),
53 5 case mongoose_domain_api:get_host_type(LDomain) of
54 {ok, HostType} ->
55 4 {ok, mod_last:count_active_users(HostType, LDomain, Timestamp)};
56 {error, not_found} ->
57 1 ?DOMAIN_NOT_FOUND_RESULT
58 end.
59
60 -spec list_old_users(timestamp()) -> [old_user()].
61 list_old_users(Timestamp) ->
62 5 lists:append([list_old_users(HostType, Domain, Timestamp) ||
63 5 HostType <- ?ALL_HOST_TYPES,
64 30 Domain <- mongoose_domain_api:get_domains_by_host_type(HostType)]).
65
66 -spec list_old_users(jid:server(), timestamp()) ->
67 {ok, [old_user()]} | {domain_not_found, binary()}.
68 list_old_users(Domain, Timestamp) ->
69 5 LDomain = jid:nameprep(Domain),
70 5 case mongoose_domain_api:get_host_type(LDomain) of
71 {ok, HostType} ->
72 3 {ok, list_old_users(HostType, LDomain, Timestamp)};
73 {error, not_found} ->
74 2 ?DOMAIN_NOT_FOUND_RESULT
75 end.
76
77 -spec remove_old_users(timestamp()) -> [old_user()].
78 remove_old_users(Timestamp) ->
79 2 OldUsers = list_old_users(Timestamp),
80 2 ok = remove_users(OldUsers),
81 2 OldUsers.
82
83 -spec remove_old_users(jid:server(), timestamp()) ->
84 {ok, [old_user()]} | {domain_not_found, binary()}.
85 remove_old_users(Domain, Timestamp) ->
86 3 case list_old_users(Domain, Timestamp) of
87 {ok, OldUsers} ->
88 2 ok = remove_users(OldUsers),
89 2 {ok, OldUsers};
90 Error ->
91 1 Error
92 end.
93
94 %% Internal
95
96 -spec list_old_users(host_type(), jid:lserver(), timestamp()) -> [old_user()].
97 list_old_users(HostType, Domain, Timestamp) ->
98 18 Users = ejabberd_auth:get_vh_registered_users(Domain),
99 18 lists:filtermap(fun(U) -> prepare_old_user(HostType, U, Timestamp) end, Users).
100
101 -spec prepare_old_user(host_type(), jid:simple_bare_jid(), timestamp()) ->
102 false | {true, old_user()}.
103 prepare_old_user(HostType, {LU, LS}, Timestamp) ->
104 31 JID = jid:make_bare(LU, LS),
105 31 case ejabberd_sm:get_user_resources(JID) of
106 [] ->
107 30 case mod_last:get_last_info(HostType, LU, LS) of
108 {ok, UserTimestamp, _} when UserTimestamp < Timestamp ->
109 7 {true, {JID, UserTimestamp}};
110 not_found ->
111 16 {true, {JID, null}};
112 _ ->
113 7 false
114 end;
115 _ ->
116 1 false
117 end.
118
119 -spec remove_users([old_user()]) -> ok.
120 remove_users(Users) ->
121 4 lists:foreach(fun({JID, _}) -> ok = ejabberd_auth:remove_user(JID) end, Users).
Line Hits Source