Files
EventHubBack/src/eventhub_app.erl

147 lines
6.6 KiB
Erlang

-module(eventhub_app).
-behaviour(application).
-export([start/2, stop/1]).
start(_StartType, _StartArgs) ->
pg:start_link(),
application:ensure_all_started(mnesia),
application:ensure_all_started(cowboy),
case infra_sup:start_link() of
{ok, Pid} ->
ok = infra_mnesia:init_tables(),
ok = infra_mnesia:wait_for_tables(),
connect_nodes(),
init_default_superadmin(),
start_http(), % Пользовательский API (8080)
start_admin_http(), % Административный API (8445)
application:ensure_all_started(prometheus),
application:ensure_all_started(prometheus_cowboy),
{ok, Pid};
Error ->
Error
end.
stop(_State) -> ok.
%% ===================================================================
%% Пользовательский HTTP (порт 8080) — только публичные эндпоинты
%% ===================================================================
start_http() ->
Port = application:get_env(eventhub, http_port, 8080),
Dispatch = cowboy_router:compile([
{'_', [
{"/metrics/[:registry]", prometheus_cowboy2_handler, []},
{"/health", handler_health, []},
{"/v1/register", handler_register, []},
{"/v1/login", handler_login, []},
{"/v1/refresh", handler_refresh, []},
{"/v1/user/me", handler_user_me, []},
{"/v1/user/bookings", handler_user_bookings, []},
{"/v1/user/reviews", handler_user_reviews, []},
{"/v1/search", handler_search, []},
{"/v1/calendars", handler_calendars, []},
{"/v1/calendars/:id", handler_calendar_by_id, []},
{"/v1/calendars/:calendar_id/events", handler_events, []},
{"/v1/events/:id", handler_event_by_id, []},
{"/v1/events/:id/occurrences", handler_event_occurrences, []},
{"/v1/events/:id/occurrences/:start_time", handler_event_occurrences, []},
{"/v1/events/:id/bookings", handler_bookings, []},
{"/v1/bookings/:id", handler_booking_by_id, []},
{"/v1/reviews", handler_reviews, []},
{"/v1/reviews/:id", handler_review_by_id, []},
{"/v1/reports", handler_reports, []},
{"/v1/tickets", handler_tickets, []},
{"/v1/tickets/:id", handler_ticket_by_id, []},
{"/v1/subscription", handler_subscription, []}
]}
]),
Middlewares = [cowboy_router, cowboy_handler],
Env = #{dispatch => Dispatch},
cowboy:start_clear(http, [{port, Port}], #{env => Env, middlewares => Middlewares}),
io:format("HTTP server started on port ~p~n", [Port]).
%% ===================================================================
%% Административный HTTP (порт 8445) — все админские эндпоинты
%% ===================================================================
start_admin_http() ->
Port = application:get_env(eventhub, admin_http_port, 8445),
Dispatch = cowboy_router:compile([
{'_', [
% ================== БАЗОВЫЕ ==================
{"/v1/admin/health", admin_handler_health, []},
{"/v1/admin/stats", admin_handler_stats, []},
{"/v1/admin/login", admin_handler_login, []},
% ================== ПОЛЬЗОВАТЕЛИ ==================
{"/v1/admin/users", admin_handler_users, []},
{"/v1/admin/users/:id", admin_handler_user_by_id, []},
% ================== ОТЧЁТЫ ==================
{"/v1/admin/reports", admin_handler_reports, []},
{"/v1/admin/reports/:id", admin_handler_report_by_id, []},
% ================== ОТЗЫВЫ ==================
{"/v1/admin/reviews/:id", admin_handler_reviews, []},
% ================== БАН-СЛОВА ==================
{"/v1/admin/banned-words", admin_handler_banned_words, []},
{"/v1/admin/banned-words/:word", admin_handler_banned_words, []},
% ================== ТИКЕТЫ ==================
{"/v1/admin/tickets/stats", admin_handler_ticket_stats, []},
{"/v1/admin/tickets/:id", admin_handler_ticket_by_id, []},
{"/v1/admin/tickets", admin_handler_tickets, []},
% ================== ПОДПИСКИ ==================
{"/v1/admin/subscriptions", admin_handler_subscriptions, []},
{"/v1/admin/subscriptions/:id", admin_handler_subscriptions, []},
% ================== МОДЕРАЦИЯ (общий маршрут) ==================
{"/v1/admin/:target_type/:id", admin_handler_moderation, []},
% ================== Управление ролями (только для superadmin) ==================
{"/v1/admin/me", admin_handler_me, []},
{"/v1/admin/admins", admin_handler_admins, []},
{"/v1/admin/admins/:id", admin_handler_admins, []},
{"/v1/admin/audit", admin_handler_audit, []}
]}
]),
Middlewares = [cowboy_router, cowboy_handler],
Env = #{dispatch => Dispatch},
cowboy:start_clear(admin_http, [{port, Port}], #{env => Env, middlewares => Middlewares}),
io:format("Admin HTTP server started on port ~p~n", [Port]),
% WebSocket для пользователей
WsDispatch = cowboy_router:compile([{'_', [{"/ws", ws_handler, []}]}]),
cowboy:start_clear(ws, [{port, 8081}], #{env => #{dispatch => WsDispatch}}),
% WebSocket для админов
AdminWsDispatch = cowboy_router:compile([{'_', [{"/admin/ws", admin_ws_handler, []}]}]),
cowboy:start_clear(admin_ws, [{port, 8446}], #{env => #{dispatch => AdminWsDispatch}}),
io:format("WebSocket started on ports 8081 (user) and 8446 (admin)~n").
%% ===================================================================
%% Ручное подключение к нодам кластера (запасной вариант)
%% ===================================================================
connect_nodes() ->
case os:getenv("JOIN_NODES") of
false -> ok;
NodesStr ->
Nodes = [list_to_atom(string:trim(N)) || N <- string:tokens(NodesStr, ",")],
lists:foreach(fun(Node) ->
case net_kernel:connect_node(Node) of
true -> io:format("Connected to ~s~n", [Node]);
false -> io:format("ERROR: Failed to connect to ~s~n", [Node]);
ignored -> ok
end
end, Nodes)
end.
init_default_superadmin() ->
case core_admin:list_all() of
[] ->
AdminEmail = os:getenv("ADMIN_EMAIL", "admin@eventhub.local"),
AdminPassword = os:getenv("ADMIN_PASSWORD", "123456"),
{ok, _Admin} = core_admin:create(
list_to_binary(AdminEmail),
list_to_binary(AdminPassword),
superadmin
),
io:format("Default superadmin created: ~s~n", [AdminEmail]);
_ ->
io:format("Superadmin already exists. Skipping creation.~n")
end.