Compare commits

...

6 Commits

11 changed files with 352 additions and 89 deletions

View File

@@ -27,10 +27,10 @@ It is based on the perl Mojolicious package. Mojolicious is a real-time web fram
smeserver-manager provides an intuitive and user-friendly web interface that allows administrators to manage various aspects of the server without needing deep technical knowledge or command-line skills.
#### User and Group Management:
Easily add, remove, and manage user accounts and groups. The interface simplifies creating email accounts, setting passwords, and configuring user permissions.
It allows you to easily add, remove, and manage user accounts and groups. The interface simplifies creating email accounts, setting passwords, and configuring user permissions.
#### Network Configuration:
Configures network settings such as IP addresses, DNS, DHCP, and gateway settings. The interface also provides options for setting up VPNs, remote access, and firewall rules.
You can configures network settings such as IP addresses, DNS, DHCP, and gateway settings. The interface also provides options for setting up VPNs, remote access, and firewall rules.
#### File Sharing and Storage:
Enables and manages file sharing services like Samba (for Windows file sharing) and NFS (for Unix/Linux file sharing). Administrators can easily create shared folders and manage permissions.

2
clog
View File

@@ -1,2 +0,0 @@
* Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-14.sme
- fix [SME: ]

View File

@@ -67,5 +67,21 @@ hr.sme-copyrightbar {
color: #8ebe43;
background-color: #8ebe43;
}
/* flag container no flag */
#flag-container span {
font-size: 24px;
}
.fallback-box {
display: inline-block; /* Make it inline-block to fit around the content */
border: 2px solid gray; /* Change the border color as desired */
padding: 10px; /* Add some padding */
border-radius: 10px; /* Round the corners of the box */
font-size: 60px; /* Adjust size if needed */
margin-top: 10px; /* Add some margin */
text-align: center; /* Center text inside the box */
}
HERE
}

View File

@@ -23,14 +23,16 @@ use File::Basename;
our $cdb = esmith::ConfigDB->open || die "Couldn't open config db";
my $dnf_status_file = '/var/cache/dnf/dnf.status';
#use File::stat;
our %dbs;
for ( qw(available installed updates) )
{
$dbs{$_} = esmith::ConfigDB->open_ro("yum_$_") or
die "Couldn't open yum_$_ DB\n";
$dbs{$_} = esmith::ConfigDB->open_ro("dnf_$_") or
die "Couldn't open dnf_$_ DB\n";
}
for ( qw(repositories) )
@@ -52,10 +54,11 @@ sub main {
$yum_datas{'trt'} = 'STAT';
if ( -e "/var/run/yum.pid" ) {
if ( $c->is_dnf_running()) {
$yum_datas{'trt'} = 'LOGF';
$dest = 'yumlogfile';
} elsif ($cdb->get_prop('yum', 'LogFile')) {
} elsif ($cdb->get_prop('dnf', 'LogFile')) {
$yum_datas{'trt'} = 'PSTU';
$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes');
$dest = 'yumpostupg';
@@ -83,9 +86,9 @@ sub do_display {
$yum_datas{'trt'} = $trt;
# force $trt if current logfile
if ( -e "/var/run/yum.pid" ) {
if ( $c->is_dnf_running() ) {
$trt = 'LOGF';
} elsif ($cdb->get_prop('yum', 'LogFile')) {
} elsif ($cdb->get_prop('dnf', 'LogFile')) {
$trt = 'PSTU';
}
@@ -106,13 +109,13 @@ sub do_display {
}
if ( $trt eq 'LOGF' ) {
if (-e "/var/run/yum.pid") {
if ($c->is_dnf_running()) {
$dest = 'yumlogfile';
}
}
if ( $trt eq 'PSTU') {
if ($cdb->get_prop('yum', 'LogFile')) {
if ($cdb->get_prop('dnf', 'LogFile')) {
$dest = 'yumpostupg';
$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes');
}
@@ -221,7 +224,7 @@ sub do_update {
if ( $trt eq 'LOGF' ) {
$dest = 'yumlogfile';
if ( ! -e "/var/run/yum.pid") {
if ( ! $c->is_dnf_running()) {
$yum_datas{trt} = 'SUC';
$result = $c->l('yum_SUCCESS');
}
@@ -247,6 +250,24 @@ sub do_update {
};
sub get_dnf_status {
#interrogate status file created and maintained by smeserver.py plugin for dnf.
my ($c) = @_;
my $file_name = $dnf_status_file;
my $content = "resolved";
if ( -e "$file_name") {
open my $fh, '<', $file_name or die "Can't open file: $!";
$content = <$fh>;
close $fh;
}
return $content;
}
sub is_dnf_running {
my ($c) = @_;
my $dnf_status = $c->get_dnf_status();
return $dnf_status ne "resolved" && $dnf_status ne "config" && $dnf_status ne "sack";
}
sub is_empty {
@@ -289,7 +310,7 @@ sub package_functions_enabled {
my ($c) = @_;
return ($cdb->get_prop("yum", "PackageFunctions") eq "enabled");
return ($cdb->get_prop("dnf", "PackageFunctions") eq "enabled");
}
@@ -298,7 +319,7 @@ sub get_status {
my ($c, $prop, $localise) = @_;
my $status = $cdb->get_prop("yum", $prop) || 'disabled';
my $status = $cdb->get_prop("dnf", $prop) || 'disabled';
return $status unless $localise;
@@ -433,7 +454,7 @@ sub change_settings {
PackageFunctions
) )
{
$cdb->set_prop('yum', $param, $c->param("yum_$param"));
$cdb->set_prop("dnf", $param, $c->param("yum_$param"));
}
my $check4updates = $c->param("yum_check4updates");
@@ -441,21 +462,21 @@ sub change_settings {
if ($check4updates ne 'disabled') { $status = 'enabled'; }
$cdb->set_prop('yum', 'check4updates', $check4updates);
$cdb->set_prop("dnf", 'check4updates', $check4updates);
my $deltarpm = $c->param("yum_DeltaRpmProcess");
$cdb->set_prop('yum', 'DeltaRpmProcess', $deltarpm);
$cdb->set_prop("dnf", 'DeltaRpmProcess', $deltarpm);
my $downloadonly = $c->param("yum_DownloadOnly");
if ($downloadonly ne 'disabled') { $status = 'enabled'; }
$cdb->set_prop('yum', 'DownloadOnly', $downloadonly);
$cdb->set_prop("dnf", 'DownloadOnly', $downloadonly);
my $AutoInstallUpdates = $c->param("yum_AutoInstallUpdates");
if ($AutoInstallUpdates ne 'disabled') { $status = 'enabled'; }
$cdb->set_prop('yum', 'AutoInstallUpdates', $AutoInstallUpdates);
$cdb->set_prop('yum', 'status', $status);
$cdb->set_prop("dnf", 'AutoInstallUpdates', $AutoInstallUpdates);
$cdb->set_prop("dnf", 'status', $status);
my %selected = map {$_ => 1} @{$c->every_param('SelectedRepositories')};
@@ -469,7 +490,7 @@ sub change_settings {
$dbs{repositories}->reload;
unless ( system( "/sbin/e-smith/signal-event", "yum-modify" ) == 0 )
unless ( system( "/sbin/e-smith/signal-event", "dnf-modify" ) == 0 )
{
return $c->l('yum_ERROR_UPDATING_CONFIGURATION');
}
@@ -484,11 +505,11 @@ sub do_yum {
for ( qw(SelectedGroups SelectedPackages) )
{
$cdb->set_prop("yum", $_, join(',', (@{$c->every_param($_)} )));
$cdb->set_prop("dnf", $_, join(',', (@{$c->every_param($_)} )));
}
esmith::util::backgroundCommand(0,
"/sbin/e-smith/signal-event", "yum-$function");
"/sbin/e-smith/signal-event", "dnf-$function");
for ( qw(available installed updates) ) {
$dbs{$_}->reload;
@@ -517,7 +538,7 @@ sub format_yum_log {
$cdb->reload;
my $filepage = $cdb->get_prop('yum', 'LogFile');
my $filepage = $cdb->get_prop('dnf', 'LogFile');
return '' unless $filepage and ( -e "$filepage" );
my $out = sprintf "<PRE>";
@@ -537,7 +558,7 @@ sub post_upgrade_reboot {
my $c = shift;
$cdb->get_prop_and_delete('yum', 'LogFile');
$cdb->get_prop_and_delete('dnf', 'LogFile');
$cdb->reload;
if (fork == 0) {
@@ -552,7 +573,7 @@ sub post_upgrade_reboot {
sub show_yum_log {
my $c = shift;
my $out = $c->format_yum_log();
my $yum_log = $cdb->get_prop_and_delete('yum', 'LogFile');
my $yum_log = $cdb->get_prop_and_delete('dnf', 'LogFile');
return $out;
}

View File

@@ -1,63 +1,278 @@
document.addEventListener('DOMContentLoaded', () => {
const flagContainer = document.getElementById('flag-container');
// Function to get the browser's locale
function getBrowserLocale() {
return navigator.language || navigator.userLanguage;
}
async function getCountryName(countryCode) {
try {
const response = await fetch(`https://restcountries.com/v3.1/alpha/${countryCode}`);
if (!response.ok) throw new Error('Country not found');
const data = await response.json();
// Return the name in the native language
return data[0].name.common;
} catch (error) {
console.error(error);
return 'Unknown Country';
}
}
// Function to map locale to country code
function getCountryCodeFromLocale(locale) {
const localeParts = locale.split('-');
return localeParts.length > 1 ? localeParts[1] : localeParts[0];
}
function getFlagEmoji(locale) {
// Split the locale to get the language and country code
const parts = locale.split('-');
let countryCode;
// Function to fetch country names from a CDN
async function fetchCountryNames() {
const response = await fetch('https://restcountries.com/v3.1/all');
const countries = await response.json();
const countryNames = {};
for (const country of countries) {
const code = country.cca2.toLowerCase(); // Country code (ISO 3166-1 alpha-2)
const name = country.name.common; // Common name of the country
countryNames[code] = name;
}
return countryNames;
}
// Handle single subtag (language only) or double subtag (language-country)
if (parts.length === 1) {
countryCode = getCountryCodeFromLanguage(parts[0]);
} else if (parts.length === 2) {
countryCode = parts[1].toLowerCase(); // Use the country code
}
// Function to create and display the flag icon
function displayFlagIcon(countryCode, countryName) {
const flagIcon = document.createElement('span');
flagIcon.className = `flag-icon flag-icon-${countryCode.toLowerCase()}`;
flagIcon.id = 'flag-icon';
flagIcon.title = countryName; // Set the title for the tooltip
// If country code is not found, set a fallback output
if (!countryCode) {
const fallback = `? ${locale.toUpperCase()}`; // Just a question mark and the full locale
return { flag: fallback, isUnknown: true, countryName: 'Unknown Country' };
}
// If you want a custom tooltip instead (uncomment the lines below):
/*
const tooltip = document.createElement('span');
tooltip.className = 'tooltip';
tooltip.innerText = countryName;
flagIcon.appendChild(tooltip);
// Convert the country code to a flag emoji
return {
flag: String.fromCodePoint(...[...countryCode.toUpperCase()].map(char => 0x1F1E6 + char.charCodeAt(0) - 'A'.charCodeAt(0))),
isUnknown: false,
countryCode: countryCode
};
}
flagIcon.addEventListener('mouseenter', () => {
tooltip.style.display = 'block';
});
function getCountryCodeFromLanguage(language) {
// Map languages to countries (this is an example, extend as needed)
const languageToCountryMap = {
// Add more mappings as needed
"af": "NA",
"agq": "CM",
"ak": "GH",
"am": "ET",
"ar": "01",
"as": "IN",
"asa": "TZ",
"ast": "ES",
"az": "rl",
"bas": "CM",
"be": "BY",
"bem": "ZM",
"bez": "TZ",
"bg": "BG",
"bm": "ML",
"bn": "BD",
"bo": "CN",
"br": "FR",
"brx": "IN",
"bs": "rl",
"ca": "AD",
"ccp": "BD",
"ce": "RU",
"cgg": "UG",
"chr": "US",
"ckb": "IQ",
"cs": "CZ",
"cy": "GB",
"da": "DK",
"dav": "KE",
"de": "DE",
"dje": "NE",
"dsb": "DE",
"dua": "CM",
"dyo": "SN",
"dz": "BT",
"ebu": "KE",
"ee": "GH",
"el": "CY",
"en": "01",
"es": "ES",
"et": "EE",
"eu": "ES",
"ewo": "CM",
"fa": "AF",
"ff": "CM",
"fi": "FI",
"fil": "PH",
"fo": "FO",
"fr": "FR",
"fur": "IT",
"fy": "NL",
"ga": "IE",
"gd": "GB",
"gl": "ES",
"gsw": "CH",
"gu": "IN",
"guz": "KE",
"gv": "IM",
"ha": "GH",
"haw": "US",
"he": "IL",
"hi": "IN",
"hr": "HR",
"hsb": "DE",
"hu": "HU",
"hy": "AM",
"id": "ID",
"ig": "NG",
"ii": "CN",
"is": "IS",
"it": "IT",
"ja": "JP",
"jgo": "CM",
"jmc": "TZ",
"ka": "GE",
"kab": "DZ",
"kam": "KE",
"kde": "TZ",
"kea": "CV",
"khq": "ML",
"ki": "KE",
"kk": "KZ",
"kkj": "CM",
"kl": "GL",
"kln": "KE",
"km": "KH",
"kn": "IN",
"ko": "KP",
"kok": "IN",
"ks": "IN",
"ksb": "TZ",
"ksf": "CM",
"ksh": "DE",
"kw": "GB",
"ky": "KG",
"lag": "TZ",
"lb": "LU",
"lg": "UG",
"lkt": "US",
"ln": "AO",
"lo": "LA",
"lrc": "IQ",
"lt": "LT",
"lu": "CD",
"luo": "KE",
"Luo": "KE",
"luy": "KE",
"lv": "LV",
"mas": "KE",
"mer": "KE",
"mfe": "MU",
"mg": "MG",
"mgh": "MZ",
"mgo": "CM",
"mk": "MK",
"ml": "IN",
"mn": "MN",
"mr": "IN",
"ms": "BN",
"mt": "MT",
"mua": "CM",
"my": "MM",
"mzn": "IR",
"naq": "NA",
"nb": "NO",
"nd": "ZW",
"nds": "DE",
"ne": "IN",
"nl": "NL",
"nmg": "CM",
"nn": "NO",
"nnh": "CM",
"nus": "SS",
"nyn": "UG",
"om": "ET",
"or": "IN",
"os": "GE",
"pa": "ab",
"pl": "PL",
"ps": "AF",
"pt": "PT",
"qu": "BO",
"rm": "CH",
"rn": "BI",
"ro": "RO",
"rof": "TZ",
"ru": "RU",
"rw": "RW",
"rwk": "TZ",
"sah": "RU",
"saq": "KE",
"sbp": "TZ",
"se": "SE",
"seh": "MZ",
"ses": "ML",
"sg": "CF",
"shi": "tn",
"si": "LK",
"sk": "SK",
"sl": "SI",
"smn": "FI",
"sn": "ZW",
"so": "SO",
"sq": "AL",
"sr": "rl",
"sv": "AX",
"sw": "CD",
"ta": "IN",
"te": "IN",
"teo": "KE",
"tg": "TJ",
"th": "TH",
"ti": "ER",
"to": "TO",
"tr": "TR",
"tt": "RU",
"twq": "NE",
"tzm": "MA",
"ug": "CN",
"uk": "UA",
"ur": "IN",
"uz": "ab",
"vai": "tn",
"Vai": "tn",
"vi": "VN",
"vun": "TZ",
"wae": "CH",
"wo": "SN",
"xog": "UG",
"yav": "CM",
"yi": "01",
"yo": "BJ",
"yue": "ns",
"zgh": "MA",
"zh": "ns",
"zu": "ZA"
flagIcon.addEventListener('mouseleave', () => {
tooltip.style.display = 'none';
});
*/
flagContainer.appendChild(flagIcon);
}
};
// Main logic
(async () => {
const locale = getBrowserLocale();
const countryCode = getCountryCodeFromLocale(locale);
const countryNames = await fetchCountryNames(); // Fetch country names
return languageToCountryMap[language] || null;
}
const countryName = countryNames[countryCode.toLowerCase()] || 'Unknown Country'; // Get the country name
displayFlagIcon(countryCode, countryName); // Display the flag with country name
})();
async function displayLocaleAndFlag() {
// Get the browser locale
const userLocale = navigator.language || navigator.userLanguage;
const { flag, isUnknown, countryCode } = getFlagEmoji(userLocale);
// Display the locale and the corresponding flag (or fallback)
//document.getElementById('locale').textContent = `Your Locale: ${userLocale}`;
if (isUnknown) {
const fallbackDiv = document.createElement('div');
fallbackDiv.className = 'fallback-box';
fallbackDiv.textContent = `? ${userLocale.toUpperCase()}`; // Only show ? and locale code inside the box
//document.getElementById('flag-container').textContent = "Flag: ";
document.getElementById('flag-container').appendChild(fallbackDiv);
// Tooltip for fallback
fallbackDiv.title = "Unknown Country"; // Tooltip for fallback
} else {
const countryName = await getCountryName(countryCode);
const flagSpan = document.createElement('span');
flagSpan.textContent = flag; // Use flag emoji
flagSpan.title = countryName; // Tooltip for the flag in country language
//document.getElementById('flag-container').textContent = "Flag: ";
document.getElementById('flag-container').appendChild(flagSpan);
}
}
displayLocaleAndFlag();
});

View File

@@ -79,9 +79,9 @@
%= hidden_field 'trt' => 'CONF'
<br>
<div class='center'>
<!--<div class='center'>-->
%= submit_button $c->l('SAVE'), class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -47,9 +47,9 @@
%= hidden_field 'trt' => 'INST'
<br><br>
<div class='center'>
<!-- <div class='center'>-->
%= submit_button $c->l('yum_INSTALL_SOFTWARE'), class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -34,9 +34,9 @@
%= hidden_field 'trt' => 'PSTU'
%= hidden_field 'reconf' => $yum_datas->{reconf}
<br>
<div class='center'>
<!-- <div class='center'>-->
%= submit_button "$btn", class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -46,9 +46,9 @@
%= hidden_field 'trt' => 'REMO'
<br>
<div class='center'>
<!--<div class='center'>-->
%= submit_button $c->l('REMOVE'), class => 'action'
</div>
<!--</div>-->
% end

View File

@@ -33,9 +33,9 @@
%= hidden_field 'trt' => 'UPDT'
<br>
<div class='center'>
<!--<div class='center'>-->
%= submit_button $c->l('yum_INSTALL_UPDATES'), class => 'action'
</div>
<!--</div>-->
% end

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 14
%define release 18
Version: %{version}
Release: %{release}%{?dist}
License: GPL
@@ -108,8 +108,21 @@ true
%defattr(-,root,root)
%changelog
* Sun Aug 25 2024 Brian Read <brianr@koozali.org> 11.0.0-18.sme
- Move flag to emojii from downloaded jpg. Fix singleton locale issue[SME: 12706]
* Thu Aug 22 2024 Brian Read <brianr@koozali.org> 11.0.0-17.sme
- Left Align Software Install panels Submit button [SME: 12727]
* Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-16.sme
- Typo uc DNF changed to lc dnf in Yum.pm [SME: 127245]
- Monitor dnf running using dnf status file
* Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-15.sme
- Migrate SM2 Software installer panel from use of yum to dnf [SME: 12718]
* Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-14.sme
- fix [SME: ]
- Version skipped due to operator error! [SME: <none> ]
* Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-13.sme
- Fix sysles.css template - overwrote it by mistake [SME: 12706]