Рефакторинг обработчиков. Часть 2 #21
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user