Skip to main content

src/vpn_peer_action_http.erl

%%%-------------------------------------------------------------------
%% @doc Cowboy handler for dashboard peer start/stop actions.
%%%-------------------------------------------------------------------
-module(vpn_peer_action_http).

-export([init/2]).

init(Req0, State) ->
    case cowboy_req:method(Req0) of
        <<"POST">> ->
            PeerIdBin = cowboy_req:binding(id, Req0),
            Action = maps:get(action, State),
            run_action(Action, PeerIdBin),
            redirect(Req0, State);
        _Other ->
            Req = cowboy_req:reply(
                405,
                #{<<"allow">> => <<"POST">>},
                Req0),
            {ok, Req, State}
    end.

run_action(Action, PeerIdBin) ->
    Result =
        case find_peer_id(PeerIdBin) of
            {ok, PeerId} ->
                apply_action(Action, PeerId);
            {error, not_found} ->
                {error, not_found}
        end,
    log_result(Action, PeerIdBin, Result),
    ok.

apply_action(start, PeerId) ->
    vpn_manager:start_peer(PeerId);
apply_action(stop, PeerId) ->
    vpn_manager:stop_peer(PeerId).

find_peer_id(PeerIdBin) ->
    case [PeerId || PeerId <- vpn_manager:list_peers(),
                    peer_id_binary(PeerId) =:= PeerIdBin] of
        [PeerId | _] ->
            {ok, PeerId};
        [] ->
            {error, not_found}
    end.

peer_id_binary(PeerId) when is_binary(PeerId) ->
    PeerId;
peer_id_binary(PeerId) when is_atom(PeerId) ->
    atom_to_binary(PeerId, utf8).

log_result(_Action, _PeerIdBin, ok) ->
    ok;
log_result(_Action, _PeerIdBin, {ok, _Pid}) ->
    ok;
log_result(Action, PeerIdBin, {error, Reason}) ->
    logger:warning("vpn dashboard peer action failed action=~p peer=~s reason=~p",
                   [Action, PeerIdBin, Reason]).

redirect(Req0, State) ->
    Req = cowboy_req:reply(
        303,
        #{<<"location">> => <<"/admin">>},
        Req0),
    {ok, Req, State}.