#!/usr/bin/perl use strict; use warnings; use NGCP::Test; use Test::More; use JSON qw/from_json to_json/; use Data::Dumper; my $test = NGCP::Test->new(); my $t = $test->generate_sid(); my $c = $test->client(); my $ref = $test->reference_data( client => $c, use_persistent => 1, delete_persistent => 0, depends => [ { resource => 'billingprofiles', hints => [{ name => 'customer billingprofile' }], name => 'my_billprof' }, { resource => 'domains', name => 'my_domain' }, { resource => 'customercontacts', name => 'my_contact' }, { resource => 'customers', name => 'my_foreign_customer', hints => [{ field => 'type', value => 'pbxaccount' }], }, { resource => 'customers', name => 'my_filled_customer', hints => [{ name => 'filled pbxaccount customer' }], }, { resource => 'subscribers', name => 'my_foreign_pilot', hints => [{ name => 'pbx pilot subscriber'}] } ], ); # first, create a pbx customer to work with my $customer_res = $test->resource( client => $c, resource => 'customers', data => { billing_profile_id => $ref->data('my_billprof')->{id}, contact_id => $ref->data('my_contact')->{id}, status => 'active', type => 'pbxaccount', }, autodelete_created_items => 1, ); $customer_res->test_post( name => 'create helper customer', expected_result => { 'code' => 201 } ); my $customer = $customer_res->pop_created_item(); # define a reference subscriber pbx my $sub_res = $test->resource( client => $c, resource => 'subscribers', data => { customer_id => $customer->{id}, domain_id => $ref->data('my_domain')->{id}, username => "user_$t", password => "pass_$t", webusername => "webuser_$t", webpassword => "webpass_$t", # TODO: why do we have to explicitly set this to create a pilot? # should be set automatically on creation of first subscriber # in pbx customer, no? is_pbx_pilot => 0, is_pbx_group => 0, administrative => 0, primary_number => { cc => '43', ac => '999', sn => $t }, pbx_extension => undef, display_name => "Admin Pilot $t", status => 'active', }, #print_summary_on_finish => 1, autodelete_created_items => 1, ); my $num_res = $test->resource( client => $c, resource => 'numbers', ); $sub_res->test_post( name => 'create subscribers', data_replace => [ [ # a pilot with administrative rights { field => 'administrative', value => 1 }, { field => 'is_pbx_pilot', value => 1 }, { field => 'username', value => "pilot_user_$t" }, { field => 'password', value => "pilot_pass_$t" }, { field => 'webusername', value => "pilot_webuser_$t" }, { field => 'webpassword', value => "pilot_webpass_$t" }, { field => 'alias_numbers', value => [map { { cc => '43', ac => '888', sn => sprintf("$t%d", $_) } } (0 .. 9)] } ], [ # an extension with administrative rights { field => 'administrative', value => 1 }, { field => 'primary_number', delete => 1 }, { field => 'pbx_extension', value => '101' }, { field => 'username', value => "subadm_user_$t" }, { field => 'password', value => "subadm_pass_$t" }, { field => 'webusername', value => "subadm_webuser_$t" }, { field => 'webpassword', value => "subadm_webpass_$t" }, ], [ # an extension without rights { field => 'primary_number', delete => 1 }, { field => 'pbx_extension', value => '102' }, { field => 'username', value => "subext_user_$t" }, { field => 'password', value => "subext_pass_$t" }, { field => 'webusername', value => "subext_webuser_$t" }, { field => 'webpassword', value => "subext_webpass_$t" }, ] ], skip_test_fields => [qw/alias_numbers.number_id primary_number.number_id/], expected_result => { code => 201 } ); my $sub_ext = $sub_res->pop_created_item(); my $subadm_ext = $sub_res->pop_created_item(); my $subadm_pilot = $sub_res->pop_created_item(); # time to create clients to access the API with the individual subs my $c_sub_ext = $test->client( role => 'subscriber', username => $sub_ext->{webusername} . '@' . $ref->data('my_domain')->{domain}, password => $sub_ext->{webpassword}, ); my $c_subadm_ext = $test->client( role => 'subscriber', username => $subadm_ext->{webusername} . '@' . $ref->data('my_domain')->{domain}, password => $subadm_ext->{webpassword}, ); my $c_subadm_pilot = $test->client( role => 'subscriber', username => $subadm_pilot->{webusername} . '@' . $ref->data('my_domain')->{domain}, password => $subadm_pilot->{webpassword}, ); my $items; # test working with subscribers with a subscriber without rights { $sub_res->client($c_sub_ext); my $name = 'unprivileged subscriber get'; # remove stuff from reference data which we don't expect in result my @blacklist = (qw/ customer_id contract_id domain_id password webpassword uuid lock status create_timestamp modify_timestamp /); foreach my $k(@blacklist) { delete $sub_ext->{$k}; } $items = $sub_res->test_get( name => $name, item => $sub_ext, expected_links => [qw/ ngcp:reminders ngcp:voicemailsettings ngcp:callforwards ngcp:subscriberpreferences /], expected_fields => [qw/ id domain administrative primary_number alias_numbers pbx_extension display_name email timezone pbx_group_ids is_pbx_pilot is_pbx_group username webusername /], expected_result => { code => 200 } ); # TODO: by configuration, we should control whether passwords are present or not! # check if creating/modifying subscribers is forbidden $sub_res->test_post( name => 'create subscriber without privileges', expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); $sub_res->test_put( name => 'modify-put subscriber without privileges', item => $sub_ext, expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); $sub_res->test_patch( name => 'modify-patch subscriber without privileges', item => $sub_ext, data_replace => { field => 'username', value => 'test', op => 'replace' }, expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); # test fetching numbers $num_res->client($c_sub_ext); $num_res->test_get( name => 'get numbers as unprivileged subscriber', expected_result => { 'code' => 403 } ); # fake a numbers item and fetch it $num_res->test_get( name => 'get numbers item as unprivileged subscriber', item => { id => 999, cc => '43', ac => '999', sn => '999', subscriber_id => $c_sub_ext->{id} }, expected_result => { 'code' => 403 } ); # check if we can't access customers $customer_res->client($c_sub_ext); $customer_res->test_get( name => 'get own customer as unprivileged subscriber', item => $customer, expected_result => { 'code' => 403 } ); $customer_res->test_get( name => 'get foreign customer as unprivileged subscriber', item => $ref->data('my_foreign_customer'), expected_result => { 'code' => 403 } ); } # test working with subscribers with a subscriberadmin { $sub_res->client($c_subadm_ext); my $name = 'subadmin subscriber get'; my @blacklist = (qw/ contract_id domain_id password webpassword uuid lock status create_timestamp modify_timestamp /); foreach my $k(@blacklist) { delete $subadm_ext->{$k}; } # get own subscriber $items = $sub_res->test_get( name => $name, item => $subadm_ext, expected_links => [qw/ ngcp:reminders ngcp:voicemailsettings ngcp:callforwards ngcp:subscriberpreferences ngcp:customers /], expected_result => { code => 200 } ); my $item = pop @{ $items }; foreach my $k(@blacklist) { ok(!exists $item->{$k}, "$name - absence of $k"); $test->inc_test_count(); } # TODO: by configuration, we should control whether passwords are present or not! # TODO: get sub_ext subscriber # TODO: get all subscribers of customer # check if creating/modifying subscribers is ok $sub_res->test_post( name => 'create subscribers as subadmin', data_replace => [ [ # a pilot with administrative rights { field => 'administrative', value => 1 }, { field => 'is_pbx_pilot', value => 1 }, { field => 'username', value => "pilot_user_subadm_$t" }, { field => 'password', value => "pilot_pass_subadm_$t" }, { field => 'webusername', value => "pilot_webuser_subadm_$t" }, { field => 'webpassword', value => "pilot_webpass_subadm_$t" }, ], [ # an extension with administrative rights { field => 'administrative', value => 1 }, { field => 'primary_number', delete => 1 }, { field => 'pbx_extension', value => '201' }, { field => 'username', value => "subadm_user_subadm_$t" }, { field => 'password', value => "subadm_pass_subadm_$t" }, { field => 'webusername', value => "subadm_webuser_subadm_$t" }, { field => 'webpassword', value => "subadm_webpass_subadm_$t" }, ], [ # an extension without rights { field => 'primary_number', delete => 1 }, { field => 'pbx_extension', value => '202' }, { field => 'username', value => "subext_user_subadm_$t" }, { field => 'password', value => "subext_pass_subadm_$t" }, { field => 'webusername', value => "subext_webuser_subadm_$t" }, { field => 'webpassword', value => "subext_webpass_subadm_$t" }, ], [ # an extension in another customer { field => 'primary_number', delete => 1 }, { field => 'pbx_extension', value => '203' }, { field => 'username', value => "subext_user_foreign_$t" }, { field => 'password', value => "subext_pass_foreign_$t" }, { field => 'webusername', value => "subext_webuser_foreign_$t" }, { field => 'webpassword', value => "subext_webpass_foreign_$t" }, { field => 'customer_id', value => $ref->data('my_foreign_customer')->{id} }, ] ], expected_result => [ { code => 422, error_re => 'Customer already has a pbx pilot subscriber.' }, { code => 201 }, { code => 201 }, { code => 201 }, # this must be checked below whether customer_id is properly set ], skip_test_fields => [qw/customer_id/], # ... so don't check explicitly here expected_fields => [qw/ id customer_id domain administrative primary_number alias_numbers pbx_extension display_name email timezone pbx_group_ids is_pbx_pilot is_pbx_group username webusername /], ); $item = $sub_res->pop_created_item(); is($item->{customer_id}, $subadm_ext->{customer_id}, "subscribers - create subscribers as subadmin - foreign customer overridden"); $test->inc_test_count(); my $sub_ext_2 = $item; $sub_res->push_created_item($sub_ext_2); # can we change own subscriber? $sub_res->test_put( name => 'modify-put subscriber as subadmin', item => $subadm_ext, expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); $sub_res->test_patch( name => 'modify-patch subscriber as subadmin', item => $subadm_ext, data_replace => { field => 'username', value => 'test', op => 'replace' }, expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); # can we change other subscriber? $sub_res->test_put( name => 'modify-put other subscriber as subadmin', item => $sub_ext, expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); $sub_res->test_patch( name => 'modify-patch other subscriber as subadmin', item => $sub_ext, data_replace => { field => 'username', value => 'test', op => 'replace' }, expected_result => { code => '403', error_re => 'Read-only resource for authenticated role' }, ); # can we fetch subscriber details of foreign customer? $items = $sub_res->test_get( name => 'fetch subscribers of foreign customer', query_params => [{ customer_id => $ref->data('my_filled_customer')->{id} }], expected_count => 0, expected_result => { code => 200 } ); # TODO: the above should actually return an error instead of an empty customer? # test fetching numbers $num_res->client($c_subadm_ext); $items = $num_res->test_get( name => 'get numbers as privileged subscriber', expected_links => [qw/ngcp:subscribers/], expected_fields => [qw/id ac cc sn subscriber_id is_primary/], skip_test_fields => [qw/is_primary/], # don't check explicitly here expected_result => { 'code' => 200 } ); my $num_item = pop @{ $items }; my ($num_item_primary, $num_item_alias); foreach my $num(@{ $num_item->{_embedded}->{'ngcp:numbers'} }) { if(!$num_item_primary && $num->{is_primary}) { $num_item_primary = $num; } elsif(!$num_item_alias) { $num_item_alias = $num; } last if($num_item_primary && $num_item_alias); } $num_res->test_put( name => 'move primary number from pilot to ext', item => $num_item_primary, data_replace => {field => 'subscriber_id', value => $sub_ext->{id}}, expected_result => { code => 422, error_re => 'Cannot reassign primary number'}, ); $num_res->test_put( name => 'move alias number from pilot to ext', item => $num_item_alias, data_replace => {field => 'subscriber_id', value => $sub_ext->{id}}, expected_result => { code => 200 }, ); $num_res->test_put( name => 'move alias number from ext to ext', item => $num_item_alias, data_replace => {field => 'subscriber_id', value => $sub_ext_2->{id}}, expected_result => { code => 200 }, ); $num_res->test_put( name => 'move alias number from ext to pilot', item => $num_item_alias, data_replace => {field => 'subscriber_id', value => $subadm_ext->{id}}, expected_result => { code => 200 }, ); $num_res->client($c_sub_ext); $items = $num_res->test_get( name => 'individual number fetch as ext', item => $num_item_alias, expected_result => { code => 403 } ); $num_res->client($c_subadm_ext); # move back to ext again, and check if it's moved to pilot on ext termination $num_res->test_put( name => 'move alias number from pilot to ext again', item => $num_item_alias, data_replace => {field => 'subscriber_id', value => $sub_ext->{id}}, expected_result => { code => 200 } ); $sub_res->client($c_sub_ext); $sub_res->test_delete( name => 'terminate extension as unprivileged sub', item => $sub_ext_2, expected_result => { code => 403 } ); $sub_res->client($c_subadm_ext); $sub_res->test_delete( name => 'terminate extension as subadmin', item => $sub_ext, expected_result => { code => 204 } ); $items = $num_res->test_get( name => 'number assignment after ext delete', item => $num_item_alias, expected_links => [qw/ngcp:subscribers/], expected_result => { code => 200 } ); $item = pop @{ $items }; is($item->{subscriber_id}, $subadm_pilot->{id}, "subscribers - number subscriber after ext delete"); $test->inc_test_count; # test deletion of own subscriber $sub_res->test_delete( name => 'terminate own subadmin as subadmin', item => $subadm_ext, expected_result => { code => 403, error_re => 'Cannot terminate own subscriber' } ); # test deletion of pilot subscriber $sub_res->test_delete( name => 'terminate pilot subscriber as subadmin', item => $subadm_pilot, expected_result => { code => 403, error_re => 'Cannot terminate pilot subscriber' } ); # can we (not) move number to foreign sub? $num_res->test_put( name => 'move number to foreign subscriber', item => $num_item_alias, data_replace => { field => 'subscriber_id', value => $ref->data('my_foreign_pilot')->{id}}, expected_result => { code => 422, error_re => "Invalid 'subscriber_id', does not exist" } ); # check if we can access own customer but not foreign $customer_res->client($c_subadm_ext); $customer_res->test_get( name => 'get own customer as privileged subscriber', item => $customer, expected_links => [], expected_result => { 'code' => 200 }, ); $customer_res->test_get( name => 'get foreign customer as privileged subscriber', item => $ref->data('my_foreign_customer'), expected_result => { 'code' => 403 } ); } # TODO: more tests for unprivileged subscriber! $sub_res->push_created_item($subadm_pilot); $sub_res->push_created_item($subadm_ext); $customer_res->push_created_item($customer); $sub_res->client($c); $customer_res->client($c); $test->done();