emqttd_rest_api.erl 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2013-2018 EMQ Enterprise, Inc. (http://emqtt.io)
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module (emqttd_rest_api).
  17. -include("emqttd.hrl").
  18. -include("emqttd_internal.hrl").
  19. -http_api({"^nodes/(.+?)/alarms/?$", 'GET', alarm_list, []}).
  20. -http_api({"^nodes/(.+?)/clients/?$", 'GET', client_list, []}).
  21. -http_api({"^nodes/(.+?)/clients/(.+?)/?$", 'GET',client_list, []}).
  22. -http_api({"^clients/(.+?)/?$", 'GET', client, []}).
  23. -http_api({"^clients/(.+?)/?$", 'DELETE', kick_client, []}).
  24. -http_api({"^clients/(.+?)/clean_acl_cache?$", 'PUT', clean_acl_cache, [{<<"topic">>, binary}]}).
  25. -http_api({"^routes?$", 'GET', route_list, []}).
  26. -http_api({"^routes/(.+?)/?$", 'GET', route, []}).
  27. -http_api({"^nodes/(.+?)/sessions/?$", 'GET', session_list, []}).
  28. -http_api({"^nodes/(.+?)/sessions/(.+?)/?$", 'GET', session_list, []}).
  29. -http_api({"^sessions/(.+?)/?$", 'GET', session, []}).
  30. -http_api({"^nodes/(.+?)/subscriptions/?$", 'GET', subscription_list, []}).
  31. -http_api({"^nodes/(.+?)/subscriptions/(.+?)/?$", 'GET', subscription_list, []}).
  32. -http_api({"^subscriptions/(.+?)/?$", 'GET', subscription, []}).
  33. -http_api({"^mqtt/publish?$", 'POST', publish, [{<<"topic">>, binary}]}).
  34. -http_api({"^mqtt/subscribe?$", 'POST', subscribe, [{<<"client_id">>, binary},{<<"topic">>, binary}]}).
  35. -http_api({"^mqtt/unsubscribe?$", 'POST', unsubscribe, [{<<"client_id">>, binary},{<<"topic">>, binary}]}).
  36. -http_api({"^management/nodes/?$", 'GET', brokers, []}).
  37. -http_api({"^management/nodes/(.+?)/?$", 'GET', broker, []}).
  38. -http_api({"^monitoring/nodes/?$", 'GET', nodes, []}).
  39. -http_api({"^monitoring/nodes/(.+?)/?$", 'GET', node, []}).
  40. -http_api({"^monitoring/listeners/?$", 'GET', listeners, []}).
  41. -http_api({"^monitoring/listeners/(.+?)/?$", 'GET', listener, []}).
  42. -http_api({"^monitoring/metrics/?$", 'GET', metrics, []}).
  43. -http_api({"^monitoring/metrics/(.+?)/?$", 'GET', metric, []}).
  44. -http_api({"^monitoring/stats/?$", 'GET', stats, []}).
  45. -http_api({"^monitoring/stats/(.+?)/?$", 'GET', stat, []}).
  46. -http_api({"^nodes/(.+?)/plugins/?$", 'GET', plugin_list, []}).
  47. -http_api({"^nodes/(.+?)/plugins/(.+?)/?$", 'PUT', enabled, [{<<"active">>, bool}]}).
  48. -http_api({"^configs/(.+?)/?$", 'PUT', modify_config, [{<<"key">>, binary}, {<<"value">>, binary}]}).
  49. -http_api({"^configs/?$", 'GET', config_list, []}).
  50. -http_api({"^nodes/(.+?)/configs/(.+?)/?$", 'PUT', modify_config, [{<<"key">>, binary}, {<<"value">>, binary}]}).
  51. -http_api({"^nodes/(.+?)/configs/?$", 'GET', config_list, []}).
  52. -http_api({"^nodes/(.+?)/plugin_configs/(.+?)/?$", 'GET', plugin_config_list, []}).
  53. -http_api({"^nodes/(.+?)/plugin_configs/(.+?)/?$", 'PUT', modify_plugin_config, []}).
  54. -http_api({"^users/?$", 'GET', users, []}).
  55. -http_api({"^users/?$", 'POST', users, [{<<"username">>, binary},
  56. {<<"password">>, binary},
  57. {<<"tags">>, binary}]}).
  58. -http_api({"^users/(.+?)/?$", 'GET', users, []}).
  59. -http_api({"^users/(.+?)/?$", 'PUT', users, [{<<"tags">>, binary}]}).
  60. -http_api({"^users/(.+?)/?$", 'DELETE', users, []}).
  61. -http_api({"^auth/?$", 'POST', auth, [{<<"username">>, binary}, {<<"password">>, binary}]}).
  62. -http_api({"^change_pwd/(.+?)/?$", 'PUT', change_pwd, [{<<"old_pwd">>, binary},
  63. {<<"new_pwd">>, binary}]}).
  64. -import(proplists, [get_value/2, get_value/3]).
  65. -export([alarm_list/3]).
  66. -export([client/3, client_list/3, client_list/4, kick_client/3, clean_acl_cache/3]).
  67. -export([route/3, route_list/2]).
  68. -export([session/3, session_list/3, session_list/4]).
  69. -export([subscription/3, subscription_list/3, subscription_list/4]).
  70. -export([nodes/2, node/3, brokers/2, broker/3, listeners/2, listener/3, metrics/2, metric/3, stats/2, stat/3]).
  71. -export([publish/2, subscribe/2, unsubscribe/2]).
  72. -export([plugin_list/3, enabled/4]).
  73. -export([modify_config/3, modify_config/4, config_list/2, config_list/3,
  74. plugin_config_list/4, modify_plugin_config/4]).
  75. -export([users/2,users/3, auth/2, change_pwd/3]).
  76. %%--------------------------------------------------------------------------
  77. %% alarm
  78. %%--------------------------------------------------------------------------
  79. alarm_list('GET', _Req, _Node) ->
  80. Alarms = emqttd_mgmt:alarm_list(),
  81. {ok, lists:map(fun alarm_row/1, Alarms)}.
  82. alarm_row(#mqtt_alarm{id = AlarmId,
  83. severity = Severity,
  84. title = Title,
  85. summary = Summary,
  86. timestamp = Timestamp}) ->
  87. [{id, AlarmId},
  88. {severity, Severity},
  89. {title, l2b(Title)},
  90. {summary, l2b(Summary)},
  91. {occurred_at, l2b(strftime(Timestamp))}].
  92. %%--------------------------------------------------------------------------
  93. %% client
  94. %%--------------------------------------------------------------------------
  95. client('GET', _Params, Key) ->
  96. Data = emqttd_mgmt:client(l2b(Key)),
  97. {ok, [{objects, [client_row(Row) || Row <- Data]}]}.
  98. client_list('GET', Params, Node) ->
  99. {PageNo, PageSize} = page_params(Params),
  100. Data = emqttd_mgmt:client_list(l2a(Node), undefined, PageNo, PageSize),
  101. Rows = get_value(result, Data),
  102. TotalPage = get_value(totalPage, Data),
  103. TotalNum = get_value(totalNum, Data),
  104. {ok, [{current_page, PageNo},
  105. {page_size, PageSize},
  106. {total_num, TotalNum},
  107. {total_page, TotalPage},
  108. {objects, [client_row(Row) || Row <- Rows]}]}.
  109. client_list('GET', Params, Node, Key) ->
  110. {PageNo, PageSize} = page_params(Params),
  111. Data = emqttd_mgmt:client_list(l2a(Node), l2b(Key), PageNo, PageSize),
  112. {ok, [{objects, [client_row(Row) || Row <- Data]}]}.
  113. kick_client('DELETE', _Params, Key) ->
  114. case emqttd_mgmt:kick_client(l2b(Key)) of
  115. true -> {ok, []};
  116. false -> {error, [{code, ?ERROR12}]}
  117. end.
  118. clean_acl_cache('PUT', Params, Key0) ->
  119. Topic = get_value(<<"topic">>, Params),
  120. [Key | _] = string:tokens(Key0, "/"),
  121. case emqttd_mgmt:clean_acl_cache(l2b(Key), Topic) of
  122. true -> {ok, []};
  123. false -> {error, [{code, ?ERROR12}]}
  124. end.
  125. client_row(#mqtt_client{client_id = ClientId,
  126. peername = {IpAddr, Port},
  127. username = Username,
  128. clean_sess = CleanSess,
  129. proto_ver = ProtoVer,
  130. keepalive = KeepAlvie,
  131. connected_at = ConnectedAt}) ->
  132. [{client_id, ClientId},
  133. {username, Username},
  134. {ipaddress, l2b(ntoa(IpAddr))},
  135. {port, Port},
  136. {clean_sess, CleanSess},
  137. {proto_ver, ProtoVer},
  138. {keepalive, KeepAlvie},
  139. {connected_at, l2b(strftime(ConnectedAt))}].
  140. %%--------------------------------------------------------------------------
  141. %% route
  142. %%--------------------------------------------------------------------------
  143. route('GET', _Params, Key) ->
  144. Data = emqttd_mgmt:route(l2b(Key)),
  145. {ok, [{objects, [route_row(Row) || Row <- Data]}]}.
  146. route_list('GET', Params) ->
  147. {PageNo, PageSize} = page_params(Params),
  148. Data = emqttd_mgmt:route_list(undefined, PageNo, PageSize),
  149. Rows = get_value(result, Data),
  150. TotalPage = get_value(totalPage, Data),
  151. TotalNum = get_value(totalNum, Data),
  152. {ok, [{current_page, PageNo},
  153. {page_size, PageSize},
  154. {total_num, TotalNum},
  155. {total_page, TotalPage},
  156. {objects, [route_row(Row) || Row <- Rows]}]}.
  157. route_row(Route) when is_record(Route, mqtt_route) ->
  158. [{topic, Route#mqtt_route.topic}, {node, Route#mqtt_route.node}];
  159. route_row({Topic, Node}) ->
  160. [{topic, Topic}, {node, Node}].
  161. %%--------------------------------------------------------------------------
  162. %% session
  163. %%--------------------------------------------------------------------------
  164. session('GET', _Params, Key) ->
  165. Data = emqttd_mgmt:session(l2b(Key)),
  166. {ok, [{objects, [session_row(Row) || Row <- Data]}]}.
  167. session_list('GET', Params, Node) ->
  168. {PageNo, PageSize} = page_params(Params),
  169. Data = emqttd_mgmt:session_list(l2a(Node), undefined, PageNo, PageSize),
  170. Rows = get_value(result, Data),
  171. TotalPage = get_value(totalPage, Data),
  172. TotalNum = get_value(totalNum, Data),
  173. {ok, [{current_page, PageNo},
  174. {page_size, PageSize},
  175. {total_num, TotalNum},
  176. {total_page, TotalPage},
  177. {objects, [session_row(Row) || Row <- Rows]}]}.
  178. session_list('GET', Params, Node, ClientId) ->
  179. {PageNo, PageSize} = page_params(Params),
  180. Data = emqttd_mgmt:session_list(l2a(Node), l2b(ClientId), PageNo, PageSize),
  181. {ok, [{objects, [session_row(Row) || Row <- Data]}]}.
  182. session_row({ClientId, _Pid, _Persistent, Session}) ->
  183. Data = lists:append(Session, emqttd_stats:get_session_stats(ClientId)),
  184. InfoKeys = [clean_sess, subscriptions, max_inflight, inflight_len, mqueue_len,
  185. mqueue_dropped, awaiting_rel_len, deliver_msg,enqueue_msg, created_at],
  186. [{client_id, ClientId} | [{Key, format(Key, get_value(Key, Data))} || Key <- InfoKeys]].
  187. %%--------------------------------------------------------------------------
  188. %% subscription
  189. %%--------------------------------------------------------------------------
  190. subscription('GET', _Params, Key) ->
  191. Data = emqttd_mgmt:subscription(l2b(Key)),
  192. {ok, [{objects, [subscription_row(Row) || Row <- Data]}]}.
  193. subscription_list('GET', Params, Node) ->
  194. {PageNo, PageSize} = page_params(Params),
  195. Data = emqttd_mgmt:subscription_list(l2a(Node), undefined, PageNo, PageSize),
  196. Rows = get_value(result, Data),
  197. TotalPage = get_value(totalPage, Data),
  198. TotalNum = get_value(totalNum, Data),
  199. {ok, [{current_page, PageNo},
  200. {page_size, PageSize},
  201. {total_num, TotalNum},
  202. {total_page, TotalPage},
  203. {objects, [subscription_row(Row) || Row <- Rows]}]}.
  204. subscription_list('GET', Params, Node, Key) ->
  205. {PageNo, PageSize} = page_params(Params),
  206. Data = emqttd_mgmt:subscription_list(l2a(Node), l2b(Key), PageNo, PageSize),
  207. {ok, [{objects, [subscription_row(Row) || Row <- Data]}]}.
  208. subscription_row({{Topic, SubPid}, Options}) when is_pid(SubPid) ->
  209. subscription_row({{Topic, {undefined, SubPid}}, Options});
  210. subscription_row({{Topic, {SubId, SubPid}}, Options}) ->
  211. Qos = proplists:get_value(qos, Options),
  212. ClientId = case SubId of
  213. undefined -> list_to_binary(pid_to_list(SubPid));
  214. SubId -> SubId
  215. end,
  216. [{client_id, ClientId}, {topic, Topic}, {qos, Qos}].
  217. %%--------------------------------------------------------------------------
  218. %% management/monitoring
  219. %%--------------------------------------------------------------------------
  220. nodes('GET', _Params) ->
  221. Data = emqttd_mgmt:nodes_info(),
  222. {ok, Data}.
  223. node('GET', _Params, Node) ->
  224. Data = emqttd_mgmt:node_info(l2a(Node)),
  225. {ok, Data}.
  226. brokers('GET', _Params) ->
  227. Data = emqttd_mgmt:brokers(),
  228. {ok, [format_broker(Node, Broker) || {Node, Broker} <- Data]}.
  229. broker('GET', _Params, Node) ->
  230. Data = emqttd_mgmt:broker(l2a(Node)),
  231. {ok, format_broker(Data)}.
  232. listeners('GET', _Params) ->
  233. Data = emqttd_mgmt:listeners(),
  234. {ok, [[{Node, format_listeners(Listeners, [])} || {Node, Listeners} <- Data]]}.
  235. listener('GET', _Params, Node) ->
  236. Data = emqttd_mgmt:listener(l2a(Node)),
  237. {ok, [format_listener(Listeners) || Listeners <- Data]}.
  238. metrics('GET', _Params) ->
  239. Data = emqttd_mgmt:metrics(),
  240. {ok, [Data]}.
  241. metric('GET', _Params, Node) ->
  242. Data = emqttd_mgmt:metrics(l2a(Node)),
  243. {ok, Data}.
  244. stats('GET', _Params) ->
  245. Data = emqttd_mgmt:stats(),
  246. {ok, [Data]}.
  247. stat('GET', _Params, Node) ->
  248. Data = emqttd_mgmt:stats(l2a(Node)),
  249. {ok, Data}.
  250. format_broker(Node, Broker) ->
  251. OtpRel = "R" ++ erlang:system_info(otp_release) ++ "/" ++ erlang:system_info(version),
  252. [{name, Node},
  253. {version, bin(get_value(version, Broker))},
  254. {sysdescr, bin(get_value(sysdescr, Broker))},
  255. {uptime, bin(get_value(uptime, Broker))},
  256. {datetime, bin(get_value(datetime, Broker))},
  257. {otp_release, l2b(OtpRel)},
  258. {node_status, 'Running'}].
  259. format_broker(Broker) ->
  260. OtpRel = "R" ++ erlang:system_info(otp_release) ++ "/" ++ erlang:system_info(version),
  261. [{version, bin(get_value(version, Broker))},
  262. {sysdescr, bin(get_value(sysdescr, Broker))},
  263. {uptime, bin(get_value(uptime, Broker))},
  264. {datetime, bin(get_value(datetime, Broker))},
  265. {otp_release, l2b(OtpRel)},
  266. {node_status, 'Running'}].
  267. format_listeners([], Acc) ->
  268. Acc;
  269. format_listeners([{Protocol, ListenOn, Info}| Listeners], Acc) ->
  270. format_listeners(Listeners, [format_listener({Protocol, ListenOn, Info}) | Acc]).
  271. format_listener({Protocol, ListenOn, Info}) ->
  272. Listen = l2b(esockd:to_string(ListenOn)),
  273. lists:append([{protocol, Protocol}, {listen, Listen}], Info).
  274. %%--------------------------------------------------------------------------
  275. %% mqtt
  276. %%--------------------------------------------------------------------------
  277. publish('POST', Params) ->
  278. Topic = get_value(<<"topic">>, Params),
  279. ClientId = get_value(<<"client_id">>, Params, http),
  280. Payload = get_value(<<"payload">>, Params, <<>>),
  281. Qos = get_value(<<"qos">>, Params, 0),
  282. Retain = get_value(<<"retain">>, Params, false),
  283. case emqttd_mgmt:publish({ClientId, Topic, Payload, Qos, Retain}) of
  284. ok ->
  285. {ok, []};
  286. {error, Error} ->
  287. {error, [{code, ?ERROR2}, {message, Error}]}
  288. end.
  289. subscribe('POST', Params) ->
  290. ClientId = get_value(<<"client_id">>, Params),
  291. Topic = get_value(<<"topic">>, Params),
  292. Qos = get_value(<<"qos">>, Params, 0),
  293. case emqttd_mgmt:subscribe({ClientId, Topic, Qos}) of
  294. ok ->
  295. {ok, []};
  296. {error, Error} ->
  297. {error, [{code, ?ERROR2}, {message, Error}]}
  298. end.
  299. unsubscribe('POST', Params) ->
  300. ClientId = get_value(<<"client_id">>, Params),
  301. Topic = get_value(<<"topic">>, Params),
  302. case emqttd_mgmt:unsubscribe({ClientId, Topic})of
  303. ok ->
  304. {ok, []};
  305. {error, Error} ->
  306. {error, [{code, ?ERROR2}, {message, Error}]}
  307. end.
  308. %%--------------------------------------------------------------------------
  309. %% plugins
  310. %%--------------------------------------------------------------------------
  311. plugin_list('GET', _Params, Node) ->
  312. Plugins = lists:map(fun plugin/1, emqttd_mgmt:plugin_list(l2a(Node))),
  313. {ok, Plugins}.
  314. enabled('PUT', Params, Node, PluginName) ->
  315. Active = get_value(<<"active">>, Params),
  316. case Active of
  317. true ->
  318. return(emqttd_mgmt:plugin_load(l2a(Node), l2a(PluginName)));
  319. false ->
  320. return(emqttd_mgmt:plugin_unload(l2a(Node), l2a(PluginName)))
  321. end.
  322. return(Result) ->
  323. case Result of
  324. ok ->
  325. {ok, []};
  326. {ok, _} ->
  327. {ok, []};
  328. {error, already_started} ->
  329. {error, [{code, ?ERROR10}, {message, <<"already_started">>}]};
  330. {error, not_started} ->
  331. {error, [{code, ?ERROR11}, {message, <<"not_started">>}]};
  332. Error ->
  333. lager:error("error:~p", [Error]),
  334. {error, [{code, ?ERROR2}, {message, <<"unknown">>}]}
  335. end.
  336. plugin(#mqtt_plugin{name = Name, version = Ver, descr = Descr,
  337. active = Active}) ->
  338. [{name, Name},
  339. {version, iolist_to_binary(Ver)},
  340. {description, iolist_to_binary(Descr)},
  341. {active, Active}].
  342. %%--------------------------------------------------------------------------
  343. %% modify config
  344. %%--------------------------------------------------------------------------
  345. modify_config('PUT', Params, App) ->
  346. Key = get_value(<<"key">>, Params, <<"">>),
  347. Value = get_value(<<"value">>, Params, <<"">>),
  348. case emqttd_mgmt:modify_config(l2a(App), b2l(Key), b2l(Value)) of
  349. true -> {ok, []};
  350. false -> {error, [{code, ?ERROR2}]}
  351. end.
  352. modify_config('PUT', Params, Node, App) ->
  353. Key = get_value(<<"key">>, Params, <<"">>),
  354. Value = get_value(<<"value">>, Params, <<"">>),
  355. case emqttd_mgmt:modify_config(l2a(Node), l2a(App), b2l(Key), b2l(Value)) of
  356. ok -> {ok, []};
  357. _ -> {error, [{code, ?ERROR2}]}
  358. end.
  359. config_list('GET', _Params) ->
  360. Data = emqttd_mgmt:get_configs(),
  361. {ok, [{Node, format_config(Config, [])} || {Node, Config} <- Data]}.
  362. config_list('GET', _Params, Node) ->
  363. Data = emqttd_mgmt:get_config(l2a(Node)),
  364. {ok, [format_config(Config) || Config <- lists:reverse(Data)]}.
  365. plugin_config_list('GET', _Params, Node, App) ->
  366. {ok, Data} = emqttd_mgmt:get_plugin_config(l2a(Node), l2a(App)),
  367. {ok, [format_plugin_config(Config) || Config <- lists:reverse(Data)]}.
  368. modify_plugin_config('PUT', Params, Node, App) ->
  369. PluginName = l2a(App),
  370. case emqttd_mgmt:modify_plugin_config(l2a(Node), PluginName, Params) of
  371. ok ->
  372. Plugins = emqttd_plugins:list(),
  373. {_, _, _, _, Status} = lists:keyfind(PluginName, 2, Plugins),
  374. case Status of
  375. true ->
  376. emqttd_plugins:unload(PluginName),
  377. timer:sleep(500),
  378. emqttd_plugins:load(PluginName),
  379. {ok, []};
  380. false ->
  381. {ok, []}
  382. end;
  383. _ ->
  384. {error, [{code, ?ERROR2}]}
  385. end.
  386. format_config([], Acc) ->
  387. Acc;
  388. format_config([{Key, Value, Datatpye, App}| Configs], Acc) ->
  389. format_config(Configs, [format_config({Key, Value, Datatpye, App}) | Acc]).
  390. format_config({Key, Value, Datatpye, App}) ->
  391. [{<<"key">>, l2b(Key)},
  392. {<<"value">>, l2b(Value)},
  393. {<<"datatpye">>, l2b(Datatpye)},
  394. {<<"app">>, App}].
  395. format_plugin_config({Key, Value, Desc, Required}) ->
  396. [{<<"key">>, l2b(Key)},
  397. {<<"value">>, l2b(Value)},
  398. {<<"desc">>, l2b(Desc)},
  399. {<<"required">>, Required}].
  400. %%--------------------------------------------------------------------------
  401. %% Admin
  402. %%--------------------------------------------------------------------------
  403. auth('POST', Params) ->
  404. Username = get_value(<<"username">>, Params),
  405. Password = get_value(<<"password">>, Params),
  406. case emqttd_mgmt:check_user(Username, Password) of
  407. ok ->
  408. {ok, []};
  409. {error, Reason} ->
  410. {error, [{code, ?ERROR3}, {message, list_to_binary(Reason)}]}
  411. end.
  412. users('POST', Params) ->
  413. Username = get_value(<<"username">>, Params),
  414. Password = get_value(<<"password">>, Params),
  415. Tag = get_value(<<"tags">>, Params),
  416. code(emqttd_mgmt:add_user(Username, Password, Tag));
  417. users('GET', _Params) ->
  418. {ok, [Admin || Admin <- emqttd_mgmt:user_list()]}.
  419. users('GET', _Params, Username) ->
  420. {ok, emqttd_mgmt:lookup_user(list_to_binary(Username))};
  421. users('PUT', Params, Username) ->
  422. code(emqttd_mgmt:update_user(list_to_binary(Username), Params));
  423. users('DELETE', _Params, "admin") ->
  424. {error, [{code, ?ERROR6}, {message, <<"admin cannot be deleted">>}]};
  425. users('DELETE', _Params, Username) ->
  426. code(emqttd_mgmt:remove_user(list_to_binary(Username))).
  427. change_pwd('PUT', Params, Username) ->
  428. OldPwd = get_value(<<"old_pwd">>, Params),
  429. NewPwd = get_value(<<"new_pwd">>, Params),
  430. code(emqttd_mgmt:change_password(list_to_binary(Username), OldPwd, NewPwd)).
  431. code(ok) -> {ok, []};
  432. code(error) -> {error, [{code, ?ERROR2}]};
  433. code({error, Error}) -> {error, Error}.
  434. %%--------------------------------------------------------------------------
  435. %% Inner function
  436. %%--------------------------------------------------------------------------
  437. format(created_at, Val) ->
  438. l2b(strftime(Val));
  439. format(_, Val) ->
  440. Val.
  441. ntoa({0,0,0,0,0,16#ffff,AB,CD}) ->
  442. inet_parse:ntoa({AB bsr 8, AB rem 256, CD bsr 8, CD rem 256});
  443. ntoa(IP) ->
  444. inet_parse:ntoa(IP).
  445. %%--------------------------------------------------------------------
  446. %% Strftime
  447. %%--------------------------------------------------------------------
  448. strftime({MegaSecs, Secs, _MicroSecs}) ->
  449. strftime(datetime(MegaSecs * 1000000 + Secs));
  450. strftime({{Y,M,D}, {H,MM,S}}) ->
  451. lists:flatten(
  452. io_lib:format(
  453. "~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w", [Y, M, D, H, MM, S])).
  454. datetime(Timestamp) when is_integer(Timestamp) ->
  455. Universal = calendar:gregorian_seconds_to_datetime(Timestamp +
  456. calendar:datetime_to_gregorian_seconds({{1970,1,1}, {0,0,0}})),
  457. calendar:universal_time_to_local_time(Universal).
  458. bin(S) when is_list(S) -> l2b(S);
  459. bin(A) when is_atom(A) -> bin(atom_to_list(A));
  460. bin(B) when is_binary(B) -> B;
  461. bin(undefined) -> <<>>.
  462. int(L) -> list_to_integer(L).
  463. l2a(L) -> list_to_atom(L).
  464. l2b(L) -> list_to_binary(L).
  465. b2l(B) -> binary_to_list(B).
  466. page_params(Params) ->
  467. PageNo = int(get_value("curr_page", Params, "1")),
  468. PageSize = int(get_value("page_size", Params, "20")),
  469. {PageNo, PageSize}.