Ролевая модель и аудит Часть 1.
This commit is contained in:
@@ -8,41 +8,12 @@ init(Req0, _Opts) ->
|
||||
{ok, Body, Req1} = cowboy_req:read_body(Req0),
|
||||
try jsx:decode(Body, [return_maps]) of
|
||||
#{<<"refresh_token">> := RefreshToken} ->
|
||||
case get_session(RefreshToken) of
|
||||
{ok, Session} ->
|
||||
% Проверяем, не истекла ли сессия
|
||||
case Session#session.expires_at > calendar:universal_time() of
|
||||
true ->
|
||||
% Генерируем новый access-токен и refresh-токен
|
||||
User = get_user(Session#session.user_id),
|
||||
NewToken = eventhub_auth:generate_user_token(
|
||||
User#user.id,
|
||||
atom_to_binary(User#user.role, utf8)
|
||||
),
|
||||
{NewRefreshToken, ExpiresAt} =
|
||||
eventhub_auth:generate_refresh_token(User#user.id),
|
||||
% Удаляем старую сессию и сохраняем новую
|
||||
mnesia:dirty_delete_object(Session),
|
||||
NewSession = #session{
|
||||
token = NewRefreshToken,
|
||||
user_id = User#user.id,
|
||||
expires_at = ExpiresAt,
|
||||
type = refresh
|
||||
},
|
||||
mnesia:dirty_write(NewSession),
|
||||
Resp = jsx:encode(#{
|
||||
token => NewToken,
|
||||
refresh_token => NewRefreshToken
|
||||
}),
|
||||
cowboy_req:reply(200, #{
|
||||
<<"content-type">> => <<"application/json">>
|
||||
}, Resp, Req1);
|
||||
false ->
|
||||
mnesia:dirty_delete_object(Session),
|
||||
send_error(Req1, 401, <<"Refresh token expired">>)
|
||||
end;
|
||||
{error, not_found} ->
|
||||
send_error(Req1, 401, <<"Refresh token not found">>)
|
||||
case find_and_refresh(RefreshToken) of
|
||||
{ok, NewTokenPair} ->
|
||||
Resp = jsx:encode(NewTokenPair),
|
||||
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json">>}, Resp, Req1);
|
||||
{error, Reason} ->
|
||||
send_error(Req1, 401, Reason)
|
||||
end;
|
||||
_ ->
|
||||
send_error(Req1, 400, <<"Missing refresh_token field">>)
|
||||
@@ -53,15 +24,50 @@ init(Req0, _Opts) ->
|
||||
send_error(Req0, 405, <<"Method not allowed">>)
|
||||
end.
|
||||
|
||||
get_session(Token) ->
|
||||
case mnesia:dirty_read({session, Token}) of
|
||||
[Session] -> {ok, Session};
|
||||
[] -> {error, not_found}
|
||||
%% --------------------------------------------------------
|
||||
%% Общая логика: проверяет обе таблицы сессий
|
||||
%% --------------------------------------------------------
|
||||
|
||||
find_and_refresh(RefreshToken) ->
|
||||
case core_session:validate(RefreshToken) of
|
||||
{ok, UserId, User} ->
|
||||
user_refresh(UserId, User, RefreshToken);
|
||||
{error, not_found} ->
|
||||
case core_admin_session:validate(RefreshToken) of
|
||||
{ok, AdminId} ->
|
||||
admin_refresh(AdminId, RefreshToken);
|
||||
{error, not_found} ->
|
||||
{error, <<"Refresh token not found">>};
|
||||
{error, expired} ->
|
||||
{error, <<"Refresh token expired">>}
|
||||
end;
|
||||
{error, expired} ->
|
||||
{error, <<"Refresh token expired">>}
|
||||
end.
|
||||
|
||||
get_user(UserId) ->
|
||||
[User] = mnesia:dirty_read({user, UserId}),
|
||||
User.
|
||||
user_refresh(UserId, User, OldToken) ->
|
||||
% Удаляем старый refresh-токен
|
||||
core_session:delete(OldToken),
|
||||
% Генерируем новый access-токен и refresh-токен
|
||||
Role = atom_to_binary(User#user.role, utf8),
|
||||
NewToken = eventhub_auth:generate_user_token(UserId, Role),
|
||||
{NewRefreshToken, _ExpiresAt} = eventhub_auth:generate_refresh_token(UserId),
|
||||
% Сохраняем новый refresh-токен в таблице session
|
||||
core_session:create(UserId, NewRefreshToken),
|
||||
{ok, #{token => NewToken, refresh_token => NewRefreshToken}}.
|
||||
|
||||
admin_refresh(AdminId, OldToken) ->
|
||||
% Удаляем старый refresh-токен
|
||||
core_admin_session:delete(OldToken),
|
||||
% Получаем роль админа
|
||||
{ok, Admin} = core_admin:get_by_id(AdminId),
|
||||
Role = atom_to_binary(Admin#admin.role, utf8),
|
||||
% Генерируем новый access-токен и refresh-токен
|
||||
NewToken = eventhub_auth:generate_admin_token(AdminId, Role),
|
||||
{NewRefreshToken, _ExpiresAt} = eventhub_auth:generate_refresh_token(AdminId),
|
||||
% Сохраняем новый refresh-токен в таблице admin_session
|
||||
core_admin_session:create(AdminId, NewRefreshToken),
|
||||
{ok, #{token => NewToken, refresh_token => NewRefreshToken}}.
|
||||
|
||||
send_error(Req, Status, Message) ->
|
||||
Body = jsx:encode(#{error => Message}),
|
||||
|
||||
Reference in New Issue
Block a user