Ролевая модель и аудит Часть 1.

This commit is contained in:
2026-04-28 19:12:02 +03:00
parent 7ea4efd7d9
commit b2cea7896d
32 changed files with 369 additions and 320 deletions
+63
View File
@@ -0,0 +1,63 @@
-module(core_admin).
-include("records.hrl").
-export([create/3, get_by_email/1, get_by_id/1, list_all/0,
update_role/2, block/1, unblock/1, generate_id/0]).
create(Email, Password, Role) ->
Id = generate_id(),
{ok, Hash} = argon2:hash(Password),
Now = calendar:universal_time(),
Admin = #admin{
id = Id,
email = Email,
password_hash = Hash,
role = Role,
status = active,
created_at = Now,
updated_at = Now
},
mnesia:dirty_write(Admin),
{ok, Admin}.
get_by_email(Email) ->
Match = #admin{email = Email, _ = '_'},
case mnesia:dirty_match_object(Match) of
[Admin] -> {ok, Admin};
[] -> {error, not_found}
end.
get_by_id(Id) ->
case mnesia:dirty_read({admin, Id}) of
[Admin] -> {ok, Admin};
[] -> {error, not_found}
end.
list_all() ->
mnesia:dirty_match_object(#admin{_ = '_'}).
update_role(Id, NewRole) when is_atom(NewRole) ->
case get_by_id(Id) of
{ok, Admin} ->
Updated = Admin#admin{role = NewRole, updated_at = calendar:universal_time()},
mnesia:dirty_write(Updated),
{ok, Updated};
Error -> Error
end.
block(Id) ->
update_status(Id, blocked).
unblock(Id) ->
update_status(Id, active).
update_status(Id, Status) ->
case get_by_id(Id) of
{ok, Admin} ->
Updated = Admin#admin{status = Status, updated_at = calendar:universal_time()},
mnesia:dirty_write(Updated),
{ok, Updated};
Error -> Error
end.
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
+35
View File
@@ -0,0 +1,35 @@
-module(core_admin_session).
-include("records.hrl").
-export([create/2, validate/1, delete/1]).
-spec create(AdminId :: binary(), RefreshToken :: binary()) -> ok.
create(AdminId, RefreshToken) ->
Session = #admin_session{
token = RefreshToken,
admin_id = AdminId,
expires_at = calendar:gregorian_seconds_to_datetime(
calendar:datetime_to_gregorian_seconds(calendar:universal_time()) + 30 * 24 * 3600),
type = refresh
},
mnesia:dirty_write(Session),
ok.
-spec validate(Token :: binary()) -> {ok, AdminId :: binary()} | {error, not_found | expired}.
validate(Token) ->
case mnesia:dirty_read({admin_session, Token}) of
[Session] ->
case Session#admin_session.expires_at > calendar:universal_time() of
true ->
{ok, Session#admin_session.admin_id};
false ->
mnesia:dirty_delete({admin_session, Token}),
{error, expired}
end;
[] ->
{error, not_found}
end.
-spec delete(Token :: binary()) -> ok.
delete(Token) ->
mnesia:dirty_delete({admin_session, Token}),
ok.
+41
View File
@@ -0,0 +1,41 @@
-module(core_session).
-include("records.hrl").
-export([create/2, validate/1, delete/1]).
-spec create(UserId :: binary(), RefreshToken :: binary()) -> ok.
create(UserId, RefreshToken) ->
Session = #session{
token = RefreshToken,
user_id = UserId,
expires_at = calendar:gregorian_seconds_to_datetime(
calendar:datetime_to_gregorian_seconds(calendar:universal_time()) + 30 * 24 * 3600),
type = refresh
},
mnesia:dirty_write(Session),
ok.
-spec validate(Token :: binary()) -> {ok, UserId :: binary(), User :: #user{}} | {error, not_found | expired}.
validate(Token) ->
case mnesia:dirty_read({session, Token}) of
[Session] ->
case Session#session.expires_at > calendar:universal_time() of
true ->
% Получаем пользователя по ID из сессии
case mnesia:dirty_read({user, Session#session.user_id}) of
[User] ->
{ok, Session#session.user_id, User};
[] ->
{error, not_found}
end;
false ->
mnesia:dirty_delete({session, Token}),
{error, expired}
end;
[] ->
{error, not_found}
end.
-spec delete(Token :: binary()) -> ok.
delete(Token) ->
mnesia:dirty_delete({session, Token}),
ok.