From c21aa55124b0a8eb5a2479424d256ab94889a3f9 Mon Sep 17 00:00:00 2001 From: Irina Peshinskaya Date: Mon, 13 Aug 2018 08:46:52 +0200 Subject: [PATCH] TT#41620 Use static banned data in datatables Change-Id: I573517e96784ab3970facffa2deebddbbca8d73f --- lib/NGCP/Panel/Controller/Security.pm | 35 ++++++-- lib/NGCP/Panel/Utils/Datatables.pm | 42 +++++++-- .../js/libs/bootstrap/datatables-paging.js | 26 ++++-- share/templates/helpers/datatables.tt | 28 +++--- share/templates/security/list.tt | 88 ++++++++----------- 5 files changed, 136 insertions(+), 83 deletions(-) diff --git a/lib/NGCP/Panel/Controller/Security.pm b/lib/NGCP/Panel/Controller/Security.pm index e20e3f7c13..1c3212bfcf 100644 --- a/lib/NGCP/Panel/Controller/Security.pm +++ b/lib/NGCP/Panel/Controller/Security.pm @@ -21,19 +21,44 @@ sub root :PathPart('/') :CaptureArgs(0) { my ( $self, $c ) = @_; } -sub security_index :Chained('/') :PathPart('security') :Args(0) { +sub base :Chained('/') :PathPart('security') :CaptureArgs(0) { my ( $self, $c ) = @_; - my $ips = NGCP::Panel::Utils::Security::list_banned_ips($c); - my $users = NGCP::Panel::Utils::Security::list_banned_users($c); + $c->stash->{bannedips_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "ip", search => 1, title => $c->loc("IP") }, + ]); + $c->stash->{bannedusers_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => "username", search => 1, title => $c->loc("User") }, + { name => "auth_count", title => $c->loc("Fail Count") }, + { name => "last_auth", search => 1, title => $c->loc("Last Attemp") }, + ]); $c->stash( template => 'security/list.tt', - banned_ips => $ips, - banned_users => $users, ); } +sub security :Chained('base') :PathPart('') :Args(0) { +} + +sub ip_list :Chained('base') :PathPart('ip') :Args(0) { + my ($self, $c) = @_; + my $ips = NGCP::Panel::Utils::Security::list_banned_ips($c); + + NGCP::Panel::Utils::Datatables::process_static_data($c, $ips, $c->stash->{bannedips_dt_columns}); + $c->detach($c->view('JSON')); + return; +} + +sub user_list :Chained('base') :PathPart('user') :Args(0) { + my ($self, $c) = @_; + my $users = NGCP::Panel::Utils::Security::list_banned_users($c); + + NGCP::Panel::Utils::Datatables::process_static_data($c, $users, $c->stash->{bannedusers_dt_columns}); + $c->detach($c->view('JSON')); + return; +} + sub ip_base :Chained('/') :PathPart('security/ip') :CaptureArgs(1) { my ( $self, $c, $ip ) = @_; my $decoder = URI::Encode->new; diff --git a/lib/NGCP/Panel/Utils/Datatables.pm b/lib/NGCP/Panel/Utils/Datatables.pm index ad867292cc..7ebbbdb5f1 100644 --- a/lib/NGCP/Panel/Utils/Datatables.pm +++ b/lib/NGCP/Panel/Utils/Datatables.pm @@ -251,9 +251,21 @@ sub process { } } + if (keys %{ $aggregations }) { + $c->stash(dt_custom_footer => $aggregations); + } + + add_arbitrary_data($c, $aaData, $params->{topData}, $cols, $row_func, $params); + + expose_data($c, $aaData, $totalRecords, $displayRecords); + +} + +sub add_arbitrary_data { + my ($c, $aaData, $topData, $cols, $row_func, $params) = @_; # show any arbitrary data rows on top, just like a union would do # hash is expected or array of hashes expected - my $topData = $params->{topData}; + my $user_tz = $params->{user_tz} // $c->session->{user_tz}; if (defined $topData) { my $topDataArray; if (ref $topData eq 'HASH') { @@ -268,26 +280,40 @@ sub process { } } } +} - if (keys %{ $aggregations }) { - $c->stash(dt_custom_footer => $aggregations); - } +sub expose_data { + my($c, $aaData, $totalRecords, $displayRecords) = @_; $c->stash( aaData => $aaData, iTotalRecords => $totalRecords, iTotalDisplayRecords => $displayRecords, sEcho => int($c->request->params->{sEcho} // 1), ); +} +sub process_static_data { + my ($c, $data, $cols, $row_func, $params) = @_; + $params //= {}; + + foreach my $field (qw/total_row_func/) { + #todo: error here about unsupported functionality + } + + my $aaData = []; + add_arbitrary_data($c, $aaData, $data, $cols, $row_func, $params); + my $totalRecords = scalar @$aaData; + my $displayRecords = $totalRecords; + expose_data($c, $aaData, $totalRecords, $displayRecords); } sub set_columns { my ($c, $cols) = @_; - for my $c(@{ $cols }) { - next if defined $c->{accessor}; - $c->{accessor} = $c->{name}; - $c->{accessor} =~ s/\./_/g; + for my $col(@{ $cols }) { + next if defined $col->{accessor}; + $col->{accessor} = $col->{name}; + $col->{accessor} =~ s/\./_/g; } return $cols; } diff --git a/share/static/js/libs/bootstrap/datatables-paging.js b/share/static/js/libs/bootstrap/datatables-paging.js index 4321650018..6a915734ca 100644 --- a/share/static/js/libs/bootstrap/datatables-paging.js +++ b/share/static/js/libs/bootstrap/datatables-paging.js @@ -60,9 +60,17 @@ $.fn.dataTableExt.oPagination.bootstrap = { // Update stateful properties this.fnUpdateState(oSettings); - var totalPages = Math.ceil(oSettings._iRecordsDisplay / oSettings._iDisplayLength); - - if (oSettings._iCurrentPage === 1) { + //var totalPages = Math.ceil(oSettings._iRecordsDisplay / oSettings._iDisplayLength); + var totalPages = Math.ceil(oSettings.fnRecordsTotal() / oSettings._iDisplayLength), + filteredPages = Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength), + iCurrentPage = oSettings._iCurrentPage; + if (totalPages > filteredPages) { + totalPages = filteredPages; + } + if (iCurrentPage > filteredPages && filteredPages > 0) { + iCurrentPage = filteredPages; + } + if (iCurrentPage === 1) { $('.paging_first', tableWrapper).attr('disabled', true); $('.paging_prev', tableWrapper).attr('disabled', true); } else { @@ -70,7 +78,7 @@ $.fn.dataTableExt.oPagination.bootstrap = { $('.paging_prev', tableWrapper).removeAttr('disabled'); } - if (totalPages === 0 || oSettings._iCurrentPage === totalPages) { + if (totalPages === 0 || iCurrentPage === totalPages) { $('.paging_next', tableWrapper).attr('disabled', true); $('.paging_last', tableWrapper).attr('disabled', true); } else { @@ -80,7 +88,7 @@ $.fn.dataTableExt.oPagination.bootstrap = { var i, oNumber, oNumbers = $('.paging_num', tableWrapper); - var lastPage = totalPages < oSettings._iLastPage ? totalPages : oSettings._iLastPage; + var lastPage = totalPages < oSettings._iLastPage ? totalPages : oSettings._iLastPage; // Erase oNumbers.html(''); @@ -112,9 +120,15 @@ $.fn.dataTableExt.oPagination.bootstrap = { 'fnUpdateState': function(oSettings) { var iCurrentPage = Math.ceil((oSettings._iDisplayStart + 1) / oSettings._iDisplayLength), iTotalPages = Math.ceil(oSettings.fnRecordsTotal() / oSettings._iDisplayLength), + filteredPages = Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength), iFirstPage = iCurrentPage - oSettings._iShowPagesHalf, iLastPage = iCurrentPage + oSettings._iShowPagesHalf; - + if (iTotalPages > filteredPages) { + iTotalPages = filteredPages; + } + if (iCurrentPage > filteredPages && filteredPages > 0) { + iCurrentPage = filteredPages; + } if (iTotalPages < oSettings._iShowPages) { iFirstPage = 1; iLastPage = iTotalPages; diff --git a/share/templates/helpers/datatables.tt b/share/templates/helpers/datatables.tt index 3fa18f21a8..2d2695e3d7 100644 --- a/share/templates/helpers/datatables.tt +++ b/share/templates/helpers/datatables.tt @@ -44,7 +44,6 @@ $(document).ready(function() { .dataTable( { "sDom": "<'row-fluid ngcp_dt_top_elements'lf>t<'row-fluid'<'pull-left'i><'pull-right'p>>", "bProcessing": true, - "bServerSide": true, "bPaginate": [% helper.paginate || 'true' %], "bFilter": [% helper.filter || 'true' %], "bStateSave": true, @@ -60,18 +59,9 @@ $(document).ready(function() { "bSort": [% IF helper.no_sort %] false [% ELSE %] true [% END %], "bInfo": true, "iDisplayLength": 5, - 'iShowPages': 5, + "iShowPages": 5, "sAjaxSource": "[% helper.ajax_uri %]", "searchDelay": 800, - "fnServerParams": function ( aoData ) { - var params = localStorage.getItem("ngcp_dt.[%helper.id_from_name%]_table.paramsJSON"); - if(params){ - var paramsParsed = JSON.parse(params); - for(var key in paramsParsed){ - aoData.push( {"name":key,"value":paramsParsed[key]} ); - } - } - }, [% IF helper.column_sort -%] "aaSorting": [ [% @@ -152,7 +142,9 @@ $(document).ready(function() { "sClass": "ngcp-actions-column" } ], - "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) { + [%IF !helper.data_static %] + "bServerSide": true, + "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) { oSettings.jqXHR = $.ajax( { "dataType": 'json', "url": sSource, @@ -165,6 +157,18 @@ $(document).ready(function() { } } ); }, + "fnServerParams": function ( aoData ) { + var params = localStorage.getItem("ngcp_dt.[%helper.id_from_name%]_table.paramsJSON"); + if(params){ + var paramsParsed = JSON.parse(params); + for(var key in paramsParsed){ + aoData.push( {"name":key,"value":paramsParsed[key]} ); + } + } + }, + [%ELSE%] + "bServerSide": false, + [%END%] [% IF helper.show_footer -%] "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) { if ([% helper.id_from_name %]_tmp_footer) { diff --git a/share/templates/security/list.tt b/share/templates/security/list.tt index 15044ca8cd..a8427f9107 100644 --- a/share/templates/security/list.tt +++ b/share/templates/security/list.tt @@ -15,6 +15,7 @@
+
@@ -23,31 +24,25 @@
+ + [% c.loc('Refresh banned IPs data') %] + + +[% + helper.name = c.loc('Banned IPs'); + helper.identifier = 'banned_ips'; + helper.length_change = 1; + helper.dt_columns = bannedips_dt_columns; + helper.data_static = 1; + helper.ajax_uri = c.uri_for_action('/security/ip_list'); + + helper.dt_buttons = [ + { name = c.loc('Unban'), uri = "/security/ip/'+encodeURI(full.ip)+'/unban", class = 'btn-small btn-primary', icon = 'icon-removet' }, + ]; + PROCESS 'helpers/datatables.tt'; +%] + - - - - - - - - - [% FOR ip IN banned_ips -%] - [% enc_ip = ip.ip | uri -%] - - - - - [% END -%] - -
[% c.loc('IP') %]
[% ip.ip %] - -
@@ -58,35 +53,24 @@
+ + [% c.loc('Refresh banned users data') %] + + +[% + helper.name = c.loc('Banned Users'); + helper.identifier = 'banned_users'; + helper.length_change = 1; + helper.dt_columns = bannedusers_dt_columns; + helper.data_static = 1; + helper.ajax_uri = c.uri_for_action('/security/user_list'); + + helper.dt_buttons = [ + { name = c.loc('Unban'), uri = "/security/user/'+encodeURI(full.username)+'/unban", class = 'btn-small btn-primary', icon = 'icon-removet' }, + ]; + PROCESS 'helpers/datatables.tt'; +%] - - - - - - - - - - - [% FOR user IN banned_users -%] - [% enc_user = user.username | uri -%] - - - - - - - [% END -%] - -
[% c.loc('User') %][% c.loc('Fail Count') %][% c.loc('Last Attempt') %]
[% user.username %][% user.auth_count %][% user.last_auth %] - -