TT#81012 ngcp-provisioning-template: allow templates from DB

Change-Id: I59ef2d3c9aaf5723e30725d1c2a9a1d22776236f
changes/22/39922/6
Rene Krenn 6 years ago
parent 10415a55f6
commit 722d3ad976

@ -12,8 +12,6 @@ use NGCP::Panel::Utils::DateTime qw();
use NGCP::Panel::Utils::ProvisioningTemplates qw();
use NGCP::Panel::Form::ProvisioningTemplate::Admin qw();
use NGCP::Panel::Form::ProvisioningTemplate::Reseller qw();
use URI::Encode qw();
use YAML::XS qw();
sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) :AllowedRole(ccareadmin) :AllowedRole(ccare) {
my ($self, $c) = @_;
@ -27,48 +25,7 @@ sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRol
sub template_list :Chained('/') :PathPart('batchprovisioning') :CaptureArgs(0) {
my ( $self, $c ) = @_;
my $templates = { %{$c->config->{provisioning_templates} // {}} };
map {
$templates->{$_}->{name} = $_;
$templates->{$_}->{static} = 1;
$templates->{$_}->{id} = undef;
$templates->{$_}->{reseller} = undef;
} keys %$templates;
my $rs = $c->model('DB')->resultset('provisioning_templates')->search_rs();
if($c->user->roles eq "admin" || $c->user->roles eq "ccareadmin") {
} elsif($c->user->roles eq "reseller" || $c->user->roles eq "ccare") {
$rs = $rs->search_rs({ -or => [
reseller_id => $c->user->reseller_id,
reseller_id => undef
], },);
} else {
$rs = $rs->search_rs({ -or => [
reseller_id => $c->user->contract->contact->reseller_id,
reseller_id => undef
], },);
}
$c->stash->{template_rs} = $rs;
foreach my $db_template ($rs->all) {
my $template = { $db_template->get_inflated_columns };
eval {
%$template = ( %{YAML::XS::Load($template->{yaml})}, %$template );
#use Data::Dumper;
#$c->log->error(Dumper($template));
delete $template->{yaml};
};
if ($@) {
$c->log->error("error parsing provisioning_template id $template->{id} '$template->{name}': " . $@);
next;
}
$template->{static} = 0;
if ($db_template->reseller) {
$template->{reseller} = $db_template->reseller->name;
}
$templates->{$template->{name}} = $template;
}
$c->stash->{provisioning_templates} = $templates;
NGCP::Panel::Utils::ProvisioningTemplates::load_template_map($c);
$c->stash->{template_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
{ name => "id", search => 1, title => $c->loc('#') },
@ -96,8 +53,7 @@ sub ajax :Chained('template_list') :PathPart('ajax') :Args(0) {
sub template_base :Chained('template_list') :PathPart('templates') :CaptureArgs(1) {
my ( $self, $c, $template ) = @_;
my $decoder = URI::Encode->new;
$template = $decoder->decode($template);
$template = pack('H*',$template);
$c->stash->{provisioning_template_name} = $template;
if (exists $c->stash->{provisioning_templates}->{$template}) {
if ($c->stash->{provisioning_templates}->{$template}->{id}) {
@ -108,7 +64,7 @@ sub template_base :Chained('template_list') :PathPart('templates') :CaptureArgs(
NGCP::Panel::Utils::Message::error(
c => $c,
data => { id => $c->stash->{provisioning_templates}->{$template}->{id} },
desc => $c->loc('Provisioning templates does not exist!'),
desc => $c->loc('Provisioning template does not exist!'),
);
$c->response->redirect($c->uri_for_action('/batchprovisioning/root'));
return;
@ -118,7 +74,7 @@ sub template_base :Chained('template_list') :PathPart('templates') :CaptureArgs(
NGCP::Panel::Utils::Message::error(
c => $c,
data => { name => $template },
desc => $c->loc('Provisioning templates does not exist!'),
desc => $c->loc('Provisioning template does not exist!'),
);
$c->response->redirect($c->uri_for_action('/batchprovisioning/root'));
return;
@ -129,7 +85,7 @@ sub do_template_form :Chained('template_base') :PathPart('form') :Args(0) {
my ($self, $c) = @_;
$c->stash(create_flag => 1);
$c->stash(modal_title => $c->loc("Subscriber with Provisioning Template '[_1]'", $c->stash->{provisioning_template_name}));
$c->stash(modal_title => $c->loc("Subscriber using Provisioning Template '[_1]'", $c->stash->{provisioning_template_name}));
$c->log->debug($c->stash->{provisioning_template_name});
$c->log->debug($c->uri_for_action('/batchprovisioning/root'));
@ -199,7 +155,7 @@ sub do_template_upload :Chained('template_base') :PathPart('upload') :Args(0) {
}
$c->stash(create_flag => 1);
$c->stash(modal_title => $c->loc("Subscribers with Provisioning Template '[_1]' from CSV", $c->stash->{provisioning_template_name}));
$c->stash(modal_title => $c->loc("Subscribers using Provisioning Template '[_1]' from CSV", $c->stash->{provisioning_template_name}));
$c->stash(form => $form);
}
@ -259,7 +215,8 @@ sub create :Chained('template_list') :PathPart('create') :Args(0) {
desc => $c->loc('Failed to create provisioning template'),
);
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/batchprovisioning'));
#NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/batchprovisioning'));
$c->response->redirect($c->uri_for_action('/batchprovisioning/root'));
}
$c->stash(create_flag => 1);
@ -334,7 +291,8 @@ sub edit :Chained('template_base') :PathPart('edit') :Args(0) {
desc => $c->loc('Failed to update provisioning template'),
);
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/batchprovisioning'));
#NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/batchprovisioning'));
$c->response->redirect($c->uri_for_action('/batchprovisioning/root'));
}
$c->stash(edit_flag => 1 );
$c->stash(modal_title => $c->loc("Provisioning Template"));
@ -372,7 +330,8 @@ sub remove :Chained('template_base') :PathPart('remove') :Args(0) {
desc => $c->loc('Failed to remove provisioning template'),
);
};
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/batchprovisioning'));
#NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/batchprovisioning'));
$c->response->redirect($c->uri_for_action('/batchprovisioning/root'));
}
1;

@ -61,7 +61,7 @@ has_field 'yaml' => (
element_class => [qw/ngcp-provtemplate-area/],
default => <<'EOS_DEFAULT_YAML',
fields:
- name: fields
- name: first_name
label: "First Name:"
type: Text
required: 1
@ -147,16 +147,30 @@ sub validate_yaml {
}
sub validate_name {
my ($self, $field) = @_;
sub validate {
my ($self) = @_;
my $c = $self->ctx;
return unless $c;
my $field = $self->field('name');
my $resource = Storable::dclone($self->values);
if (defined $resource->{reseller}) {
$resource->{reseller_id} = $resource->{reseller}{id};
delete $resource->{reseller};
} else {
$resource->{reseller_id} = ($c->user->is_superuser ? undef : $c->user->reseller_id);
}
my $reseller;
$reseller = $c->model('DB')->resultset('resellers')->find($resource->{reseller_id}) if $resource->{reseller_id};
my $template = $field->value;
$template = ($reseller->name . '/' . $template) if $reseller;
#$c->log->warn("test: ".$template);
if (not defined $c->stash->{old_name}
or $c->stash->{old_name} ne $field->value) {
or $c->stash->{old_name} ne $template) {
$field->add_error("a provisioning template with name '" . $field->value . "' already exists")
if exists $c->stash->{provisioning_templates}->{$field->value};
if exists $c->stash->{provisioning_templates}->{$template};
}
}

@ -20,6 +20,7 @@ $Data::Dumper::Sortkeys = sub {
return \@keys;
};
use Text::CSV_XS qw();
use YAML::XS qw();
use NGCP::Panel::Utils::DateTime qw();
use NGCP::Panel::Utils::BillingMappings qw();
use NGCP::Panel::Utils::Contract qw();
@ -81,6 +82,55 @@ foreach my $sub (@DISABLED_CORE_FUNCTIONS) {
my $JS_ENV = '';
sub load_template_map {
my $c = shift;
my $templates = { %{$c->config->{provisioning_templates} // {}} };
map {
$templates->{$_}->{name} = $_;
$templates->{$_}->{static} = 1;
$templates->{$_}->{id} = undef;
$templates->{$_}->{reseller} = undef;
} keys %$templates;
my $rs = $c->model('DB')->resultset('provisioning_templates')->search_rs();
if($c->user->roles eq "admin" || $c->user->roles eq "ccareadmin") {
} elsif($c->user->roles eq "reseller" || $c->user->roles eq "ccare") {
$rs = $rs->search_rs({ -or => [
reseller_id => $c->user->reseller_id,
reseller_id => undef
], },);
} else {
$rs = $rs->search_rs({ -or => [
reseller_id => $c->user->contract->contact->reseller_id,
reseller_id => undef
], },);
}
$c->stash->{template_rs} = $rs;
foreach my $db_template ($rs->all) {
my $template = { $db_template->get_inflated_columns };
eval {
%$template = ( %{YAML::XS::Load($template->{yaml})}, %$template );
#use Data::Dumper;
#$c->log->error(Dumper($template));
delete $template->{yaml};
};
if ($@) {
$c->log->error("error parsing provisioning_template id $template->{id} '$template->{name}': " . $@);
next;
}
$template->{static} = 0;
if ($db_template->reseller) {
$template->{reseller} = $db_template->reseller->name;
$templates->{$template->{reseller} . '/' . $template->{name}} = $template;
} else {
$templates->{$template->{name}} = $template;
}
}
$c->stash->{provisioning_templates} = $templates;
}
sub create_provisioning_template_form {
my %params = @_;

@ -12,6 +12,13 @@ $( document ).ready(function() {
});
}
});
function toHex(str) {
var result = '';
for (var i=0; i<str.length; i++) {
result += str.charCodeAt(i).toString(16);
}
return result;
}
</script>
[% site_config.title = c.loc('Batch Provisioning') -%]
@ -32,10 +39,10 @@ $( document ).ready(function() {
UNLESS c.user.read_only;
helper.dt_buttons = [
{ name = c.loc('Delete'), condition = "full.static == 0", uri = "/batchprovisioning/templates/'+encodeURI(full.name)+'/remove", class = 'btn-small btn-secondary', icon = 'icon-remove' },
{ name = c.loc('Edit'), condition = "full.static == 0", uri = "/batchprovisioning/templates/'+encodeURI(full.name)+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = c.loc('Open Form'), uri = "/batchprovisioning/templates/'+encodeURI(full.name)+'/form", class = 'btn-small btn-tertiary', icon = 'icon-list' },
{ name = c.loc('Upload CSV'), uri = "/batchprovisioning/templates/'+encodeURI(full.name)+'/upload", class = 'btn-small btn-tertiary', icon = 'icon-star' },
{ name = c.loc('Delete'), condition = "full.static == 0", uri = "/batchprovisioning/templates/'+toHex((full.reseller ? full.reseller + '/' : '') + full.name)+'/remove", no_back = 1, class = 'btn-small btn-secondary', icon = 'icon-remove' },
{ name = c.loc('Edit'), condition = "full.static == 0", uri = "/batchprovisioning/templates/'+toHex((full.reseller ? full.reseller + '/' : '') + full.name)+'/edit", no_back = 1, class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = c.loc('Open Form'), uri = "/batchprovisioning/templates/'+toHex((full.reseller ? full.reseller + '/' : '') + full.name)+'/form", no_back = 1, class = 'btn-small btn-tertiary', icon = 'icon-list' },
{ name = c.loc('Upload CSV'), uri = "/batchprovisioning/templates/'+toHex((full.reseller ? full.reseller + '/' : '') + full.name)+'/upload", no_back = 1, class = 'btn-small btn-tertiary', icon = 'icon-star' },
];
helper.top_buttons = [
{ name = c.loc('Create Provisioning Template'), uri = c.uri_for_action('/batchprovisioning/create'), icon = 'icon-star' },

@ -150,7 +150,7 @@ $(document).ready(function() {
IF button.uri.search('\?');
separator = '&';
END;
IF !( button.uri.search('[\?\&]back=|^javascript:') );
IF !( button.no_back or button.uri.search('[\?\&]back=|^javascript:') );
button.uri = button.uri _ separator _ 'back=' _ backuri;
END;
IF button.condition;

@ -53,11 +53,9 @@ GetOptions(
pod2usage(1) if $help;
my %mock_objs = ();
my $c = _create_c();
my $templates = ($c->config->{provisioning_templates} // {});
if (exists $templates->{$template_name}) {
NGCP::Panel::Utils::ProvisioningTemplates::load_template_map($c);
if (exists $c->stash->{'provisioning_templates'}->{$template_name}) {
$c->stash->{'provisioning_template_name'} = $template_name;
$c->stash->{'provisioning_templates'} = $templates;
map { $templates->{$_}->{name} = $_; } keys %$templates;
my $fields = NGCP::Panel::Utils::ProvisioningTemplates::get_fields($c,0);
my $values = { map { $_ => undef; } grep { $_ ne 'purge'; } keys %$fields };
@ -312,11 +310,13 @@ ngcp-provisioning-template - Create subscribers with detailed settings according
=head1 SYNOPSIS
ngcp-provisioning-template <provisioning template name> [options]
B<ngcp-provisioning-template> I<provisioning-template-name> [I<options>]
B<ngcp-provisioning-template> I<reseller-name>B</>I<provisioning-template-name> [I<options>]
=head1 DESCRIPTION
B<This program> This program allows to run a 'provisioning template' defined in config.yml. This will produce a
B<This program> This program allows to run a 'provisioning template' from database or config.yml. This will produce a
subscriber setup including required billing contact, contract, preferences, etc. from an input form defined by that
template. The form fields can be passed as command line options.
@ -328,27 +328,27 @@ template. The form fields can be passed as command line options.
Print a brief help message and exits.
=item B<--db_host>
=item B<--db_host=>I<db-host-IP-address>
The host of the ngcp database to connect to. If omitted, the database connection settings of ngcp-panel will be used.
=item B<--db_port>
=item B<--db_port=>I<db-host-port>
The port of the ngcp database to connect to. Only relevant if --db_host is specified.
=item B<--db_user>
=item B<--db_user=>I<db-username>
The database user for the ngcp database to connect to. Only relevant if --db_host is specified.
=item B<--db_password>
=item B<--db_password=>I<db-password>
The the database user passowrd (if any) for the ngcp database to connect to. Only relevant if --db_host is specified.
The the database user password (if any) for the ngcp database to connect to. Only relevant if --db_host is specified.
=item B<--file>
=item B<--file=>I<.csv-filename>
Specify a .csv file to process. Each row repesent form values for one subscriber to create.
=item B<--first_name>
=item B<--first_name=>I<first-name>
Provide the value for a form field "first_name" (if you have such in your provisioning template). Only relevant if no --file is specified.
@ -366,7 +366,11 @@ Verbosity of printed messages while processing (degug, info, error).
ngcp-provisioning-template "My First Provisioning Template" --first_name="John" --last_name="Doe" --cc="43" --ac="316" --sn="123456" --purge
ngcp-provisioning-template "My First Provisioning Template" --file="subscriberdata.csv" --purge
... runs "My First Provisioning Template" from config.yml using first_name "John", last_name "Doe" etc.
ngcp-provisioning-template "Reseller1/Provisioning Template 1" --file="subscriberdata.csv" --purge
... runs "Provisioning Template 1" of "Reseller1" for each row in "subscriberdata.csv"
=head1 AUTHOR

Loading…
Cancel
Save