Реализовать модуль регистрации ботов #19
This commit is contained in:
15
Makefile
15
Makefile
@@ -307,6 +307,21 @@ docker-swarm-reg-admin:
|
||||
docker-swarm-check-admin:
|
||||
@docker exec $$(docker ps -qf "name=eventhub_eventhub" | head -n 1) /app/bin/eventhub eval 'eventhub_auth:authenticate_admin_request(<<"">>,<<"admin@eventhub.local">>,<<"123456">>).'
|
||||
|
||||
docker-swarm-reg-bots:
|
||||
@docker exec $$(docker ps -qf "name=eventhub_eventhub" | head -n 1) /app/bin/eventhub eval "os:putenv(\"BOT_COUNT\", \"3000\"), bot_controller:register()."
|
||||
|
||||
docker-swarm-reg-bots-stop:
|
||||
@docker exec $$(docker ps -qf "name=eventhub_eventhub" | head -n 1) /app/bin/eventhub eval 'bot_controller:stop().'
|
||||
|
||||
docker-swarm-delete-bots:
|
||||
@docker exec $$(docker ps -qf "name=eventhub_eventhub" | head -n 1) /app/bin/eventhub eval 'bot_controller:delete().'
|
||||
|
||||
docker-swarm-count-bots:
|
||||
@for id in $$(docker ps -qf "name=eventhub_eventhub"); do \
|
||||
echo "=== $$id ==="; \
|
||||
docker exec $$id /app/bin/eventhub eval 'bot_controller:count_bots().'; \
|
||||
done
|
||||
|
||||
docker-swarm-shell:
|
||||
@docker exec $$(docker ps -qf "name=eventhub_eventhub" | head -n 1) /app/bin/eventhub remote_console
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
-export([list_users/0]).
|
||||
-export([block/2, unblock/2]).
|
||||
-export([count_users/0, count_users_by_date/2]).
|
||||
-export([create_bot/2, delete_bot/1]).
|
||||
|
||||
%% Создание пользователя
|
||||
create(Email, Password) ->
|
||||
@@ -170,4 +171,44 @@ set_field(email, Value, U) -> U#user{email = Value};
|
||||
set_field(password_hash, Value, U) -> U#user{password_hash = Value};
|
||||
set_field(role, Value, U) when Value =:= user; Value =:= admin -> U#user{role = Value};
|
||||
set_field(status, Value, U) when Value =:= active; Value =:= frozen; Value =:= deleted -> U#user{status = Value};
|
||||
set_field(_, _, U) -> U.
|
||||
set_field(_, _, U) -> U.
|
||||
|
||||
%% ------------------------------------------------------------------
|
||||
%% API для ботов
|
||||
%% ------------------------------------------------------------------
|
||||
|
||||
-spec create_bot(Email :: binary(), Password :: binary()) ->
|
||||
{ok, User :: #user{}} | {error, duplicate_email | invalid_email}.
|
||||
create_bot(Email, Password) ->
|
||||
case email_exists(Email) of
|
||||
true ->
|
||||
{error, email_exists};
|
||||
false ->
|
||||
case mnesia:dirty_index_read(user, Email, email) of
|
||||
[] ->
|
||||
{ok, PasswordHash} = logic_auth:hash_password(Password),
|
||||
Id = generate_id(),
|
||||
User = #user{
|
||||
id = Id,
|
||||
email = Email,
|
||||
password_hash = PasswordHash,
|
||||
role = bot,
|
||||
status = active,
|
||||
created_at = calendar:universal_time(),
|
||||
updated_at = calendar:universal_time()
|
||||
},
|
||||
ok = mnesia:dirty_write(User),
|
||||
{ok, User};
|
||||
_ ->
|
||||
{error, duplicate_email}
|
||||
end
|
||||
end.
|
||||
|
||||
-spec delete_bot(Id :: binary()) -> ok | {error, not_found}.
|
||||
delete_bot(Id) ->
|
||||
case mnesia:dirty_read({user, Id}) of
|
||||
[#user{role = bot}] ->
|
||||
mnesia:dirty_delete({user, Id}),
|
||||
ok;
|
||||
[] -> {error, not_found}
|
||||
end.
|
||||
88
src/infra/bot_controller.erl
Normal file
88
src/infra/bot_controller.erl
Normal file
@@ -0,0 +1,88 @@
|
||||
-module(bot_controller).
|
||||
-include("records.hrl").
|
||||
|
||||
-export([register/0, stop/0, delete/0, count_bots/0]).
|
||||
|
||||
-define(REG_NAME, {bot_registration, node()}).
|
||||
|
||||
%% ------------------------------------------------------------------
|
||||
%% @doc Асинхронно регистрирует ботов (одновременно только один процесс).
|
||||
%% Возвращает pid процесса или ошибку.
|
||||
%% ------------------------------------------------------------------
|
||||
register() ->
|
||||
Count = list_to_integer(os:getenv("BOT_COUNT", "0")),
|
||||
Domain = list_to_binary(os:getenv("BOT_DOMAIN", "eventhub.com")),
|
||||
Password = list_to_binary(os:getenv("BOT_DEFAULT_PASSWORD", "botpass123")),
|
||||
if Count =< 0 ->
|
||||
{error, <<"BOT_COUNT must be greater than 0">>};
|
||||
true ->
|
||||
io:format("Starting async registration of ~p bots with domain ~s...~n", [Count, Domain]),
|
||||
Pid = spawn(fun() ->
|
||||
register_bots(Count, Domain, Password)
|
||||
end),
|
||||
case global:register_name(?REG_NAME, Pid) of
|
||||
yes ->
|
||||
{ok, Pid};
|
||||
no ->
|
||||
% Уже есть активный процесс регистрации
|
||||
exit(Pid, kill),
|
||||
{error, registration_already_running}
|
||||
end
|
||||
end.
|
||||
|
||||
%% ------------------------------------------------------------------
|
||||
%% @doc Останавливает текущий процесс регистрации.
|
||||
%% ------------------------------------------------------------------
|
||||
stop() ->
|
||||
case global:whereis_name(?REG_NAME) of
|
||||
undefined ->
|
||||
io:format("No active bot registration found.~n");
|
||||
Pid ->
|
||||
exit(Pid, kill),
|
||||
io:format("Bot registration process ~p stopped.~n", [Pid])
|
||||
end.
|
||||
|
||||
%% ------------------------------------------------------------------
|
||||
%% @doc Удаляет всех пользователей с ролью bot.
|
||||
%% ------------------------------------------------------------------
|
||||
delete() ->
|
||||
Bots = mnesia:dirty_match_object(#user{role = bot, _ = '_'}),
|
||||
lists:foreach(fun(#user{id = Id}) ->
|
||||
mnesia:dirty_delete({user, Id})
|
||||
end, Bots),
|
||||
io:format("Deleted ~p bots.~n", [length(Bots)]),
|
||||
ok.
|
||||
|
||||
%% ------------------------------------------------------------------
|
||||
%% @doc Возвращает количество ботов в базе.
|
||||
%% ------------------------------------------------------------------
|
||||
count_bots() ->
|
||||
length(mnesia:dirty_match_object(#user{role = bot, _ = '_'})).
|
||||
|
||||
%% ------------------------------------------------------------------
|
||||
%% Внутренние функции
|
||||
%% ------------------------------------------------------------------
|
||||
register_bots(Count, Domain, Password) ->
|
||||
register_bots(Count, Domain, Password, []).
|
||||
|
||||
register_bots(0, _, _, Acc) ->
|
||||
io:format("Async registration completed. Created ~p bots.~n", [length(Acc)]),
|
||||
global:unregister_name(?REG_NAME);
|
||||
register_bots(N, Domain, Password, Acc) ->
|
||||
Email = generate_email(Domain),
|
||||
case core_user:create_bot(Email, Password) of
|
||||
{ok, _User} ->
|
||||
register_bots(N-1, Domain, Password, [Email | Acc]);
|
||||
{error, duplicate_email} ->
|
||||
register_bots(N, Domain, Password, Acc);
|
||||
{error, _} ->
|
||||
register_bots(N-1, Domain, Password, Acc)
|
||||
end.
|
||||
|
||||
generate_email(Domain) ->
|
||||
Name = random_string(8),
|
||||
<<"bot_", Name/binary, "@", Domain/binary>>.
|
||||
|
||||
random_string(Length) ->
|
||||
Chars = <<"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789">>,
|
||||
list_to_binary([lists:nth(rand:uniform(byte_size(Chars)), binary_to_list(Chars)) || _ <- lists:seq(1, Length)]).
|
||||
@@ -242,6 +242,7 @@ create_indices() ->
|
||||
mnesia:add_table_index(calendar_specialist, calendar_id),
|
||||
mnesia:add_table_index(calendar_specialist, user_id),
|
||||
mnesia:add_table_index(user, nickname),
|
||||
mnesia:add_table_index(user, email),
|
||||
mnesia:add_table_index(notification, user_id),
|
||||
mnesia:add_table_index(notification, is_read),
|
||||
ok.
|
||||
Reference in New Issue
Block a user