You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							502 lines
						
					
					
						
							15 KiB
						
					
					
				
			
		
		
	
	
							502 lines
						
					
					
						
							15 KiB
						
					
					
				| package NGCP::Panel::Controller::Pbx;
 | |
| use NGCP::Panel::Utils::Generic qw(:all);
 | |
| use Sipwise::Base;
 | |
| use parent 'Catalyst::Controller';
 | |
| 
 | |
| use NGCP::Panel::Utils::Message;
 | |
| use NGCP::Panel::Utils::DateTime;
 | |
| use NGCP::Panel::Utils::Contract;
 | |
| use NGCP::Panel::Utils::Phonebook;
 | |
| 
 | |
| sub auto :Private {
 | |
|     my ($self, $c) = @_;
 | |
|     $c->log->debug(__PACKAGE__ . '::auto');
 | |
|     NGCP::Panel::Utils::Navigation::check_redirect_chain(c => $c);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| sub base :Chained('/') :PathPart('') :CaptureArgs(0) :Does(License) :RequiresLicense('device_provisioning') :RequiresLicense('pbx') :RequiresLicense('phonebook') :LicenseDetachTo('/denied_page') {
 | |
|     my ($self, $c) = @_;
 | |
| 
 | |
|     $c->stash->{schema} = $c->config->{deviceprovisioning}->{secure} ? 'https' : 'http';
 | |
|     $c->stash->{host} = $c->config->{deviceprovisioning}->{host} // $c->req->uri->host;
 | |
|     $c->stash->{port} = $c->config->{deviceprovisioning}->{port} // 1444;
 | |
|     $c->stash->{cisco_port} = $c->config->{deviceprovisioning}->{cisco_port} // 1447;
 | |
| 
 | |
|     $c->log->debug("SSL_CLIENT_M_DN: " . ($c->request->env->{SSL_CLIENT_M_DN} // ""));
 | |
|     unless(
 | |
|         ($c->user_exists && ($c->user->roles eq "admin" || $c->user->roles eq "reseller")) ||
 | |
|         defined $c->request->env->{SSL_CLIENT_M_DN}
 | |
|     ) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("403 - unauthenticated pbx access");
 | |
|         } else {
 | |
|             $c->response->body("403 - forbidden");
 | |
|         }
 | |
|         $c->response->status(403);
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| sub spa_directory_getsearch :Chained('base') :PathPart('pbx/directory/spasearch') :Args(1) {
 | |
|     my ($self, $c, $id) = @_;
 | |
| 
 | |
|     my $schema = $c->stash->{schema};
 | |
|     my $host = $c->stash->{host};
 | |
|     my $port = $c->stash->{cisco_port};
 | |
| 
 | |
|     my $baseuri = "$schema://$host:$port/pbx/directory/spa/$id";
 | |
|     my $data = '';
 | |
| 
 | |
|     $data = <<EOF;
 | |
|     <CiscoIPPhoneInput>
 | |
|         <Title>Search User</Title>
 | |
|         <Prompt>Enter (part of) Name</Prompt>
 | |
|         <URL>$baseuri</URL>
 | |
|         <InputItem>
 | |
|             <QueryStringParam>q</QueryStringParam>
 | |
|             <InputFlags>A</InputFlags>
 | |
|         </InputItem>
 | |
|     </CiscoIPPhoneInput>
 | |
| EOF
 | |
| 
 | |
|     $c->log->debug("providing config to $id");
 | |
|     $c->log->debug($data);
 | |
| 
 | |
|     $c->response->content_type('text/xml');
 | |
|     $c->response->body($data);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| sub spa_directory_list :Chained('base') :PathPart('pbx/directory/spa') :Args(1) {
 | |
|     my ($self, $c, $id) = @_;
 | |
| 
 | |
|     unless($id) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id not given");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     $id =~ s/^([^\=]+)\=0$/$1/;
 | |
|     $id = lc $id;
 | |
| 
 | |
|     my $dev = $c->model('DB')->resultset('autoprov_field_devices')->find({
 | |
|         identifier => $id
 | |
|     });
 | |
|     unless($dev) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id '" . $id . "' not found");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     my $schema = $c->stash->{schema};
 | |
|     my $host = $c->stash->{host};
 | |
|     my $port = $c->stash->{cisco_port};
 | |
| 
 | |
|     my $baseuri = "$schema://$host:$port/pbx/directory/spa/$id";
 | |
|     my $data = '';
 | |
| 
 | |
|     my $delim = '?';
 | |
|     my $q;
 | |
|     my $dirsuffix = '';
 | |
|     if(exists $c->req->params->{q} && length($c->req->params->{q})) {
 | |
|         $q = $c->req->params->{q};
 | |
|         $baseuri .= "?q=$q";
 | |
|         $delim = '&';
 | |
|         $dirsuffix = ' (Search Results)';
 | |
|     }
 | |
| 
 | |
| 
 | |
|     my $customer = $dev->contract;
 | |
| 
 | |
|     my $page = $c->req->params->{page} // 1;
 | |
|     my $rows = 10;
 | |
| 
 | |
|     my $rs = $self->_get_dirsearch_rs($customer, $q);
 | |
|     my $total = $rs->count;
 | |
|     my ($nextpage, $prevpage);
 | |
| 
 | |
|     if(($total / $rows) > $page ) {
 | |
|         $nextpage = $page + 1;
 | |
|     }
 | |
|     if($page > 1) {
 | |
|         $prevpage = $page - 1;
 | |
|     }
 | |
| 
 | |
|     my @entries = ();
 | |
|     my %entries = ();
 | |
|     foreach my $sub($rs->search(undef,{page => $page, rows => $rows})->all) {
 | |
|         my $prov_sub = $sub->provisioning_voip_subscriber;
 | |
|         next unless($prov_sub && $prov_sub->pbx_extension);
 | |
|         my $display_name = $sub->get_column('display_name');
 | |
|         push @entries, { name => $display_name, ext => $prov_sub->pbx_extension };
 | |
|         $entries{$prov_sub->pbx_extension} = 1;
 | |
|     }
 | |
| 
 | |
|     $self->add_phonebook_entries($c, $dev, \@entries, \%entries);
 | |
| 
 | |
|     my $nexturi =  $baseuri . $delim . 'page='.($nextpage//0);
 | |
|     my $prevuri = $baseuri . $delim . 'page='.($prevpage//0);
 | |
| 
 | |
|     my $searchuri = "$schema://$host:$port/pbx/directory/spasearch/$id";
 | |
| 
 | |
|     $data = "<CiscoIPPhoneDirectory><Title>PBX Address Book$dirsuffix</Title><Prompt>Select the User</Prompt>";
 | |
|     $data .= join '', map {"<DirectoryEntry><Name>$$_{name}</Name><Telephone>$$_{ext}</Telephone></DirectoryEntry>"} @entries;
 | |
|     $data .= "<SoftKeyItem><Name>Dial</Name><URL>SoftKey:Dial</URL><Position>1</Position></SoftKeyItem>";
 | |
|     if($prevpage) {
 | |
|         $data .= "<SoftKeyItem><Name>Prev</Name><URL>$prevuri</URL><Position>2</Position></SoftKeyItem>";
 | |
|     } else {
 | |
|         $data .= "<SoftKeyItem><Name>Search</Name><URL>$searchuri</URL><Position>2</Position></SoftKeyItem>";
 | |
|     }
 | |
|     $data .= "<SoftKeyItem><Name>Next</Name><URL>$nexturi</URL><Position>3</Position></SoftKeyItem>"
 | |
|         if($nextpage);
 | |
|     $data .= "<SoftKeyItem><Name>Cancel</Name><URL>Init:Services</URL><Position>4</Position></SoftKeyItem>";
 | |
|     $data .= '</CiscoIPPhoneDirectory>';
 | |
| 
 | |
|     $c->log->debug("providing config to $id");
 | |
|     $c->log->debug($data);
 | |
| 
 | |
|     $c->response->content_type('text/xml');
 | |
|     $c->response->body($data);
 | |
| }
 | |
| 
 | |
| sub panasonic_directory_list :Chained('base') :PathPart('pbx/directory/panasonic') :Args() {
 | |
|     my ($self, $c) = @_;
 | |
| 
 | |
|     my $id = $c->req->params->{userid};
 | |
|     my $q = $c->req->params->{name};
 | |
| 
 | |
|     unless($id) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id not given");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     $id =~ s/^([^\=]+)\=0$/$1/;
 | |
|     $id = lc $id;
 | |
| 
 | |
|     my $dev = $c->model('DB')->resultset('autoprov_field_devices')->find({
 | |
|         identifier => $id
 | |
|     });
 | |
|     unless($dev) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id '" . $id . "' not found");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     my $schema = $c->stash->{schema};
 | |
|     my $host = $c->stash->{host};
 | |
|     my $port = $c->stash->{port};
 | |
| 
 | |
|     my $customer = $dev->contract;
 | |
| 	my $rs = $self->_get_dirsearch_rs($customer, $q);
 | |
| 
 | |
|     my @entries = ();
 | |
|     my %entries = ();
 | |
|     foreach my $sub($rs->all) {
 | |
|         my $prov_sub = $sub->provisioning_voip_subscriber;
 | |
|         next unless($prov_sub && $prov_sub->pbx_extension);
 | |
|         my $display_name = $sub->get_column('display_name');
 | |
|         push @entries, { name => $display_name, ext => $prov_sub->pbx_extension };
 | |
|         $entries{$prov_sub->pbx_extension} = 1;
 | |
|     }
 | |
| 
 | |
|     $self->add_phonebook_entries($c, $dev, \@entries, \%entries);
 | |
| 
 | |
|     my $data = <<'EOS_XML';
 | |
| <?xml version="1.0" encoding="utf-8"?>
 | |
| <ppxml xmlns="http://panasonic/sip_phone"
 | |
|        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | |
|        xsi:schemaLocation="http://panasonic/sip_phone sip_phone.xsd">
 | |
|     <Screen version="2.0">
 | |
|         <PhoneBook version="2.0">
 | |
| EOS_XML
 | |
|         my $person_id = 0;
 | |
|         $data .= join '', map {
 | |
|             $person_id++;
 | |
|             <<EOS_XMLLOOP;
 | |
|             <Personnel id="$person_id">
 | |
|                  <Name>$$_{name}</Name>
 | |
|                  <PhoneNums>
 | |
|                     <PhoneNum type="ext">$$_{ext}</PhoneNum>
 | |
|                  </PhoneNums>
 | |
|              </Personnel>
 | |
| EOS_XMLLOOP
 | |
|         } @entries;
 | |
| 
 | |
|     $data .= <<EOS_XML;
 | |
|         </PhoneBook>
 | |
|     </Screen>
 | |
| </ppxml>
 | |
| EOS_XML
 | |
| 
 | |
| 
 | |
|     $c->log->debug("providing config to $id");
 | |
|     $c->log->debug($data);
 | |
| 
 | |
|     $c->response->content_type('text/xml');
 | |
|     $c->response->body($data);
 | |
| }
 | |
| 
 | |
| sub yealink_directory_list :Chained('base') :PathPart('pbx/directory/yealink') :Args() {
 | |
|     my ($self, $c) = @_;
 | |
| 
 | |
|     my $id = $c->req->params->{userid};
 | |
|     my $q = $c->req->params->{name};
 | |
| 
 | |
|     unless($id) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id not given");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     $id =~ s/^([^\=]+)\=0$/$1/;
 | |
|     $id = lc $id;
 | |
| 
 | |
|     my $dev = $c->model('DB')->resultset('autoprov_field_devices')->find({
 | |
|         identifier => $id
 | |
|     });
 | |
|     unless($dev) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id '" . $id . "' not found");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     my $schema = $c->stash->{schema};
 | |
|     my $host = $c->stash->{host};
 | |
|     my $port = $c->stash->{port};
 | |
| 
 | |
|     my $customer = $dev->contract;
 | |
|     my $rs = $self->_get_dirsearch_rs($customer, $q);
 | |
| 
 | |
|     my @entries = ();
 | |
|     my %entries = ();
 | |
|     foreach my $sub($rs->all) {
 | |
|         my $prov_sub = $sub->provisioning_voip_subscriber;
 | |
|         next unless($prov_sub && $prov_sub->pbx_extension);
 | |
|         my $display_name = $sub->get_column('display_name');
 | |
|         push @entries, { name => $display_name, ext => $prov_sub->pbx_extension };
 | |
|         $entries{$prov_sub->pbx_extension} = 1;
 | |
|     }
 | |
| 
 | |
|     $self->add_phonebook_entries($c, $dev, \@entries, \%entries);
 | |
| 
 | |
|     my $req_uri = $c->req->uri;
 | |
|     my $data = <<EOS_XML;
 | |
| <?xml version="1.0" encoding="utf-8"?>
 | |
| <SipwiseIPPhoneDirectory>
 | |
|   <SoftKeyItem>
 | |
|     <Name>0</Name>
 | |
|     <URL>$req_uri</URL>
 | |
|   </SoftKeyItem>
 | |
| EOS_XML
 | |
|     $data .= join '', map { <<EOS_XMLLOOP;
 | |
|         <DirectoryEntry>
 | |
|              <Name>$$_{name}</Name>
 | |
|              <Telephone>$$_{ext}</Telephone>
 | |
|          </DirectoryEntry>
 | |
| EOS_XMLLOOP
 | |
|     } @entries;
 | |
|     $data .= '</SipwiseIPPhoneDirectory>';
 | |
| 
 | |
| 
 | |
|     $c->log->debug("providing config to $id");
 | |
|     $c->log->debug($data);
 | |
| 
 | |
|     $c->response->content_type('text/xml');
 | |
|     $c->response->body($data);
 | |
| }
 | |
| 
 | |
| sub polycom_directory_list :Chained('base') :PathPart('pbx/directory/polycom') :Args(1) {
 | |
|     my ($self, $c, $id) = @_;
 | |
| 
 | |
|     $id =~ s/\-directory\.xml$//;
 | |
|     my $q;
 | |
| 
 | |
|     unless($id) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id not given");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     $id = lc $id;
 | |
|     my $dev = $c->model('DB')->resultset('autoprov_field_devices')->find({
 | |
|         identifier => $id
 | |
|     });
 | |
|     unless($dev) {
 | |
|         $c->response->content_type('text/plain');
 | |
|         if($c->config->{features}->{debug}) {
 | |
|             $c->response->body("404 - device id '" . $id . "' not found");
 | |
|         } else {
 | |
|             $c->response->body("404 - device not found");
 | |
|         }
 | |
|         $c->response->status(404);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     my $schema = $c->stash->{schema};
 | |
|     my $host = $c->stash->{host};
 | |
|     my $port = $c->stash->{port};
 | |
| 
 | |
|     my $customer = $dev->contract;
 | |
|     my $rs = $self->_get_dirsearch_rs($customer, $q);
 | |
| 
 | |
|     my @entries = ();
 | |
|     my %entries = ();
 | |
|     foreach my $sub($rs->all) {
 | |
|         my $prov_sub = $sub->provisioning_voip_subscriber;
 | |
|         next unless($prov_sub && $prov_sub->pbx_extension);
 | |
|         my $display_name = $sub->get_column('display_name');
 | |
|         push @entries, { name => $display_name, ext => $prov_sub->pbx_extension };
 | |
|         $entries{$prov_sub->pbx_extension} = 1;
 | |
|     }
 | |
| 
 | |
|     $self->add_phonebook_entries($c, $dev, \@entries, \%entries);
 | |
| 
 | |
|     foreach my $entry (@entries) {
 | |
|         my ($fname, @rest) = split / +/, $entry->{name};
 | |
|         my $lname = join ' ', @rest;
 | |
|         $entry->{fname} = $fname;
 | |
|         $entry->{lname} = $lname;
 | |
|     }
 | |
| 
 | |
|     my $data = <<EOS_XML;
 | |
| <?xml version="1.0" encoding="utf-8"?>
 | |
| <directory>
 | |
|   <item_list>
 | |
| EOS_XML
 | |
| 
 | |
| # ln  last name
 | |
| # fn  first name
 | |
| # ct  contact
 | |
| # sd  speed-dial index
 | |
| # rt  ring type
 | |
| # dc  divert contact for auto divert
 | |
| # ad  auto divert
 | |
| # ar  auto reject
 | |
| # bw  buddy watching
 | |
| # bb  buddy block
 | |
| 
 | |
|     $data .= join '', map { <<EOS_XMLLOOP;
 | |
|         <item>
 | |
|              <ln>$$_{lname}</ln>
 | |
|              <fn>$$_{fname}</fn>
 | |
|              <ct>$$_{ext}</ct>
 | |
|              <sd/>
 | |
|              <rt/>
 | |
|              <dc/>
 | |
|              <ad>0</ad>
 | |
|              <ar>0</ar>
 | |
|              <bw>0</bw>
 | |
|              <bb>0</bb>
 | |
|          </item>
 | |
| EOS_XMLLOOP
 | |
|     } @entries;
 | |
|     $data .= '</item_list></directory>';
 | |
| 
 | |
|     $c->log->debug("providing config to $id");
 | |
|     $c->log->debug($data);
 | |
| 
 | |
|     $c->response->content_type('text/xml');
 | |
|     $c->response->body($data);
 | |
| }
 | |
| 
 | |
| sub _get_dirsearch_rs :Private {
 | |
|     my ($self, $customer, $q) = @_;
 | |
| 
 | |
|     my $rs = $customer->voip_subscribers->search({
 | |
|         'status' => 'active',
 | |
|         'provisioning_voip_subscriber.pbx_extension' => { '!=' => undef },
 | |
|         'voip_usr_preferences.value' => { '!=' => undef },
 | |
|         'attribute.attribute' => 'display_name',
 | |
|         defined $q ? (
 | |
|           -or => [
 | |
|             'voip_usr_preferences.value' => { like => "%$q%" },
 | |
|             'provisioning_voip_subscriber.pbx_extension' => { like => "$q%" }
 | |
|           ]
 | |
|         ) : (),
 | |
|     },{
 | |
|         join => { provisioning_voip_subscriber => { voip_usr_preferences => 'attribute'  } },
 | |
|         '+select' => [qw/voip_usr_preferences.value/],
 | |
|         '+as' => [qw/display_name/],
 | |
|         order_by => { '-asc' => 'voip_usr_preferences.value' },
 | |
|     });
 | |
| 
 | |
|     return $rs;
 | |
| }
 | |
| 
 | |
| sub add_phonebook_entries {
 | |
|     my ($self, $c, $dev, $entries, $entries_existent) = @_;
 | |
|     my %phonebook = ();
 | |
|     foreach my $private_line ($dev->autoprov_field_device_lines->search_rs({ line_type => 'private' })->all) {
 | |
|         my $private_line_subscriber_id = $private_line->provisioning_voip_subscriber->voip_subscriber->id;
 | |
|         $phonebook{$private_line_subscriber_id} //= NGCP::Panel::Utils::Phonebook::get_subscriber_phonebook($c, $private_line_subscriber_id);
 | |
|         foreach my $entry (@{$phonebook{$private_line_subscriber_id}}) {
 | |
|             push @$entries, { name => $entry->{name}, ext => $entry->{number} }
 | |
|                 unless $entries_existent->{$entry->{number}};
 | |
|             $entries_existent->{$entry->{number}} = 1;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 1;
 | |
| 
 | |
| __END__
 | |
| 
 | |
| =head1 NAME
 | |
| 
 | |
| NGCP::Panel::Controller::Pbx
 | |
| 
 | |
| =head1 DESCRIPTION
 | |
| 
 | |
| A controller to manipulate the PBX data
 | |
| 
 | |
| =head1 AUTHOR
 | |
| 
 | |
| Sipwise Development Team
 | |
| 
 | |
| =head1 LICENSE
 | |
| 
 | |
| This library is free software. You can redistribute it and/or modify
 | |
| it under the same terms as Perl itself.
 | |
| 
 | |
| =cut
 | |
| 
 | |
| # vim: set tabstop=4 expandtab:
 |