1 |
|
-module(mongoose_admin_api_users). |
2 |
|
|
3 |
|
-behaviour(mongoose_admin_api). |
4 |
|
-export([routes/1]). |
5 |
|
|
6 |
|
-behaviour(cowboy_rest). |
7 |
|
-export([init/2, |
8 |
|
is_authorized/2, |
9 |
|
content_types_provided/2, |
10 |
|
content_types_accepted/2, |
11 |
|
allowed_methods/2, |
12 |
|
to_json/2, |
13 |
|
from_json/2, |
14 |
|
delete_resource/2]). |
15 |
|
|
16 |
|
-ignore_xref([to_json/2, from_json/2]). |
17 |
|
|
18 |
|
-import(mongoose_admin_api, [parse_body/1, try_handle_request/3, throw_error/2, resource_created/4]). |
19 |
|
|
20 |
|
-type req() :: cowboy_req:req(). |
21 |
|
-type state() :: mongoose_admin_api:state(). |
22 |
|
|
23 |
|
-spec routes(state()) -> mongoose_http_handler:routes(). |
24 |
|
routes(State) -> |
25 |
100 |
[{"/users/:domain/[:username]", ?MODULE, State}]. |
26 |
|
|
27 |
|
-spec init(req(), state()) -> {cowboy_rest, req(), state()}. |
28 |
|
init(Req, State) -> |
29 |
25 |
mongoose_admin_api:init(Req, State). |
30 |
|
|
31 |
|
-spec is_authorized(req(), state()) -> {true | {false, iodata()}, req(), state()}. |
32 |
|
is_authorized(Req, State) -> |
33 |
25 |
mongoose_admin_api:is_authorized(Req, State). |
34 |
|
|
35 |
|
-spec content_types_provided(req(), state()) -> |
36 |
|
{[{{binary(), binary(), '*'}, atom()}], req(), state()}. |
37 |
|
content_types_provided(Req, State) -> |
38 |
23 |
{[ |
39 |
|
{{<<"application">>, <<"json">>, '*'}, to_json} |
40 |
|
], Req, State}. |
41 |
|
|
42 |
|
-spec content_types_accepted(req(), state()) -> |
43 |
|
{[{{binary(), binary(), '*'}, atom()}], req(), state()}. |
44 |
|
content_types_accepted(Req, State) -> |
45 |
15 |
{[ |
46 |
|
{{<<"application">>, <<"json">>, '*'}, from_json} |
47 |
|
], Req, State}. |
48 |
|
|
49 |
|
-spec allowed_methods(req(), state()) -> {[binary()], req(), state()}. |
50 |
|
allowed_methods(Req, State) -> |
51 |
25 |
{[<<"OPTIONS">>, <<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>], Req, State}. |
52 |
|
|
53 |
|
%% @doc Called for a method of type "GET" |
54 |
|
-spec to_json(req(), state()) -> {iodata() | stop, req(), state()}. |
55 |
|
to_json(Req, State) -> |
56 |
5 |
try_handle_request(Req, State, fun handle_get/2). |
57 |
|
|
58 |
|
%% @doc Called for a method of type "POST" or "PUT" |
59 |
|
-spec from_json(req(), state()) -> {true | stop, req(), state()}. |
60 |
|
from_json(Req, State) -> |
61 |
15 |
F = case cowboy_req:method(Req) of |
62 |
8 |
<<"POST">> -> fun handle_post/2; |
63 |
7 |
<<"PUT">> -> fun handle_put/2 |
64 |
|
end, |
65 |
15 |
try_handle_request(Req, State, F). |
66 |
|
|
67 |
|
%% @doc Called for a method of type "DELETE" |
68 |
|
-spec delete_resource(req(), state()) -> {true | stop, req(), state()}. |
69 |
|
delete_resource(Req, State) -> |
70 |
3 |
try_handle_request(Req, State, fun handle_delete/2). |
71 |
|
|
72 |
|
%% Internal functions |
73 |
|
|
74 |
|
handle_get(Req, State) -> |
75 |
5 |
#{domain := Domain} = cowboy_req:bindings(Req), |
76 |
5 |
Users = mongoose_account_api:list_users(Domain), |
77 |
5 |
{_, UsersList} = Users, |
78 |
5 |
{jiffy:encode(UsersList), Req, State}. |
79 |
|
|
80 |
|
handle_post(Req, State) -> |
81 |
8 |
#{domain := Domain} = cowboy_req:bindings(Req), |
82 |
8 |
Args = parse_body(Req), |
83 |
7 |
UserName = get_user_name(Args), |
84 |
6 |
Password = get_password(Args), |
85 |
5 |
case mongoose_account_api:register_user(UserName, Domain, Password) of |
86 |
|
{exists, Reason} -> |
87 |
1 |
throw_error(denied, Reason); |
88 |
|
{invalid_jid, Reason} -> |
89 |
1 |
throw_error(bad_request, Reason); |
90 |
|
{cannot_register, Reason} -> |
91 |
2 |
throw_error(denied, Reason); |
92 |
|
{ok, Result} -> |
93 |
1 |
Path = [cowboy_req:uri(Req), "/", UserName], |
94 |
1 |
resource_created(Req, State, Path, Result) |
95 |
|
end. |
96 |
|
|
97 |
|
handle_put(Req, State) -> |
98 |
7 |
#{domain := Domain} = Bindings = cowboy_req:bindings(Req), |
99 |
7 |
UserName = get_user_name(Bindings), |
100 |
6 |
Args = parse_body(Req), |
101 |
6 |
Password = get_new_password(Args), |
102 |
5 |
case mongoose_account_api:change_password(UserName, Domain, Password) of |
103 |
|
{empty_password, Reason} -> |
104 |
1 |
throw_error(bad_request, Reason); |
105 |
|
{invalid_jid, Reason} -> |
106 |
1 |
throw_error(bad_request, Reason); |
107 |
|
{not_allowed, Reason} -> |
108 |
1 |
throw_error(denied, Reason); |
109 |
|
{ok, _} -> |
110 |
2 |
{true, Req, State} |
111 |
|
end. |
112 |
|
|
113 |
|
handle_delete(Req, State) -> |
114 |
3 |
#{domain := Domain} = Bindings = cowboy_req:bindings(Req), |
115 |
3 |
UserName = get_user_name(Bindings), |
116 |
3 |
case mongoose_account_api:unregister_user(UserName, Domain) of |
117 |
|
{invalid_jid, Reason} -> |
118 |
1 |
throw_error(bad_request, Reason); |
119 |
|
{not_allowed, Reason} -> |
120 |
1 |
throw_error(denied, Reason); |
121 |
|
{ok, _} -> |
122 |
1 |
{true, Req, State} |
123 |
|
end. |
124 |
|
|
125 |
15 |
get_user_name(#{username := UserName}) -> UserName; |
126 |
2 |
get_user_name(#{}) -> throw_error(bad_request, <<"Missing user name">>). |
127 |
|
|
128 |
5 |
get_password(#{password := Password}) -> Password; |
129 |
1 |
get_password(#{}) -> throw_error(bad_request, <<"Missing password">>). |
130 |
|
|
131 |
5 |
get_new_password(#{newpass := Password}) -> Password; |
132 |
1 |
get_new_password(#{}) -> throw_error(bad_request, <<"Missing new password">>). |