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 |
53 |
case ejabberd_auth:does_user_exist(JID) of |
25 |
|
true -> |
26 |
49 |
{ok, HostType} = mongoose_domain_api:get_host_type(Server), |
27 |
49 |
ok = mod_last:store_last_info(HostType, User, Server, Timestamp, Status), |
28 |
49 |
{ok, #{timestamp => Timestamp, status => Status}}; |
29 |
|
false -> |
30 |
4 |
?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 |
12 |
case ejabberd_auth:does_user_exist(JID) of |
37 |
|
true -> |
38 |
8 |
{ok, HostType} = mongoose_domain_api:get_host_type(Server), |
39 |
8 |
case mod_last:get_last_info(HostType, User, Server) of |
40 |
|
{ok, Timestamp, Status} -> |
41 |
5 |
{ok, #{timestamp => Timestamp, status => Status}}; |
42 |
|
not_found -> |
43 |
3 |
{last_not_found, <<"Given user's last info not found">>} |
44 |
|
end; |
45 |
|
false -> |
46 |
4 |
?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 |
11 |
LDomain = jid:nameprep(Domain), |
53 |
11 |
case mongoose_domain_api:get_host_type(LDomain) of |
54 |
|
{ok, HostType} -> |
55 |
9 |
{ok, mod_last:count_active_users(HostType, LDomain, Timestamp)}; |
56 |
|
{error, not_found} -> |
57 |
2 |
?DOMAIN_NOT_FOUND_RESULT |
58 |
|
end. |
59 |
|
|
60 |
|
-spec list_old_users(timestamp()) -> {ok, [old_user()]}. |
61 |
|
list_old_users(Timestamp) -> |
62 |
12 |
OldUsers = lists:append([list_old_users(HostType, Domain, Timestamp) || |
63 |
12 |
HostType <- ?ALL_HOST_TYPES, |
64 |
72 |
Domain <- mongoose_domain_api:get_domains_by_host_type(HostType)]), |
65 |
12 |
{ok, OldUsers}. |
66 |
|
|
67 |
|
-spec list_old_users(jid:server(), timestamp()) -> |
68 |
|
{ok, [old_user()]} | {domain_not_found, binary()}. |
69 |
|
list_old_users(Domain, Timestamp) -> |
70 |
9 |
LDomain = jid:nameprep(Domain), |
71 |
9 |
case mongoose_domain_api:get_host_type(LDomain) of |
72 |
|
{ok, HostType} -> |
73 |
5 |
{ok, list_old_users(HostType, LDomain, Timestamp)}; |
74 |
|
{error, not_found} -> |
75 |
4 |
?DOMAIN_NOT_FOUND_RESULT |
76 |
|
end. |
77 |
|
|
78 |
|
-spec remove_old_users(timestamp()) -> {ok, [old_user()]}. |
79 |
|
remove_old_users(Timestamp) -> |
80 |
4 |
{ok, OldUsers} = list_old_users(Timestamp), |
81 |
4 |
ok = remove_users(OldUsers), |
82 |
4 |
{ok, OldUsers}. |
83 |
|
|
84 |
|
-spec remove_old_users(jid:server(), timestamp()) -> |
85 |
|
{ok, [old_user()]} | {domain_not_found, binary()}. |
86 |
|
remove_old_users(Domain, Timestamp) -> |
87 |
4 |
case list_old_users(Domain, Timestamp) of |
88 |
|
{ok, OldUsers} -> |
89 |
2 |
ok = remove_users(OldUsers), |
90 |
2 |
{ok, OldUsers}; |
91 |
|
Error -> |
92 |
2 |
Error |
93 |
|
end. |
94 |
|
|
95 |
|
%% Internal |
96 |
|
|
97 |
|
-spec list_old_users(host_type(), jid:lserver(), timestamp()) -> [old_user()]. |
98 |
|
list_old_users(HostType, Domain, Timestamp) -> |
99 |
41 |
Users = ejabberd_auth:get_vh_registered_users(Domain), |
100 |
41 |
lists:filtermap(fun(U) -> prepare_old_user(HostType, U, Timestamp) end, Users). |
101 |
|
|
102 |
|
-spec prepare_old_user(host_type(), jid:simple_bare_jid(), timestamp()) -> |
103 |
|
false | {true, old_user()}. |
104 |
|
prepare_old_user(HostType, {LU, LS}, Timestamp) -> |
105 |
30 |
JID = jid:make_bare(LU, LS), |
106 |
30 |
case ejabberd_sm:get_user_resources(JID) of |
107 |
|
[] -> |
108 |
28 |
case mod_last:get_last_info(HostType, LU, LS) of |
109 |
|
{ok, UserTimestamp, _} when UserTimestamp < Timestamp -> |
110 |
13 |
{true, {JID, UserTimestamp}}; |
111 |
|
not_found -> |
112 |
6 |
{true, {JID, null}}; |
113 |
|
_ -> |
114 |
9 |
false |
115 |
|
end; |
116 |
|
_ -> |
117 |
2 |
false |
118 |
|
end. |
119 |
|
|
120 |
|
-spec remove_users([old_user()]) -> ok. |
121 |
|
remove_users(Users) -> |
122 |
6 |
lists:foreach(fun({JID, _}) -> ok = ejabberd_auth:remove_user(JID) end, Users). |