104 lines
4.1 KiB
Erlang
104 lines
4.1 KiB
Erlang
%%%-------------------------------------------------------------------
|
|
%%% @doc Обработчик регистрации пользователя (клиентский API).
|
|
%%% POST – создаёт нового пользователя (статус pending), возвращает
|
|
%%% информацию о пользователе без JWT токена.
|
|
%%% @end
|
|
%%%-------------------------------------------------------------------
|
|
-module(handler_register).
|
|
-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 (account will be pending until email verified)">>,
|
|
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 successfully (pending verification)">>},
|
|
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">> -> register(Req);
|
|
_ -> handler_utils:send_error(Req, 405, <<"Method not allowed">>)
|
|
end.
|
|
|
|
%% @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} ->
|
|
% Создаём верификационный токен и отправляем письмо
|
|
{ok, VerificationToken, _Expires} = core_verification:create_token(User#user.id),
|
|
logic_email:send_verification_email(Email, VerificationToken),
|
|
Response = #{
|
|
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) % <<"pending">>
|
|
}
|
|
},
|
|
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. |