diff --git a/root/etc/e-smith/events/actions/letsencrypt-kill-dehydrated-timer b/root/etc/e-smith/events/actions/letsencrypt-kill-dehydrated-timer deleted file mode 100644 index c10cbfb..0000000 --- a/root/etc/e-smith/events/actions/letsencrypt-kill-dehydrated-timer +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh -systemctl is-active --quiet dehydrated.timer && systemctl stop dehydrated.timer - diff --git a/root/etc/e-smith/events/actions/letsencrypt-setdomains b/root/etc/e-smith/events/actions/letsencrypt-setdomains deleted file mode 100644 index bf2c1ad..0000000 --- a/root/etc/e-smith/events/actions/letsencrypt-setdomains +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/bash - -#---------------------------------------------------------------------- -# copyright (C) 2022 Koozali SME Server -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -#---------------------------------------------------------------------- - -event=$1 -fqdn=$2 -todo=$3 -domainlist="" - -case $todo in - disabled|enabled) - # - ;; - *) - todo="all" - ;; -esac - -if [[ ! -z "$fqdn" ]] - then - # if fqdn not empty just use this one - domainlist="$fqdn" -elif [[ ! -z "$event" ]] && [[ "$event" == *"domain"* ]] - then - # else if event *domains* => all domains - domainlist=$(perl -Mesmith::DomainsDB -e 'my $domains = esmith::DomainsDB->open; my @DOM = $domains->get_all_by_prop(type=>"domain"); print( join(" " , map { $_->key } @DOM)) ') -elif [[ ! -z "$event" ]] && [[ "$event" == *"host"* ]] - then - # else if event *hosts* => all hosts - domainlist=$(perl -Mesmith::HostsDB -e 'my $domains = esmith::HostsDB->open; my @DOM = $domains->get_all_by_prop(type=>"host"); print( join(" " , map { $_->key } @DOM)) ') -else - # else all domain and hosts - domains=$(perl -Mesmith::DomainsDB -e 'my $domains = esmith::DomainsDB->open; my @DOM = $domains->get_all_by_prop(type=>"domain"); print( join(" " , map { $_->key } @DOM)) ') - hosts=$(perl -Mesmith::HostsDB -e 'my $domains = esmith::HostsDB->open; my @DOM = $domains->get_all_by_prop(type=>"host"); print( join(" " , map { $_->key } @DOM)) ') - domainlist="$domains $hosts" -fi -domainlist=$(echo $domainlist |sort|uniq) - -#list from pihole install script; only ipv4 ones -#here we select our -dns=$(/sbin/e-smith/db configuration getprop letesencrypt dnscheck||echo "https://cloudflare-dns.com/dns-query,8.8.8.8,8.8.4.4,1.1.1.1,1.0.0.1,208.67.222.222,208.67.220.220,4.2.2.1,4.2.2.2,8.20.247.20,84.200.69.80,84.200.70.40,9.9.9.10,149.112.112.10") -# from https://stackoverflow.com/questions/10586153/how-to-split-a-string-into-an-array-in-bash -IFS=', ' read -r -a DNS <<< "$dns" -RANDOM=$$$(date +%s) -x=1 -#TODO: if only one element skip the random selection -while [ $x -le 5 ]; do -mydns=${DNS[ $RANDOM % ${#DNS[@]} ]} -if [[ $mydns == http* ]] ; then - curl -s $mydns >/dev/null - if [[ "$?" == "0" ]]; then - break - fi -else - nc -z -w2 $mydns 53 - if [[ "$?" == "0" ]]; then - break - fi -fi -x=$(( $x + 1 )) -#in case of failure defaulting on a dns over https after 5 -mydns="https://cloudflare-dns.com/dns-query" -done -echo "External DNS Server : $mydns" - -MYFORCEDIP=$(/sbin/e-smith/db configuration getprop letesencrypt ExternalIP) -# check if gateway or server only -MYMODE=$(/sbin/e-smith/db configuration get SystemMode) -# check our external ip if gateway, internal else -LOCALIP=$(/sbin/e-smith/db configuration get InternalIP) -MYIP=$LOCALIP -# check the ip suggested by external world that point to us. -MYEXTIP=$(/usr/sbin/e-smith/getmyip) - -if [ -z "$MYFORCEDIP" ]; then - # we do not expect that a server-only has an ip routable on internet as firewall is not designed for that - # but in case, we handle the situation as for ExternalIP in servergateway mode, please write ad hoc rules for masq if you do so... - if [[ "$MYMODE" == "servergateway" ]] ; then - MYIP=$(/sbin/e-smith/db configuration get ExternalIP); - fi - if [[ "$MYIP" != "$MYEXTIP" ]] ; then - echo "External Interface IP: $MYIP" - echo "Detected Wan IP : $MYEXTIP" - echo "You seem to be behind a firewall, using the external IP obtained with our test $MYEXTIP" - MYIP=$MYEXTIP - fi -else - MYIP=$MYFORCEDIP -fi - -echo "=============================================================================================" -OUTPUT="Domain\tStatus\tMYIP\tA\tLE_status\tLE_previous" -# TODO all : check disabled and enabled ; active : check enabled and undef only - -for DOMAIN in $domainlist - do - # is it a host, a domain or should we ignore it - TYPE=$(/sbin/e-smith/db domains gettype $DOMAIN || /sbin/e-smith/db hosts gettype $DOMAIN ) - if [[ "$TYPE" == "domain" ]] ; then - TYPE="domains" - elif [[ "$TYPE" == "host" ]] ; then - TYPE="hosts" - else - echo "$DOMAIN is not in domains and not in hosts ($TYPE)" - continue - fi - # do we have a priority ? - currentstate=$(/sbin/e-smith/db $TYPE getprop $DOMAIN letsencryptSSLcert || echo "disabled") - if [ "$currentstate" != "$todo" -a "$todo" != "all" ] ; then - #echo "$DOMAIN skipping, only checking $todo $TYPE" - continue - fi - # https://stackoverflow.com/questions/15268987/bash-based-regex-domain-name-validation - if ( ! echo $DOMAIN| grep -P -q '(?=^.{4,253}$)(^(?:[a-zA-Z0-9](?:(?:[a-zA-Z0-9\-]){0,61}[a-zA-Z0-9])?\.)+([a-zA-Z]{2,}|xn--[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])$)' -Z ) ; then - if [[ "$currentstate" == "disabled" ]]; then continue; fi - echo "$DOMAIN is not a RFC compliant domain, disabling" - /sbin/e-smith/db $TYPE setprop $DOMAIN letsencryptSSLcert disabled - /sbin/e-smith/db $TYPE delprop $DOMAIN letsencryptMYIP - continue - fi - THISDOMIP=$(/usr/bin/q A @$mydns $DOMAIN -f json |jq -r 'first(.Answers[].A | select( . != null )) // null' 2>/dev/null || /usr/bin/q A @$LOCALIP $DOMAIN -f json |jq -r 'first(.Answers[].A | select( . != null )) // null' 2>/dev/null ) - previous=$(/sbin/e-smith/db $TYPE getprop $DOMAIN letsencryptSSLcert||echo 'undefined'); - # if it does not resolve, next - if [[ "$THISDOMIP" == "" ]] - then - OUTPUT="$OUTPUT\n$DOMAIN\tNOK\t$MYIP\tnoip\tdisabled\t$previous" - /sbin/e-smith/db $TYPE setprop $DOMAIN letsencryptSSLcert disabled - /sbin/e-smith/db $TYPE delprop $DOMAIN letsencryptMYIP - continue; - fi - if [[ "$MYIP" == "$THISDOMIP" ]] - then - OUTPUT="$OUTPUT\n$DOMAIN\tOK\t$MYIP\t$THISDOMIP\tenabled\t$previous" - /sbin/e-smith/db $TYPE setprop $DOMAIN letsencryptSSLcert enabled letsencryptMYIP $THISDOMIP - else - OUTPUT="$OUTPUT\n$DOMAIN\tNOK\t$MYIP\t$THISDOMIP\tdisabled\t$previous" - /sbin/e-smith/db $TYPE setprop $DOMAIN letsencryptSSLcert disabled letsencryptMYIP $THISDOMIP - fi - sleep 1 -done -printf "%b" $OUTPUT |column -t -s $'\t' - diff --git a/root/usr/sbin/e-smith/getmyip b/root/usr/sbin/e-smith/getmyip deleted file mode 100755 index fc9b5ef..0000000 --- a/root/usr/sbin/e-smith/getmyip +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# List of services to query for the public IP -services=( - "ifconfig.me" - "ipinfo.io/ip" - "icanhazip.com" - "api.ipify.org" - "ident.me" - "ip.tyk.nu" - "checkip.amazonaws.com" - "ipecho.net/plain" - "myip.dnsomatic.com" - "ip.seeip.org" - "ipapi.co/ip" - "wtfismyip.com/text" - "openident.net/ip" - "ifconfig.co/ip" -) - -# Function to shuffle the array of services -shuffle_services() { - local i - for ((i=${#services[@]} - 1; i > 0; i--)); do - local j=$((RANDOM % (i + 1))) - local temp="${services[i]}" - services[i]="${services[j]}" - services[j]="$temp" - done -} - -# Function to fetch the public IP address -get_public_ip() { - shuffle_services - for service in "${services[@]}"; do - public_ip=$(curl -s --max-time 5 "$service") - - # Check if the curl request was successful and there's a valid IP address - if [[ $? -eq 0 && $public_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - logger -t public_ip_script "Service used: $service, IP found: $public_ip" - echo "$public_ip" - return - fi - done - - # If none of the services returned a valid IP, output an error message - echo "Failed to retrieve public IP using all services." >&2 - logger -t public_ip_script "Error: Failed to retrieve public IP using all services." - exit 1 -} - -# Execute the function -get_public_ip - diff --git a/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm new file mode 100644 index 0000000..e6f32d7 --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm @@ -0,0 +1,472 @@ +# +# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-11-16 10:30:16 +# +# +# Routines to be edited by the developer to provide content and validation for parameters +# and provison of the control data for table(s) +# +use esmith::util; +use esmith::util::network; +use esmith::ConfigDB; +use esmith::HostsDB; +use esmith::AccountsDB; +use esmith::NetworksDB; +use esmith::DomainsDB; + +use constant FALSE => 0; +use constant TRUE => 1; + + +#The most common ones +our $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); +our $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); +our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); +our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); +our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + +# Validation routines - parameters for each panel + + sub validate_LIST { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (! TRUE) #validate $c->param('InternalIP') + {$ret .= 'Validation for InternalIP failed';} + if (! TRUE) #validate $c->param('ExternalIP') + {$ret .= 'Validation for ExternalIP failed';} + if (! TRUE) #validate $c->param('InternetIP') + {$ret .= 'Validation for InternetIP failed';} + if (! TRUE) #validate $c->param('Issuer') + {$ret .= 'Validation for Issuer failed';} + if (! TRUE) #validate $c->param('Expiry') + {$ret .= 'Validation for Expiry failed';} + if (! TRUE) #validate $c->param('NotBefore') + {$ret .= 'Validation for NotBefore failed';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub validate_PARAMS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + if (! TRUE) #validate $c->param('status') + {$ret .= 'Validation for status failed';} + if (! TRUE) #validate $c->param('hookScript') + {$ret .= 'Validation for hookScript failed';} + if (! TRUE) #validate $c->param('hostOverride') + {$ret .= 'Validation for hostOverride failed';} + if (! TRUE) #validate $c->param('ACCEPT_TERMS') + {$ret .= 'Validation for ACCEPT_TERMS failed';} + if (! TRUE) #validate $c->param('API') + {$ret .= 'Validation for API failed';} + if (! TRUE) #validate $c->param('keysize') + {$ret .= 'Validation for keysize failed';} + if (! TRUE) #validate $c->param('configure') + {$ret .= 'Validation for configure failed';} + if (! TRUE) #validate $c->param('Email') + {$ret .= 'Validation for Email failed';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub validate_CHECKALLDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (! TRUE) #validate $c->param('AllDomainsCheck') + {$ret .= 'Validation for AllDomainsCheck failed';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub validate_CHECKALLENABLEDDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (! TRUE) #validate $c->param('EnabledDomainsCheck') + {$ret .= 'Validation for EnabledDomainsCheck failed';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub validate_CHECKONEDOMAIN { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + # Validation for each field + my $ret = ""; + + if (! TRUE) #validate $c->param('OneDomainToCheck') + {$ret .= 'Validation for OneDomainToCheck failed';} + if (! TRUE) #validate $c->param('OneDomainsCheck') + {$ret .= 'Validation for OneDomainsCheck failed';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + +# Get singleton data for each panel + + sub get_data_for_panel_LIST { + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; +# my ($reply, $err, $server_cert) = Net::SSLeay::sslcat('localhost', 443, '/'); +# my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($server_cert)); +# my $before = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($server_cert)); +# my $expiry = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($server_cert)); + + my %ret = ( + 'Data1'=>'Data for LIST', #Example + # fields from Inputs in LIST $fields['LIST'] + 'InternalIP'=>$cdb->get_prop('InternalInterface','IPAddress'), + 'ExternalIP'=>$cdb->get_prop('ExternalInterface','IPAddress'), + 'InternetIP'=>$c->get_my_ip(), + 'Issuer'=>'$issuer', + 'Expiry'=>'$expiry', + 'NotBefore'=>'$before', + ); + return %ret; + } + + sub get_data_for_panel_PARAMS { + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1'=>'Data for PARAMS', #Example + # fields from Inputs in PARAMS $fields['PARAMS'] + 'status'=>$cdb->get_prop('letsencrypt', 'status', 'disabled'), + 'hookScript'=>$cdb->get_prop('letsencrypt', 'hookScript', 'disabled'), + 'hostOverride'=>$cdb->get_prop('letsencrypt', 'hostOverride', 'disabled'), + 'ACCEPT_TERMS'=>$cdb->get_prop('letsencrypt', 'ACCEPT_TERMS', ''), + 'API'=>$cdb->get_prop('letsencrypt', 'API', '2'), + 'keysize'=>$cdb->get_prop('letsencrypt', 'keysize', '4096'), + 'configure'=>$cdb->get_prop('letsencrypt', 'configure', 'none' ), + 'email'=>$cdb->get_prop('letsencrypt', 'email') + ); + return %ret; + } + + sub get_data_for_panel_CHECKALLDOMAINS { + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1'=>'Data for CHECKALLDOMAINS', #Example + # fields from Inputs in CHECKALLDOMAINS $fields['CHECKALLDOMAINS'] + 'AllDomainsCheck'=>$c->update_all_domains(), + + ); + return %ret; + } + + sub get_data_for_panel_CHECKALLENABLEDDOMAINS { + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1'=>'Data for CHECKALLENABLEDDOMAINS', #Example + # fields from Inputs in CHECKALLENABLEDDOMAINS $fields['CHECKALLENABLEDDOMAINS'] + 'EnabledDomainsCheck'=>$c->update_enabled_domains(), + + ); + return %ret; + } + + sub get_data_for_panel_CHECKONEDOMAIN { + # Return a hash with the fields required which will be loaded into the shared data + my $c = shift; + my %ret = ( + 'Data1'=>'Data for CHECKONEDOMAIN', #Example + # fields from Inputs in CHECKONEDOMAIN $fields['CHECKONEDOMAIN'] + 'OneDomainToCheck'=>$c->param("CHECKONEDOMAIN"), + 'OneDomainsCheck'=>$c->update_one_domain($c->param("CHECKONEDOMAIN")) + ); + return %ret; + } + + + +# Get control data for table(s) + + # Define a constant hash for field name mapping + use constant DomainList_FIELD_MAPPING => ( + 'Table1-Domain name / HOSTNAME' => 'Domain', + 'Table1-Brief description' => 'Description', + 'Table1-Content' => 'Content', + 'Table1-LABEL_NAMESERVERS' => 'Nameservers', + 'Table1-LABEL_POINT' => 'Source-for-Table1-LABEL_POINT', + 'Table1-LABEL_LECERT' => 'letsencryptSSLcert', + 'Table1-IS_IN_CERT' => 'isincert', + 'Table1-CHECK' => 'Check' + #'target_field2' => 'source_field2', + # Add more mappings as needed + ); + + +use constant TEST_DOMAIN_LIST => ( + { "domain" => "Domain1","fred" => "fred1" , "description"=>"Description1"}, + { "domain" => "Domain2", "fred" => "fred2", "description"=>"Description2" }, + { "domain" => "Domain3", "fred" => "fred3", "description"=>"Description3" }, + # Add more test entries as needed +); + +sub actual_DomainList { + my $c = shift; + # Actual code for extracting DomainList + my @list = (); +# my @rv = Net::SSLeay::X509_get_subjectAltNames($server_cert); +# foreach my $element (@rv) { +# next if $element =~ /^\d+$/; ; +# #print $element . "\n"; +# push @list, $element; +# } + my @data = (); + my $check = $c->l('Check Domain'); + for ($ddb->domains) + { + my $ns = $_->prop('Nameservers') || 'internet'; + my $le = $_->prop('letsencryptSSLcert') || 'disabled';#letsencrypt configure all + my $dname= $_->key; + my $isincert = "N"; + my $link = $c->create_link("letsencryptd","CHECKONEDOMAIN",""); + my $checklink = "".$check.""; + #my $checklink = "check"; + $isincert = "Y" if ( $dname ~~ @list); + # domain + push @data, + { Domain => $_->key, + $_->props, + letsencryptSSLcert => $le, + isincert => $isincert, + Check => $checklink, + Nameservers => $ns, + }; + #and hosts + for my $h ($hdb->get_hosts_by_domain($dname)) + { + next if $ddb->get($h->key); + next unless ($h->prop('HostType') eq "Self" || $h->prop('HostType') eq "Local"); + $le = $h->prop('letsencryptSSLcert') || 'disabled';#letsencrypt configure all + $isincert = "N"; + $isincert = "Y" if ( $h->key ~~ @list); + push @data, + { Domain => "--> ". $h->key, + $h->props, + Description=>$h->prop('ExternalIP')|| $h->prop('InternalIP')||"", + Content => $h->prop('HostType'), + isincert => $isincert, + Check => "", #$checklink + Nameservers => $c->l($ns), + } + } + } + return @data; +} + +sub get_DomainList { + # Return an array of hashes of the contents for each row and column for DomainList + my $c = shift; + my @source_records = $c->actual_DomainList(); #TEST_DOMAIN_LIST #Replace by code or call to produce contents of table; + my @transformed_records; + my %Field_Mapping = DomainList_FIELD_MAPPING; + # Iterate over each record in the source array + for my $source_record (@source_records) { + my %transformed_record; + # Iterate over each key-value pair in the $Field_Mapping constant + while (my ($target, $source) = each %Field_Mapping) { + # Check if the source field exists in the source record + if (exists $source_record->{$source}) { + # Assign the source field value to the target field in the transformed record + $transformed_record{$target} = $source_record->{$source}; + } + } + # Add transformed record to the array if it's not empty + push @transformed_records, \%transformed_record if %transformed_record; + } + return \@transformed_records; +} + + + +# Return hash with values from row in which link clicked on table + + sub get_selected_LIST { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return $ret; + } + + sub get_selected_PARAMS { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return $ret; + } + + sub get_selected_CHECKALLDOMAINS { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return $ret; + } + + sub get_selected_CHECKALLENABLEDDOMAINS { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return $ret; + } + + sub get_selected_CHECKONEDOMAIN { + my $c = shift; + my $selected = shift; #Parameter is name of selected row. + my $is_new_record = shift; #Indicates new record required (defaults) + my %ret = {}; + return $ret; + } + + +#after sucessful modify or create or whatever and submit then perfom (if the params validate) + + sub perform_LIST { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (! TRUE) #copy or perform with value: InternalIP e.g. $db->set_prop($dbkey,'InternalIP',$c->param('InternalIP'),type=>'service')) + {$ret .= 'Perform/save failed for InternalIP';} + if (! TRUE) #copy or perform with value: ExternalIP e.g. $db->set_prop($dbkey,'ExternalIP',$c->param('ExternalIP'),type=>'service')) + {$ret .= 'Perform/save failed for ExternalIP';} + if (! TRUE) #copy or perform with value: InternetIP e.g. $db->set_prop($dbkey,'InternetIP',$c->param('InternetIP'),type=>'service')) + {$ret .= 'Perform/save failed for InternetIP';} + if (! TRUE) #copy or perform with value: Issuer e.g. $db->set_prop($dbkey,'Issuer',$c->param('Issuer'),type=>'service')) + {$ret .= 'Perform/save failed for Issuer';} + if (! TRUE) #copy or perform with value: Expiry e.g. $db->set_prop($dbkey,'Expiry',$c->param('Expiry'),type=>'service')) + {$ret .= 'Perform/save failed for Expiry';} + if (! TRUE) #copy or perform with value: NotBefore e.g. $db->set_prop($dbkey,'NotBefore',$c->param('NotBefore'),type=>'service')) + {$ret .= 'Perform/save failed for NotBefore';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub perform_PARAMS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'letsencrypt'; + # To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g." + + if (! $db->set_prop($dbkey,'status',$c->param('status'),type=>'service')) + {$ret .= 'Perform/save failed for status';} + if (! $db->set_prop($dbkey,'hookScript',$c->param('hookScript'),type=>'service')) + {$ret .= 'Perform/save failed for hookScript';} + if (! $db->set_prop($dbkey,'hostOverride',$c->param('hostOverride'),type=>'service')) + {$ret .= 'Perform/save failed for hostOverride';} + if (! $db->set_prop($dbkey,'ACCEPT_TERMS',$c->param('ACCEPT_TERMS'),type=>'service')) + {$ret .= 'Perform/save failed for ACCEPT_TERMS';} + if (! $db->set_prop($dbkey,'API',$c->param('API'),type=>'service')) + {$ret .= 'Perform/save failed for API';} + if (! $db->set_prop($dbkey,'keysize',$c->param('keysize'),type=>'service')) + {$ret .= 'Perform/save failed for keysize';} + if (! $db->set_prop($dbkey,'configure',$c->param('configure'),type=>'service')) + {$ret .= 'Perform/save failed for configure';} + if (! $db->set_prop($dbkey,'email',$c->param('email'),type=>'service')) + {$ret .= 'Perform/save failed for email';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub perform_CHECKALLDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (! TRUE) #copy or perform with value: AllDomainsCheck e.g. $db->set_prop($dbkey,'AllDomainsCheck',$c->param('AllDomainsCheck'),type=>'service')) + {$ret .= 'Perform/save failed for AllDomainsCheck';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub perform_CHECKALLENABLEDDOMAINS { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (! TRUE) #copy or perform with value: EnabledDomainsCheck e.g. $db->set_prop($dbkey,'EnabledDomainsCheck',$c->param('EnabledDomainsCheck'),type=>'service')) + {$ret .= 'Perform/save failed for EnabledDomainsCheck';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + sub perform_CHECKONEDOMAIN { + my $c = shift; + my $prefix_data = shift; #Data hash as parameter + my $ret = ""; + my $db = $cdb; #maybe one of the others + my $dbkey = 'ChangeThis'; + + if (! TRUE) #copy or perform with value: OneDomainToCheck e.g. $db->set_prop($dbkey,'OneDomainToCheck',$c->param('OneDomainToCheck'),type=>'service')) + {$ret .= 'Perform/save failed for OneDomainToCheck';} + if (! TRUE) #copy or perform with value: OneDomainsCheck e.g. $db->set_prop($dbkey,'OneDomainsCheck',$c->param('OneDomainsCheck'),type=>'service')) + {$ret .= 'Perform/save failed for OneDomainsCheck';} + if ($ret eq "") {$ret = 'ok';} + return $ret; + } + + +sub create_link{ + # WIP + my ($c,$route, $panel, $index) = @_; + my $link = "$route?trt=$panel&Selected=$index"; + return $link; +} + +sub get_my_ip +{ + my ($self, $item, $prop, $default) = @_; + my $output = `/usr/sbin/e-smith/getmyip`; + return $output || "IP"; +} + +sub update_one_domain +{ + my ($self,$domain) = @_; + return "$domain not domain" unless ($ddb->get($domain) || $hdb->get($domain)); + ($domain) = ($domain =~ /([\w\p{L}.]+)/); + my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains " " $domain `; + return $output || "-empty-"; +} + +sub update_all_domains +{ + my $self = shift; + my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" all `; + return $output || "-empty-"; +} + +sub update_enabled_domains +{ + my $self = shift; + my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" enabled `; + return $output || "-empty-"; +} + + +1; \ No newline at end of file diff --git a/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm new file mode 100644 index 0000000..220b439 --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm @@ -0,0 +1,429 @@ +package SrvMngr::Controller::Letsencrypt; +# +# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +# +#---------------------------------------------------------------------- +# heading : Network +# description : Letsencrypt certificate +# navigation : 6000 6600 +# +# name : letsencrypt, method : get, url : /letsencrypt, ctlact : Letsencrypt#main +# name : letsencryptu, method : post, url : /letsencryptu, ctlact : Letsencrypt#do_update +# name : letsencryptd, method : get, url : /letsencryptd, ctlact : Letsencrypt#do_display +# +# routes : end +# +# Documentation: https://wiki.contribs.org/Letsencrypt +#---------------------------------------------------------------------- + +# +# Scheme of things: +# +# TBA!! + +use strict; +use warnings; +use Mojo::Base 'Mojolicious::Controller'; + +use constant FALSE => 0; +use constant TRUE => 1; + +use Locale::gettext; +use SrvMngr::I18N; +use SrvMngr qw(theme_list init_session); + +use Data::Dumper; + +use esmith::util; +use esmith::util::network; +use esmith::ConfigDB; +use esmith::AccountsDB; +use esmith::NetworksDB; +use esmith::HostsDB; +use esmith::DomainsDB; + + + +require '/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm'; #The code that is to be added by the developer + +sub main { +# +# Initial entry - route is "/" +# +#set initial panel +#for initial panel: + #Specifiy panel to enter + #load up _data hash with DB fields + #load up stash with pointer(s) to control fields hash(= get-)) + #and a pointer to the prefix_data hash +#render initial panel + + my $c = shift; + $c->app->log->info( $c->log_req ); + + #The most common ones + my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); + my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); + my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); + my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); + my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + + my %lets_data = (); + my $title = $c->l('lets_Letsencrypt_certificate'); + my $modul = ''; + + $lets_data{'trt'} = 'LIST'; + + #Load any DB entries into the _data area so as they are preset in the form + # which DB - this only really works if the initial panel is a PARAMS type panel and not a TABLE + my $db = $cdb; #pickup local or global db or Default to config + + + $c->do_display($lets_data{'trt'}); + +} + +# Post request with params - submit from the form +sub do_update { +# +# Return after submit pushed on panel (this is a post) - route is "/u" +# parameters in the params hash. +# +#load up all params into prefix_data hash: +#By panel (series of if statements - only one executed): + #call validate-PANEL() - return ret = ok or error message + +#if validation not ok: + #render back to current panel with error message in stash +#otherwise: + #By panel (series of if statements - only one executed): + #do whatever is required: call perform-PANEL() - return "ok" or Error Message + #call signal-event for any global actions specified (check it exists - error and continue?) + #if action smeserver--update exists + #signal_event smeserver--update + #call signal-event for any specific actions for thids panel (check it exists first - error and continue) + #set success in stash + #if no "nextpanel" entry: + #set firstpanel + #else + #set nextpanel + #call render + + my $c = shift; + $c->app->log->info($c->log_req); + my $modul = ''; + + #The most common ones - you might want to comment out any not used. + my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); + my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); + my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); + my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); + my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + + my %lets_data = (); + my $title = $c->l('lets_Letsencrypt_certificate'); + + # Accessing all POST parameters + my %params = $c->req->params->to_hash; + + # Get number of POST parameters + my $num_params = keys %params; + + #Params are available in the hash "params" - copy to the prefix_data hash + #while (my ($key, $value) = each %{$c->req->params->to_hash}) { + # $lets_data{$key} = $value; + #} + + # the value of trt will tell you which panel has returned + my $trt = $c->param('trt') || 'LIST'; #hidden control on every form. + my $ret = 'ok'; + + #Validate the parameters in a custom sub one for each panel (although only one of these will be executed) + my $thispanel; + + if ($trt eq 'LIST'){ + #Validate form parameters for panel LIST + $ret = $c->validate_LIST(\%lets_data); + $thispanel = 'LIST'; + } + + if ($trt eq 'PARAMS'){ + #Validate form parameters for panel PARAMS + $ret = $c->validate_PARAMS(\%lets_data); + $thispanel = 'PARAMS'; + } + + if ($trt eq 'CHECKALLDOMAINS'){ + #Validate form parameters for panel CHECKALLDOMAINS + $ret = $c->validate_CHECKALLDOMAINS(\%lets_data); + $thispanel = 'CHECKALLDOMAINS'; + } + + if ($trt eq 'CHECKALLENABLEDDOMAINS'){ + #Validate form parameters for panel CHECKALLENABLEDDOMAINS + $ret = $c->validate_CHECKALLENABLEDDOMAINS(\%lets_data); + $thispanel = 'CHECKALLENABLEDDOMAINS'; + } + + if ($trt eq 'CHECKONEDOMAIN'){ + #Validate form parameters for panel CHECKONEDOMAIN + $ret = $c->validate_CHECKONEDOMAIN(\%lets_data); + $thispanel = 'CHECKONEDOMAIN'; + } + + if ($ret ne "ok"){ + $c->do_display($thispanel); + } else { + #Do whatever is needed, including writing values to the DB + + + if ($trt eq 'LIST'){ + #do whatever is required ... + $ret = $c->perform_LIST(\%lets_data); + if ($ret ne "ok") { + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash( success => $c->l('lets_LIST_panel_action_was_successful')); #A bit bland - edit it in the lex file + } + } + + if ($trt eq 'PARAMS'){ + #do whatever is required ... + $ret = $c->perform_PARAMS(\%lets_data); + if ($ret ne "ok") { + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash( success => $c->l('lets_PARAMS_panel_action_was_successful')); #A bit bland - edit it in the lex file + } + } + + if ($trt eq 'CHECKALLDOMAINS'){ + #do whatever is required ... + $ret = $c->perform_CHECKALLDOMAINS(\%lets_data); + if ($ret ne "ok") { + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash( success => $c->l('lets_CHECKALLDOMAINS_panel_action_was_successful')); #A bit bland - edit it in the lex file + } + } + + if ($trt eq 'CHECKALLENABLEDDOMAINS'){ + #do whatever is required ... + $ret = $c->perform_CHECKALLENABLEDDOMAINS(\%lets_data); + if ($ret ne "ok") { + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash( success => $c->l('lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful')); #A bit bland - edit it in the lex file + } + } + + if ($trt eq 'CHECKONEDOMAIN'){ + #do whatever is required ... + $ret = $c->perform_CHECKONEDOMAIN(\%lets_data); + if ($ret ne "ok") { + # return to the panel with error message + $c->stash(error => $c->l($ret)); + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); + } else { + $c->stash( success => $c->l('lets_CHECKONEDOMAIN_panel_action_was_successful')); #A bit bland - edit it in the lex file + } + } + + # and call any signal-events needed + #TBD + # Setup shared data and call panel + if ('none' eq 'none') { + $lets_data{'trt'} = 'LIST'; + } else { + $lets_data{'trt'} = 'none'; + } + $c->do_display($lets_data{'trt'}); + } +} + +sub do_display { +# +# Return after link clicked in table (this is a get) - route is "/d" +# Expects ?trt=PANEL&selected="TableRowName" plus any other required +# +# OR it maybe a post from the main panel to add a new record +# +#load up all supplied params into prefix_data hash +#call get-selected-PANEL() - returns hash of all relevent parameters +#load up returned hash into prefix_data +#render - to called panel + + my ($c,$trt) = @_; + $c->app->log->info($c->log_req); + + #The most common ones - you might want to comment out any not used. + my $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); + my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); + my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); + my $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); + my $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + + my %lets_data = (); + my $title = $c->l('lets_Letsencrypt_certificate'); + my $modul = ""; + + # Accessing all parameters + my %params = $c->req->params->to_hash; + + # Get number of parameters + my $num_params = keys %params; + + #Tag as Post or Get (ie. create new entry or edit existing one + my $is_new_record = ($c->req->method() eq 'POST'); + + #Params are available in the hash "params" - copy to the prefix_data hash + #while (my ($key, $value) = each %{$c->req->params->to_hash}) { + # $lets_data{$key} = $value; + #} + + # the value of trt will tell you which panel has returned + if (! $trt){ + $trt = $c->param('trt') || 'LIST'; #Indicates where to go now + } + + # Now add in the params from the selected row from the table + + my %selectedrow; + + if ($trt eq 'LIST'){ + #Validate Get selected row (if applicable) LIST + %selectedrow = $c->get_selected_LIST($lets_data{'Selected'},$is_new_record); + } + + if ($trt eq 'PARAMS'){ + #Validate Get selected row (if applicable) PARAMS + %selectedrow = $c->get_selected_PARAMS($lets_data{'Selected'},$is_new_record); + } + + if ($trt eq 'CHECKALLDOMAINS'){ + #Validate Get selected row (if applicable) CHECKALLDOMAINS + %selectedrow = $c->get_selected_CHECKALLDOMAINS($lets_data{'Selected'},$is_new_record); + } + + if ($trt eq 'CHECKALLENABLEDDOMAINS'){ + #Validate Get selected row (if applicable) CHECKALLENABLEDDOMAINS + %selectedrow = $c->get_selected_CHECKALLENABLEDDOMAINS($lets_data{'Selected'},$is_new_record); + } + + if ($trt eq 'CHECKONEDOMAIN'){ + #Validate Get selected row (if applicable) CHECKONEDOMAIN + %selectedrow = $c->get_selected_CHECKONEDOMAIN($lets_data{'Selected'},$is_new_record); + } + + + #Copy in the selected row params to the prefix_data hash to pass to the panel + while (my ($key, $value) = each %selectedrow){ + $lets_data{$key} = $value; + } + # Where to go now + $lets_data{'trt'} = $trt; + + # Set up other shared data according to the panel to go to + + if ($trt eq 'LIST'){ + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_LIST(); + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } + + if ($trt eq 'PARAMS'){ + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_PARAMS(); + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } + + if ($trt eq 'CHECKALLDOMAINS'){ + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_CHECKALLDOMAINS(); + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } + + if ($trt eq 'CHECKALLENABLEDDOMAINS'){ + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_CHECKALLENABLEDDOMAINS(); + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } + + if ($trt eq 'CHECKONEDOMAIN'){ + # pickup any other contents needed and load them into hash shared with panel + my %returned_hash; + # subroutine returns a hash directly + %returned_hash = $c->get_data_for_panel_CHECKONEDOMAIN(); + # Copy each key-value pair from the returned hash to the prefix data hash + while (my ($key, $value) = each %returned_hash) { + $lets_data{$key} = $value; + } + } + + + # and table control fields + $c->stash(DomainList=>$c->get_DomainList()); + + + # Data for panel + $c->stash( + title => $title, + modul => $modul, + lets_data => \%lets_data + ); + $c->render(template => "letsencrypt"); +} +1; \ No newline at end of file diff --git a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm new file mode 100644 index 0000000..d4bacec --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/en.pm @@ -0,0 +1,72 @@ +package SrvMngr::I18N::Modules::Letsencrypt::en; +use strict; +use warnings; +use utf8; +use Mojo::Base 'SrvMngr::I18N'; + +use SrvMngr::I18N::Modules::General::en; + +my %lexicon = ( +# +# Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +# +'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings', +'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status', +'lets_SERVICE_STATUS' => 'Service Status', +'lets_EMAIL' => 'Email', +'lets_Back' => 'Back', +'lets_Internal_IP' => 'Internal IP', +'lets_Save' => 'Save', +'lets_Issuer' => 'Issuer', +'lets_IS_IN_CERT' => 'Is In cart', +'lets_For_this_Server' => 'For this Server', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled', +'lets_Check_just_one_domain' => 'Check just one domain', +'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', +'lets_Check_all_domains' => 'Check all domains', +'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful', +'lets_Status_Report' => 'Status Report', +'lets_LABEL_NAMESERVERS' => 'Label timeservers', +'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain', +'lets_Letsencrypt_certificate' => 'Letsencrypt certificate', +'lets_Error_Status_Report' => 'Error Status Report', +'lets_Not_Before' => 'Not Before', +'lets_Content' => 'Content', +'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt', +'lets_API_STATUS' => 'ape Status', +'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status', +'lets_Check_all_enabled_domains' => 'Check all enabled domains', +'lets_All_domains_check_result' => 'All domains check result', +'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful', +'lets_Domains_name' => 'Domains name', +'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status', +'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts', +'lets_Brief_description' => 'Brief description', +'lets_KEYSIZE_STATUS' => 'Keysize Status', +'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME', +'lets_Enabled_domains_check_result' => 'Enabled domains check result', +'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful', +'lets_Internet_IP' => 'Internet IP', +'lets_Expiry' => 'Expiry', +'lets_CHECK_ALL_DOMAINS' => 'Check All Domains', +'lets_LABEL_POINT' => 'Label Point', +'lets_CHECK' => 'Check', +'lets_CONFIG' => 'Config', +'lets_Current_certificate_details' => 'Current certificate details', +'lets_LABEL_LECERT' => 'Label secret', +'lets_One_domain_check_result' => 'One domain check result', +'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful', +'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status', +'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains', +'lets_External_Interface_IP' => 'External Interface IP', +'lets_APPLY' => 'Apply', +); + +our %Lexicon = ( + %{ SrvMngr::I18N::Modules::General::en::Lexicon }, + %lexicon +); + + +1; diff --git a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex new file mode 100644 index 0000000..7da303e --- /dev/null +++ b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Letsencrypt/letsencrypt_en.lex @@ -0,0 +1,54 @@ +# +# Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +# +'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings', +'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status', +'lets_SERVICE_STATUS' => 'Service Status', +'lets_EMAIL' => 'Email', +'lets_Back' => 'Back', +'lets_Internal_IP' => 'Internal IP', +'lets_Save' => 'Save', +'lets_Issuer' => 'Issuer', +'lets_IS_IN_CERT' => 'Is In cart', +'lets_For_this_Server' => 'For this Server', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain', +'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled', +'lets_Check_just_one_domain' => 'Check just one domain', +'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', +'lets_Check_all_domains' => 'Check all domains', +'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful', +'lets_Status_Report' => 'Status Report', +'lets_LABEL_NAMESERVERS' => 'Label timeservers', +'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain', +'lets_Letsencrypt_certificate' => 'Letsencrypt certificate', +'lets_Error_Status_Report' => 'Error Status Report', +'lets_Not_Before' => 'Not Before', +'lets_Content' => 'Content', +'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt', +'lets_API_STATUS' => 'ape Status', +'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status', +'lets_Check_all_enabled_domains' => 'Check all enabled domains', +'lets_All_domains_check_result' => 'All domains check result', +'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful', +'lets_Domains_name' => 'Domains name', +'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status', +'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts', +'lets_Brief_description' => 'Brief description', +'lets_KEYSIZE_STATUS' => 'Keysize Status', +'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME', +'lets_Enabled_domains_check_result' => 'Enabled domains check result', +'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful', +'lets_Internet_IP' => 'Internet IP', +'lets_Expiry' => 'Expiry', +'lets_CHECK_ALL_DOMAINS' => 'Check All Domains', +'lets_LABEL_POINT' => 'Label Point', +'lets_CHECK' => 'Check', +'lets_CONFIG' => 'Config', +'lets_Current_certificate_details' => 'Current certificate details', +'lets_LABEL_LECERT' => 'Label secret', +'lets_One_domain_check_result' => 'One domain check result', +'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful', +'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status', +'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains', +'lets_External_Interface_IP' => 'External Interface IP', +'lets_APPLY' => 'Apply', diff --git a/root/usr/share/smanager/themes/default/public/css/letsencrypt.css b/root/usr/share/smanager/themes/default/public/css/letsencrypt.css new file mode 100644 index 0000000..3d2f1ba --- /dev/null +++ b/root/usr/share/smanager/themes/default/public/css/letsencrypt.css @@ -0,0 +1,90 @@ +/* +Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +*/ +.Letsencrypt-panel {} +.name {} +.rout {} +.grou {} +.link2 {} +.link3 {} +.link4 {} +.endg {} +.subh2 {} +.read4 {} +.read5 {} +.read6 {} +.subh3 {} +.read1 {} +.read2 {} +.read3 {} +.subh4 {} +.tabl1 {} +thead .tabl1 {} +tbody .tabl1 {} +.name {} +.rout {} +.subh {} +.para1 {} +.sele1 {} +.sele2 {} +.sele3 {} +.sele4 {} +.sele5 {} +.sele6 {} +.sele7 {} +.emai8 {} +.subm9 {} +.name {} +.rout {} +.head {} +.subh {} +.text1 {} +.back2 {} +.name {} +.rout {} +.head {} +.subh {} +.text1 {} +.back2 {} +.name {} +.rout {} +.head {} +.subh {} +.read1 {} +.text2 {} +.back3 {} + .inline-buttons { + display: flex; /* Use flexbox to arrange items horizontally */ + gap: 10px; /* Optional: Add space between buttons */ + } + + .inline-buttons .link { + /* Additional styling can be added here if needed */ + } + + + .inline-buttons .link { + display: inline-block; /* Keep links as inline-block for button shape */ + padding: 7px 14px; /* Adjusted padding to approximate 70% of the original */ + margin: 0; /* Remove margin */ + background-color: #efefef; /* Light gray background color */ + color: black; /* Text color */ + text-decoration: none; /* Remove underline */ + border: 2px solid #bbb; /* Thin, light gray border */ + border-radius: 3px; /* Slightly rounded corners */ + font-size: 11.2px; /* Adjusted font size to approximate 70% of the original */ + text-align: center; /* Center the text */ + cursor: pointer; /* Pointer cursor on hover */ } + + /* Hover and active effects for better interaction */ + .inline-buttons .link:hover { + background-color: #d9d9d9; /* Darker shade on hover */ + } + + .inline-buttons .link:active { + background-color: #c0c0c0; /* Even darker shade on click */ + } + + span .label { + padding-top:13em; + } diff --git a/root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep b/root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep new file mode 100644 index 0000000..b6558b0 --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/letsencrypt.html.ep @@ -0,0 +1,69 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +% layout 'default', title => "Sme server 2 - Letsencrypt certificate", share_dir => './'; +%# css specific to this panel: +% content_for 'module' => begin +%= stylesheet '/css/letsencrypt.css' +
+ + % if ($config->{debug} == 1) { +
+		%= dumper $c->current_route
+		%= dumper $lets_data->{trt}
+	
+ % } + +

<%=$title%>

+ + % if ( stash('modul')) { + %= $c->render_to_string(inline => stash('modul') ); + % } + + %if ($c->stash('first')) { +

+ %=$c->render_to_string(inline =>$c->l($c->stash('first'))) +

+ + %} elsif ($c->stash('success')) { +
+

<%=$c->l('lets_Status_Report') %>

+ %= $c->l($c->stash('success')); +

+
+ + %} elsif ($c->stash('error')) { +
+

<%=$c->l('lets_Error_Status_Report') %>

+ %= $c->l($c->stash('error')); +

+
+ %} + + %#Routing to partials according to trt parameter. + %#This ought to be cascading if/then/elsif, but is easier to just stack the if/then's rather like a case statement' + + % if ($lets_data->{trt} eq "LIST") { + %= include 'partials/_lets_LIST' + %} + + % if ($lets_data->{trt} eq "PARAMS") { + %= include 'partials/_lets_PARAMS' + %} + + % if ($lets_data->{trt} eq "CHECKALLDOMAINS") { + %= include 'partials/_lets_CHECKALLDOMAINS' + %} + + % if ($lets_data->{trt} eq "CHECKALLENABLEDDOMAINS") { + %= include 'partials/_lets_CHECKALLENABLEDDOMAINS' + %} + + % if ($lets_data->{trt} eq "CHECKONEDOMAIN") { + %= include 'partials/_lets_CHECKONEDOMAIN' + %} + + + +
+%end \ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep new file mode 100644 index 0000000..84d9c1a --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLDOMAINS.html.ep @@ -0,0 +1,39 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if ($config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Check_all_domains')%>

+ +

<%=l('lets_Loop_through_checking_the_letsencrypt')%>

+ + + %=l('lets_All_domains_check_result') + + % param 'AllDomainsCheck' => $lets_data->{AllDomainsCheck} unless param 'AllDomainsCheck'; + %= text_area 'AllDomainsCheck', cols=>40, rows=>10, Readonly=>'true' +
+ + + %= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()' + + + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep new file mode 100644 index 0000000..df6f8e3 --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKALLENABLEDDOMAINS.html.ep @@ -0,0 +1,39 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if ($config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Check_all_enabled_domains')%>

+ +

<%=l('lets_Loop_through_checking_the_letsencrypt')%>

+ + + %=l('lets_Enabled_domains_check_result') + + % param 'EnabledDomainsCheck' => $lets_data->{EnabledDomainsCheck} unless param 'EnabledDomainsCheck'; + %= text_area 'EnabledDomainsCheck', cols=>40, rows=>10, Readonly=>'true' +
+ + + %= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()' + + + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep new file mode 100644 index 0000000..1480119 --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_CHECKONEDOMAIN.html.ep @@ -0,0 +1,46 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if ($config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Check_just_one_domain')%>

+ +

<%=l('lets_Loop_through_and_check_the')%>

+ +

+ %=l('lets_Domains_name') + + % param 'OneDomainToCheck' => $lets_data->{OneDomainToCheck} unless param 'OneDomainToCheck'; + %= text_field 'OneDomainToCheck', size => '50', class => 'textinput OneDomainToCheck' , pattern=>'.*' , placeholder=>'OneDomainToCheck', Readonly=>'true' +

+ + + %=l('lets_One_domain_check_result') + + % param 'OneDomainsCheck' => $lets_data->{OneDomainsCheck} unless param 'OneDomainsCheck'; + %= text_area 'OneDomainsCheck', cols=>40, rows=>10, Readonly=>'true' +
+ + + %= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()' + + + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep new file mode 100644 index 0000000..aacb2cd --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_LIST.html.ep @@ -0,0 +1,126 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if ($config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +
+ + + + %= l('lets_CONFIG') + + %#= link_to l('lets_CONFIG'), 'letsencryptd?trt=PARAMS' , class=>'link link2' + + + + %= l('lets_CHECK_ALL_DOMAINS') + + %#= link_to l('lets_CHECK_ALL_DOMAINS'), 'letsencryptd?trt=CHECKALLDOMAINS' , class=>'link link3' + + + + %= l('lets_CHECK_ALL_ENABLED_DOMAINS') + + %#= link_to l('lets_CHECK_ALL_ENABLED_DOMAINS'), 'letsencryptd?trt=CHECKALLENABLEDDOMAINS' , class=>'link link4' + + +
+ + +

<%=l('lets_For_this_Server')%>

+ +

+ %=l('lets_Internal_IP') + + % param 'InternalIP' => $lets_data->{InternalIP} unless param 'InternalIP'; + %= text_field 'InternalIP', size => '50', class => 'textinput InternalIP' , pattern=>'.*' , placeholder=>'InternalIP', Readonly=>'true' +

+ +

+ %=l('lets_External_Interface_IP') + + % param 'ExternalIP' => $lets_data->{ExternalIP} unless param 'ExternalIP'; + %= text_field 'ExternalIP', size => '50', class => 'textinput ExternalIP' , pattern=>'.*' , placeholder=>'ExternalIP', Readonly=>'true' +

+ +

+ %=l('lets_Internet_IP') + + % param 'InternetIP' => $lets_data->{InternetIP} unless param 'InternetIP'; + %= text_field 'InternetIP', size => '50', class => 'textinput InternetIP' , pattern=>'.*' , placeholder=>'InternetIP', Readonly=>'true' +

+ +

<%=l('lets_Current_certificate_details')%>

+ +

+ %=l('lets_Issuer') + + % param 'Issuer' => $lets_data->{Issuer} unless param 'Issuer'; + %= text_field 'Issuer', size => '50', class => 'textinput Issuer' , pattern=>'.*' , placeholder=>'Issuer', Readonly=>'true' +

+ +

+ %=l('lets_Expiry') + + % param 'Expiry' => $lets_data->{Expiry} unless param 'Expiry'; + %= text_field 'Expiry', size => '50', class => 'textinput Expiry' , pattern=>'.*' , placeholder=>'Expiry', Readonly=>'true' +

+ +

+ %=l('lets_Not_Before') + + % param 'NotBefore' => $lets_data->{NotBefore} unless param 'NotBefore'; + %= text_field 'NotBefore', size => '50', class => 'textinput NotBefore' , pattern=>'.*' , placeholder=>'NotBefore', Readonly=>'true' +

+ +

<%=l('lets_List_of_Domains_and_Hosts')%>

+ +
+ + + + + + + + + + + + + + % my $control_data = $c->stash('DomainList'); + % foreach my $row (@$control_data) { + + + + + + + + + + + %} + +
<%=l('lets_Domain_name_/_HOSTNAME')%><%=l('lets_Brief_description')%><%=l('lets_Content')%><%=l('lets_LABEL_NAMESERVERS')%><%=l('lets_LABEL_POINT')%><%=l('lets_LABEL_LECERT')%><%=l('lets_IS_IN_CERT')%><%=l('lets_CHECK')%>
<%=$c->render_to_string(inline=>$row->{'Table1-Domain name / HOSTNAME'})%><%=$c->render_to_string(inline=>$row->{'Table1-Brief description'})%><%=$c->render_to_string(inline=>$row->{'Table1-Content'})%><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_NAMESERVERS'})%><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_POINT'})%><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_LECERT'})%><%=$c->render_to_string(inline=>$row->{'Table1-IS_IN_CERT'})%><%=$c->render_to_string(inline=>$row->{'Table1-CHECK'})%>
+ + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep b/root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep new file mode 100644 index 0000000..2dfb0ba --- /dev/null +++ b/root/usr/share/smanager/themes/default/templates/partials/_lets_PARAMS.html.ep @@ -0,0 +1,97 @@ +%# +%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 +%# +
+ + % if ($config->{debug} == 1) { +
+			%= dumper $lets_data
+		
+ % } + % my $btn = l('lets_APPLY'); + %= form_for "letsencryptu" => (method => 'POST') => begin + % param 'trt' => $lets_data->{trt} unless param 'trt'; + %= hidden_field 'trt' => $lets_data->{trt} + %# Inputs etc in here. + +

<%=l('lets_Manage_letsencrypt-config_settings:')%>

+ +

+ %=l('lets_CONFIG_LETSENCRYPT') +

+ +

+ %=l('lets_SERVICE_STATUS') + + % my @status_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled'], ['TEST' => 'test']]; + % param 'status' => $lets_data->{status} unless param 'status'; + %= select_field 'status' => @status_options, class => 'input' +

+ +

+ %=l('lets_HOOKSCRIPT_STATUS') + + % my @hookScript_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled']]; + % param 'hookScript' => $lets_data->{hookScript} unless param 'hookScript'; + %= select_field 'hookScript' => @hookScript_options, class => 'input' +

+ +

+ %=l('lets_HOSTOVERRIDE_STATUS') + + % my @hostOverride_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']]; + % param 'hostOverride' => $lets_data->{hostOverride} unless param 'hostOverride'; + %= select_field 'hostOverride' => @hostOverride_options, class => 'input' +

+ +

+ %=l('lets_ACCEPT_TERMS_STATUS') + + % my @ACCEPT_TERMS_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']]; + % param 'ACCEPT_TERMS' => $lets_data->{ACCEPT_TERMS} unless param 'ACCEPT_TERMS'; + %= select_field 'ACCEPT_TERMS' => @ACCEPT_TERMS_options, class => 'input' +

+ +

+ %=l('lets_API_STATUS') + + % my @API_options = [['2' => '2']]; + % param 'API' => $lets_data->{API} unless param 'API'; + %= select_field 'API' => @API_options, class => 'input' +

+ +

+ %=l('lets_KEYSIZE_STATUS') + + % my @keysize_options = [['2048' => '2048'], ['3072' => '3072'], ['4096' => '4096']]; + % param 'keysize' => $lets_data->{keysize} unless param 'keysize'; + %= select_field 'keysize' => @keysize_options, class => 'input' +

+ +

+ %=l('lets_CONFIGUREMODE_STATUS') + + % my @configure_options = [['ALL' => 'all'], ['Domains' => 'domains'], ['HOSTS' => 'hosts'], ['NONE' => 'none']]; + % param 'configure' => $lets_data->{configure} unless param 'configure'; + %= select_field 'configure' => @configure_options, class => 'input' +

+ +

+ %=l('lets_EMAIL') + + % param 'email' => $lets_data->{email} unless param 'email'; + %=email_field 'email', class => 'emai8' +

+ + + + %= submit_button l('lets_Save'), class => 'action subm9' + + + %# Probably finally by a submit. + %end +
\ No newline at end of file diff --git a/smeserver-manager.spec b/smeserver-manager.spec index 1a8aeda..88e7ba0 100644 --- a/smeserver-manager.spec +++ b/smeserver-manager.spec @@ -2,7 +2,7 @@ Summary: Sme server navigation module : manager 2 %define name smeserver-manager Name: %{name} %define version 11.0.0 -%define release 29 +%define release 30 Version: %{version} Release: %{release}%{?dist} License: GPL @@ -35,6 +35,8 @@ Requires: perl(DBM::Deep) >= 2.0011-1 Requires: perl(Mojo::JWT) >= 0.08-1 Requires: mutt >= 1.5.21 Requires: smeserver-manager-jsquery >= 1.0 +Requires: smeserver-lib >= 11.0 +Requires: smeserver-certificates >= 11.0 #Requires: js-jquery > 2.2.4-3 (optional) Provides: server-manager @@ -113,6 +115,9 @@ true %defattr(-,root,root) %changelog +* Fri Dec 13 2024 Brian Read 11.0.0-30.sme +- Add in letsencrypt panel, add requires for smeserver-lib and smeserver-certificates [SME: 12810] + * Tue Nov 26 2024 Brian Read 11.0.0-29.sme - Fix remoteaccess panel, reformat pm file and bring success panel into line with other similar panels [SME: 12747]