diff --git a/include_apps/oacd_freeswitch/src/freeswitch_fetch_handler.erl b/include_apps/oacd_freeswitch/src/freeswitch_fetch_handler.erl
new file mode 100644
index 00000000..1c01bcb5
--- /dev/null
+++ b/include_apps/oacd_freeswitch/src/freeswitch_fetch_handler.erl
@@ -0,0 +1,263 @@
+%% @doc Fetch handler for freeswitch sip authentication. Adds trigger for
+%% the auth_agent_success hook to nab the agent password and generate some
+%% a1 hashes for it.
+
+-module(freeswitch_fetch_handler).
+-behavior(gen_server).
+
+-include_lib("OpenACD/include/log.hrl").
+
+-define(default_dial_string(Type), case Type of
+ sip_registration -> "sofia/internal/$1%";
+ sip -> "sofia/internal/sip:$1";
+ iax2 -> "iax2/$1";
+ h323 -> "opal/h3232:$1";
+ pstn -> "";
+ rtmp -> "rtmp/$1"
+end).
+-define(EMPTYRESPONSE, "").
+-define(NOTFOUNDRESPONSE,
+"
+
+").
+
+-define(DIALUSERRESPONSE,
+"
+
+").
+
+-define(REGISTERRESPONSE,
+"
+
+").
+
+-define(USERRESPONSE,
+"
+
+").
+
+-define(ets, oacd_freeswitch_a1).
+
+% gen_server
+-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,
+ code_change/3]).
+% public api
+-export([start_link/3,hook_callback/3,set_hook/0]).
+
+%% ======================================================================
+%% API
+%% ======================================================================
+
+
+start_link(Freeswitch,DialstringBases,SipAuth) when SipAuth =:= sip_auth; SipAuth =:= no_sip_auth ->
+ Pid = proc_lib:spawn_link(fun() ->
+ {foo, Freeswitch} ! {bind, directory},
+ receive
+ ok ->
+ erlang:register(?MODULE,self()),
+ {ok, State} = init({Freeswitch,DialstringBases,SipAuth}),
+ gen_server:enter_loop(?MODULE,[],State,{local, ?MODULE});
+ {error,Reason} ->
+ exit(Reason)
+ after 5000 ->
+ exit(timeout)
+ end
+ end),
+ {ok, Pid}.
+
+hook_callback(User, Pass, _Res) ->
+ ?DEBUG("Hook triggered for user auth: ~p", [User]),
+ {ok, Ifs} = inet:getif(),
+ IfsToIpStrings = fun({Ip,_,_},Acc) ->
+ {A,B,C,D} = Ip,
+ Ips = lists:flatten(io_lib:format("~p.~p.~p.~p",[A,B,C,D])),
+ [Ips | Acc]
+ end,
+ Localhost = net_adm:localhost(),
+ IpStrings = lists:foldl(IfsToIpStrings,[Localhost],Ifs),
+ Hashes = [{IPString,util:bin_to_hexstr(erlang:md5(User++":"++IPString++":"++Pass))} || IPString <- IpStrings],
+ ets:insert(?ets, {User, Hashes}).
+
+set_hook() ->
+ cpx_hooks:set_hook(?MODULE, auth_agent_success, {?MODULE, hook_callback, []}).
+
+%% ======================================================================
+%% gen_server
+%% ======================================================================
+
+%% ----------------------------------------------------------------------
+%% init
+%% ----------------------------------------------------------------------
+
+init({Freeswitch,Dialstrings,SipAuth}) ->
+ ets:new(?ets, [named_table, public]),
+ set_hook(),
+ ?INFO("Started",[]),
+ {ok, {Freeswitch,Dialstrings,SipAuth}}.
+
+%% ----------------------------------------------------------------------
+%% handle_call
+%% ----------------------------------------------------------------------
+
+handle_call(_Msg,_From,State) ->
+ {reply, {error, invalid},State}.
+
+%% ----------------------------------------------------------------------
+%% handle_cast
+%% ----------------------------------------------------------------------
+
+handle_cast(_Msg,State) ->
+ {noreply,State}.
+
+%% ----------------------------------------------------------------------
+%% handle_info
+%% ----------------------------------------------------------------------
+
+handle_info({fetch, directory, "domain", "name", _Value, Id, [undefined | Data]}, State) ->
+ %?DEBUG("The data: ~p", [Data]),
+ case proplists:get_value("as_channel", Data) of
+ "true" ->
+ fetch_as_channel(Id,Data,State);
+ _Else ->
+ case proplists:get_value("action",Data) of
+ "sip_auth" ->
+ fetch_sip_auth(Id,Data,State);
+ _ ->
+ fetch_user_lookup(Id,Data,State)
+ end
+ end,
+ {noreply, State};
+
+handle_info({fetch, _Section, _Something, _Key, _Value, ID, [undefined | _Data]},{Node,_,_}=State) ->
+ freeswitch:fetch_reply(Node, ID, ?EMPTYRESPONSE),
+ {noreply,State};
+
+handle_info({nodedown,Node},{Node,_,_}=State) ->
+ {stop,nodedown,State};
+
+handle_info(_Msg,State) ->
+ {noreoply,State}.
+
+%% ----------------------------------------------------------------------
+%% terminate
+%% ----------------------------------------------------------------------
+
+terminate(_Why,_State)-> ok.
+
+%% ----------------------------------------------------------------------
+%% code_change
+%% ----------------------------------------------------------------------
+
+code_change(_Old,State,_Extra) ->
+ {ok,State}.
+
+%% ======================================================================
+%% Internal
+%% ======================================================================
+
+fetch_user_lookup(Id,_Data,{Node,_,no_sip_auth}) ->
+ ?DEBUG("Lookup when not doing sip auth, empty response",[]),
+ % I guess we're just looking up a user?
+ % Looking up for first part of an auth most likely.
+ % only auth we support is sip (which is above) so we'll
+ % depend on that.
+ freeswitch:fetch_reply(Node, Id, ?EMPTYRESPONSE);
+
+fetch_user_lookup(ID,Data,{Node,_,_}) ->
+ User = proplists:get_value("user", Data),
+ Domain = proplists:get_value("domain", Data),
+ case agent_manager:query_agent(User) of
+ {true, _Pid} ->
+ ?DEBUG("Lookup succeeded for user ~s@~s", [User,Domain]),
+ freeswitch:fetch_reply(Node, ID, lists:flatten(io_lib:format(?USERRESPONSE, [Domain, User])));
+ false ->
+ freeswitch:fetch_reply(Node, ID, ?EMPTYRESPONSE)
+ end.
+
+fetch_sip_auth(ID,_Data,{Node,_,no_sip_auth}) ->
+ %% not doing sip auth, return nothing
+ ?DEBUG("Not doing SIP auth", []),
+ freeswitch:fetch_reply(Node, ID, "");
+
+fetch_sip_auth(ID,Data,{Node,_,sip_auth}) ->
+ User = proplists:get_value("user", Data),
+ Domain = proplists:get_value("domain", Data),
+ Realm = proplists:get_value("sip_auth_realm", Data),
+ % TODO Can this be done w/o dealing w/ a plain text pw?
+ case ets:lookup(?ets, User) of
+ [] ->
+ ?DEBUG("Sip auth ~s@~s for relam ~s is not found",[User,Domain,Realm]),
+ freeswitch:fetch_reply(Node, ID, ?EMPTYRESPONSE);
+ [{User,Hashes}] ->
+ case proplists:get_value(Realm,Hashes) of
+ undefined ->
+ ?DEBUG("Sip auth ~s@~s for relam ~s has no hash",[User,Domain,Realm]),
+ freeswitch:fetch_reply(Node, ID, ?EMPTYRESPONSE);
+ Hash ->
+ ?DEBUG("Sip auth ~s@~s for relam ~s found hash ~s",[User,Domain,Realm,Hash]),
+ freeswitch:fetch_reply(Node, ID, lists:flatten(io_lib:format(?REGISTERRESPONSE,[Domain,User,Hash])))
+ end
+ end.
+
+fetch_as_channel(ID,Data,{Node,State,_}) ->
+ User = proplists:get_value("user", Data),
+ Domain = proplists:get_value("domain", Data),
+ case agent_manager:query_agent(User) of
+ {true, Pid} ->
+ try agent:dump_state(Pid) of
+ Agent ->
+ {ok, {Opts, _}} = agent:get_endpoint(freeswitch_media, Agent),
+ Type = proplists:get_value(type, Opts),
+ Dat = proplists:get_value(data, Opts),
+
+ DialString = case {Type, Dat} of
+ {sip_registration, undefined} ->
+ "${sofia_contact("++User++"@"++Domain++")}";
+ {sip_registration, D} ->
+ "${sofia_contact("++re:replace(D, "@", "_", [{return, list}])++"@"++Domain++")}";
+ {sip, D} ->
+ freeswitch_media_manager:do_dial_string(proplists:get_value(sip, State, "sofia/internal/sip:"), D, []);
+ {iax2, D} ->
+ freeswitch_media_manager:do_dial_string(proplists:get_value(iax2, State, "iax2/"), D, []);
+ {h323, D} ->
+ freeswitch_media_manager:do_dial_string(proplists:get_value(h323, State, "opal/h323:"), D, []);
+ {pstn, D} ->
+ freeswitch_media_manager:do_dial_string(proplists:get_value(dialstring, State, ""), D, []);
+ {rtmp,D} ->
+ freeswitch_media_manager:do_dial_string(proplists:get_value(rtmp, State, "rtmp/$1"), D, [])
+ end,
+ ?NOTICE("returning ~s for user directory entry ~s", [DialString, User]),
+ freeswitch:fetch_reply(Node, ID, lists:flatten(io_lib:format(?DIALUSERRESPONSE, [Domain, User, DialString])))
+ catch
+ _:_ -> % agent pid is toast?
+ freeswitch:fetch_reply(Node, ID, ?NOTFOUNDRESPONSE)
+ end;
+ false ->
+ freeswitch:fetch_reply(Node, ID, ?NOTFOUNDRESPONSE)
+ end.
diff --git a/include_apps/oacd_freeswitch/src/freeswitch_media.erl b/include_apps/oacd_freeswitch/src/freeswitch_media.erl
index ff47a52f..6f444063 100644
--- a/include_apps/oacd_freeswitch/src/freeswitch_media.erl
+++ b/include_apps/oacd_freeswitch/src/freeswitch_media.erl
@@ -146,24 +146,33 @@
%%====================================================================
%% API
%%====================================================================
-%% @doc starts the freeswitch media gen_server. `Cnode' is the C node the communicates directly with freeswitch.
+
+%% @doc starts the freeswitch media gen_media. `Cnode' is the C node the
+%% communicates directly with freeswitch. Dialstring is the data used to
+%% connect to an outside line. UUID is the id of the channel on
+%% freeswith, and therefore the id of the call in OpenACD.
-spec(start/3 :: (Cnode :: atom(), DialString :: string(), UUID :: string()) -> {'ok', pid()}).
start(Cnode, DialString, UUID) ->
gen_media:start(?MODULE, [Cnode, DialString, UUID]).
+%% @doc Starts the freeswitch gen_media linked to the calling process.
+%% @see start/3
-spec(start_link/3 :: (Cnode :: atom(), DialString :: string(), UUID :: string()) -> {'ok', pid()}).
start_link(Cnode, DialString, UUID) ->
gen_media:start_link(?MODULE, [Cnode, DialString, UUID]).
-%% @doc returns the record of the call freeswitch media `MPid' is in charge of.
+%% @doc returns the record of the call freeswitch media `MPid' is in
+%% charge of.
-spec(get_call/1 :: (MPid :: pid()) -> #call{}).
get_call(MPid) ->
gen_media:get_call(MPid).
+%% @doc A debugging function that returns the state record.
-spec(dump_state/1 :: (Mpid :: pid()) -> #state{}).
dump_state(Mpid) when is_pid(Mpid) ->
gen_media:call(Mpid, dump_state).
+%% @hidden
'3rd_party_pickup'(Mpid) ->
Self = self(),
gen_media:cast(Mpid, {'3rd_party_pickup', Self}).
@@ -171,6 +180,7 @@ dump_state(Mpid) when is_pid(Mpid) ->
%%====================================================================
%% gen_media callbacks
%%====================================================================
+
%% @private
init([Cnode, DialString, UUID]) ->
process_flag(trap_exit, true),
@@ -179,10 +189,12 @@ init([Cnode, DialString, UUID]) ->
Call = #call{id = UUID, source = self(), client = Client, priority = Priority, callerid={CidName, CidNum}, dnis=DNIS, media_path = inband},
{ok, {#state{statename = inivr, cnode=Cnode, manager_pid = Manager, dialstring = DialString, dial_vars = ["sip_h_X-FromData='"++SIPFrom++"'"], uuid = UUID}, Call, {inivr, [DNIS]}}}.
+%% @private
-spec(urlpop_getvars/1 :: (State :: #state{}) -> [{binary(), binary()}]).
urlpop_getvars(#state{ivroption = Ivropt} = _State) ->
[{"itxt", Ivropt}].
+%% @private
-spec(handle_announce/3 :: (Announcement :: string(), Callrec :: #call{}, State :: #state{}) -> {'ok', #state{}}).
handle_announce(Announcement, Callrec, State) ->
freeswitch:sendmsg(State#state.cnode, Callrec#call.id,
@@ -195,6 +207,19 @@ handle_announce(Announcement, Callrec, State) ->
%% perpare_endpoint
%%--------------------------------------------------------------------
+-type(agent_registration_type() :: 'sip' | 'sip_registration' | 'h323' |
+ 'iax2' | 'pstn').
+-type(agent_registration_data_opt() :: {'date', string()}).
+-type(agent_registration_type_opt() :: {'type', agent_registration_type()}).
+-type(persistant_ring_opt() :: 'persistant').
+-type(endpoint_opt() :: persistant_ring_opt() |
+ agent_registration_type_opt() | agent_registration_data_opt()).
+-type(endpoint_opts() :: [endpoint_opt()]).
+-type(freeswitch_ring_endpoint() :: pid() | {'freeswitch_ring','start',[_]}).
+%% @doc Handle an agent being setup with a freeswitch_media endpoint.
+%% Options uses defaults of [{type,sip_registration},{data,agent_login()}].
+-spec(prepare_endpoint/2 :: (Agent :: #agent{}, Options :: endpoint_opts())
+ -> {'ok', freeswitch_ring_endpoint()}).
prepare_endpoint(Agent, Options) ->
{Node, Dialstring, Dest} = freeswitch_media_manager:get_ring_data(Agent, Options),
case proplists:get_value(persistant, Options) of
@@ -214,6 +239,7 @@ prepare_endpoint(Agent, Options) ->
%% handle_answer
%%--------------------------------------------------------------------
+%% @hidden
handle_answer(Apid, StateName, Callrec, GenMediaState, State) when
StateName =:= inqueue_ringing; StateName =:= oncall_ringing ->
{RingUUID, RingPid} = case GenMediaState of
@@ -251,7 +277,9 @@ handle_answer(Apid, StateName, Callrec, GenMediaState, State) when
{error, Error, State}
end.
-%% TODO added for testing only (implemented with focus on real Calls - no other media)
+
+% TODO added for testing only (implemented with focus on real Calls - no other media)
+%% @hidden
-spec(handle_end_call/4 :: (GMState :: atom(), Callrec :: #call{},
GMStateData :: any(), State :: #state{}) -> {'ok', #state{}}).
handle_end_call(_Gmstate, Callrec, _Gmstatedata, State) ->
@@ -260,6 +288,7 @@ handle_end_call(_Gmstate, Callrec, _Gmstatedata, State) ->
{"hangup-cause", "SUBSCRIBER_ABSENT"}]),
{deferred, State}.
+%% @hidden
handle_ring(Apid, RingData, Callrec, State) when is_pid(Apid) ->
?INFO("ring to agent ~p for call ~s", [Apid, Callrec#call.id]),
% TODO - we could avoid this if we had the agent's login,
@@ -281,6 +310,7 @@ handle_ring({Apid, #agent{ring_channel = {RPid, transient, _}} = AgentRec}, _Rin
{ok, [{"itxt", State#state.ivroption}], State#state{statename = NewStatename, agent_pid = Apid, ringchannel = RPid}}.
% TODO This needs to be updated when conferencing is fixed.
+%% @hidden
handle_ring_stop(_StateName, Callrec, _GenMedia, #state{xferchannel = RingChannel} = State) when is_pid(RingChannel) ->
?DEBUG("hanging up transfer channel for ~p", [Callrec#call.id]),
freeswitch_ring:hangup(RingChannel),
@@ -303,6 +333,7 @@ handle_ring_stop(_StateName, Callrec, _GenMedia, State) ->
end,
{ok, State#state{statename = NewStatename, ringchannel=undefined}}.
+%% @hidden
-spec(handle_voicemail/3 :: (Agent :: pid() | 'undefined', Call :: #call{}, State :: #state{}) -> {'ok', #state{}}).
handle_voicemail(Agent, Callrec, State) when is_pid(Agent) ->
{ok, Midstate} = handle_ring_stop(undefined, Callrec, undefined, State),
@@ -312,6 +343,7 @@ handle_voicemail(undefined, Call, State) ->
freeswitch:bgapi(State#state.cnode, uuid_transfer, UUID ++ " 'playback:IVR/prrec.wav,gentones:%(500\\,0\\,500),sleep:600,record:/tmp/${uuid}.wav' inline"),
{ok, State#state{statename = inivr, voicemail = "/tmp/"++UUID++".wav"}}.
+%% @hidden
-spec(handle_spy/3 :: (Agent :: {pid(), #agent{}}, Call :: #call{}, State :: #state{}) -> {'error', 'bad_agent', #state{}} | {'ok', #state{}}).
handle_spy({Agent, AgentRec}, Call, #state{cnode = Fnode, ringchannel = Chan} = State) when is_pid(Chan) ->
agent:blab(Agent, "While spying, you have the following options:\n"++
@@ -325,6 +357,7 @@ handle_spy({Agent, AgentRec}, Call, #state{cnode = Fnode, ringchannel = Chan} =
handle_spy(_Agent, _Call, State) ->
{invalid, State}.
+%% @hidden
handle_agent_transfer(AgentPid, Timeout, Call, State) ->
AgentRec = agent:dump_state(AgentPid), % TODO - avoid this
?INFO("transfer_agent to ~p for call ~p", [AgentRec#agent.login, Call#call.id]),
@@ -346,6 +379,7 @@ handle_agent_transfer(AgentPid, Timeout, Call, State) ->
{error, Error, State}
end.
+%% @hidden
handle_wrapup(_From, _StateName, #call{media_path = inband} = Call, _GenMediaState, State) ->
?DEBUG("Handling wrapup request", []),
% TODO This could prolly stand to be a bit more elegant.
@@ -356,7 +390,8 @@ handle_wrapup(_From, _StateName, _Call, _GenMediaState, State) ->
% no direct hangup by the agent
?DEBUG("Not doing wrapup request", []),
{ok, State}.
-
+
+%% @hidden
handle_queue_transfer(_Queue, _StateName, Call, _GenMediaState, #state{cnode = Fnode} = State) ->
case State#state.record_path of
undefined ->
diff --git a/include_apps/oacd_freeswitch/src/freeswitch_media_manager.erl b/include_apps/oacd_freeswitch/src/freeswitch_media_manager.erl
index 2b2c3cd4..9de47b9e 100644
--- a/include_apps/oacd_freeswitch/src/freeswitch_media_manager.erl
+++ b/include_apps/oacd_freeswitch/src/freeswitch_media_manager.erl
@@ -27,13 +27,14 @@
%% Micah Warren
%%
-%% @doc The controlling module for connection CPX to a freeswitch
+%% @doc The controlling module for connection OpenACD to a freeswitch
%% installation. There are 2 primary requirements for this work:
-%% the freeswitch installaction must have mod_erlang installed and active, and the freeswitch dialplan must add the following
-%% variables to the call data:
+%% the freeswitch installation must have mod_erlang installed and active,
+%% and the freeswitch dialplan must add the following variables added
+%% to the call data:
%%
-%% - queue
- The name of the queue as entered into the queue_manager
-%% - brand
- As the combined brand id
+%% - queue
- The name of the queue as configured in OpenACD
+%% - brand
- The Id of the client to associate the call with
%%
%% Primary job of this module is to listen to freeswitch for events, and
%% shove those events to the appriate child process.
@@ -371,9 +372,9 @@ init([Nodename, Options]) ->
Lpid = start_listener(Nodename),
freeswitch:event(Nodename, ['CHANNEL_DESTROY']),
StrippedOpts = [ X || {Key, _} = X <- Options, Key /= domain],
- {ok, Pid} = freeswitch:start_fetch_handler(Nodename, directory, ?MODULE, fetch_domain_user, StrippedOpts),
- link(Pid),
- {Lpid, Pid, StrippedOpts};
+ %{ok, Pid} = freeswitch:start_fetch_handler(Nodename, directory, ?MODULE, fetch_domain_user, StrippedOpts),
+ %link(Pid),
+ {Lpid, undefined, StrippedOpts};
_ ->
StrippedOpts = [ X || {Key, _} = X <- Options, Key /= domain],
{undefined, undefined, StrippedOpts}
@@ -866,6 +867,7 @@ fetch_domain_user(Node, State) ->
Domain = proplists:get_value("domain", Data),
Realm = proplists:get_value("sip_auth_realm", Data),
% TODO Can this be done w/o dealing w/ a plain text pw?
+ ?DEBUG("Sip auth\n\tUser: ~p\n\tdomain: ~p\n\tRelam: ~p",[User,Domain,Realm]),
freeswitch:fetch_reply(Node, ID, ?EMPTYRESPONSE)
% case agent_manager:query_agent(User) of
% {true, Pid} ->
diff --git a/include_apps/oacd_freeswitch/src/oacd_freeswitch_sup.erl b/include_apps/oacd_freeswitch/src/oacd_freeswitch_sup.erl
index f46d0d2c..528c5016 100644
--- a/include_apps/oacd_freeswitch/src/oacd_freeswitch_sup.erl
+++ b/include_apps/oacd_freeswitch/src/oacd_freeswitch_sup.erl
@@ -10,4 +10,13 @@ start_link(FsNode, Args) ->
init({FsNode, Args}) ->
MFA = {freeswitch_media_manager, start_link, [FsNode, Args]},
Kid = {freeswitch_media_manager, MFA, permanent, 1000, worker, [freeswitch_media_manager]},
- {ok, {{one_for_one, 5, 10}, [Kid]}}.
+
+ SipAuth = case proplists:get_bool(sipauth,Args) of
+ sipauth -> sip_auth;
+ true -> sip_auth;
+ _ -> no_sip_auth
+ end,
+ MFA2 = {freeswitch_fetch_handler, start_link, [FsNode,Args,SipAuth]},
+ Kid2 = {freeswitch_fetch_handler, MFA2, permanent, 1000, worker, [freeswitch_fetch_handler]},
+
+ {ok, {{one_for_one, 5, 10}, [Kid,Kid2]}}.
diff --git a/priv/www/admin/openacd/queues.js b/priv/www/admin/openacd/queues.js
index db40da26..fe607b46 100644
--- a/priv/www/admin/openacd/queues.js
+++ b/priv/www/admin/openacd/queues.js
@@ -271,11 +271,12 @@ queues.newQueue = function(form, reciper, node){
}
});
};
- queues.store.fetchItemByIdentity({
- identity:vals.group,
- onItem:function(i){
- vals.group = queues.store.getValue(i, 'name');
- doxhr();
- }
- });
+ var group = queues.store.query({'name':vals.group});
+ if(group.length){
+ group = group[0];
+ } else {
+ group = 'Default';
+ }
+ vals.group = group;
+ doxhr();
};
diff --git a/src/agent_auth.erl b/src/agent_auth.erl
index e1aab6a6..386cbd1b 100644
--- a/src/agent_auth.erl
+++ b/src/agent_auth.erl
@@ -87,6 +87,23 @@
%%
%% Aysnchronously triggers all hooks when an agent is created.
%% Args :: [Record :: #agent_auth{}]
+%%
+%% === auth_agent ===
+%%
+%% Synchronously triggers hooks until one returns a response. If no hooks
+%% return a response, a denial is returned.
+%%
+%% Args :: [Username :: string(), Password :: string()]
+%% Returns :: 'deny' | {'allow', string(), skill_list(), security_level(),
+%% profile_name()}).
+%%
+%% === auth_agent_success ===
+%%
+%% Asynchronously triggers all hooks when an agent is successfully
+%% authenticated.
+%%
+%% Args :: [Username :: string(), Password :: string(),
+%% Return :: auth_agent_return()]
-module(agent_auth).
@@ -428,7 +445,10 @@ get_extended_prop({_, _} = U, Prop) ->
-spec(auth/2 :: (Username :: string(), Password :: string()) -> 'deny' | {'allow', string(), skill_list(), security_level(), profile_name()}).
auth(Username, Password) ->
case cpx_hooks:trigger_hooks(auth_agent, [Username, Password], first) of
- {ok, Res} -> Res;
+ {ok, deny} -> deny;
+ {ok, Res} ->
+ cpx_hooks:async_trigger_hooks(auth_agent_success, [Username, Password, Res]),
+ Res;
_ -> deny
end.
diff --git a/src/cpx.erl b/src/cpx.erl
index e0d6ace8..9bbc1b02 100644
--- a/src/cpx.erl
+++ b/src/cpx.erl
@@ -80,6 +80,7 @@
unload_plugin/1,
load_plugin/1,
plugins_running/0,
+ set_plugin_env/2,
call_state/1,
get_queue/1,
get_agent/1,
@@ -331,6 +332,17 @@ load_plugin(Plugin) ->
end
end.
+%% @doc Sets the application variables for a plugin.
+-spec set_plugin_env(PluginName :: atom(), Env :: [{atom(),any()}]) -> 'ok'.
+set_plugin_env(_PluginName, []) ->
+ ok;
+set_plugin_env(PluginName, [{Key,Val}|Tail]) ->
+ application:set_env(PluginName, Key, Val),
+ set_plugin_env(PluginName,Tail);
+set_plugin_env(PluginName, [Key | Tail]) when is_atom(Key) ->
+ application:set_env(PluginName, Key, true),
+ set_plugin_env(PluginName,Tail).
+
-spec(get_queue/1 :: (Queue :: string()) -> pid() | 'none').
get_queue(Queue) ->
queue_manager:get_queue(Queue).
diff --git a/src/cpx_web_management.erl b/src/cpx_web_management.erl
index a6faab27..96483e07 100644
--- a/src/cpx_web_management.erl
+++ b/src/cpx_web_management.erl
@@ -1018,8 +1018,13 @@ api({queues, "queue", Queue, "update"}, ?COOKIE, Post) ->
queue_manager:load_queue(Queue),
{200, [], mochijson2:encode({struct, [{success, true}]})};
api({queues, "queue", Queue, "delete"}, ?COOKIE, _Post) ->
- call_queue_config:destroy_queue(Queue),
- {200, [], mochijson2:encode({struct, [{success, true}]})};
+ case call_queue_config:get_queue(Queue) of
+ noexists ->
+ {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"No such queue">>}]})};
+ Queuerec ->
+ call_queue_config:destroy_queue(Queuerec),
+ {200, [], mochijson2:encode({struct, [{success, true}]})}
+ end;
api({queues, "queue", "new"}, ?COOKIE = Cookie, Post) ->
Name = proplists:get_value("name", Post),
Qrec = #call_queue{
@@ -2066,7 +2071,8 @@ api({modules, Node, "freeswitch_media_manager", "update"}, ?COOKIE, Post) ->
Atomnode = list_to_existing_atom(Node),
case proplists:get_value("enabled", Post) of
undefined ->
- rpc:call(Atomnode, cpx_supervisor, destroy, [freeswitch_media_manager], 2000),
+ rpc:call(Atomnode, cpx, unload_plugin, [oacd_freeswitch]),
+ %rpc:call(Atomnode, cpx_supervisor, destroy, [freeswitch_media_manager], 2000),
{200, [], mochijson2:encode({struct, [{success, true}]})};
_Else ->
PostToProp = [
@@ -2086,14 +2092,16 @@ api({modules, Node, "freeswitch_media_manager", "update"}, ?COOKIE, Post) ->
end,
MidOptions = lists:foldl(Builder, [], PostToProp),
Options = [X || {_K, Val} = X <- MidOptions, Val =/= ""],
- Args = [list_to_atom(proplists:get_value("cnode", Post)), Options],
- Conf = #cpx_conf{
- id = freeswitch_media_manager,
- module_name = freeswitch_media_manager,
- start_function = start_link,
- supervisor = mediamanager_sup,
- start_args = Args},
- rpc:call(Atomnode, cpx_supervisor, update_conf, [freeswitch_media_manager, Conf], 2000),
+ Args = [{freeswitch_node, list_to_atom(proplists:get_value("cnode", Post))} | Options],
+ Args0 = case proplists:get_value(sipauth,Args) of
+ "sipauth" -> [sipauth | proplists:delete(sipauth,Args)];
+ _ -> proplists:delete(sipauth,Args)
+ end,
+ %Conf = #cpx_conf{ id = freeswitch_media_manager, module_name = freeswitch_media_manager, start_function = start_link, supervisor = mediamanager_sup, start_args = Args},
+ %rpc:call(Atomnode, cpx_supervisor, update_conf, [freeswitch_media_manager, Conf], 2000),
+ rpc:call(Atomnode, cpx, set_plugin_env, [oacd_freeswitch, Args0]),
+ rpc:call(Atomnode, cpx, reload_plugin, [oacd_freeswitch]),
+ rpc:call(Atomnode, application, start, [oacd_freeswitch]),
{200, [], mochijson2:encode({struct, [{success, true}]})}
end;
api({modules, Node, "freeswitch_media_manager", "get"}, ?COOKIE, _Post) ->