152 lines
5.5 KiB
Erlang
152 lines
5.5 KiB
Erlang
-module(admin_handler_user_by_id).
|
|
-include("records.hrl").
|
|
-export([init/2]).
|
|
|
|
init(Req, _Opts) ->
|
|
case cowboy_req:method(Req) of
|
|
<<"GET">> -> get_user(Req);
|
|
<<"PUT">> -> update_user(Req);
|
|
<<"DELETE">> -> delete_user(Req);
|
|
_ -> send_error(Req, 405, <<"Method not allowed">>)
|
|
end.
|
|
|
|
get_user(Req) ->
|
|
case handler_auth:authenticate(Req) of
|
|
{ok, AdminId, Req1} ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
UserId = cowboy_req:binding(id, Req1),
|
|
case core_user:get_by_id(UserId) of
|
|
{ok, User} ->
|
|
send_json(Req1, 200, user_to_json(User));
|
|
{error, not_found} ->
|
|
send_error(Req1, 404, <<"User not found">>)
|
|
end;
|
|
false ->
|
|
send_error(Req1, 403, <<"Admin access required">>)
|
|
end;
|
|
{error, Code, Message, Req1} ->
|
|
send_error(Req1, Code, Message)
|
|
end.
|
|
|
|
update_user(Req) ->
|
|
case handler_auth:authenticate(Req) of
|
|
{ok, AdminId, Req1} ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
UserId = cowboy_req:binding(id, Req1),
|
|
{ok, Body, Req2} = cowboy_req:read_body(Req1),
|
|
try jsx:decode(Body, [return_maps]) of
|
|
Updates when map_size(Updates) > 0 ->
|
|
% Проверка на наличие reason при изменении статуса
|
|
case maps:find(<<"status">>, Updates) of
|
|
{ok, NewStatus} when NewStatus =:= <<"blocked">> orelse NewStatus =:= <<"active">> ->
|
|
case maps:find(<<"reason">>, Updates) of
|
|
{ok, Reason} when byte_size(Reason) > 0 ->
|
|
apply_updates(UserId, Updates, AdminId, Reason, Req2);
|
|
_ ->
|
|
send_error(Req2, 400, <<"Missing or empty reason">>)
|
|
end;
|
|
_ ->
|
|
apply_updates(UserId, Updates, AdminId, undefined, Req2)
|
|
end;
|
|
_ ->
|
|
send_error(Req2, 400, <<"Request body is empty">>)
|
|
catch
|
|
_:_ -> send_error(Req2, 400, <<"Invalid JSON">>)
|
|
end;
|
|
false ->
|
|
send_error(Req1, 403, <<"Admin access required">>)
|
|
end;
|
|
{error, Code, Message, Req1} ->
|
|
send_error(Req1, Code, Message)
|
|
end.
|
|
|
|
delete_user(Req) ->
|
|
case handler_auth:authenticate(Req) of
|
|
{ok, AdminId, Req1} ->
|
|
case admin_utils:is_admin(AdminId) of
|
|
true ->
|
|
UserId = cowboy_req:binding(id, Req1),
|
|
case core_user:delete(UserId) of
|
|
{ok, _} ->
|
|
send_json(Req1, 200, #{status => <<"deleted">>});
|
|
{error, not_found} ->
|
|
send_error(Req1, 404, <<"User not found">>)
|
|
end;
|
|
false ->
|
|
send_error(Req1, 403, <<"Admin access required">>)
|
|
end;
|
|
{error, Code, Message, Req1} ->
|
|
send_error(Req1, Code, Message)
|
|
end.
|
|
|
|
%% ── Вспомогательная функция обновления ────────────────────
|
|
apply_updates(UserId, Updates, AdminId, Reason, Req) ->
|
|
Converted = convert_updates(maps:to_list(Updates)),
|
|
case core_user:update(UserId, Converted) of
|
|
{ok, User} ->
|
|
% Логируем, если был указан reason
|
|
case Reason of
|
|
undefined -> ok;
|
|
_ ->
|
|
case core_admin:get_by_id(AdminId) of
|
|
{ok, Admin} ->
|
|
Action = case maps:get(<<"status">>, Updates, undefined) of
|
|
<<"blocked">> -> <<"block_user">>;
|
|
<<"active">> -> <<"unblock_user">>;
|
|
_ -> <<"update_user">>
|
|
end,
|
|
core_admin_audit:log(AdminId, Admin#admin.email, Admin#admin.role,
|
|
Action, <<"user">>, UserId, <<"127.0.0.1">>, Reason);
|
|
_ -> ok
|
|
end
|
|
end,
|
|
send_json(Req, 200, user_to_json(User));
|
|
{error, not_found} ->
|
|
send_error(Req, 404, <<"User not found">>);
|
|
{error, _} ->
|
|
send_error(Req, 500, <<"Internal server error">>)
|
|
end.
|
|
|
|
convert_updates(Updates) ->
|
|
lists:map(fun({<<"status">>, Value}) -> {status, binary_to_existing_atom(Value, utf8)};
|
|
({<<"role">>, Value}) -> {role, binary_to_existing_atom(Value, utf8)};
|
|
({<<"reason">>, Value}) -> {reason, Value};
|
|
(Other) -> Other
|
|
end, Updates).
|
|
|
|
user_to_json(User) ->
|
|
#{
|
|
id => User#user.id,
|
|
email => User#user.email,
|
|
role => atom_to_binary(User#user.role, utf8),
|
|
status => atom_to_binary(User#user.status, utf8),
|
|
reason => User#user.reason,
|
|
created_at => datetime_to_iso8601(User#user.created_at),
|
|
updated_at => datetime_to_iso8601(User#user.updated_at)
|
|
}.
|
|
|
|
datetime_to_iso8601({{Y,M,D},{H,Min,S}}) ->
|
|
iolist_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0BZ", [Y,M,D,H,Min,S]));
|
|
datetime_to_iso8601(_) -> null.
|
|
|
|
send_json(Req, Status, Data) ->
|
|
Headers = #{
|
|
<<"content-type">> => <<"application/json">>,
|
|
<<"access-control-allow-origin">> => <<"*">>,
|
|
<<"access-control-expose-headers">> => <<"Content-Range">>
|
|
},
|
|
Body = jsx:encode(Data),
|
|
cowboy_req:reply(Status, Headers, Body, Req),
|
|
{ok, Body, []}.
|
|
|
|
send_error(Req, Code, Message) ->
|
|
Headers = #{
|
|
<<"content-type">> => <<"application/json">>,
|
|
<<"access-control-allow-origin">> => <<"*">>,
|
|
<<"access-control-expose-headers">> => <<"Content-Range">>
|
|
},
|
|
Body = jsx:encode(#{error => Message}),
|
|
cowboy_req:reply(Code, Headers, Body, Req),
|
|
{ok, Body, []}. |