blob: 5f11ab88509b9d8bd8f077d9d28162bf0614e91d [file] [log] [blame]
package UI::Cachegroup;
#
# Copyright 2015 Comcast Cable Communications Management, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
#
# a note about locations and cachegroups. This used to be "Location", before we had physical locations in 12M. Very confusing.
# What used to be called a location is now called a "cachegroup" and location is now a physical address, not a group of caches working together.
#
# JvD Note: you always want to put Utils as the first use. Sh*t don't work if it's after the Mojo lines.
use UI::Utils;
use Mojo::Base 'Mojolicious::Controller';
use Data::Dumper;
# Table view
sub index {
my $self = shift;
&navbarpage($self);
}
sub add {
my $self = shift;
$self->stash( fbox_layout => 1, cg_data => {} );
&stash_role($self);
if ( $self->stash('priv_level') < 30 ) {
$self->stash( alertmsg => "Insufficient privileges!" );
$self->redirect_to('/cachegroups');
}
}
sub view {
my $self = shift;
my $mode = $self->param('mode');
my $id = $self->param('id');
$self->stash( cg_data => {} );
my $rs_param = $self->db->resultset('Cachegroup')->search( { id => $id } );
my $data = $rs_param->single;
my $type_id = $self->db->resultset('Cachegroup')->search( { id => $id } )->get_column('type')->single();
my $selected_type = $self->db->resultset('Type')->search( { id => $type_id } )->get_column('name')->single();
my @param_ids = $self->db->resultset('CachegroupParameter')->search( { cachegroup => $id } )->get_column('parameter')->all();
$rs_param = $self->db->resultset('Parameter')->search( { id => { -in => \@param_ids } } );
my @cachegroup_vars;
while ( my $row = $rs_param->next ) {
$self->stash( extra_vars => 1 );
my $var;
$var->{value} = $row->value;
$var->{id} = $row->id;
$var->{name} = $row->name;
my @profiles = $self->db->resultset('ProfileParameter')->search( { parameter => $row->id } )->get_column('profile')->all();
my @cachegroups = $self->db->resultset('CachegroupParameter')->search( { parameter => $row->id } )->get_column('cachegroup')->all();
if ( $#profiles > 0 || $#cachegroups > 1 ) {
$var->{editable} = 0;
}
else {
$var->{editable} = 1;
}
push( @cachegroup_vars, $var );
}
my $parent_name = "NO_PARENT";
if ( defined( $data->parent_cachegroup_id ) ) {
my $parent_id = $data->parent_cachegroup_id;
my $rs = $self->db->resultset('Cachegroup')->search( { id => $parent_id } )->single;
$parent_name = $rs->name;
}
my $secondary_parent_name = "NO_PARENT";
if ( defined( $data->secondary_parent_cachegroup_id ) ) {
my $secondary_parent_id = $data->secondary_parent_cachegroup_id;
my $rs = $self->db->resultset('Cachegroup')->search( { id => $secondary_parent_id } )->single;
$secondary_parent_name = $rs->name;
}
$self->stash(
cachegroup_vars => \@cachegroup_vars,
parent_cachegroup_id => $data->parent_cachegroup_id // -1,
parent_name => $parent_name,
secondary_parent_cachegroup_id => $data->secondary_parent_cachegroup_id // -1,
secondary_parent_name => $secondary_parent_name,
);
# $self->stash( cg_data => $data );
&stash_role($self);
$self->stash( fbox_layout => 1, cg_data => $data, selected_type => $selected_type );
if ( $mode eq "edit" and $self->stash('priv_level') > 20 ) {
$self->render( template => 'cachegroup/edit' );
}
else {
$self->render( template => 'cachegroup/view' );
}
}
# Read
# Note: This sub will be removed soon. It's just here for backward compatibility with current users of /datalocation that still use
# location as the term for cachegroup
sub read {
my $self = shift;
my @data;
my %idnames;
my $orderby = "name";
$orderby = $self->param('orderby') if ( defined $self->param('orderby') );
# Can't figure out how to do the join on the same table
my $rs_idnames = $self->db->resultset("Cachegroup")->search( undef, { columns => [qw/id name/] } );
while ( my $row = $rs_idnames->next ) {
$idnames{ $row->id } = $row->name;
}
my $rs_data = $self->db->resultset("Cachegroup")->search( undef, { prefetch => [ { 'type' => undef, } ], order_by => 'me.' . $orderby } );
while ( my $row = $rs_data->next ) {
if ( defined $row->parent_cachegroup_id ) {
push(
@data, {
"id" => $row->id,
"name" => $row->name,
"short_name" => $row->short_name,
"latitude" => $row->latitude,
"longitude" => $row->longitude,
"last_updated" => $row->last_updated,
"parent_location_id" => $row->parent_cachegroup_id,
"parent_location_name" => $idnames{ $row->parent_cachegroup_id },
"type_id" => $row->type->id,
"type_name" => $row->type->name,
}
);
}
else {
push(
@data, {
"id" => $row->id,
"name" => $row->name,
"short_name" => $row->short_name,
"latitude" => $row->latitude,
"longitude" => $row->longitude,
"last_updated" => $row->last_updated,
"parent_location_id" => $row->parent_cachegroup_id,
"parent_location_name" => undef,
"type_id" => $row->type->id,
"type_name" => $row->type->name,
}
);
}
}
$self->render( json => \@data );
}
# Read
sub readcachegrouptrimmed {
my $self = shift;
my @data;
my %idnames;
my $orderby = "name";
$orderby = $self->param('orderby') if ( defined $self->param('orderby') );
# Can't figure out how to do the join on the same table
my $rs_idnames = $self->db->resultset("Cachegroup")->search( undef, { columns => [qw/id name/] } );
while ( my $row = $rs_idnames->next ) {
$idnames{ $row->id } = $row->name;
}
my $rs_data = $self->db->resultset("Cachegroup")->search( undef, { prefetch => [ { 'type' => undef, } ], order_by => 'me.' . $orderby } );
while ( my $row = $rs_data->next ) {
push( @data, { "name" => $row->name, } );
}
$self->render( json => \@data );
}
# Delete
sub delete {
my $self = shift;
my $id = $self->param('id');
if ( !&is_admin($self) ) {
$self->flash( alertmsg => "No can do. Get more privs." );
}
else {
my $p_name = $self->db->resultset('Cachegroup')->search( { id => $id } )->get_column('name')->single();
my $delete = $self->db->resultset('Cachegroup')->search( { id => $id } );
$delete->delete();
&log( $self, "Delete cachegroup " . $p_name, "UICHANGE" );
}
return $self->redirect_to('/close_fancybox.html');
}
sub check_cachegroup_input {
my $self = shift;
my $sep = "__NEWLINE__"; # the line separator sub that with \n in the .ep javascript
my $err = undef;
# First, check permissions
if ( !&is_oper($self) ) {
$err .= "You do not have enough privileges to modify this." . $sep;
return $err;
}
return $err;
}
# Update
sub update {
my $self = shift;
my $id = $self->param('id');
my $priv_level = $self->stash('priv_level');
my $cachegroup_vars = $self->stash('cachegroup_vars');
my $extra_vars = $self->stash('extra_vars');
my $parent_cachegroup_id = $self->param('cg_data.parent_cachegroup_id') // -1;
my $secondary_parent_cachegroup_id = $self->param('cg_data.secondary_parent_cachegroup_id') // -1;
$self->stash(
id => $id,
fbox_layout => 1,
priv_level => $priv_level,
cachegroup_vars => $cachegroup_vars,
extra_vars => $extra_vars,
cg_data => {
id => $id,
name => $self->param('cg_data.name'),
short_name => $self->param('cg_data.short_name'),
latitude => $self->param('cg_data.latitude'),
longitude => $self->param('cg_data.longitude'),
parent_cachegroup_id => $parent_cachegroup_id,
secondary_parent_cachegroup_id => $secondary_parent_cachegroup_id,
type => $self->param('cg_data.type')
}
);
if ( !$self->isValidCachegroup() ) {
return $self->render( template => 'cachegroup/edit' );
}
# JvD Note: the "cachegroup" parameter in this $self->param is actually the parent_cachegroup_id, because, i'm re-using the
# cachegroup.js functions.
my $err = &check_cachegroup_input($self);
if ( defined($err) ) {
$self->flash( alertmsg => $err );
}
else {
my $update = $self->db->resultset('Cachegroup')->find( { id => $self->param('id') } );
$update->name( $self->param('cg_data.name') );
$update->short_name( $self->param('cg_data.short_name') );
$update->latitude( $self->param('cg_data.latitude') );
$update->longitude( $self->param('cg_data.longitude') );
if ( $parent_cachegroup_id != -1 ) {
$update->parent_cachegroup_id( $self->param('cg_data.parent_cachegroup_id') );
}
else {
$update->parent_cachegroup_id( undef );
}
if ( $secondary_parent_cachegroup_id != -1 ) {
$update->secondary_parent_cachegroup_id( $self->param('cg_data.secondary_parent_cachegroup_id') );
}
else {
$update->secondary_parent_cachegroup_id( undef );
}
$update->type( $self->param('cg_data.type') );
$update->update();
foreach my $param ( $self->param ) {
next unless $param =~ /^param:/;
my $param_id = $param;
$param_id =~ s/^param://;
$update = $self->db->resultset('Parameter')->find( { id => $param_id } );
$update->value( $self->param($param) );
$update->update();
}
# if the update has failed, we don't even get here, we go to the exception page.
}
&log( $self, "Update cachegroup with name:" . $self->param('cg_data.name'), "UICHANGE" );
$self->flash( message => "Successfully updated Cache Group." );
return $self->redirect_to( '/cachegroup/edit/' . $id );
}
# Create
sub create {
my $self = shift;
my $name = $self->param('cg_data.name');
my $short_name = $self->param('cg_data.short_name');
my $latitude = $self->param('cg_data.latitude');
my $longitude = $self->param('cg_data.longitude');
my $cachegroup = $self->param('cg_data.parent_cachegroup_id');
my $type = $self->param('cg_data.type');
my $data = $self->get_cachegroups();
my $cachegroups = $data->{'cachegroups'};
my $short_names = $data->{'short_names'};
if ( !$self->isValidCachegroup() ) {
$self->stash(
fbox_layout => 1,
cg_data => {
name => $name,
short_name => $short_name,
latitude => $latitude,
longitude => $longitude
}
);
return $self->render('cachegroup/add');
}
if ( exists $cachegroups->{$name} ) {
$self->field('cg_data.name')->is_like( qr/^\/(?!$name\/)/i, "The name exists." );
$self->stash(
fbox_layout => 1,
cg_data => {
name => $name,
short_name => $short_name,
latitude => $latitude,
longitude => $longitude
}
);
return $self->render('cachegroup/add');
}
if ( exists $short_names->{$short_name} ) {
$self->field('cg_data.short_name')->is_like( qr/^\/(?!$short_name\/)/i, "The short name exists." );
$self->stash(
fbox_layout => 1,
cg_data => {
name => $name,
short_name => $short_name,
latitude => $latitude,
longitude => $longitude
}
);
return $self->render('cachegroup/add');
}
my $new_id = -1;
my $err = &check_cachegroup_input($self);
if ( defined($err) ) {
return $self->redirect_to( '/cachegroup/edit/' . $new_id );
}
else {
my $parent_cachegroup_id = $cachegroup; # sharing the code in JS for create and edit.
$parent_cachegroup_id = undef if ( $parent_cachegroup_id == -1 );
my $insert = $self->db->resultset('Cachegroup')->create(
{
name => $name,
short_name => $short_name,
latitude => $latitude,
longitude => $longitude,
parent_cachegroup_id => $parent_cachegroup_id,
type => $type,
}
);
$insert->insert();
$new_id = $insert->id;
}
if ( $new_id == -1 ) {
my $referer = $self->req->headers->header('referer');
return $self->redirect_to($referer);
}
else {
&log( $self, "Create cachegroup with name:" . $self->param('cg_data.name'), "UICHANGE" );
$self->flash( message => "Successfully updated Cache Group." );
return $self->redirect_to( '/cachegroup/edit/' . $new_id );
}
}
sub isValidCachegroup {
my $self = shift;
$self->field('cg_data.name')->is_required->is_like( qr/^[0-9a-zA-Z_\.\-]+$/, "Use alphanumeric . or _ ." );
$self->field('cg_data.short_name')->is_required->is_like( qr/^[0-9a-zA-Z_\.\-]+$/, "Use alphanumeric . or _" );
$self->field('cg_data.latitude')->is_required->is_like( qr/^[-]*[0-9]+[.]*[0-9]*/, "Invalid latitude entered." );
$self->field('cg_data.longitude')->is_required->is_like( qr/^[-]*[0-9]+[.]*[0-9]*/, "Invalid latitude entered." );
my $latitude = $self->param('cg_data.latitude');
my $longitude = $self->param('cg_data.longitude');
if ( abs $latitude > 90 ) {
$self->field('cg_data.latitude')->is_required->is_like( qr/^\./, "May not exceed +- 90.0." );
}
if ( abs $longitude > 180 ) {
$self->field('cg_data.longitude')->is_required->is_like( qr/^\./, "May not exceed +- 180.0." );
}
return $self->valid;
}
sub get_cachegroups {
my $self = shift;
my %data;
my %cachegroups;
my %short_names;
my $rs = $self->db->resultset('Cachegroup');
while ( my $cachegroup = $rs->next ) {
$cachegroups{ $cachegroup->name } = $cachegroup->id;
$short_names{ $cachegroup->short_name } = $cachegroup->id;
}
%data = ( cachegroups => \%cachegroups, short_names => \%short_names );
return \%data;
}
1;