MT#59662 enhance subscriber assigned header rules/sets handling

* POST /api/headerrules now supports either 'set_id' or 'subscriber_id'.
  When 'subsriber_id' is specified, a subscriber assigned header rule
  set is automatically created if it does not exist, as well as
  automatically removed when its last header rule is deleted.
* It is now possible to directly GET and DELETE /api/headerrules/:id
  where :id is a subscriber assigned header rule.
* It is now possible to directly GET and DELETE /api/headerrulesets/:id
  where :id is a subscriber assigned header rule set.
* Improve /api/headerrules data validation and duplicate header rule
  detection.
* It is now possible to expand by /api/headerrules/?expand=set_id field

Change-Id: I681bc61c2eed47a8e54847f07f31134f643930c2
mr12.3
Kirill Solomko 1 year ago
parent 1fb8d04136
commit aef4c89197

@ -39,7 +39,7 @@ sub query_params {
}, },
{ {
param => 'subscriber_id', param => 'subscriber_id',
description => 'Filter for header rule sets of a specific subscriber', description => 'Filter for header rules of a specific subscriber',
} }
]; ];
} }
@ -49,10 +49,46 @@ sub create_item {
my $item; my $item;
my $schema = $c->model('DB'); my $schema = $c->model('DB');
try { try {
my $header_actions = delete $resource->{actions}; my $header_actions = delete $resource->{actions};
my $header_conditions = delete $resource->{conditions}; my $header_conditions = delete $resource->{conditions};
my $subscriber_id = delete $resource->{subscriber_id};
my $set;
if ($subscriber_id) {
my $sub = $schema->resultset('voip_subscribers')->find($subscriber_id);
my $prov_sub = $sub->provisioning_voip_subscriber;
my $reseller_id = $sub->contract->contact->reseller_id;
$set = $schema->resultset('voip_header_rule_sets')->search({
subscriber_id => $prov_sub->id,
})->first;
unless ($set) {
$set = $schema->resultset('voip_header_rule_sets')->create({
name => 'subscriber_'.$subscriber_id,
subscriber_id => $prov_sub->id,
reseller_id => $reseller_id,
description => '',
});
}
$resource->{set_id} = $set->id;
} else {
$set = $schema->resultset('voip_header_rule_sets')->find($resource->{set_id});
}
my $existing_item = $schema->resultset('voip_header_rules')->search({
name => $resource->{name},
set_id => $set->id,
})->first;
if ($existing_item) {
$c->log->error("header rule with name '$$resource{name}' already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Header rule with this name already exists");
return;
}
$item = $schema->resultset('voip_header_rules')->create($resource); $item = $schema->resultset('voip_header_rules')->create($resource);
if ($header_actions) { if ($header_actions) {
foreach my $action (@$header_actions) { foreach my $action (@$header_actions) {
$action->{rule_id} = $item->id; $action->{rule_id} = $item->id;
@ -65,6 +101,7 @@ sub create_item {
my $action_result = $schema->resultset('voip_header_rule_actions')->create($action); my $action_result = $schema->resultset('voip_header_rule_actions')->create($action);
} }
} }
if ($header_conditions) { if ($header_conditions) {
foreach my $condition (@$header_conditions) { foreach my $condition (@$header_conditions) {
$condition->{rule_id} = $item->id; $condition->{rule_id} = $item->id;
@ -77,6 +114,7 @@ sub create_item {
my $condition_result = $schema->resultset('voip_header_rule_conditions')->create($condition); my $condition_result = $schema->resultset('voip_header_rule_conditions')->create($condition);
} }
} }
NGCP::Panel::Utils::HeaderManipulations::invalidate_ruleset( NGCP::Panel::Utils::HeaderManipulations::invalidate_ruleset(
c => $c, set_id => $item->ruleset->id c => $c, set_id => $item->ruleset->id
); );

@ -32,9 +32,18 @@ sub get_journal_methods {
sub delete_item { sub delete_item {
my ($self, $c, $item) = @_; my ($self, $c, $item) = @_;
my $set_id = $item->ruleset->id; my $ruleset = $item->ruleset;
my $set_id = $ruleset->id;
my $subscriber_id = $ruleset->subscriber_id;
my $res = $self->SUPER::delete_item($c, $item); my $res = $self->SUPER::delete_item($c, $item);
if ($ruleset->subscriber_id) {
$ruleset->discard_changes;
if (!$ruleset->voip_header_rules->count()) {
$ruleset->delete;
}
}
NGCP::Panel::Utils::HeaderManipulations::invalidate_ruleset( NGCP::Panel::Utils::HeaderManipulations::invalidate_ruleset(
c => $c, set_id => $set_id c => $c, set_id => $set_id
); );

@ -5,10 +5,23 @@ extends 'NGCP::Panel::Form::Header::Rule';
has_field 'set_id' => ( has_field 'set_id' => (
type => 'PosInteger', type => 'PosInteger',
required => 1, required => 0,
element_attr => { element_attr => {
rel => ['tooltip'], rel => ['tooltip'],
title => ['Header rule set id, one the rule must belong to.'], title => ['Header rule set id, one the rule must belong to.'],
expand => {
class => 'NGCP::Panel::Role::API::HeaderRuleSets',
allowed_roles => [qw(admin reseller)],
},
},
);
has_field 'subscriber_id' => (
type => 'PosInteger',
required => 0,
element_attr => {
rel => ['tooltip'],
title => ['Subscriber id, to create a subscriber assigned header rule.'],
}, },
); );

@ -28,7 +28,7 @@ sub get_form {
} }
sub _item_rs { sub _item_rs {
my ($self, $c, $type) = @_; my ($self, $c, $by_id) = @_;
my $item_rs; my $item_rs;
if ($c->user->roles eq "admin") { if ($c->user->roles eq "admin") {
@ -43,20 +43,26 @@ sub _item_rs {
); );
$item_rs = $item_rs->search_rs( $item_rs = $item_rs->search_rs(
{ subscriber_id => $prov_subscriber_id }); { subscriber_id => $prov_subscriber_id });
} else { } elsif (!$by_id) {
$item_rs = $item_rs->search_rs( $item_rs = $item_rs->search_rs(
{ subscriber_id => undef }); { subscriber_id => undef });
} }
return $item_rs; return $item_rs;
} }
sub item_by_id {
my ($self, $c, $id) = @_;
my $item_rs = $self->item_rs($c, 1);
return $item_rs->find($id);
}
sub post_process_hal_resource { sub post_process_hal_resource {
my ($self, $c, $item, $resource, $form) = @_; my ($self, $c, $item, $resource, $form) = @_;
if ($resource->{subscriber_id}) { if ($resource->{subscriber_id}) {
my $subscriber_id = NGCP::Panel::Utils::Subscriber::prov_to_billing_subscriber_id( my $subscriber_id = NGCP::Panel::Utils::Subscriber::prov_to_billing_subscriber_id(
c => $c, subscriber_id => $resource->{subscriber_id} c => $c, subscriber_id => $resource->{subscriber_id}
); );
$resource->{subscriber_id} = $subscriber_id // 0; $resource->{subscriber_id} = $subscriber_id // undef;
} }
return $resource; return $resource;
} }

@ -21,13 +21,12 @@ sub config_allowed_roles {
} }
sub _item_rs { sub _item_rs {
my ($self, $c, $type) = @_; my ($self, $c, $by_id) = @_;
my $item_rs = $c->model('DB')->resultset('voip_header_rules')->search_rs(undef, { my $item_rs = $c->model('DB')->resultset('voip_header_rules')->search_rs(undef, {
join => 'ruleset' join => 'ruleset'
}); });
if ($c->user->roles eq "reseller") { if ($c->user->roles eq "reseller") {
$item_rs = $c->model('DB')->resultset('voip_header_rules')->search_rs({ $item_rs = $c->model('DB')->resultset('voip_header_rules')->search_rs({
'ruleset.reseller_id' => $c->user->reseller_id, 'ruleset.reseller_id' => $c->user->reseller_id,
@ -40,7 +39,7 @@ sub _item_rs {
); );
$item_rs = $item_rs->search_rs( $item_rs = $item_rs->search_rs(
{ 'ruleset.subscriber_id' => $prov_subscriber_id }); { 'ruleset.subscriber_id' => $prov_subscriber_id });
} else { } elsif (!$by_id) {
$item_rs = $item_rs->search_rs( $item_rs = $item_rs->search_rs(
{ 'ruleset.subscriber_id' => undef }); { 'ruleset.subscriber_id' => undef });
} }
@ -48,6 +47,12 @@ sub _item_rs {
return $item_rs; return $item_rs;
} }
sub item_by_id {
my ($self, $c, $id) = @_;
my $item_rs = $self->item_rs($c, 1);
return $item_rs->find($id);
}
sub get_form { sub get_form {
my ($self, $c) = @_; my ($self, $c) = @_;
return ( NGCP::Panel::Form::get("NGCP::Panel::Form::Header::RuleAPI", $c) ); return ( NGCP::Panel::Form::get("NGCP::Panel::Form::Header::RuleAPI", $c) );
@ -64,8 +69,8 @@ sub check_resource {
my ($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_; my ($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
my $schema = $c->model('DB'); my $schema = $c->model('DB');
unless (defined $resource->{set_id}) { unless ($resource->{set_id} || $resource->{subscriber_id}) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Required: 'set_id'"); $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Required: 'set_id' or 'subscriber_id'");
return; return;
} }
@ -74,6 +79,7 @@ sub check_resource {
$reseller_id = $c->user->reseller_id; $reseller_id = $c->user->reseller_id;
} }
if ($resource->{set_id}) {
my $ruleset = $schema->resultset('voip_header_rule_sets')->find({ my $ruleset = $schema->resultset('voip_header_rule_sets')->find({
id => $resource->{set_id}, id => $resource->{set_id},
($reseller_id ? (reseller_id => $reseller_id) : ()), ($reseller_id ? (reseller_id => $reseller_id) : ()),
@ -82,8 +88,24 @@ sub check_resource {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'set_id'."); $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'set_id'.");
return; return;
} }
$c->stash->{checked}->{ruleset} = $ruleset; $c->stash->{checked}->{ruleset} = $ruleset;
}
if ($resource->{subscriber_id}) {
my $sub = $schema->resultset('voip_subscribers')->find({
id => $resource->{subscriber_id},
status => { '!=' => 'terminated' },
($reseller_id
? ('contract.contact.reseller_id' => $reseller_id)
: ()),
},{
join => { 'contract' => 'contact' },
});
unless ($sub) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id'");
return;
}
}
return 1; return 1;
} }

Loading…
Cancel
Save