commit
						e923b71022
					
				| @ -0,0 +1,130 @@ | ||||
| package NGCP::Panel::Controller::API::SubscriberPreferenceDefs; | ||||
| use Sipwise::Base; | ||||
| use namespace::sweep; | ||||
| use boolean qw(true); | ||||
| use Data::HAL qw(); | ||||
| use Data::HAL::Link qw(); | ||||
| use HTTP::Headers qw(); | ||||
| use HTTP::Status qw(:constants); | ||||
| use MooseX::ClassAttribute qw(class_has); | ||||
| use NGCP::Panel::Utils::DateTime; | ||||
| use Path::Tiny qw(path); | ||||
| use Safe::Isa qw($_isa); | ||||
| use JSON::Types qw(); | ||||
| BEGIN { extends 'Catalyst::Controller::ActionRole'; } | ||||
| require Catalyst::ActionRole::ACL; | ||||
| require Catalyst::ActionRole::CheckTrailingSlash; | ||||
| require Catalyst::ActionRole::HTTPMethods; | ||||
| require Catalyst::ActionRole::RequireSSL; | ||||
| 
 | ||||
| with 'NGCP::Panel::Role::API'; | ||||
| 
 | ||||
| class_has('resource_name', is => 'ro', default => 'subscriberpreferencedefs'); | ||||
| class_has('dispatch_path', is => 'ro', default => '/api/subscriberpreferencedefs/'); | ||||
| class_has('relation', is => 'ro', default => 'http://purl.org/sipwise/ngcp-api/#rel-subscriberpreferencedefs'); | ||||
| 
 | ||||
| __PACKAGE__->config( | ||||
|     action => { | ||||
|         map { $_ => { | ||||
|             ACLDetachTo => '/api/root/invalid_user', | ||||
|             AllowedRole => 'admin', | ||||
|             Args => 0, | ||||
|             Does => [qw(ACL CheckTrailingSlash RequireSSL)], | ||||
|             Method => $_, | ||||
|             Path => __PACKAGE__->dispatch_path, | ||||
|         } } @{ __PACKAGE__->allowed_methods } | ||||
|     }, | ||||
|     action_roles => [qw(HTTPMethods)], | ||||
| ); | ||||
| 
 | ||||
| sub auto :Private { | ||||
|     my ($self, $c) = @_; | ||||
| 
 | ||||
|     $self->set_body($c); | ||||
|     $self->log_request($c); | ||||
| } | ||||
| 
 | ||||
| sub GET :Allow { | ||||
|     my ($self, $c) = @_; | ||||
|     { | ||||
|         my @links; | ||||
|         push @links, | ||||
|             Data::HAL::Link->new( | ||||
|                 relation => 'curies', | ||||
|                 href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}', | ||||
|                 name => 'ngcp', | ||||
|                 templated => true, | ||||
|             ), | ||||
|             Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'), | ||||
|             Data::HAL::Link->new(relation => 'self', href => sprintf('%s', $self->dispatch_path)); | ||||
| 
 | ||||
|         my $hal = Data::HAL->new( | ||||
|             links => [@links], | ||||
|         ); | ||||
| 
 | ||||
|         my $preferences = $c->model('DB')->resultset('voip_preferences')->search({ | ||||
|             internal => 0, | ||||
|             usr_pref => 1, | ||||
|         }); | ||||
|         my $resource = {}; | ||||
|         for my $pref($preferences->all) { | ||||
|             my $fields = { $pref->get_inflated_columns }; | ||||
|             # remove internal fields | ||||
|             for my $del(qw/type attribute expose_to_customer internal peer_pref usr_pref dom_pref voip_preference_groups_id id modify_timestamp/) { | ||||
|                 delete $fields->{$del}; | ||||
|             } | ||||
|             $fields->{max_occur} = int($fields->{max_occur}); | ||||
|             $fields->{read_only} = JSON::Types::bool($fields->{read_only}); | ||||
|             if($fields->{data_type} eq "enum") { | ||||
|                 my @enums = $pref->voip_preferences_enums->search({ | ||||
|                     dom_pref => 1, | ||||
|                 })->all; | ||||
|                 $fields->{enum_values} = []; | ||||
|                 foreach my $enum(@enums) { | ||||
|                     my $efields = { $enum->get_inflated_columns }; | ||||
|                     for my $del(qw/id preference_id usr_pref dom_pref peer_pref/) { | ||||
|                         delete $efields->{$del}; | ||||
|                     } | ||||
|                     $efields->{default_val} = JSON::Types::bool($efields->{default_val}); | ||||
|                     push @{ $fields->{enum_values} }, $efields; | ||||
|                 } | ||||
|             } | ||||
|             $resource->{$pref->attribute} = $fields; | ||||
|         } | ||||
|         $hal->resource($resource); | ||||
| 
 | ||||
|         my $response = HTTP::Response->new(HTTP_OK, undef,  | ||||
|             HTTP::Headers->new($hal->http_headers(skip_links => 1)), $hal->as_json); | ||||
|         $c->response->headers($response->headers); | ||||
|         $c->response->body($response->content); | ||||
|         return; | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub HEAD :Allow { | ||||
|     my ($self, $c) = @_; | ||||
|     $c->forward(qw(GET)); | ||||
|     $c->response->body(q()); | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub OPTIONS :Allow { | ||||
|     my ($self, $c) = @_; | ||||
|     my $allowed_methods = $self->allowed_methods; | ||||
|     $c->response->headers(HTTP::Headers->new( | ||||
|         Allow => $allowed_methods->join(', '), | ||||
|         Accept_Post => 'application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-'.$self->resource_name, | ||||
|     )); | ||||
|     $c->response->content_type('application/json'); | ||||
|     $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n"); | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub end : Private { | ||||
|     my ($self, $c) = @_; | ||||
| 
 | ||||
|     $self->log_response($c); | ||||
| } | ||||
| 
 | ||||
| # vim: set tabstop=4 expandtab: | ||||
| @ -0,0 +1,131 @@ | ||||
| package NGCP::Panel::Controller::API::SubscriberPreferences; | ||||
| use Sipwise::Base; | ||||
| use namespace::sweep; | ||||
| use boolean qw(true); | ||||
| use Data::HAL qw(); | ||||
| use Data::HAL::Link qw(); | ||||
| use HTTP::Headers qw(); | ||||
| use HTTP::Status qw(:constants); | ||||
| use MooseX::ClassAttribute qw(class_has); | ||||
| use NGCP::Panel::Utils::DateTime; | ||||
| use Path::Tiny qw(path); | ||||
| use Safe::Isa qw($_isa); | ||||
| BEGIN { extends 'Catalyst::Controller::ActionRole'; } | ||||
| require Catalyst::ActionRole::ACL; | ||||
| require Catalyst::ActionRole::CheckTrailingSlash; | ||||
| require Catalyst::ActionRole::HTTPMethods; | ||||
| require Catalyst::ActionRole::RequireSSL; | ||||
| 
 | ||||
| class_has 'api_description' => ( | ||||
|     is => 'ro', | ||||
|     isa => 'Str', | ||||
|     default =>  | ||||
|         'Specifies certain properties (preferences) for a <a href="#subscribers">Subscriber</a>. The full list of properties can be obtained via <a href="/api/subscriberpreferencedefs/">SubscriberPreferenceDefs</a>.' | ||||
| ); | ||||
| 
 | ||||
| with 'NGCP::Panel::Role::API'; | ||||
| with 'NGCP::Panel::Role::API::Preferences'; | ||||
| 
 | ||||
| class_has('resource_name', is => 'ro', default => 'subscriberpreferences'); | ||||
| class_has('dispatch_path', is => 'ro', default => '/api/subscriberpreferences/'); | ||||
| class_has('relation', is => 'ro', default => 'http://purl.org/sipwise/ngcp-api/#rel-subscriberpreferences'); | ||||
| 
 | ||||
| __PACKAGE__->config( | ||||
|     action => { | ||||
|         map { $_ => { | ||||
|             ACLDetachTo => '/api/root/invalid_user', | ||||
|             AllowedRole => 'admin', | ||||
|             Args => 0, | ||||
|             Does => [qw(ACL CheckTrailingSlash RequireSSL)], | ||||
|             Method => $_, | ||||
|             Path => __PACKAGE__->dispatch_path, | ||||
|         } } @{ __PACKAGE__->allowed_methods } | ||||
|     }, | ||||
|     action_roles => [qw(HTTPMethods)], | ||||
| ); | ||||
| 
 | ||||
| sub auto :Private { | ||||
|     my ($self, $c) = @_; | ||||
| 
 | ||||
|     $self->set_body($c); | ||||
|     $self->log_request($c); | ||||
| } | ||||
| 
 | ||||
| sub GET :Allow { | ||||
|     my ($self, $c) = @_; | ||||
|     my $page = $c->request->params->{page} // 1; | ||||
|     my $rows = $c->request->params->{rows} // 10; | ||||
|     { | ||||
|         my $subscribers = $self->item_rs($c, "subscribers"); | ||||
|         my $total_count = int($subscribers->count); | ||||
|         $subscribers = $subscribers->search(undef, { | ||||
|             page => $page, | ||||
|             rows => $rows, | ||||
|         }); | ||||
|         my (@embedded, @links); | ||||
|         for my $subscriber ($subscribers->search({}, {order_by => {-asc => 'me.id'}})->all) { | ||||
|             next unless($subscriber->provisioning_voip_subscriber); | ||||
|             push @embedded, $self->hal_from_item($c, $subscriber, "subscribers"); | ||||
|             push @links, Data::HAL::Link->new( | ||||
|                 relation => 'ngcp:'.$self->resource_name, | ||||
|                 href     => sprintf('%s%d', $self->dispatch_path, $subscriber->id), | ||||
|             ); | ||||
|         } | ||||
|         push @links, | ||||
|             Data::HAL::Link->new( | ||||
|                 relation => 'curies', | ||||
|                 href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}', | ||||
|                 name => 'ngcp', | ||||
|                 templated => true, | ||||
|             ), | ||||
|             Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'), | ||||
|             Data::HAL::Link->new(relation => 'self', href => sprintf('%s?page=%s&rows=%s', $self->dispatch_path, $page, $rows)); | ||||
|         if(($total_count / $rows) > $page ) { | ||||
|             push @links, Data::HAL::Link->new(relation => 'next', href => sprintf('%s?page=%d&rows=%d', $self->dispatch_path, $page + 1, $rows)); | ||||
|         } | ||||
|         if($page > 1) { | ||||
|             push @links, Data::HAL::Link->new(relation => 'prev', href => sprintf('%s?page=%d&rows=%d', $self->dispatch_path, $page - 1, $rows)); | ||||
|         } | ||||
| 
 | ||||
|         my $hal = Data::HAL->new( | ||||
|             embedded => [@embedded], | ||||
|             links => [@links], | ||||
|         ); | ||||
|         $hal->resource({ | ||||
|             total_count => $total_count, | ||||
|         }); | ||||
|         my $response = HTTP::Response->new(HTTP_OK, undef,  | ||||
|             HTTP::Headers->new($hal->http_headers(skip_links => 1)), $hal->as_json); | ||||
|         $c->response->headers($response->headers); | ||||
|         $c->response->body($response->content); | ||||
|         return; | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub HEAD :Allow { | ||||
|     my ($self, $c) = @_; | ||||
|     $c->forward(qw(GET)); | ||||
|     $c->response->body(q()); | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub OPTIONS :Allow { | ||||
|     my ($self, $c) = @_; | ||||
|     my $allowed_methods = $self->allowed_methods; | ||||
|     $c->response->headers(HTTP::Headers->new( | ||||
|         Allow => $allowed_methods->join(', '), | ||||
|         Accept_Post => 'application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-'.$self->resource_name, | ||||
|     )); | ||||
|     $c->response->content_type('application/json'); | ||||
|     $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n"); | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub end : Private { | ||||
|     my ($self, $c) = @_; | ||||
| 
 | ||||
|     $self->log_response($c); | ||||
| } | ||||
| 
 | ||||
| # vim: set tabstop=4 expandtab: | ||||
| @ -0,0 +1,181 @@ | ||||
| package NGCP::Panel::Controller::API::SubscriberPreferencesItem; | ||||
| use Sipwise::Base; | ||||
| use namespace::sweep; | ||||
| use boolean qw(true); | ||||
| use Data::HAL qw(); | ||||
| use Data::HAL::Link qw(); | ||||
| use HTTP::Headers qw(); | ||||
| use HTTP::Status qw(:constants); | ||||
| use MooseX::ClassAttribute qw(class_has); | ||||
| use NGCP::Panel::Utils::ValidateJSON qw(); | ||||
| use NGCP::Panel::Utils::DateTime; | ||||
| use Path::Tiny qw(path); | ||||
| use Safe::Isa qw($_isa); | ||||
| BEGIN { extends 'Catalyst::Controller::ActionRole'; } | ||||
| require Catalyst::ActionRole::ACL; | ||||
| require Catalyst::ActionRole::HTTPMethods; | ||||
| require Catalyst::ActionRole::RequireSSL; | ||||
| 
 | ||||
| with 'NGCP::Panel::Role::API'; | ||||
| with 'NGCP::Panel::Role::API::Preferences'; | ||||
| 
 | ||||
| class_has('resource_name', is => 'ro', default => 'subscriberpreferences'); | ||||
| class_has('dispatch_path', is => 'ro', default => '/api/subscriberpreferences/'); | ||||
| class_has('relation', is => 'ro', default => 'http://purl.org/sipwise/ngcp-api/#rel-subscriberpreferences'); | ||||
| 
 | ||||
| __PACKAGE__->config( | ||||
|     action => { | ||||
|         map { $_ => { | ||||
|             ACLDetachTo => '/api/root/invalid_user', | ||||
|             AllowedRole => 'admin', | ||||
|             Args => 1, | ||||
|             Does => [qw(ACL RequireSSL)], | ||||
|             Method => $_, | ||||
|             Path => __PACKAGE__->dispatch_path, | ||||
|         } } @{ __PACKAGE__->allowed_methods } | ||||
|     }, | ||||
|     action_roles => [qw(HTTPMethods)], | ||||
| ); | ||||
| 
 | ||||
| sub auto :Private { | ||||
|     my ($self, $c) = @_; | ||||
| 
 | ||||
|     $self->set_body($c); | ||||
|     $self->log_request($c); | ||||
| } | ||||
| 
 | ||||
| sub GET :Allow { | ||||
|     my ($self, $c, $id) = @_; | ||||
|     { | ||||
|         last unless $self->valid_id($c, $id); | ||||
|         my $subscriber = $self->item_by_id($c, $id, "subscribers"); | ||||
|         last unless $self->resource_exists($c, subscriberpreference => $subscriber); | ||||
| 
 | ||||
|         my $hal = $self->hal_from_item($c, $subscriber, "subscribers"); | ||||
| 
 | ||||
|         my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new( | ||||
|             (map { # XXX Data::HAL must be able to generate links with multiple relations | ||||
|                 s|rel="(http://purl.org/sipwise/ngcp-api/#rel-resellers)"|rel="item $1"|; | ||||
|                 s/rel=self/rel="item self"/; | ||||
|                 $_ | ||||
|             } $hal->http_headers), | ||||
|         ), $hal->as_json); | ||||
|         $c->response->headers($response->headers); | ||||
|         $c->response->body($response->content); | ||||
|         return; | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub HEAD :Allow { | ||||
|     my ($self, $c, $id) = @_; | ||||
|     $c->forward(qw(GET)); | ||||
|     $c->response->body(q()); | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub OPTIONS :Allow { | ||||
|     my ($self, $c, $id) = @_; | ||||
|     my $allowed_methods = $self->allowed_methods; | ||||
|     $c->response->headers(HTTP::Headers->new( | ||||
|         Allow => $allowed_methods->join(', '), | ||||
|         Accept_Patch => 'application/json-patch+json', | ||||
|     )); | ||||
|     $c->response->content_type('application/json'); | ||||
|     $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n"); | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub PATCH :Allow { | ||||
|     my ($self, $c, $id) = @_; | ||||
|     my $guard = $c->model('DB')->txn_scope_guard; | ||||
|     { | ||||
|         my $preference = $self->require_preference($c); | ||||
|         last unless $preference; | ||||
| 
 | ||||
|         my $json = $self->get_valid_patch_data( | ||||
|             c => $c, | ||||
|             id => $id, | ||||
|             media_type => 'application/json-patch+json', | ||||
|             ops => [qw/add replace remove copy/], | ||||
|         ); | ||||
|         last unless $json; | ||||
| 
 | ||||
|         my $subscriber = $self->item_by_id($c, $id, "subscribers"); | ||||
|         last unless $self->resource_exists($c, subscriberpreferences => $subscriber); | ||||
|         my $old_resource = $self->get_resource($c, $subscriber, "subscribers"); | ||||
|         my $resource = $self->apply_patch($c, $old_resource, $json); | ||||
|         last unless $resource; | ||||
| 
 | ||||
|         # last param is "no replace" to NOT delete existing prefs | ||||
|         # for proper PATCH behavior | ||||
|         $subscriber = $self->update_item($c, $subscriber, $old_resource, $resource, 0, "subscribers"); | ||||
|         last unless $subscriber; | ||||
| 
 | ||||
|         $guard->commit;  | ||||
| 
 | ||||
|         if ('minimal' eq $preference) { | ||||
|             $c->response->status(HTTP_NO_CONTENT); | ||||
|             $c->response->header(Preference_Applied => 'return=minimal'); | ||||
|             $c->response->body(q()); | ||||
|         } else { | ||||
|             my $hal = $self->hal_from_item($c, $subscriber, "subscribers"); | ||||
|             my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new( | ||||
|                 $hal->http_headers, | ||||
|             ), $hal->as_json); | ||||
|             $c->response->headers($response->headers); | ||||
|             $c->response->header(Preference_Applied => 'return=representation'); | ||||
|             $c->response->body($response->content); | ||||
|         } | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub PUT :Allow { | ||||
|     my ($self, $c, $id) = @_; | ||||
|     my $guard = $c->model('DB')->txn_scope_guard; | ||||
|     { | ||||
|         my $preference = $self->require_preference($c); | ||||
|         last unless $preference; | ||||
| 
 | ||||
|         my $subscriber = $self->item_by_id($c, $id, "subscribers"); | ||||
|         last unless $self->resource_exists($c, systemcontact => $subscriber); | ||||
|         my $resource = $self->get_valid_put_data( | ||||
|             c => $c, | ||||
|             id => $id, | ||||
|             media_type => 'application/json', | ||||
|         ); | ||||
|         last unless $resource; | ||||
|         my $old_resource = $self->get_resource($c, $subscriber, "subscribers"); | ||||
| 
 | ||||
|         # last param is "replace" to delete all existing prefs | ||||
|         # for proper PUT behavior | ||||
|         $subscriber = $self->update_item($c, $subscriber, $old_resource, $resource, 1, "subscribers"); | ||||
|         last unless $subscriber; | ||||
| 
 | ||||
|         $guard->commit;  | ||||
| 
 | ||||
|         if ('minimal' eq $preference) { | ||||
|             $c->response->status(HTTP_NO_CONTENT); | ||||
|             $c->response->header(Preference_Applied => 'return=minimal'); | ||||
|             $c->response->body(q()); | ||||
|         } else { | ||||
|             my $hal = $self->hal_from_item($c, $subscriber, "subscribers"); | ||||
|             my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new( | ||||
|                 $hal->http_headers, | ||||
|             ), $hal->as_json); | ||||
|             $c->response->headers($response->headers); | ||||
|             $c->response->header(Preference_Applied => 'return=representation'); | ||||
|             $c->response->body($response->content); | ||||
|         } | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| sub end : Private { | ||||
|     my ($self, $c) = @_; | ||||
| 
 | ||||
|     $self->log_response($c); | ||||
| } | ||||
| 
 | ||||
| # vim: set tabstop=4 expandtab: | ||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -1,23 +1,24 @@ | ||||
| { | ||||
| 	"sEmptyTable":     "Nessun dato presente nella tabella", | ||||
| 	"sInfo":           "Vista da _START_ a _END_ di _TOTAL_ elementi", | ||||
| 	"sInfoEmpty":      "Vista da 0 a 0 di 0 elementi", | ||||
| 	"sInfoFiltered":   "(filtrati da _MAX_ elementi totali)", | ||||
| 	"sInfoPostFix":    "", | ||||
| 	"sInfoThousands":  ",", | ||||
| 	"sLengthMenu":     "Visualizza _MENU_ elementi", | ||||
| 	"sLoadingRecords": "Caricamento...", | ||||
| 	"sProcessing":     "Elaborazione...", | ||||
| 	"sSearch":         "Cerca:", | ||||
| 	"sZeroRecords":    "La ricerca non ha portato alcun risultato.", | ||||
| 	"oPaginate": { | ||||
| 		"sFirst":      "Inizio", | ||||
| 		"sPrevious":   "Precedente", | ||||
| 		"sNext":       "Successivo", | ||||
| 		"sLast":       "Fine" | ||||
| 	}, | ||||
| 	"oAria": { | ||||
| 		"sSortAscending":  ": attiva per ordinare la colonna in ordine crescente", | ||||
| 		"sSortDescending": ": attiva per ordinare la colonna in ordine decrescente" | ||||
| 	} | ||||
|     "sProcessing":     "Procesando...", | ||||
|     "sLengthMenu":     "Mostrar _MENU_ registros", | ||||
|     "sZeroRecords":    "No se encontraron resultados", | ||||
|     "sEmptyTable":     "Ningún dato disponible en esta tabla", | ||||
|     "sInfo":           "Mostrando registros del _START_ al _END_ de un total de _TOTAL_ registros", | ||||
|     "sInfoEmpty":      "Mostrando registros del 0 al 0 de un total de 0 registros", | ||||
|     "sInfoFiltered":   "(filtrado de un total de _MAX_ registros)", | ||||
|     "sInfoPostFix":    "", | ||||
|     "sSearch":         "Buscar:", | ||||
|     "sUrl":            "", | ||||
|     "sInfoThousands":  ",", | ||||
|     "sLoadingRecords": "Cargando...", | ||||
|     "oPaginate": { | ||||
|         "sFirst":    "Primero", | ||||
|         "sLast":     "Último", | ||||
|         "sNext":     "Siguiente", | ||||
|         "sPrevious": "Anterior" | ||||
|     }, | ||||
|     "oAria": { | ||||
|         "sSortAscending":  ": Activar para ordenar la columna de manera ascendente", | ||||
|         "sSortDescending": ": Activar para ordenar la columna de manera descendente" | ||||
|     } | ||||
| } | ||||
|  | ||||
					Loading…
					
					
				
		Reference in new issue