Рефакторинг обработчиков. Часть 2 #21

This commit is contained in:
2026-05-11 21:51:45 +03:00
parent 6403f061df
commit 61bb44ab4a
31 changed files with 8391 additions and 1480 deletions
+93 -54
View File
@@ -1,65 +1,104 @@
%%%-------------------------------------------------------------------
%%% @doc Обработчик регистрации пользователя (клиентский API).
%%% POST – создаёт нового пользователя, возвращает JWT токен.
%%% @end
%%%-------------------------------------------------------------------
-module(handler_register).
-include("records.hrl").
-behaviour(cowboy_handler).
-export([init/2]).
-export([trails/0]).
-include("records.hrl").
%%% cowboy_handler callback
-spec init(cowboy_req:req(), any()) -> {ok, cowboy_req:req(), any()}.
init(Req, Opts) ->
handle(Req, Opts).
%%% Swagger metadata
-spec trails() -> [map()].
trails() ->
[
#{
path => <<"/v1/register">>,
method => <<"POST">>,
description => <<"Register a new user">>,
tags => [<<"Auth">>],
requestBody => #{
required => true,
content => #{<<"application/json">> => #{schema => #{
type => object,
required => [<<"email">>, <<"password">>],
properties => #{
email => #{type => string, format => <<"email">>},
password => #{type => string, format => <<"password">>}
}
}}}
},
responses => #{
201 => #{description => <<"User registered, returns token and user info">>},
400 => #{description => <<"Missing email or password, or invalid JSON">>},
409 => #{description => <<"Email already exists">>}
}
}
].
%%%===================================================================
%%% HTTP-методы
%%%===================================================================
%% @private
-spec handle(cowboy_req:req(), any()) -> {ok, cowboy_req:req(), any()}.
handle(Req, _Opts) ->
case cowboy_req:method(Req) of
<<"POST">> ->
case cowboy_req:has_body(Req) of
true ->
{ok, Body, Req1} = cowboy_req:read_body(Req),
case Body of
<<>> ->
send_error(Req1, 400, <<"Empty request body">>);
_ ->
try jsx:decode(Body, [return_maps]) of
#{<<"email">> := Email, <<"password">> := Password} ->
case core_user:email_exists(Email) of
true ->
send_error(Req1, 409, <<"Email already exists">>);
false ->
case core_user:create(Email, Password) of
{ok, User} ->
Token = logic_auth:generate_jwt(User#user.id, atom_to_binary(User#user.role, utf8)),
Response = #{
user => #{
id => User#user.id,
email => User#user.email,
role => User#user.role
},
token => Token
},
send_json(Req1, 201, Response);
{error, email_exists} ->
send_error(Req1, 409, <<"Email already exists">>);
{error, _} ->
send_error(Req1, 500, <<"Internal server error">>)
end
end;
_ ->
send_error(Req1, 400, <<"Missing email or password">>)
catch
_:_ ->
send_error(Req1, 400, <<"Invalid JSON">>)
end
end;
false ->
send_error(Req, 400, <<"Missing request body">>)
end;
_ ->
send_error(Req, 405, <<"Method not allowed">>)
<<"POST">> -> register(Req);
_ -> handler_utils:send_error(Req, 405, <<"Method not allowed">>)
end.
send_json(Req, Status, Data) ->
Body = jsx:encode(Data),
cowboy_req:reply(Status, #{<<"content-type">> => <<"application/json">>}, Body, Req),
{ok, Body, []}.
send_error(Req, Status, Message) ->
Body = jsx:encode(#{error => Message}),
cowboy_req:reply(Status, #{<<"content-type">> => <<"application/json">>}, Body, Req),
{ok, Body, []}.
%% @doc POST /v1/register — регистрация нового пользователя.
-spec register(cowboy_req:req()) -> {ok, binary(), cowboy_req:req()}.
register(Req) ->
case cowboy_req:has_body(Req) of
true ->
{ok, Body, Req1} = cowboy_req:read_body(Req),
case Body of
<<>> ->
handler_utils:send_error(Req1, 400, <<"Empty request body">>);
_ ->
try jsx:decode(Body, [return_maps]) of
#{<<"email">> := Email, <<"password">> := Password} ->
case core_user:email_exists(Email) of
true ->
handler_utils:send_error(Req1, 409, <<"Email already exists">>);
false ->
case core_user:create(Email, Password) of
{ok, User} ->
Token = logic_auth:generate_jwt(
User#user.id,
atom_to_binary(User#user.role, utf8)
),
Response = #{
user => #{
id => User#user.id,
email => User#user.email,
role => User#user.role
},
token => Token
},
handler_utils:send_json(Req1, 201, Response);
{error, email_exists} ->
handler_utils:send_error(Req1, 409, <<"Email already exists">>);
{error, _} ->
handler_utils:send_error(Req1, 500, <<"Internal server error">>)
end
end;
_ ->
handler_utils:send_error(Req1, 400, <<"Missing email or password">>)
catch
_:_ -> handler_utils:send_error(Req1, 400, <<"Invalid JSON">>)
end
end;
false ->
handler_utils:send_error(Req, 400, <<"Missing request body">>)
end.