Compare commits

...

3 Commits

Author SHA1 Message Date
717d34a53d * Thu Jul 03 2025 Brian Read <brianr@koozali.org> 11.0.0-102.sme
- Local Network panel: Make DEL and ADD robust even if called more than once by browser [SME: 13065]
2025-07-03 10:18:28 +01:00
bec39af49c * Wed Jul 02 2025 Brian Read <brianr@koozali.org> 11.0.0-101.sme
- Fix busy cursor, csp intervened. [SME: 13064]
2025-07-02 14:10:06 +01:00
ff9c2fee8c * Tue Jul 01 2025 Brian Read <brianr@koozali.org> 11.0.0-100.sme
- Add code in top template default.html.ep to incorporate any panel specific js and css [SME: 13062]
2025-07-01 11:28:58 +01:00
10 changed files with 163 additions and 129 deletions

View File

@@ -5,6 +5,12 @@ package SrvMngr::Controller::Localnetworks;
# description : Local networks
# navigation : 6000 500
#
#$if_admin->get('/localnetworks')->to('localnetworks#main')->name('localnetworks');
#$if_admin->post('/localnetworks')->to('localnetworks#do_display')->name('localnetworks');
#$if_admin->post('/localnetworksa')->to('localnetworks#do_display')->name('localnetworksadd');
#$if_admin->post('/localnetworksb')->to('localnetworks#do_display')->name('localnetworksadd1');
#$if_admin->get('/localnetworksd')->to('localnetworks#do_display')->name('localnetworksdel');
#$if_admin->post('/localnetworkse')->to('localnetworks#do_display')->name('localnetworksdel1');
# routes : end
#----------------------------------------------------------------------
use strict;
@@ -53,6 +59,7 @@ sub do_display {
$trt = 'ADD' if ($rt eq 'localnetworksadd');
$trt = 'ADD1' if ($rt eq 'localnetworksadd1');
$trt = 'DEL1' if ($rt eq 'localnetworksdel1');
$c->app->log->info("Localnetworks:trt:$trt");
my %ln_datas = ();
my $title = $c->l('ln_LOCAL NETWORKS');
my $modul = '';
@@ -83,16 +90,21 @@ sub do_display {
if ($trt eq 'DEL1') {
#After Remove clicked on Delete network panel
#$network_db = esmith::NetworksDB::UTF8->open() || die("Failed to open Networkdb-1");
#$network_db = esmith::NetworksDB::UTF8->open() || die("Failed to open Networkdb-1");
my $localnetwork = $c->param("localnetwork");
my $delete_hosts = $c->param("deletehost") || "1"; #default to deleting them.
my $rec = $network_db->get($localnetwork) || die("Failed to find network on db:$localnetwork");
if ($rec and $rec->prop('type') eq 'localnetwork') {
$ln_datas{localnetwork} = $localnetwork;
}
my %ret = remove_network($localnetwork, $delete_hosts);
#$network_db = esmith::NetworksDB::UTF8->open() || die("Failed to open Networkdb-2"); #Refresh the network DB
my $delete_hosts = $c->param("deletehost") || "1"; #default to deleting them.
$c->app->log->info("Localnetworks:deleting $localnetwork");
my ($rec,%ret);
if ($rec = $network_db->get($localnetwork)){ #|| die("Failed to find network on db:$localnetwork");
if ($rec and $rec->prop('type') eq 'localnetwork') {
$ln_datas{localnetwork} = $localnetwork;
}
%ret = $c->remove_network($localnetwork, $delete_hosts);
} else {
$c->app->log->info("Local network: delete failed to find network in db: $localnetwork");
%ret = ();
}
#$network_db = esmith::NetworksDB::UTF8->open() || die("Failed to open Networkdb-2"); #Refresh the network DB
my @localnetworks;
if ($network_db) {
@@ -100,8 +112,10 @@ sub do_display {
}
# Load up ln_datas with values need by template
$ln_datas{subnet} = $rec->prop('Mask');
$ln_datas{router} = $rec->prop('Router');
if ($rec){
$ln_datas{subnet} = $rec->prop('Mask');
$ln_datas{router} = $rec->prop('Router');
}
$c->stash(ln_datas => \%ln_datas, localnetworks => \@localnetworks, ret => \%ret);
} ## end if ($trt eq 'DEL1')
@@ -109,14 +123,20 @@ sub do_display {
#Initial delete panel requiring confirmation
my $localnetwork = $c->param("localnetwork") || '';
my ($rec,%ret);
$c->stash(localnetwork => $localnetwork);
my $rec = $network_db->get($localnetwork) || die("Failed to get local network in db::$localnetwork");
my $subnet = $rec->prop('Mask');
$ln_datas{subnet} = $subnet;
$ln_datas{router} = $rec->prop('Router');
my $numhosts = hosts_on_network($localnetwork, $subnet);
$ln_datas{localnetwork} = $localnetwork;
$ln_datas{deletehosts} = $numhosts > 0 ? 1 : 0;
if ($rec = $network_db->get($localnetwork)){
my $subnet = $rec->prop('Mask');
$ln_datas{subnet} = $subnet;
$ln_datas{router} = $rec->prop('Router');
my $numhosts =$c->hosts_on_network($localnetwork, $subnet);
$ln_datas{localnetwork} = $localnetwork;
$ln_datas{deletehosts} = $numhosts > 0 ? 1 : 0;
} else {
$c->app->log->info("Local network:Initial Failed to find network in Db: $localnetwork");
$c->flash('error',$c->l('ln_Failed to find network in Db'));
$trt = 'LIST';
}
} ## end if ($trt eq 'DEL')
if ($trt eq 'LIST') {
@@ -136,6 +156,7 @@ sub do_display {
} ## end sub do_display
sub remove_network {
my $c = shift;
my $network = shift;
$network_db = esmith::NetworksDB::UTF8->open();
my $record = $network_db->get($network);
@@ -152,7 +173,7 @@ sub remove_network {
if (system("/sbin/e-smith/signal-event", "network-delete", $network) == 0) {
if ($delete_hosts) {
my @hosts_to_delete = hosts_on_network($network, $subnet);
my @hosts_to_delete = $c->hosts_on_network($network, $subnet);
foreach my $host (@hosts_to_delete) {
$host->delete;
@@ -169,6 +190,7 @@ sub remove_network {
} ## end sub remove_network
sub hosts_on_network {
my $c = shift;
my $network = shift;
my $netmask = shift;
die if not $network and $netmask;
@@ -191,17 +213,20 @@ sub hosts_on_network {
} ## end sub hosts_on_network
sub add_network {
my ($fm) = @_;
my $networkAddress = $fm->param('networkAddress');
my $networkMask = $fm->param('networkMask');
my $networkRouter = $fm->param('networkRouter');
my ($c) = @_;
my $networkAddress = $c->param('networkAddress');
my $networkMask = $c->param('networkMask');
my $networkRouter = $c->param('networkRouter');
#Start by checking that the network does not already exist
#Validate Ips and subnet mask
my $res = ip_number($fm, $networkAddress);
my $res = ip_number($c, $networkAddress);
return (ret => 'ln_INVALID_IP_ADDRESS', vars => "Network Address $res") unless $res eq 'OK';
$res = subnet_mask($networkMask);
return (ret => 'ln_INVALID_SUBNET_MASK', vars => "$networkMask") unless $res eq 'OK';
$res = ip_number($fm, $networkRouter);
$res = ip_number($c, $networkRouter);
return (ret => 'ln_INVALID_IP_ADDRESS', vars => "Routeur Address $res") unless $res eq 'OK';
# we transform bit mask to regular mask
@@ -234,19 +259,25 @@ sub add_network {
if ($network_db->get($network)) {
return (ret => 'ln_NETWORK_ALREADY_ADDED', vars => "$network,$networkMask,$networkRouter");
}
$network_db->new_record(
$res = $network_db->new_record(
$network,
{ Mask => $networkMask,
Router => $networkRouter,
type => 'network',
}
);
# Untaint $network before use in system()
$network =~ /(.+)/;
$network = $1;
system("/sbin/e-smith/signal-event", "network-create", $network) == 0
or (return (ret => 'ln_ERROR_CREATING_NETWORK', vars => "$network,$networkMask,$networkRouter"));
if (! $res) {
#Record already existed
$c->app->log->info("Local Network:Network already exists:$network");
#return success message
} else {
#Only call underlying batch if new record created
# Untaint $network before use in system()
$network =~ /(.+)/;
$network = $1;
system("/sbin/e-smith/signal-event", "network-create", $network) == 0
or (return (ret => 'ln_ERROR_CREATING_NETWORK', vars => "$network,$networkMask,$networkRouter"));
}
my ($totalHosts, $firstAddr, $lastAddr) = esmith::util::computeHostRange($network, $networkMask);
my $msg;

View File

@@ -280,4 +280,14 @@ background-color: #e8f3e1;
/* Or specify the desired color */
text-decoration: none;
/* Or any other style you want to reset */
}
#busy-indicator {
display: none;
margin-top: 10px;
font-weight: bold;
color: red;
}
.busy {
cursor: wait; /* Change the cursor to a 'wait' cursor */
}

View File

@@ -28,4 +28,16 @@ $(document).ready(function() {
var iconSrc = inputType === 'password' ? 'images/visible.png' : 'images/visible-slash.png';
$(this).attr('src', iconSrc);
});
});
// and busy cursor
$(document).ready(function() {
// Handle form submission for any form
$('form').on('submit', function(event) {
// Disable all submit buttons and update their labels
$(this).find('button[type="submit"]').prop('disabled', true).text('Please wait...');
$(this).find('input[type="submit"]').prop('disabled', true).val('Please wait...');
// Add busy cursor
$('body').addClass('busy');
});
});

View File

@@ -1,7 +1,5 @@
% layout 'default', title => 'Sme server 2 - datetime';
% content_for 'module' => begin
%= javascript 'js/datetime.js'
%= stylesheet 'css/datetime.css'
<div id='module' class='module datetime-panel'>
% if (config->{debug} == 1) {
<p>

View File

@@ -4,8 +4,6 @@
% layout 'default', title => "Sme server 2 - E-Mail", share_dir => './';
%# css specific to this panel:
% content_for 'module' => begin
%= stylesheet '/css/emailsettings.css'
%= javascript '/js/emailsettings.js'
% use constant FALSE => 0;
% use constant TRUE => 1;

View File

@@ -2,7 +2,6 @@
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- default +jquery -->
<head>
<title><%= $title %></title>
<link rel="made" href="mailto:bugs%40koozali.org">
@@ -11,27 +10,16 @@
%= stylesheet '/css/new_sme.css'
%= stylesheet '/css/new-sme-main.css'
%# Replaced by consolidated (and rationlised) CSS files as above March 2025
%#= stylesheet '/css/sme_core.css'
%#= stylesheet '/css/sme_main.css'
%#= stylesheet '/css/sme_menu.css'
%#= stylesheet '/css/styles.css'
%#= stylesheet '/css/sme-password.css'
%= content_for 'head_contrib'
% if (config 'hasJquery') {
%= include 'partials/_js_imports'
%= include 'common_js'
% if (config 'hasJquery') {
%= include 'partials/_js_imports'
%= include 'common_js'
% }
%= content_for 'refresh'
%= content_for 'refresh'
%= stylesheet '/js/datatables.min.css'
%= javascript '/js/datatables.min.js'
%= stylesheet '/js/jquery-ui.min.css'
%= javascript '/js/jquery-ui.min.js'
%= javascript '/js/dataTables.buttons.min.js'
%= javascript '/js/jszip.min.js'
@@ -44,26 +32,23 @@
<link rel="stylesheet" href="/smanager/css/flag-icon.min.css">
%= stylesheet '/css/sme-jquery-overrides.css'
<style>
#busy-indicator {
display: none;
margin-top: 10px;
font-weight: bold;
color: red;
}
.busy {
cursor: wait; /* Change the cursor to a 'wait' cursor */
}
</style>
%# panel specific css file
% my $controller = stash('controller');
% if ($controller) {
% my $css_path = "css/$controller.css";
%# Use the url_for helper to generate the correct static file URL
% if (app->static->file($css_path)) {
<link rel="stylesheet" href="<%= url_for("/$css_path") %>">
% }
% }
</head>
<body>
% if ( not defined $c->session->{lang} ) {
% SrvMngr::init_session ( $c );
% }
% if ( not defined $c->session->{lang} ) {
% SrvMngr::init_session ( $c );
% }
<div id="header">
%= include 'partials/_header'
% if ($c->is_logged_in && scalar @{SrvMngr::theme_list( $c )} > 1) {
@@ -72,42 +57,40 @@
</div>
<div id="container">
% if (config 'hasJquery') {
%= content 'js_toggleMenu'
% }
% if (config 'hasJquery') {
%= content 'js_toggleMenu'
% }
<div id="navigation" class="col-md-3 module">
%= include 'partials/_nav_menu'
% if ( $c->is_logged_in ) {
%= include 'partials/_user_menu'
% }
% if ( $c->is_admin ) {
%= include 'partials/_navig2'
% }
</div>
<div id="main" class="col-md-9">
%= include 'partials/_info'
% if (flash 'success') {
<br><div class="success module">
%= $c->render_to_string(inline => flash 'success')
<div id="navigation" class="col-md-3 module">
%= include 'partials/_nav_menu'
% if ( $c->is_logged_in ) {
%= include 'partials/_user_menu'
% }
% if ( $c->is_admin ) {
%= include 'partials/_navig2'
% }
</div>
% }
% if ( flash 'warning' ) {
<br><div class="sme-warning module">
%= $c->render_to_string(inline => flash 'warning')
<div id="main" class="col-md-9">
%= include 'partials/_info'
% if (flash 'success') {
<br><div class="success module">
%= $c->render_to_string(inline => flash 'success')
</div>
% }
% if ( flash 'warning' ) {
<br><div class="sme-warning module">
%= $c->render_to_string(inline => flash 'warning')
</div>
%}
% if ( flash 'error' ) {
<br><div class="sme-error module">
%= $c->render_to_string(inline => flash 'error')
</div>
%}
%= content 'module'
%= include 'partials/_footer'
</div>
%}
% if ( flash 'error' ) {
<br><div class="sme-error module">
%= $c->render_to_string(inline => flash 'error')
</div>
%}
%= content 'module'
%= include 'partials/_footer'
</div>
</div>
% if (config 'hasJquery') {
@@ -115,23 +98,17 @@
%= content 'js_togglePassword'
% }
%= javascript '/js/sme-dataTable-setup.js'
<script>
$(document).ready(function() {
// Handle form submission for any form
$('form').on('submit', function(event) {
// Disable the submit button
$(this).find('button[type="submit"], input[type="submit"]').prop('disabled', true);
// Show the busy indicator
// $('#busy-indicator').show();
// Change the cursor to "wait"
$('body').addClass('busy');
});
});
</script>
%= javascript '/js/sme-dataTable-setup.js'
%# Specific panel js code
% $controller = stash('controller');
% if ($controller) {
% my $js_path = "js/$controller.js";
%# Use the url_for helper to generate the correct static file URL
% if (app->static->file($js_path)) {
<script src="<%= url_for("/$js_path") %>"></script>
% }
% }
</body>
</html>

View File

@@ -6,12 +6,12 @@
% my $router = $ln_datas->{router};
% if (config->{debug} == 1) {
<p>
%= dumper $c->current_route
%= dumper $c->stash("ret")
%= dumper %$ln_datas
%= dumper $deletehosts
</p>
<pre>
%= dumper $c->current_route
%= dumper $c->stash("ret")
%= dumper %$ln_datas
%= dumper $deletehosts
</pre>
% }
%= form_for '/localnetworkse' => (method => 'POST') => begin
@@ -56,4 +56,4 @@
%end
</div>
</div>

View File

@@ -8,9 +8,9 @@
% my ($var1, $var2, $var3, $var4, $var5, $var6, $var7) = @vars;
% if ($c->app->config->{debug}) {
<p>
<pre>
%= dumper { ret_data => \%ret }
</p>
</pre>
% }
% if ($ret{ret} eq "") {

View File

@@ -1,6 +1,5 @@
% layout 'default', title => "Sme server 2 - qmailanalog";
% content_for 'module' => begin
%= javascript '/js/qmailanalog.js'
<div id='module' class='module qmailanalog-panel'>
%if (config->{debug} == 1) {
<p>

View File

@@ -2,7 +2,7 @@ Summary: Sme server navigation module : manager 2
%define name smeserver-manager
Name: %{name}
%define version 11.0.0
%define release 99
%define release 102
Version: %{version}
Release: %{release}%{?dist}
License: GPL
@@ -146,6 +146,15 @@ true
%defattr(-,root,root)
%changelog
* Thu Jul 03 2025 Brian Read <brianr@koozali.org> 11.0.0-102.sme
- Local Network panel: Make DEL and ADD robust even if called more than once by browser [SME: 13065]
* Wed Jul 02 2025 Brian Read <brianr@koozali.org> 11.0.0-101.sme
- Fix busy cursor, csp intervened. [SME: 13064]
* Tue Jul 01 2025 Brian Read <brianr@koozali.org> 11.0.0-100.sme
- Add code in top template default.html.ep to incorporate any panel specific js and css [SME: 13062]
* Mon Jun 30 2025 Brian Read <brianr@koozali.org> 11.0.0-99.sme
- Directory panel - Add in open for config db as required by cacheing [SME: 13059]