Claves por usuario

Versión para impresiónSend by email

Le he sacado bastante provecho a esta web y me decidí en colaborar un poco (gran parte de lo que sé de Asterisk lo he obtenido de aquí así que no va de mucho repetir lo que ya esta escrito).

Conozco poquísimo de PHP y AGI, pero logré desarrollar (compilar distintas ideas en realidad) una mini app, aquí va mi primer aporte.

Quizás ya muchos ya tengan esto resuelto, pero no encontré nada parecido para quien no sepa de PHP.

Lo que hace es básicamente utilizar la contraseña de voicemail para validar al usuario y luego según el destino deseado, compara ciertos parámetros en MySQL y asigna o no los permisos necesarios:

Se divide básicamente en 3 partes:

   1.      Creación de un macro o contexto especifico de salida (en este caso así lo hice) en nuestro archivo de configuración extensions.conf y añadir las líneas necesarias para mandarlo llamar desde un Goto en otro contexto X.

   2.      Implementación de un script hecho en PHP que va a procesar la información de quién está llamando, si tiene permisos y al final realizar la llamada.

   3.      Un tabla SQL donde se guardan y asignan los permisos que tiene cada usuario.

Creación del contexto para marcar:

[salientes]

exten => _XX.,1,VMAuthenticate(${CALLERID(num)},s)

exten => _XX.,n,NoOp(Llamada saliente destino ${EXTEN})

exten => _XX.,n,NoOp(Verifico permisos de ${CALLERID(all)})

exten => _XX.,n,AGI(claves_vm.php,${CALLERID(num)},${EXTEN})

exten => _XX.,n,Gotoif($["${continua}" = "NO"]?bloquea:)

exten => _XX.,n,NoOp(El usuario tiene permisos , ${continua} , llamar)

exten => _XX.,n,Goto(${contexto},${destino},1)

exten => _XX.,n,Hangup

exten => _XX.,n(bloquea),NoOp(--- Llamada saliente no permitida al usuario ${CALLERID(all)} , restringida por permisos ---)

exten => _XX.,n(bloquea),Playback(vm-incorrect)

exten => _XX.,n(bloquea),Hangup

Este código lo que hará será crear un contexto llamado salientes, el cual pedirá al usuario que introduzca su clave de voicemail. Si la contraseña es correcta se sigue ejecutando el contexto, de lo contrario la aplicación vuelve a pedir la clave de acceso.

Ya estando autentificado el usuario hacemos uso del script PHP llamado claves_vm.agi pasando como parámetros la extensión del usuario ya validado y el número que quiere marcar, que revisaremos más adelante.

Si el AGI valida que el usuario tiene permisos de marcar a dicho número, salta a un Goto donde se encuentra el número que se desea marcar.

Se presume que el dialplan está separado en contextos la manera de llamar a distintos disposiivos:

[local]

exten => _NXXXXXX,1,Dial(${PSTN2}/${EXTEN},30,wWkKT)

exten => _NXXXXXX,n,Hangup

[celuar]

exten => _[6-9]XXXXXXX,1,Dial(${PSTN2}/${EXTEN},30,wWkKT)

exten => _[6-9]XXXXXXX,n,Hangup

etc..

Para poder mandar llamar el contexto desde nuestro contexto sólo basta con añadir las siguientes líneas dependiendo de los esquemas a marcar:

exten => _XX.,1,Goto(salientes,${EXTEN},1)

Script PHP – AGI

La función de nuestro script es revisar los permisos de marcación que tiene determinado usuario validándolo contra la tabla permisos_usuario, y así regresar una respuesta a nuestro Asterisk.

El archivo se llama claves_vm.php y deberá ser colocado en la ruta por omisión de los archivos AGI (/var/lib/asterisk/agi-bin/).

#!/usr/bin/php -q

<?php

require('phpagi.php');          // no se si es realmente necesario, como dije en un principio, se muy poco de PHP y AGI

error_reporting(E_ALL);

ob_implicit_flush(true);

set_time_limit(6);

$stdout = fopen('php://stdout', 'w');

$in = fopen("php://stdin","r");

$stdlog = fopen("/var/log/asterisk/claves_agi.log", "w");

// toggle debugging output (more verbose)

$debug = true;

// Do function definitions before we start the main loop

function read() {

global $in, $debug, $stdlog;

$input = str_replace("\n", "", fgets($in, 4096));

if ($debug) fputs($stdlog, "read: $input\n");

return $input;

}

function errlog($line) {

global $err;

echo "VERBOSE \"$line\"\n";

}

function write($line) {

global $debug, $stdlog;

if ($debug) fputs($stdlog, "write: $line\n");

echo $line."\n";

}

function revisaNumero($numero){

if(preg_match("/^(1[0-3]{2})$/",$numero))

return "emergencias";

if(preg_match("/^([23468][0-9]{3})$/",$numero))

return "anexos";

if(preg_match("/^[2-9][0-9]{6}$/",$numero))

return "local";

if(preg_match("/^(09[6-9][0-9]{7})$/",$numero))

return "celular";

//if(preg_match("/^123[0-9]{8}$/",$numero) || preg_match("/^123[0-9]{2}[2-9]{1}[0-9]{6}$/",$numero))

if(preg_match("/^(123[3-7][1-9][2-9][0-9]{5,6})$/",$numero))

return "LDN";

if(preg_match("/^(600[0-9]{6,9})$/",$numero))

return "600";

if(preg_match("/^(700[0-9]{6,9})$/",$numero))

return "700";

if(preg_match("/^(800[0-9]{6,9})$/",$numero))

return "800";

if(preg_match("/^1230[0-9]{9,}/",$numero))

return "LDI";

}

 

// parse agi headers into array

while (!feof($in)) {

$temp = fgets($in);

$temp = str_replace("\n","",$temp);

$s = explode(":",$temp);

$agivar[$s[0]] = trim($s[1]);

if (($temp == "") || ($temp == "\n")) {

break;

}

}

 

// main program

echo "VERBOSE \"Revisión del contexto del usuario\" 2\n";

$destino = $_SERVER["argv"][2];

$usuario = $_SERVER["argv"][1];

$contexto = revisaNumero($destino);

echo "VERBOSE \"Usuario: $usuario\" 2\n";

echo "SET VARIABLE \usuario $usuario\"\n";

echo "VERBOSE \"Tel Destino: $destino\" 2\n";

echo "SET VARIABLE \destino $destino\"\n";

echo "VERBOSE \"Contexto al que quiere acceder: $contexto\" 2\n";

echo "SET VARIABLE \contexto $contexto\"\n";

 

$db = 'asteriskcdrdb';

$dbuser = 'asterisk_cdr';

$dbpass = 'password';

$dbhost = 'localhost';

 

$conexion=mysql_connect($dbhost,$dbuser,$dbpass) or die ("No es posible conectarse con el servidor \n");

mysql_select_db($db,$conexion) or die ("No es posible selecionar la base de datos \n");

$consulta="select * from permisos_usuario where anexo='$usuario'";

$resultado=mysql_query($consulta,$conexion) or die ('ERROR SQL');

$respuesta=mysql_fetch_array($resultado);

 

if($respuesta[$contexto] == SI) {

echo "SET VARIABLE \continua SI\"\n";

exit();

}

else {

echo "SET VARIABLE \continua NO\"\n";

exit();

}

?>

 

 

Lo más probable es que hayan funciones que ni se ocupen, como les mencioné, es una compilación de ideas y no se mucho de PHP.

 

El script básicamente recibe dos parámetros, la extensión del usuario y el número al que desea marcar. Una vez guardados los parámetros en variables en nuestro PHP revisa los permisos en la tabla permisos_usuario. Localiza al usuario, valida la lista de permisos que tiene. Mediante la función revisaNumero() y el uso de expresiones regulares definimos el esquema de marcación o permiso al que el usuario quiere acceder. En este caso definimos “local”, “LDN = nacionales”, “LDI = internacionales”, “celulares”,  “600”, “700”, “800”, “anexos” y  “emergencias”, que es un esquema tipico de Chile, pero se pueden adecuar a esquemas diferentes. Ya con el dato de el esquema al que quiere acceder y el permiso con el que cuenta el usuario simplemente asigna una variable "SI o NO", la cuál es usada al final del script para determinar si el usuario puede o no puede llamar.

 

Terminando la ejecución del script se regresa el control a nuestro Asterisk que continúa con la ejecución del macro mencionado en el punto anterior.

 

 

 

Tabla SQL

 

 

 

CREATE TABLE `permisos_usuario` (

  `id` int(11) NOT NULL auto_increment,

  `anexo` varchar(4) NOT NULL default '0000',

  `anexos` enum('SI','NO') NOT NULL default 'SI',

  `emergencias` enum('SI','NO') NOT NULL default 'SI',

  `local` enum('SI','NO') NOT NULL default 'SI',

  `celular` enum('SI','NO') NOT NULL default 'SI',

  `LDN` enum('SI','NO') NOT NULL default 'SI',

  `LDI` enum('SI','NO') NOT NULL default 'SI',

  `600` enum('SI','NO') NOT NULL default 'SI',

  `700` enum('SI','NO') NOT NULL default 'SI',

  `800` enum('SI','NO') NOT NULL default 'SI',

  PRIMARY KEY  (`id`),

  UNIQUE KEY `anexo` (`anexo`)

) ENGINE=MyISAM AUTO_INCREMENT=1163 DEFAULT CHARSET=latin1 AUTO_INCREMENT=1163 ;

 

 

La gracias de esto, es lo sigueinte:

 

Imagina que en tu empresa controlan al maximo posible el consumo telefónico por lo cual dependiento el grado, jineta o como le llamen en sus paises, los usuarios tienen deistintos privilegios para llamar, ok conocido, pero que ocurre si el gerente pasa por el taller del gasfiter (sin desmerecer) y necesita urgente hacer una llamada al extranjero y su oficina esta en remodelación, o simplemente, lejos... aquí la solución:

 

exten => _11XX.,1,Goto(salientes-2,${EXTEN:2},1)

 

[salientes-2]

 

exten => _XX.,1,Set(TIMEOUT(digit)=2)

exten => _XX.,n,Read(ext_num,vm-extension)

exten => _XX.,n,VMAuthenticate(${ext_num}|s)

exten => _XX.,2,NoOp(Llamada saliente destino ${EXTEN})

exten => _XX.,n,NoOp(Verifico permisos de ${ext_num})

exten => _XX.,n,AGI(claves_vm.agi,${ext_num},${EXTEN})

exten => _XX.,n,NoOp(contexto ${contexto})

exten => _XX.,n,NoOp(usuario ${usuario})

exten => _XX.,n,NoOp(destino ${destino})

exten => _XX.,n,Gotoif($["${continua}" = "NO"]?bloquea:)

exten => _XX.,n,NoOp(El usuario tiene permisos , ${continua} , llamar)

exten => _XX.,n,Playback(vm-dialout)

exten => _XX.,n,Set(CALLERID(all)=clave <${ext_num}>)

exten => _XX.,n,NoOp(${CALLERID(all)})

exten => _XX.,n,Goto(${contexto},${destino},1)

exten => _XX.,n,Hangup

exten => _XX.,n(bloquea),NoOp(--- Llamada saliente no permitida al usuario ${CALLERID(all)} , restringida por permisos ---)

exten => _XX.,n(bloquea),Playback(vm-incorrect)

exten => _XX.,n(bloquea),Hangup

 

 

Anteponiedo 11 al numero que discará, se le solicitara numero de anexo + contraseña, luego que esto se valide, verá los permisos y luego cuando estos últimos se encuentren OK, antes de llamar modificará el CID del gasfiter por el del gerente....... simpatico no....

 

Esto es una modificación a http://www.nucleum.com.mx/www/index.php?Itemid=55&id=41&option=com_conte...

 

Tomando tambien datos de http://www.comunidadasterisk.cl/index.php?option=com_content&task=view&i...

 

Más un AGI de Blacklist que no recuerdo de donde lo tome.

 

Espero y les sirva

 

http://www.megaupload.com/?d=0DVXQNVC

 

Comentarios

Re: Claves usuarios

Hola Mauricio,

se te agradece mucho el aporte.

Saludos

ayuda

mauricio las ip dynamic del host no se me registran en el asterisk que tengo hacer?

o que tengo que verificar?

Distribuir contenido Distribuir contenido