diff --git a/lib/NGCP/Panel/Controller/API/BillingFees.pm b/lib/NGCP/Panel/Controller/API/BillingFees.pm index f24f70df2c..98cc48f70c 100644 --- a/lib/NGCP/Panel/Controller/API/BillingFees.pm +++ b/lib/NGCP/Panel/Controller/API/BillingFees.pm @@ -8,7 +8,6 @@ use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use NGCP::Panel::Utils::DateTime; -use NGCP::Panel::Form::BillingFee qw(); use Path::Tiny qw(path); BEGIN { extends 'Catalyst::Controller::ActionRole'; } require Catalyst::ActionRole::ACL; @@ -16,6 +15,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Specifies the fees to be applied for a call if it matches the source or destination number of the call.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::BillingFees'; @@ -76,7 +82,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::BillingFee->new; + my $form = $self->get_form($c); for my $fee ($fees->all) { push @embedded, $self->hal_from_fee($c, $fee, $form); push @links, Data::HAL::Link->new( @@ -156,7 +162,7 @@ sub POST :Allow { $reseller_id = $c->user->contract->contact->reseller_id; } - my $form = NGCP::Panel::Form::BillingFee->new; + my $form = $self->get_form($c); my $billing_profile_id = $resource->{billing_profile_id} // undef; my $profile; diff --git a/lib/NGCP/Panel/Controller/API/BillingFeesItem.pm b/lib/NGCP/Panel/Controller/API/BillingFeesItem.pm index 818a6e110d..0a9b8a9cbd 100644 --- a/lib/NGCP/Panel/Controller/API/BillingFeesItem.pm +++ b/lib/NGCP/Panel/Controller/API/BillingFeesItem.pm @@ -4,7 +4,6 @@ use namespace::sweep; use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::BillingFee qw(); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::ValidateJSON qw(); use Path::Tiny qw(path); @@ -105,7 +104,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::BillingFee->new; + my $form = $self->get_form($c); $fee = $self->update_fee($c, $fee, $old_resource, $resource, $form); last unless $fee; @@ -145,7 +144,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $fee->get_inflated_columns }; - my $form = NGCP::Panel::Form::BillingFee->new; + my $form = $self->get_form($c); $fee = $self->update_fee($c, $fee, $old_resource, $resource, $form); last unless $fee; diff --git a/lib/NGCP/Panel/Controller/API/BillingProfiles.pm b/lib/NGCP/Panel/Controller/API/BillingProfiles.pm index cff3b981dc..9215c78669 100644 --- a/lib/NGCP/Panel/Controller/API/BillingProfiles.pm +++ b/lib/NGCP/Panel/Controller/API/BillingProfiles.pm @@ -8,7 +8,6 @@ use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use NGCP::Panel::Utils::DateTime; -use NGCP::Panel::Form::BillingProfile::Admin qw(); use Path::Tiny qw(path); BEGIN { extends 'Catalyst::Controller::ActionRole'; } require Catalyst::ActionRole::ACL; @@ -16,6 +15,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines a collection of Billing Fees and Billing Zones and can be assigned to Customers and System Contracts.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::BillingProfiles'; @@ -62,7 +68,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::BillingProfile::Admin->new; + my $form = $self->get_form($c); for my $profile ($profiles->all) { push @embedded, $self->hal_from_profile($c, $profile, $form); push @links, Data::HAL::Link->new( @@ -141,7 +147,7 @@ sub POST :Allow { $resource->{reseller_id} = $c->user->contract->contact->reseller_id; } - my $form = NGCP::Panel::Form::BillingProfile::Admin->new; + my $form = $self->get_form($c); $resource->{reseller_id} //= undef; last unless $self->validate_form( c => $c, diff --git a/lib/NGCP/Panel/Controller/API/BillingProfilesItem.pm b/lib/NGCP/Panel/Controller/API/BillingProfilesItem.pm index fa860e93da..b278ce4617 100644 --- a/lib/NGCP/Panel/Controller/API/BillingProfilesItem.pm +++ b/lib/NGCP/Panel/Controller/API/BillingProfilesItem.pm @@ -4,7 +4,6 @@ use namespace::sweep; use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::BillingProfile::Admin qw(); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::ValidateJSON qw(); use Path::Tiny qw(path); @@ -105,7 +104,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::BillingProfile::Admin->new; + my $form = $self->get_form($c); $profile = $self->update_profile($c, $profile, $old_resource, $resource, $form); last unless $profile; @@ -145,7 +144,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $profile->get_inflated_columns }; - my $form = NGCP::Panel::Form::BillingProfile::Admin->new; + my $form = $self->get_form($c); use Data::Printer; p $profile; $profile = $self->update_profile($c, $profile, $old_resource, $resource, $form); use Data::Printer; p $profile; diff --git a/lib/NGCP/Panel/Controller/API/BillingZones.pm b/lib/NGCP/Panel/Controller/API/BillingZones.pm index 968bbd2e09..91c55edfb8 100644 --- a/lib/NGCP/Panel/Controller/API/BillingZones.pm +++ b/lib/NGCP/Panel/Controller/API/BillingZones.pm @@ -8,7 +8,6 @@ use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use NGCP::Panel::Utils::DateTime; -use NGCP::Panel::Form::BillingZone qw(); use Path::Tiny qw(path); BEGIN { extends 'Catalyst::Controller::ActionRole'; } require Catalyst::ActionRole::ACL; @@ -16,6 +15,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines zones used to group destinations within Billing Profiles. The zones can be used to group customer\'s calls, like calls within his country or any calls to mobile numbers.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::BillingZones'; @@ -76,7 +82,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::BillingZone->new; + my $form = $self->get_form($c); for my $zone ($zones->all) { push @embedded, $self->hal_from_zone($c, $zone, $form); push @links, Data::HAL::Link->new( @@ -156,7 +162,7 @@ sub POST :Allow { $reseller_id = $c->user->contract->contact->reseller_id; } - my $form = NGCP::Panel::Form::BillingZone->new; + my $form = $self->get_form($c); my $billing_profile_id = $resource->{billing_profile_id} // undef; last unless $self->validate_form( c => $c, diff --git a/lib/NGCP/Panel/Controller/API/BillingZonesItem.pm b/lib/NGCP/Panel/Controller/API/BillingZonesItem.pm index 3af2ad7837..f6b6f3c506 100644 --- a/lib/NGCP/Panel/Controller/API/BillingZonesItem.pm +++ b/lib/NGCP/Panel/Controller/API/BillingZonesItem.pm @@ -4,7 +4,6 @@ use namespace::sweep; use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::BillingZone qw(); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::ValidateJSON qw(); use Path::Tiny qw(path); @@ -105,7 +104,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::BillingZone->new; + my $form = $self->get_form($c); $zone = $self->update_zone($c, $zone, $old_resource, $resource, $form); last unless $zone; @@ -145,7 +144,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $zone->get_inflated_columns }; - my $form = NGCP::Panel::Form::BillingZone->new; + my $form = $self->get_form($c); $zone = $self->update_zone($c, $zone, $old_resource, $resource, $form); last unless $zone; diff --git a/lib/NGCP/Panel/Controller/API/Contracts.pm b/lib/NGCP/Panel/Controller/API/Contracts.pm index 962b510757..217f09bb1e 100644 --- a/lib/NGCP/Panel/Controller/API/Contracts.pm +++ b/lib/NGCP/Panel/Controller/API/Contracts.pm @@ -9,7 +9,6 @@ use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::Contract; -use NGCP::Panel::Form::Contract::PeeringReseller qw(); use Path::Tiny qw(path); BEGIN { extends 'Catalyst::Controller::ActionRole'; } require Catalyst::ActionRole::ACL; @@ -17,6 +16,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines a billing container for peerings and resellers. A Billing Profile is assigned to a contract, and it has Contract Balances indicating the saldo of the contract for current and past billing intervals.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::Contracts'; @@ -66,7 +72,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::Contract::PeeringReseller->new; + my $form = $self->get_form($c); for my $contract ($contracts->all) { push @embedded, $self->hal_from_contract($c, $contract, $form); push @links, Data::HAL::Link->new( @@ -152,7 +158,7 @@ sub POST :Allow { $resource->{contact_id} //= undef; - my $form = NGCP::Panel::Form::Contract::PeeringReseller->new; + my $form = $self->get_form($c); last unless $self->validate_form( c => $c, resource => $resource, diff --git a/lib/NGCP/Panel/Controller/API/ContractsItem.pm b/lib/NGCP/Panel/Controller/API/ContractsItem.pm index 5a06fa6771..decca067fe 100644 --- a/lib/NGCP/Panel/Controller/API/ContractsItem.pm +++ b/lib/NGCP/Panel/Controller/API/ContractsItem.pm @@ -7,7 +7,6 @@ use Data::HAL::Link qw(); use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Contract::PeeringReseller qw(); use NGCP::Panel::Utils::ValidateJSON qw(); use NGCP::Panel::Utils::DateTime; use Path::Tiny qw(path); @@ -109,7 +108,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::Contract::PeeringReseller->new; + my $form = $self->get_form($c); $contract = $self->update_contract($c, $contract, $old_resource, $resource, $form); last unless $contract; @@ -149,7 +148,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $contract->get_inflated_columns }; - my $form = NGCP::Panel::Form::Contract::PeeringReseller->new; + my $form = $self->get_form($c); $contract = $self->update_contract($c, $contract, $old_resource, $resource, $form); last unless $contract; diff --git a/lib/NGCP/Panel/Controller/API/CustomerContacts.pm b/lib/NGCP/Panel/Controller/API/CustomerContacts.pm index e346f74c1a..6cb8fad54a 100644 --- a/lib/NGCP/Panel/Controller/API/CustomerContacts.pm +++ b/lib/NGCP/Panel/Controller/API/CustomerContacts.pm @@ -7,7 +7,6 @@ use Data::HAL::Link qw(); use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Contact::Admin qw(); use NGCP::Panel::Utils::DateTime; use Path::Tiny qw(path); use Safe::Isa qw($_isa); @@ -17,6 +16,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines a physical or legal person\'s address (postal and/or email) to be used to identify Customers.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::CustomerContacts'; @@ -58,7 +64,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::Contact::Admin->new; + my $form = $self->get_form($c); for my $contact ($contacts->search({}, {order_by => {-asc => 'me.id'}, prefetch => ['reseller']})->all) { push @embedded, $self->hal_from_contact($c, $contact, $form); push @links, Data::HAL::Link->new( @@ -127,7 +133,7 @@ sub POST :Allow { ); last unless $resource; - my $form = NGCP::Panel::Form::Contact::Admin->new; + my $form = $self->get_form($c); $resource->{reseller_id} //= undef; last unless $self->validate_form( c => $c, diff --git a/lib/NGCP/Panel/Controller/API/CustomerContactsItem.pm b/lib/NGCP/Panel/Controller/API/CustomerContactsItem.pm index 5c42c00d19..672866c79c 100644 --- a/lib/NGCP/Panel/Controller/API/CustomerContactsItem.pm +++ b/lib/NGCP/Panel/Controller/API/CustomerContactsItem.pm @@ -4,7 +4,6 @@ use namespace::sweep; use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Contact::Admin qw(); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::ValidateJSON qw(); use Path::Tiny qw(path); @@ -105,7 +104,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::Contact::Admin->new; + my $form = $self->get_form($c); $contact = $self->update_contact($c, $contact, $old_resource, $resource, $form); last unless $contact; @@ -145,7 +144,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $contact->get_inflated_columns }; - my $form = NGCP::Panel::Form::Contact::Admin->new; + my $form = $self->get_form($c); $contact = $self->update_contact($c, $contact, $old_resource, $resource, $form); last unless $contact; diff --git a/lib/NGCP/Panel/Controller/API/Customers.pm b/lib/NGCP/Panel/Controller/API/Customers.pm index 3d238c697c..fca5392c61 100644 --- a/lib/NGCP/Panel/Controller/API/Customers.pm +++ b/lib/NGCP/Panel/Controller/API/Customers.pm @@ -9,7 +9,6 @@ use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::Contract; -use NGCP::Panel::Form::Contract::ProductSelect qw(); use Path::Tiny qw(path); BEGIN { extends 'Catalyst::Controller::ActionRole'; } require Catalyst::ActionRole::ACL; @@ -17,6 +16,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines a billing container for end customers. Customers usually have one or more Subscribers. A Billing Profile is assigned to a customer, and it has Contract Balances indicating the saldo of the customer for current and past billing intervals.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::Customers'; @@ -83,7 +89,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::Contract::ProductSelect->new; + my $form = $self->get_form($c); for my $customer($customers->all) { push @embedded, $self->hal_from_customer($c, $customer, $form); push @links, Data::HAL::Link->new( @@ -175,7 +181,7 @@ sub POST :Allow { $resource->{product_id} = $product->id; $resource->{contact_id} //= undef; - my $form = NGCP::Panel::Form::Contract::ProductSelect->new; + my $form = $self->get_form($c); last unless $self->validate_form( c => $c, resource => $resource, diff --git a/lib/NGCP/Panel/Controller/API/CustomersItem.pm b/lib/NGCP/Panel/Controller/API/CustomersItem.pm index 7dc71992e0..2a49fe4d92 100644 --- a/lib/NGCP/Panel/Controller/API/CustomersItem.pm +++ b/lib/NGCP/Panel/Controller/API/CustomersItem.pm @@ -7,7 +7,6 @@ use Data::HAL::Link qw(); use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Contract::ProductSelect qw(); use NGCP::Panel::Utils::ValidateJSON qw(); use NGCP::Panel::Utils::DateTime; use Path::Tiny qw(path); @@ -111,7 +110,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::Contract::ProductSelect->new; + my $form = $self->get_form($c); $customer = $self->update_customer($c, $customer, $old_resource, $resource, $form); last unless $customer; @@ -151,7 +150,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $customer->get_inflated_columns }; - my $form = NGCP::Panel::Form::Contract::ProductSelect->new; + my $form = $self->get_form($c); $customer = $self->update_customer($c, $customer, $old_resource, $resource, $form); last unless $customer; diff --git a/lib/NGCP/Panel/Controller/API/DomainPreferences.pm b/lib/NGCP/Panel/Controller/API/DomainPreferences.pm index 610d18e195..634ecf8733 100644 --- a/lib/NGCP/Panel/Controller/API/DomainPreferences.pm +++ b/lib/NGCP/Panel/Controller/API/DomainPreferences.pm @@ -16,6 +16,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Specifies certain settings (preferences) for a Domain. The full list of settings can be obtained via DomainPreferenceDefs.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::DomainPreferences'; diff --git a/lib/NGCP/Panel/Controller/API/Domains.pm b/lib/NGCP/Panel/Controller/API/Domains.pm index 4463ae4487..7ef4240a0a 100644 --- a/lib/NGCP/Panel/Controller/API/Domains.pm +++ b/lib/NGCP/Panel/Controller/API/Domains.pm @@ -16,6 +16,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Specifies a SIP Domain to be used as host part for SIP Subscribers. You need a domain before you can create a subscriber. Multiple domains can be created. A domain could also be an IPv4 or IPv6 address (whereas the latter needs to be enclosed in square brackets, e.g. [::1]).' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::Domains'; diff --git a/lib/NGCP/Panel/Controller/API/Resellers.pm b/lib/NGCP/Panel/Controller/API/Resellers.pm index e54ca23a6f..a71817edde 100644 --- a/lib/NGCP/Panel/Controller/API/Resellers.pm +++ b/lib/NGCP/Panel/Controller/API/Resellers.pm @@ -8,7 +8,6 @@ use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use NGCP::Panel::Utils::DateTime; -use NGCP::Panel::Form::Reseller qw(); use Path::Tiny qw(path); BEGIN { extends 'Catalyst::Controller::ActionRole'; } require Catalyst::ActionRole::ACL; @@ -16,6 +15,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines a reseller on the system. A reseller can manage his own Domains and Customers.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::Resellers'; @@ -56,7 +62,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::Reseller->new; + my $form = $self->get_form($c); for my $reseller ($resellers->all) { push @embedded, $self->hal_from_reseller($c, $reseller, $form); push @links, Data::HAL::Link->new( @@ -128,7 +134,7 @@ sub POST :Allow { ); last unless $resource; - my $form = NGCP::Panel::Form::Reseller->new; + my $form = $self->get_form($c); $resource->{contract_id} //= undef; last unless $self->validate_form( c => $c, diff --git a/lib/NGCP/Panel/Controller/API/ResellersItem.pm b/lib/NGCP/Panel/Controller/API/ResellersItem.pm index b631a997fe..238bef0654 100644 --- a/lib/NGCP/Panel/Controller/API/ResellersItem.pm +++ b/lib/NGCP/Panel/Controller/API/ResellersItem.pm @@ -4,7 +4,6 @@ use namespace::sweep; use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Reseller qw(); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::ValidateJSON qw(); use Path::Tiny qw(path); @@ -105,7 +104,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::Reseller->new; + my $form = $self->get_form($c); $reseller = $self->update_reseller($c, $reseller, $old_resource, $resource, $form); last unless $reseller; @@ -145,7 +144,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $reseller->get_inflated_columns }; - my $form = NGCP::Panel::Form::Reseller->new; + my $form = $self->get_form($c); $reseller = $self->update_reseller($c, $reseller, $old_resource, $resource, $form); last unless $reseller; diff --git a/lib/NGCP/Panel/Controller/API/Root.pm b/lib/NGCP/Panel/Controller/API/Root.pm index 061abd2c90..080c72205e 100644 --- a/lib/NGCP/Panel/Controller/API/Root.pm +++ b/lib/NGCP/Panel/Controller/API/Root.pm @@ -40,12 +40,36 @@ sub auto :Private { sub GET : Allow { my ($self, $c) = @_; + + my @colls = $self->get_collections; + foreach my $coll(@colls) { + my $mod = $coll; + $mod =~ s/^.+\/([a-zA-Z0-9_]+)\.pm$/$1/; + next if($mod eq "DomainPreferenceDefs"); # not a "real" collection + my $rel = lc $mod; + my $full_mod = 'NGCP::Panel::Controller::API::'.$mod; + + my $role = $full_mod->config->{action}->{GET}->{AllowedRole}; + if(ref $role eq "ARRAY") { + next unless grep @{ $role }, $c->user->roles; + } else { + next unless $role eq $c->user->roles; + } + + my $form = $full_mod->get_form($c); + $c->stash->{collections}->{$rel} = { + name => $mod, + description => $full_mod->api_description, + fields => $self->get_collection_properties($form), + }; + } + $c->stash(template => 'api/root.tt'); $c->forward($c->view); $c->response->headers(HTTP::Headers->new( Content_Language => 'en', Content_Type => 'application/xhtml+xml', - $self->collections_link_headers, + #$self->collections_link_headers, )); return; } @@ -69,7 +93,7 @@ sub OPTIONS : Allow { return; } -sub collections_link_headers : Private { +sub get_collections { my ($self) = @_; # figure out base path of our api modules @@ -88,6 +112,14 @@ sub collections_link_headers : Private { ->not($itemrule); my @colls = $rule->in($libpath); + return @colls; +} + +sub collections_link_headers : Private { + my ($self) = @_; + + my @colls = $self->get_collections; + # create Link header for each of the collections my @links = (); foreach my $mod(@colls) { @@ -108,6 +140,81 @@ sub invalid_user : Private { return; } +sub field_to_json : Private { + my ($self, $name) = @_; + + given($name) { + when(/Float|Integer|Money|PosInteger|Minute|Hour|MonthDay|Year/) { + return "Number"; + } + when(/Boolean/) { + return "Boolean"; + } + when(/Repeatable/) { + return "Array"; + } + when(/\+NGCP::Panel::Field::Regex/) { + return "String"; + } + when(/\+NGCP::Panel::Field::EmailList/) { + return "String"; + } + when(/\+NGCP::Panel::Field::SubscriberStatusSelect/) { + return "String"; + } + when(/\+NGCP::Panel::Field::SubscriberLockSelect/) { + return "Number"; + } + when(/\+NGCP::Panel::Field::E164/) { + return "Object"; + } + when(/\+NGCP::Panel::Field::AliasNumber/) { + return "Array"; + } + # usually {xxx}{id} + when(/\+NGCP::Panel::Field::/) { + return "Number"; + } + default { + return "String"; + } + } +} + +sub get_collection_properties { + my ($self, $form) = @_; + + my @props = (); + foreach my $f($form->fields) { + next if ( + $f->type eq "Hidden" || + $f->type eq "Button" || + $f->type eq "Submit" || + 0); + my @types = (); + push @types, 'null' unless $f->required; + push @types, $self->field_to_json($f->type); + my $name = $f->name; + if($f->type =~ /^\+NGCP::Panel::Field::/) { + if($f->type =~ /E164/) { + $name = 'primary_number'; + } elsif($f->type =~ /AliasNumber/) { + $name = 'alias_numbers'; + } elsif($f->type !~ /Regex|EmailList|SubscriberStatusSelect|SubscriberLockSelect/) { + $name .= '_id'; + } + } + my $desc; + if($f->element_attr) { + $desc = $f->element_attr->{title}->[0]; + } else { + $desc = $name; + } + push @props, { name => $name, description => $desc, types => \@types }; + } + return \@props; +} + sub end : Private { my ($self, $c) = @_; diff --git a/lib/NGCP/Panel/Controller/API/Subscribers.pm b/lib/NGCP/Panel/Controller/API/Subscribers.pm index 49718836b2..ae32f58758 100644 --- a/lib/NGCP/Panel/Controller/API/Subscribers.pm +++ b/lib/NGCP/Panel/Controller/API/Subscribers.pm @@ -19,6 +19,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines an actual user who can log into the web panel, register devices via SIP and/or XMPP and place and receive calls via SIP. A subscriber always belongs to a Customer and is placed inside a Domain.' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::Subscribers'; diff --git a/lib/NGCP/Panel/Controller/API/SystemContacts.pm b/lib/NGCP/Panel/Controller/API/SystemContacts.pm index d61357f6d2..4b0dfd8d67 100644 --- a/lib/NGCP/Panel/Controller/API/SystemContacts.pm +++ b/lib/NGCP/Panel/Controller/API/SystemContacts.pm @@ -7,7 +7,6 @@ use Data::HAL::Link qw(); use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Contact::Reseller qw(); use NGCP::Panel::Utils::DateTime; use Path::Tiny qw(path); use Safe::Isa qw($_isa); @@ -17,6 +16,13 @@ require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; +class_has 'api_description' => ( + is => 'ro', + isa => 'Str', + default => + 'Defines a physical or legal person\'s address (postal and/or email) to be used in System Contracts (contracts for peerings and resellers).' +); + with 'NGCP::Panel::Role::API'; with 'NGCP::Panel::Role::API::SystemContacts'; @@ -58,7 +64,7 @@ sub GET :Allow { rows => $rows, }); my (@embedded, @links); - my $form = NGCP::Panel::Form::Contact::Reseller->new; + my $form = $self->get_form($c); for my $contact ($contacts->search({}, {order_by => {-asc => 'me.id'}, prefetch => ['reseller']})->all) { push @embedded, $self->hal_from_contact($c, $contact, $form); push @links, Data::HAL::Link->new( @@ -127,7 +133,7 @@ sub POST :Allow { ); last unless $resource; - my $form = NGCP::Panel::Form::Contact::Reseller->new; + my $form = $self->get_form($c); last unless $self->validate_form( c => $c, resource => $resource, diff --git a/lib/NGCP/Panel/Controller/API/SystemContactsItem.pm b/lib/NGCP/Panel/Controller/API/SystemContactsItem.pm index c5fd891075..20b992a6b9 100644 --- a/lib/NGCP/Panel/Controller/API/SystemContactsItem.pm +++ b/lib/NGCP/Panel/Controller/API/SystemContactsItem.pm @@ -4,7 +4,6 @@ use namespace::sweep; use HTTP::Headers qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); -use NGCP::Panel::Form::Contact::Reseller qw(); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::ValidateJSON qw(); use Path::Tiny qw(path); @@ -105,7 +104,7 @@ sub PATCH :Allow { my $resource = $self->apply_patch($c, $old_resource, $json); last unless $resource; - my $form = NGCP::Panel::Form::Contact::Reseller->new; + my $form = $self->get_form($c); $contact = $self->update_contact($c, $contact, $old_resource, $resource, $form); last unless $contact; @@ -145,7 +144,7 @@ sub PUT :Allow { last unless $resource; my $old_resource = { $contact->get_inflated_columns }; - my $form = NGCP::Panel::Form::Contact::Admin->new; + my $form = $self->get_form($c); $contact = $self->update_contact($c, $contact, $old_resource, $resource, $form); last unless $contact; diff --git a/lib/NGCP/Panel/Form/BillingFee.pm b/lib/NGCP/Panel/Form/BillingFee.pm index e229390897..12c2569930 100644 --- a/lib/NGCP/Panel/Form/BillingFee.pm +++ b/lib/NGCP/Panel/Form/BillingFee.pm @@ -17,7 +17,7 @@ has_field 'source' => ( maxlength => 255, element_attr => { rel => ['tooltip'], - title => ['string, empty or POSIX regular expression, e.g.: ^431.+$'] + title => ['A POSIX regular expression to match the calling number (e.g. ^.+$).'] }, ); @@ -27,7 +27,7 @@ has_field 'destination' => ( required => 1, element_attr => { rel => ['tooltip'], - title => ['string, POSIX regular expression, e.g.: ^431.+$'] + title => ['A POSIX regular expression to match the called number (e.g. ^431.+$).'] }, ); @@ -39,12 +39,20 @@ has_field 'direction' => ( ], default => 'out', required => 1, + element_attr => { + rel => ['tooltip'], + title => ['The call direction when to apply this fee (either for inbound or outbound calls).'] + }, ); has_field 'billing_zone' => ( type => '+NGCP::Panel::Field::BillingZone', label => 'Zone', validate_when_empty => 1, + element_attr => { + rel => ['tooltip'], + title => ['The billing zone id this fee belongs to.'] + }, ); has_field 'onpeak_init_rate' => ( @@ -52,7 +60,7 @@ has_field 'onpeak_init_rate' => ( precision => 18, element_attr => { rel => ['tooltip'], - title => ['The cost of the init interval in cents per second (e.g 0.90)'] + title => ['The cost of the first interval in cents per second (e.g. 0.90).'] }, default => 0, ); @@ -61,7 +69,7 @@ has_field 'onpeak_init_interval' => ( type => 'Integer', element_attr => { rel => ['tooltip'], - title => ['The length of the first interval'] + title => ['The length of the first interval in seconds (e.g. 60).'] }, default => 60, required => 1, @@ -73,7 +81,7 @@ has_field 'onpeak_follow_rate' => ( precision => 18, element_attr => { rel => ['tooltip'], - title => ['The cost of each following interval in cents per second (e.g 0.90)'] + title => ['The cost of each following interval in cents per second (e.g. 0.90).'] }, default => 0, ); @@ -82,7 +90,7 @@ has_field 'onpeak_follow_interval' => ( type => 'Integer', element_attr => { rel => ['tooltip'], - title => ['The length of the following intervals'] + title => ['The length of each following interval in seconds (e.g. 30).'] }, default => 60, required => 1, @@ -94,7 +102,7 @@ has_field 'offpeak_init_rate' => ( precision => 18, element_attr => { rel => ['tooltip'], - title => ['The cost of the init interval in cents per second (e.g 0.90)'] + title => ['The cost of the first interval in cents per second (e.g. 0.90).'] }, default => 0, ); @@ -103,7 +111,7 @@ has_field 'offpeak_init_interval' => ( type => 'Integer', element_attr => { rel => ['tooltip'], - title => ['The length of the first interval'] + title => ['The length of the first interval in seconds (e.g. 60).'] }, default => 60, required => 1, @@ -115,7 +123,7 @@ has_field 'offpeak_follow_rate' => ( precision => 18, element_attr => { rel => ['tooltip'], - title => ['The cost of each following interval in cents per second (e.g 0.90)'] + title => ['The cost of each following interval in cents per second (e.g. 0.90).'] }, default => 0, ); @@ -124,7 +132,7 @@ has_field 'offpeak_follow_interval' => ( type => 'Integer', element_attr => { rel => ['tooltip'], - title => ['The length of the following intervals'] + title => ['The length of each following interval in seconds (e.g. 30).'] }, default => 60, required => 1, @@ -135,7 +143,7 @@ has_field 'use_free_time' => ( type => 'Boolean', element_attr => { rel => ['tooltip'], - title => ['Free minutes may be used when calling this destination'] + title => ['Whether free minutes may be used when calling this destination.'] }, default => 0, ); diff --git a/lib/NGCP/Panel/Form/Domain/Admin.pm b/lib/NGCP/Panel/Form/Domain/Admin.pm index 83f07f731c..1d63a1c951 100644 --- a/lib/NGCP/Panel/Form/Domain/Admin.pm +++ b/lib/NGCP/Panel/Form/Domain/Admin.pm @@ -7,6 +7,10 @@ use Moose::Util::TypeConstraints; has_field 'reseller' => ( type => '+NGCP::Panel::Field::Reseller', validate_when_empty => 1, + element_attr => { + rel => ['tooltip'], + title => ['The reseller id to assign this domain to.'] + }, ); has_block 'fields' => ( diff --git a/lib/NGCP/Panel/Form/Domain/Reseller.pm b/lib/NGCP/Panel/Form/Domain/Reseller.pm index d3e3f05bb7..2cc7375de1 100644 --- a/lib/NGCP/Panel/Form/Domain/Reseller.pm +++ b/lib/NGCP/Panel/Form/Domain/Reseller.pm @@ -19,6 +19,10 @@ has_field 'domain' => ( type => 'Text', required => 1, label => 'SIP Domain', + element_attr => { + rel => ['tooltip'], + title => ['The fully qualified domain name (e.g. sip.example.org).'] + }, ); has_field 'save' => ( diff --git a/lib/NGCP/Panel/Role/API/BillingFees.pm b/lib/NGCP/Panel/Role/API/BillingFees.pm index 2a5ee1d7b9..0dedd0d8e8 100644 --- a/lib/NGCP/Panel/Role/API/BillingFees.pm +++ b/lib/NGCP/Panel/Role/API/BillingFees.pm @@ -11,6 +11,11 @@ use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::Contract; use NGCP::Panel::Form::BillingFee qw(); +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::BillingFee->new; +} + sub hal_from_fee { my ($self, $c, $fee, $form) = @_; @@ -33,7 +38,7 @@ sub hal_from_fee { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::BillingFee->new; + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, form => $form, @@ -79,7 +84,7 @@ sub update_fee { } else { $reseller_id = $c->user->contract->contact->reseller_id; } - $form //= NGCP::Panel::Form::BillingFee->new; + $form //= $self->get_form($c); # TODO: for some reason, formhandler lets missing profile/zone id my $billing_profile_id = $resource->{billing_profile_id} // undef; diff --git a/lib/NGCP/Panel/Role/API/BillingProfiles.pm b/lib/NGCP/Panel/Role/API/BillingProfiles.pm index 1866751a7a..cb98b6bcb6 100644 --- a/lib/NGCP/Panel/Role/API/BillingProfiles.pm +++ b/lib/NGCP/Panel/Role/API/BillingProfiles.pm @@ -12,6 +12,11 @@ use NGCP::Panel::Utils::Contract; use NGCP::Panel::Utils::Preferences; use NGCP::Panel::Form::BillingProfile::Admin qw(); +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::BillingProfile::Admin->new; +} + sub hal_from_profile { my ($self, $c, $profile, $form) = @_; @@ -38,7 +43,7 @@ sub hal_from_profile { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::BillingProfile::Admin->new; + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, form => $form, @@ -72,7 +77,7 @@ sub profile_by_id { sub update_profile { my ($self, $c, $profile, $old_resource, $resource, $form) = @_; - $form //= NGCP::Panel::Form::BillingProfile::Admin->new; + $form //= $self->get_form($c); # TODO: for some reason, formhandler lets missing reseller slip thru $resource->{reseller_id} //= undef; return unless $self->validate_form( diff --git a/lib/NGCP/Panel/Role/API/BillingZones.pm b/lib/NGCP/Panel/Role/API/BillingZones.pm index ebe4da6a6d..68e1db4967 100644 --- a/lib/NGCP/Panel/Role/API/BillingZones.pm +++ b/lib/NGCP/Panel/Role/API/BillingZones.pm @@ -11,6 +11,11 @@ use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::Contract; use NGCP::Panel::Form::BillingZone qw(); +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::BillingZone->new; +} + sub hal_from_zone { my ($self, $c, $zone, $form) = @_; @@ -33,7 +38,7 @@ sub hal_from_zone { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::BillingZone->new; + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, form => $form, @@ -79,7 +84,7 @@ sub update_zone { } else { $reseller_id = $c->user->contract->contact->reseller_id; } - $form //= NGCP::Panel::Form::BillingZone->new; + $form //= $self->get_form($c); # TODO: for some reason, formhandler lets missing profile id my $billing_profile_id = $resource->{billing_profile_id} // undef; return unless $self->validate_form( diff --git a/lib/NGCP/Panel/Role/API/Contracts.pm b/lib/NGCP/Panel/Role/API/Contracts.pm index d33b762ba3..1820ab9933 100644 --- a/lib/NGCP/Panel/Role/API/Contracts.pm +++ b/lib/NGCP/Panel/Role/API/Contracts.pm @@ -11,6 +11,11 @@ use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::Contract; use NGCP::Panel::Form::Contract::PeeringReseller qw(); +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::Contract::PeeringReseller->new; +} + sub hal_from_contract { my ($self, $c, $contract, $form) = @_; @@ -61,7 +66,7 @@ sub hal_from_contract { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::Contract::PeeringReseller->new; + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, form => $form, @@ -105,7 +110,7 @@ sub update_contract { return; } - $form //= NGCP::Panel::Form::Contract::PeeringReseller->new; + $form //= $self->get_form($c); # TODO: for some reason, formhandler lets missing contact_id slip thru $resource->{contact_id} //= undef; return unless $self->validate_form( diff --git a/lib/NGCP/Panel/Role/API/CustomerContacts.pm b/lib/NGCP/Panel/Role/API/CustomerContacts.pm index 9fb0bd1a9c..e7cc441e8c 100644 --- a/lib/NGCP/Panel/Role/API/CustomerContacts.pm +++ b/lib/NGCP/Panel/Role/API/CustomerContacts.pm @@ -9,6 +9,11 @@ use Data::HAL::Link qw(); use HTTP::Status qw(:constants); use NGCP::Panel::Form::Contact::Admin; +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::Contact::Admin->new; +} + sub hal_from_contact { my ($self, $c, $contact, $form) = @_; my %resource = $contact->get_inflated_columns; @@ -28,7 +33,7 @@ sub hal_from_contact { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::Contact::Admin->new; + $form //= $self->get_form($c); $self->validate_form( c => $c, resource => \%resource, @@ -53,7 +58,7 @@ sub contact_by_id { sub update_contact { my ($self, $c, $contact, $old_resource, $resource, $form) = @_; - $form //= NGCP::Panel::Form::Contact::Admin->new; + $form //= $self->get_form($c); # TODO: for some reason, formhandler lets missing reseller_id slip thru $resource->{reseller_id} //= undef; return unless $self->validate_form( diff --git a/lib/NGCP/Panel/Role/API/Customers.pm b/lib/NGCP/Panel/Role/API/Customers.pm index 2ca71ce1d6..0d99ad8a9c 100644 --- a/lib/NGCP/Panel/Role/API/Customers.pm +++ b/lib/NGCP/Panel/Role/API/Customers.pm @@ -12,6 +12,11 @@ use NGCP::Panel::Utils::Contract; use NGCP::Panel::Utils::Preferences; use NGCP::Panel::Form::Contract::ProductSelect qw(); +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::Contract::PeeringReseller->new; +} + sub hal_from_customer { my ($self, $c, $customer, $form) = @_; @@ -62,7 +67,7 @@ sub hal_from_customer { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::Contract::ProductSelect->new; + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, form => $form, @@ -126,7 +131,7 @@ sub update_customer { return; } - $form //= NGCP::Panel::Form::Contract::ProductSelect->new; + $form //= $self->get_form($c); # TODO: for some reason, formhandler lets missing contact_id slip thru $resource->{contact_id} //= undef; return unless $self->validate_form( diff --git a/lib/NGCP/Panel/Role/API/Resellers.pm b/lib/NGCP/Panel/Role/API/Resellers.pm index 00c45e638d..f0b79cc614 100644 --- a/lib/NGCP/Panel/Role/API/Resellers.pm +++ b/lib/NGCP/Panel/Role/API/Resellers.pm @@ -10,6 +10,11 @@ use HTTP::Status qw(:constants); use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Form::Reseller qw(); +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::Reseller->new; +} + sub hal_from_reseller { my ($self, $c, $reseller, $form) = @_; @@ -41,7 +46,7 @@ sub hal_from_reseller { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::Reseller->new; + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, form => $form, @@ -65,7 +70,7 @@ sub reseller_by_id { sub update_reseller { my ($self, $c, $reseller, $old_resource, $resource, $form) = @_; - $form //= NGCP::Panel::Form::Reseller->new; + $form //= $self->get_form($c); $resource->{contract_id} //= undef; return unless $self->validate_form( c => $c, diff --git a/lib/NGCP/Panel/Role/API/SystemContacts.pm b/lib/NGCP/Panel/Role/API/SystemContacts.pm index c79132f24c..f301f82a7f 100644 --- a/lib/NGCP/Panel/Role/API/SystemContacts.pm +++ b/lib/NGCP/Panel/Role/API/SystemContacts.pm @@ -9,6 +9,11 @@ use Data::HAL::Link qw(); use HTTP::Status qw(:constants); use NGCP::Panel::Form::Contact::Reseller; +sub get_form { + my ($self, $c) = @_; + return NGCP::Panel::Form::Contact::Reseller->new; +} + sub hal_from_contact { my ($self, $c, $contact, $form) = @_; my %resource = $contact->get_inflated_columns; @@ -29,7 +34,7 @@ sub hal_from_contact { relation => 'ngcp:'.$self->resource_name, ); - $form //= NGCP::Panel::Form::Contact::Reseller->new; + $form //= $self->get_form($c); # TODO: i'd expect reseller to be removed automatically delete $resource{reseller_id}; @@ -57,7 +62,7 @@ sub contact_by_id { sub update_contact { my ($self, $c, $contact, $old_resource, $resource, $form) = @_; - $form //= NGCP::Panel::Form::Contact::Reseller->new; + $form //= $self->get_form($c); delete $resource->{reseller_id}; return unless $self->validate_form( c => $c, diff --git a/sandbox/read_form_fields.pl b/sandbox/read_form_fields.pl new file mode 100755 index 0000000000..acb2ed4524 --- /dev/null +++ b/sandbox/read_form_fields.pl @@ -0,0 +1,39 @@ +#!/usr/bin/perl -w +use strict; +use Sipwise::Base; +use Data::Printer; +use NGCP::Panel::Form::BillingFee; + +sub field_to_json { + my $name = shift; + + given($name) { + when(/Float|Integer|Money|PosInteger|Minute|Hour|MonthDay|Year/) { + return "Number"; + } + when(/Boolean/) { + return "Boolean"; + } + when(/Repeatable/) { + return "Array"; + } + default { + return "String"; + } + } +} + +my $form = NGCP::Panel::Form::BillingFee->new; + +foreach my $f($form->fields) { + next if ( + $f->type eq "Hidden" || + $f->type eq "Button" || + $f->type eq "Submit" || + 0); + my @types = (); + push @types, 'null' unless $f->required; + push @types, field_to_json($f->type); + + print $f->name . " (" . join(', ', @types) . ")" . "\n"; +} diff --git a/share/templates/api/root.tt b/share/templates/api/root.tt index 04bf9b2523..98cbbcd37d 100644 --- a/share/templates/api/root.tt +++ b/share/templates/api/root.tt @@ -53,16 +53,11 @@ { level = 2, id = 'intro', title = 'Introduction', }, { level = 2, id = 'auth', title = 'Authentication', }, { level = 2, id = 'relations', title = 'Resources', }, - - { level = 3, id = 'rel-systemcontacts', title = 'System Contacts', uri = '/api/contacts/' }, -# { level = 3, id = 'rel-resellers', title = 'Resellers', uri = '/api/resellers/' }, -# { level = 3, id = 'rel-admins', title = 'Admins', uri = '/api/admins/' }, -# { level = 3, id = 'rel-customers', title = 'Customers', uri = '/api/customers/' }, - -# { level = 3, id = 'rel-billingprofiles', title = 'Billing Profiles', uri = '/api/billing/' }, - - { level = 2, id = 'definitions', title = 'Definitions', }, ]; + FOREACH col IN collections.keys.sort; + chapters.push({ level = 3, id = col, title = collections.$col.name, uri = '/api/' _ col _ '/' }); + END; + chapters.push({ level = 2, id = 'definitions', title = 'Definitions' }); -%]

Sipwise NGCP HTTP API Documentation

@@ -91,8 +86,14 @@ [% END -%]
[% + IF chapter.level != 3; t = 'api/root/' _ chapter.id _ '.tt'; INCLUDE $t level=chapter.level title=chapter.title id=chapter.id uri=chapter.uri; + ELSE; + t = 'api/root/collection.tt'; + colname = chapter.id; + INCLUDE $t level=chapter.level title=chapter.title id=chapter.id uri=chapter.uri col=collections.$colname; + END; -%]
[% END -%] diff --git a/share/templates/api/root/collection.tt b/share/templates/api/root/collection.tt new file mode 100644 index 0000000000..bb103b3716 --- /dev/null +++ b/share/templates/api/root/collection.tt @@ -0,0 +1,431 @@ + + [% IF uri -%] + + [% END -%] + [% title %] + [% IF uri -%] + + [% END -%] + + +Description + +[% col.description %] + +Properties + + + +Examples +
+ +Request available HTTP methods on the URI +

+[% + cmd = 'curl -i -X OPTIONS -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem https://example.org:1443/api/' _ id _ '/'; + INCLUDE helpers/api_command.tt cmd=cmd level=level+3; + + request = +'OPTIONS /api/' _ id _ '/ HTTP/1.1'; + + response = +'HTTP/1.1 200 OK +Allow: GET, HEAD, OPTIONS, POST +Accept-Post: application/hal+json; profile="http://purl.org/sipwise/ngcp-api/#rel-' _ id _ '"'; + INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; +-%] +

+ +Request the entire [% id %] collection +

+

+ You cannot request the entire collection at once, but instead you can simply page through the results. The response provides prev and next links you can follow to get the next page. + + To define the page number and the rows per page to return, you can pass the parameters page and rows. Default values are page=1 and rows=10, if you do not provide them. +

+[% + cmd = 'curl -i -X GET -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/' _ id _ '/?page=1&rows=2\''; + INCLUDE helpers/api_command.tt cmd=cmd level=level+3; + + props = ' "id" : 1'; + FOREACH p IN col.fields; + NEXT IF p.types.0 == 'null'; + props = props _ ', +'; + IF p.types.0 == "Number"; + val = 4; + ELSIF p.types.0 == "String"; + val = '"test"'; + ELSIF p.types.0 == "Boolean"; + val = 'true'; + ELSIF p.types.0 == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ ' "' _ p.name _ '" : ' _ val; + END; + props = props _ ' +'; + + request = +'GET /api/' _ id _ '/?page=1&rows=1 HTTP/1.1'; + response = +'HTTP/1.1 200 OK +Content-Type: application/hal+json; profile="http://purl.org/sipwise/ngcp-api/" + +{ + "_embedded" : { + "ngcp:' _ id _ '" : [ + { + "_links" : { + "collection" : { + "href" : "/api/' _ id _ '/" + }, + "curies" : { + "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", + "name" : "ngcp", + "templated" : true + }, + "profile" : { + "href" : "http://purl.org/sipwise/ngcp-api/" + }, + "self" : { + "href" : "/api/' _ id _ '/1" + } + }, +' _ props _ ' }, + ] + }, + "_links" : { + "curies" : { + "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", + "name" : "ngcp", + "templated" : true + }, + "next" : { + "href" : "/api/' _ id _ '/?page=2&rows=1" + }, + "ngcp:' _ id _ '" : [ + { + "href" : "/api/' _ id _ '/1" + }, + ], + "profile" : { + "href" : "http://purl.org/sipwise/ngcp-api/" + }, + "self" : { + "href" : "/api/' _ id _ '/?page=1&rows=1" + } + }, + "total_count" : 100 +}'; + + INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; +-%] +

+ +Request a specific [% id %] item +

+ +[% + cmd = 'curl -i -X GET -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/' _ id _ '/1\''; + INCLUDE helpers/api_command.tt cmd=cmd level=level+3; + + props = ' "id" : 1'; + FOREACH p IN col.fields; + NEXT IF p.types.0 == 'null'; + props = props _ ', +'; + IF p.types.0 == "Number"; + val = 4; + ELSIF p.types.0 == "String"; + val = '"test"'; + ELSIF p.types.0 == "Boolean"; + val = 'true'; + ELSIF p.types.0 == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ ' "' _ p.name _ '" : ' _ val; + END; + props = props _ ' +'; + request = +'GET /api/' _ id _ '/1 HTTP/1.1'; + response = +'HTTP/1.1 200 OK +Content-Type: application/hal+json; profile="http://purl.org/sipwise/ngcp-api/" +Link: ; rel=collection +Link: ; rel=profile +Link: ; rel="item self" + +{ + "_links" : { + "collection" : { + "href" : "/api/' _ id _ '/" + }, + "curies" : { + "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", + "name" : "ngcp", + "templated" : true + }, + "profile" : { + "href" : "http://purl.org/sipwise/ngcp-api/" + }, + "self" : { + "href" : "/api/' _ id _ '/1" + } + }, +' _ props _ ' }'; + + INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; +-%] +

+ +Create a new [% id %] item +

+[% + props = ''; + FOREACH p IN col.fields; + NEXT IF p.types.0 == 'null'; + IF p.types.0 == "Number"; + val = 4; + ELSIF p.types.0 == "String"; + val = '"test"'; + ELSIF p.types.0 == "Boolean"; + val = 'true'; + ELSIF p.types.0 == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ '"' _ p.name _ '" : ' _ val; + props = props _ ', '; + END; + props = props.substr(0, props.length - 2); + + cmd = 'curl -i -X POST -H \'Connection: close\' -H \'Content-Type: application/json\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/' _ id _ '/\' --data-binary \'{ ' _ props _ ' }\''; + INCLUDE helpers/api_command.tt cmd=cmd level=level+3; + + props = ''; + FOREACH p IN col.fields; + NEXT IF p.types.0 == 'null'; + IF p.types.0 == "Number"; + val = 4; + ELSIF p.types.0 == "String"; + val = '"test"'; + ELSIF p.types.0 == "Boolean"; + val = 'true'; + ELSIF p.types.0 == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ ' "' _ p.name _ '" : ' _ val; + props = props _ ', +'; + END; + props = props.substr(0, props.length - 2); + request = +'POST /api/' _ id _ '/ HTTP/1.1 +Content-Type: application/json + +{ +' _ props _ ' +}'; + response = +'HTTP/1.1 201 Created +Location: /api/' _ id _ '/2'; + + INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; +%] +

+ +Update an existing [% id %] item +

+[% + props = ''; + FOREACH p IN col.fields; + NEXT IF p.types.0 == 'null'; + IF p.types.0 == "Number"; + val = 4; + ELSIF p.types.0 == "String"; + val = '"test"'; + ELSIF p.types.0 == "Boolean"; + val = 'true'; + ELSIF p.types.0 == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ '"' _ p.name _ '" : ' _ val; + props = props _ ', '; + END; + props = props.substr(0, props.length - 2); + + cmd = 'curl -i -X PUT -H \'Connection: close\' -H \'Content-Type: application/json\' -H \'Prefer: return=minimal\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/' _ id _ '/2\' --data-binary \'{ ' _ props _ ' }\''; + INCLUDE helpers/api_command.tt cmd=cmd extended=1 level=level+3; + + props = ''; + FOREACH p IN col.fields; + NEXT IF p.types.0 == 'null'; + IF p.types.0 == "Number"; + val = 4; + ELSIF p.types.0 == "String"; + val = '"test"'; + ELSIF p.types.0 == "Boolean"; + val = 'true'; + ELSIF p.types.0 == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ ' "' _ p.name _ '" : ' _ val; + props = props _ ', +'; + END; + props = props.substr(0, props.length - 2); + request = +'PUT /api/' _ id _ '/2 HTTP/1.1 +Content-Type: application/json +Prefer: return=minimal + +{ +' _ props _ ' +}'; + response = +'HTTP/1.1 204 No Content +Preference-Applied: return=minimal'; + + INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; +-%] +

+ +Update specific fields of an existing systemcontacts entry +

+[% + props = ''; rem = 0; rep = 0; + FOREACH p IN col.fields; + type = p.types.0; + IF type == 'null'; + NEXT IF rem >= 1; + op = "remove"; + type = p.types.1; + rem = rem + 1; + ELSE; + NEXT IF rep >= 1; + op = "replace"; + rep = rep + 1; + END; + + IF type == "Number"; + val = 5; + ELSIF type == "String"; + val = '"other"'; + ELSIF type == "Boolean"; + val = 'false'; + ELSIF type == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ '{ '; + props = props _ '"op" : "' _ op _ '", "path" : "/' _ p.name _ '"'; + UNLESS op == "remove"; + props = props _ ', "value" : ' _ val; + END; + props = props _ ' }, '; + LAST IF rep >= 1 && rem >= 1; + END; + props = props.substr(0, props.length - 2); + + cmd = 'curl -i -X PATCH -H \'Connection: close\' -H \'Content-Type: application/json-patch+json\' -H \'Prefer: return=minimal\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/' _ id _ '/2\' --data-binary \'[ ' _ props _ ' ]\''; + INCLUDE helpers/api_command.tt cmd=cmd extended=1 level=level+3; +%] + +

+ The PATCH method allows to operate on specific fields of an item. The path attribute can point to a normal property (e.g. /something) or to a specific element in an array (e.g. /something/0). Available op values are: +

+

+ +[% + props = ''; rem = 0; rep = 0; + FOREACH p IN col.fields; + type = p.types.0; + IF type == 'null'; + NEXT IF rem >= 1; + op = "remove"; + type = p.types.1; + rem = rem + 1; + ELSE; + NEXT IF rep >= 1; + op = "replace"; + rep = rep + 1; + END; + + IF type == "Number"; + val = 5; + ELSIF type == "String"; + val = '"other"'; + ELSIF type == "Boolean"; + val = 'false'; + ELSIF type == "Array"; + val = '[]'; + ELSE; + val = '"missing"'; + END; + props = props _ ' + { +'; + props = props _ ' "op" : "' _ op _ '", + "path" : "/' _ p.name _ '"'; + UNLESS op == "remove"; + props = props _ ', + "value" : ' _ val; + END; + props = props _ ' + }, '; + LAST IF rep >= 1 && rem >= 1; + END; + props = props.substr(0, props.length - 2); + + request = +'PATCH /api/' _ id _ '/2 HTTP/1.1 +Content-Type: application/json-patch+json +Prefer: return=minimal + +[' _ props _ ' +]'; + response = +'HTTP/1.1 204 No Content +Preference-Applied: return=minimal'; + + INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; +-%] +

+ +
+[% # vim: set tabstop=4 syntax=html expandtab: -%] diff --git a/share/templates/api/root/rel-systemcontacts.tt b/share/templates/api/root/rel-systemcontacts.tt deleted file mode 100644 index e04d7cd2a8..0000000000 --- a/share/templates/api/root/rel-systemcontacts.tt +++ /dev/null @@ -1,338 +0,0 @@ - - [% IF uri -%] - - [% END -%] - [% title %] - [% IF uri -%] - - [% END -%] - - -Description - -

-The systemcontacts item is used to specify the contact information of peering and reseller contracts. -

- -Properties - - - -Relation Links -

None

- - -Examples -
- -Request available HTTP methods on the URI -

-[% - cmd = 'curl -i -X OPTIONS -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem https://example.org:1443/api/systemcontacts/'; - INCLUDE helpers/api_command.tt cmd=cmd level=level+3; - - request = [ - 'OPTIONS /api/systemcontacts/ HTTP/1.1' - ]; - response = [ - 'HTTP/1.1 200 OK', - 'Allow: GET, HEAD, OPTIONS, POST', - 'Accept-Post: application/hal+json; profile="http://purl.org/sipwise/ngcp-api/#rel-systemcontacts"', - ]; - INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; --%] -

- -Request the entire systemcontacts collection -

-

- You cannot request the entire collection at once, but instead you can simply page through the results. The response provides prev and next links you can follow to get the next page. - - To define the page number and the rows per page to return, you can pass the parameters page and rows. Default values are page=1 and rows=10, if you do not provide them. -

-[% - cmd = 'curl -i -X GET -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/systemcontacts/?page=1&rows=2\''; - INCLUDE helpers/api_command.tt cmd=cmd level=level+3; - - request = [ - 'GET /api/systemcontacts/ HTTP/1.1', - ]; - response = [ -'HTTP/1.1 200 OK -Content-Type: application/hal+json; profile="http://purl.org/sipwise/ngcp-api/" -Link: ; rel="item http://purl.org/sipwise/ngcp-api/#rel-systemcontacts" -Link: ; rel="item http://purl.org/sipwise/ngcp-api/#rel-systemcontacts" -Link: ; rel=profile -Link: ; rel="collection self" -Link: ; rel=next - -{ - "_embedded" : { - "ngcp:systemcontacts" : [ - { - "_links" : { - "collection" : { - "href" : "/api/systemcontacts/" - }, - "curies" : { - "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", - "name" : "ngcp", - "templated" : true - }, - "profile" : { - "href" : "http://purl.org/sipwise/ngcp-api/" - }, - "self" : { - "href" : "/api/systemcontacts/1" - } - }, - "city" : null, - "company" : null, - "country" : null, - "email" : "default-peering@default.invalid", - "firstname" : null, - "lastname" : null, - "phonenumber" : null, - "postcode" : null, - "street" : null - }, - { - "_links" : { - "collection" : { - "href" : "/api/systemcontacts/" - }, - "curies" : { - "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", - "name" : "ngcp", - "templated" : true - }, - "profile" : { - "href" : "http://purl.org/sipwise/ngcp-api/" - }, - "self" : { - "href" : "/api/systemcontacts/2" - } - }, - "city" : null, - "company" : null, - "country" : null, - "email" : "default-reseller@default.invalid", - "firstname" : null, - "lastname" : null, - "phonenumber" : null, - "postcode" : null, - "street" : null - } - ] - }, - "_links" : { - "curies" : { - "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", - "name" : "ngcp", - "templated" : true - }, - "next" : { - "href" : "/api/systemcontacts/?page=2&rows=2" - }, - "ngcp:systemcontacts" : [ - { - "href" : "/api/systemcontacts/1" - }, - { - "href" : "/api/systemcontacts/2" - } - ], - "profile" : { - "href" : "http://purl.org/sipwise/ngcp-api/" - }, - "self" : { - "href" : "/api/systemcontacts/?page=1&rows=2" - } - }, - "total_count" : 57 -}' - ]; - INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; --%] -

- -Request a specific systemcontacts item -

-[% - cmd = 'curl -i -X GET -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/systemcontacts/3\''; - INCLUDE helpers/api_command.tt cmd=cmd level=level+3; - - request = [ - 'GET /api/systemcontacts/3 HTTP/1.1', - ]; - response = [ -'HTTP/1.1 200 OK -Content-Type: application/hal+json; profile="http://purl.org/sipwise/ngcp-api/" -Link: ; rel=collection -Link: ; rel=profile -Link: ; rel="item self" - -{ - "_links" : { - "collection" : { - "href" : "/api/systemcontacts/" - }, - "curies" : { - "href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}", - "name" : "ngcp", - "templated" : true - }, - "profile" : { - "href" : "http://purl.org/sipwise/ngcp-api/" - }, - "self" : { - "href" : "/api/systemcontacts/3" - } - }, - "city" : null, - "company" : null, - "country" : null, - "email" : "default-reseller@default.invalid", - "firstname" : null, - "lastname" : null, - "phonenumber" : null, - "postcode" : null, - "street" : null -}' - ]; - INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; --%] -

- -Create a new systemcontacts entry -

-[% - cmd = 'curl -i -X POST -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.com:1443/api/systemcontacts/\' --data-binary \'{ "firstname": "John", "lastname": "Doe", "city": null, "company": null, "country": null, "phonenumber": null, "postcode": null, "street": null, "email": "john.doe@reseller.invalid", "reseller_id": 1 }\' -H \'Content-Type: application/json\''; - INCLUDE helpers/api_command.tt cmd=cmd level=level+3; - - request = [ - 'POST /api/systemcontacts/ HTTP/1.1', - 'Content-Type: application/json', - '', -'{ - "firstname": "John", - "lastname": "Doe", - "email": "john.doe@reseller.invalid", - "city": null, - "company": null, - "country": null, - "phonenumber": null, - "postcode": null, - "street": null -}', - ]; - response = [ -'HTTP/1.1 201 Created -Location: /api/systemcontacts/280' - ]; - - INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; --%] -

- -Update an existing systemcontacts entry -

-[% - cmd = 'curl -i -X PUT -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/systemcontacts/10\' --data-binary \'{ "firstname": "John", "lastname": "Doe", "email": "something.else@reseller.invalid", "city": null, "company": null, "country": null, "phonenumber": null, "postcode": null, "street": null }\' -H \'Content-Type: application/json\' -H \'Prefer: return=minimal\''; - INCLUDE helpers/api_command.tt cmd=cmd extended=1 level=level+3; - - request = [ - 'PUT /api/contacts/10 HTTP/1.1', - 'Content-Type: application/json', - 'Prefer: return=minimal', - '', -'{ - "firstname": "John", - "lastname": "Doe", - "email": "something.else@reseller.invalid", - "city": null, - "company": null, - "country": null, - "phonenumber": null, - "postcode": null, - "street": null -}', - ]; - response = [ - 'HTTP/1.1 204 No Content', - 'Preference-Applied: return=minimal', - ]; - - INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; --%] -

- -Update specific fields of an existing systemcontacts entry -

-[% - cmd = 'curl -i -X PATCH -H \'Connection: close\' --cert NGCP-API-client-certificate.pem --cacert ca-cert.pem \'https://example.org:1443/api/systemcontacts/10 --data-binary \'[ { "op": "replace", "path": "/email", "value": "other.john.doe@reseller.invalid" }, { "op": "replace", "path": "/street", "value": "Some Street" } ]\' -H \'Content-Type: application/json-patch+json\' -H \'Prefer: return=minimal\''; - INCLUDE helpers/api_command.tt cmd=cmd extended=1 level=level+3; - - request = [ - 'PATCH /api/systemcontacts/10 HTTP/1.1', - 'Content-Type: application/json-patch+json', - 'Prefer: return=minimal', - '', -'[ - { - "op": "replace", - "path": "/email", - "value": "other.john.doe@reseller.invalid" - }, - { - "op": "replace", - "path": "/street", - "value": "Some Street" - } -]', - ]; - response = [ - 'HTTP/1.1 204 No Content', - 'Preference-Applied: return=minimal', - ]; - - INCLUDE helpers/api_req_res.tt request=request response=response level=level+3; --%] - -

- Note that for PATCH, the body must be a JSON Array, even if there is only one 'op' entry. -

-

- - -
-[% # vim: set tabstop=4 syntax=html expandtab: -%] diff --git a/share/templates/helpers/api_command.tt b/share/templates/helpers/api_command.tt index c97547eb59..c637f92765 100644 --- a/share/templates/helpers/api_command.tt +++ b/share/templates/helpers/api_command.tt @@ -3,10 +3,10 @@ [% IF extended -%]

- Note that you MUST to pass the following additional headers for this request: + Note that you MUST pass the following additional headers for this request: