-module(logic_admin). -export([list_admins/2, get_admin/1, update_admin/2, delete_admin/1, create_admin/3]). -include("records.hrl"). %% @doc Создаёт нового администратора (доступно только суперадмину). %% Роль может быть superadmin, admin, moderator или support. -spec create_admin(binary(), binary(), atom()) -> {ok, #admin{}} | {error, email_exists | invalid_role}. create_admin(Email, Password, Role) when Role =:= superadmin; Role =:= admin; Role =:= moderator; Role =:= support -> case core_admin:get_by_email(Email) of {ok, _} -> {error, email_exists}; {error, not_found} -> {ok, PasswordHash} = logic_auth:hash_password(Password), core_admin:create(Email, PasswordHash, Role) end; create_admin(_, _, _) -> {error, invalid_role}. %%%------------------------------------------------------------------- %%% Административный список администраторов с пагинацией %%%------------------------------------------------------------------- -spec list_admins(map(), #{limit => integer(), offset => integer(), sort => binary(), order => binary()}) -> {ok, non_neg_integer(), [#admin{}]}. list_admins(Filters, Pagination) -> #{limit := Limit, offset := Offset, sort := Sort, order := Order} = Pagination, AllAdmins = core_admin:list_all(), Filtered = apply_filters(AllAdmins, Filters), Sorted = sort_admins(Filtered, Sort, Order), Total = length(Sorted), Page = lists:sublist(Sorted, Offset + 1, Limit), {ok, Total, Page}. %%%------------------------------------------------------------------- %%% Получение администратора по ID %%%------------------------------------------------------------------- -spec get_admin(binary()) -> {ok, #admin{}} | {error, not_found}. get_admin(AdminId) -> core_admin:get_by_id(AdminId). %%%------------------------------------------------------------------- %%% Обновление администратора %%%------------------------------------------------------------------- -spec update_admin(binary(), proplists:proplist()) -> {ok, #admin{}} | {error, not_found | invalid_field}. update_admin(AdminId, Updates) -> case core_admin:get_by_id(AdminId) of {ok, _Admin} -> ValidUpdates = validate_admin_updates(Updates), core_admin:update(AdminId, ValidUpdates); Error -> Error end. %%%------------------------------------------------------------------- %%% Удалить администратора (физическое удаление из базы) %%%------------------------------------------------------------------- -spec delete_admin(binary()) -> {ok, deleted} | {error, not_found}. delete_admin(AdminId) -> core_admin:delete(AdminId). %%%=================================================================== %%% Внутренние функции %%%=================================================================== apply_filters(Admins, Filters) -> Role = maps:get(role, Filters, undefined), Status = maps:get(status, Filters, undefined), F1 = case Role of undefined -> Admins; _ -> [A || A <- Admins, A#admin.role =:= Role] end, case Status of undefined -> F1; _ -> [A || A <- F1, A#admin.status =:= Status] end. sort_admins(Admins, SortField, Order) -> Field = binary_to_existing_atom(SortField, utf8), Sorted = lists:sort( fun(A, B) -> ValA = admin_field(A, Field), ValB = admin_field(B, Field), if Order == <<"asc">> -> ValA =< ValB; true -> ValA >= ValB end end, Admins), Sorted. admin_field(#admin{created_at = V}, created_at) -> V; admin_field(#admin{email = V}, email) -> V; admin_field(#admin{role = V}, role) -> V; admin_field(_, _) -> undefined. validate_admin_updates(Updates) -> lists:filter(fun validate_admin_update/1, Updates). validate_admin_update({nickname, V}) when is_binary(V); V =:= undefined -> true; validate_admin_update({avatar_url, V}) when is_binary(V); V =:= undefined -> true; validate_admin_update({timezone, V}) when is_binary(V); V =:= undefined -> true; validate_admin_update({language, V}) when is_binary(V); V =:= undefined -> true; validate_admin_update({phone, V}) when is_binary(V); V =:= undefined -> true; validate_admin_update({preferences, V}) when is_map(V); V =:= undefined -> true; validate_admin_update(_) -> false.