diff --git a/admin_domains.php b/admin_domains.php index 147f5319..6239035c 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -699,9 +699,14 @@ if ($page == 'domains' || $page == 'overview') { } elseif ($page == 'domaindnseditor' && Settings::Get('system.dnsenabled') == '1') { require_once __DIR__ . '/dns_editor.php'; + } elseif ($page == 'sslcertificates') { - + require_once __DIR__ . '/ssl_certificates.php'; + +} elseif ($page == 'logfiles') { + + require_once __DIR__.'/logfiles_viewer.php'; } function formatDomainEntry(&$row, &$idna_convert) diff --git a/customer_domains.php b/customer_domains.php index 096a930f..ad6420f3 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -496,4 +496,7 @@ if ($page == 'overview') { require_once __DIR__.'/ssl_certificates.php'; -} \ No newline at end of file +} elseif ($page == 'logfiles') { + + require_once __DIR__.'/logfiles_viewer.php'; +} diff --git a/install/froxlor.sql b/install/froxlor.sql index 9801cfd5..c861cbd4 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -204,6 +204,7 @@ CREATE TABLE `panel_customers` ( `allowed_phpconfigs` varchar(500) NOT NULL default '', `type_2fa` tinyint(1) NOT NULL default '0', `data_2fa` varchar(500) NOT NULL default '', + `logviewenabled` tinyint(1) NOT NULL default '0', PRIMARY KEY (`customerid`), UNIQUE KEY `loginname` (`loginname`) ) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci; @@ -693,7 +694,7 @@ opcache.interned_strings_buffer'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'version', '0.10.0'), - ('panel', 'db_version', '201811300'); + ('panel', 'db_version', '201812010'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index 7ff7a986..8bab98e7 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -96,3 +96,12 @@ if (isDatabaseVersion('201811180')) { updateToDbVersion('201811300'); } + +if (isDatabaseVersion('201811300')) { + + showUpdateStep("Adding new logview-flag to customers"); + Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `logviewenabled` tinyint(1) NOT NULL default '0';"); + lastStepStatus(0); + + updateToDbVersion('201812010'); +} diff --git a/lib/classes/api/commands/class.Customers.php b/lib/classes/api/commands/class.Customers.php index 2b3d9b75..154b7655 100644 --- a/lib/classes/api/commands/class.Customers.php +++ b/lib/classes/api/commands/class.Customers.php @@ -197,10 +197,12 @@ class Customers extends ApiCommand implements ResourceEntity * @param bool $perlenabled * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, ether to allow usage of the DNS editor (requires activated nameserver in settings) + * optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) + * @param bool $logviewenabled + * optional, ether to allow acccess to webserver access/error-logs, default 0 (false) * @param bool $store_defaultindex * optional, whether to store the default index file to customers homedir - * + * * @access admin * @throws Exception * @return array @@ -248,6 +250,7 @@ class Customers extends ApiCommand implements ResourceEntity $p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array()); $perlenabled = $this->getParam('perlenabled', true, 0); $dnsenabled = $this->getParam('dnsenabled', true, 0); + $logviewenabled = $this->getParam('logviewenabled', true, 0); $store_defaultindex = $this->getParam('store_defaultindex', true, 0); $loginname = $this->getParam('new_loginname', true, ''); @@ -375,6 +378,10 @@ class Customers extends ApiCommand implements ResourceEntity $dnsenabled = '1'; } + if ($logviewenabled != '0') { + $logviewenabled = '1'; + } + if ($password == '') { $password = generatePassword(); } @@ -415,6 +422,7 @@ class Customers extends ApiCommand implements ResourceEntity 'pop3' => $email_pop3, 'perlenabled' => $perlenabled, 'dnsenabled' => $dnsenabled, + 'logviewenabled' => $logviewenabled, 'theme' => $_theme, 'custom_notes' => $custom_notes, 'custom_notes_show' => $custom_notes_show @@ -456,6 +464,7 @@ class Customers extends ApiCommand implements ResourceEntity `pop3` = :pop3, `perlenabled` = :perlenabled, `dnsenabled` = :dnsenabled, + `logviewenabled` = :logviewenabled, `theme` = :theme, `custom_notes` = :custom_notes, `custom_notes_show` = :custom_notes_show @@ -828,7 +837,9 @@ class Customers extends ApiCommand implements ResourceEntity * @param bool $perlenabled * optional, whether to allow usage of Perl/CGI, default 0 (false) * @param bool $dnsenabled - * optional, ether to allow usage of the DNS editor (requires activated nameserver in settings) + * optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) + * @param bool $logviewenabled + * optional, ether to allow acccess to webserver access/error-logs, default 0 (false) * @param string $theme * optional, change theme * @@ -888,6 +899,7 @@ class Customers extends ApiCommand implements ResourceEntity $allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, json_decode($result['allowed_phpconfigs'], true)); $perlenabled = $this->getParam('perlenabled', true, $result['perlenabled']); $dnsenabled = $this->getParam('dnsenabled', true, $result['dnsenabled']); + $logviewenabled = $this->getParam('logviewenabled', true, $result['logviewenabled']); $deactivated = $this->getParam('deactivated', true, $result['deactivated']); $theme = $this->getParam('theme', true, $result['theme']); } else { @@ -1029,6 +1041,10 @@ class Customers extends ApiCommand implements ResourceEntity inserttask('1'); } + if ($logviewenabled != '0') { + $logviewenabled = '1'; + } + // activate/deactivate customer services if ($deactivated != $result['deactivated']) { @@ -1167,6 +1183,7 @@ class Customers extends ApiCommand implements ResourceEntity 'pop3' => $email_pop3, 'perlenabled' => $perlenabled, 'dnsenabled' => $dnsenabled, + 'logviewenabled' => $logviewenabled, 'custom_notes' => $custom_notes, 'custom_notes_show' => $custom_notes_show ); @@ -1208,6 +1225,7 @@ class Customers extends ApiCommand implements ResourceEntity `pop3` = :pop3, `perlenabled` = :perlenabled, `dnsenabled` = :dnsenabled, + `logviewenabled` = :logviewenabled, `custom_notes` = :custom_notes, `custom_notes_show` = :custom_notes_show"; $upd_query .= $admin_upd_query; diff --git a/lib/formfields/admin/customer/formfield.customer_add.php b/lib/formfields/admin/customer/formfield.customer_add.php index 862ecb9f..43a0808f 100644 --- a/lib/formfields/admin/customer/formfield.customer_add.php +++ b/lib/formfields/admin/customer/formfield.customer_add.php @@ -327,6 +327,16 @@ return array( ) ), 'visible' => (Settings::Get('system.dnsenabled') == '1' ? true : false) + ), + 'logviewenabled' => array( + 'label' => $lng['admin']['logviewenabled'] . '?', + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ) ) ) ) diff --git a/lib/formfields/admin/customer/formfield.customer_edit.php b/lib/formfields/admin/customer/formfield.customer_edit.php index 86d8820c..22370ec8 100644 --- a/lib/formfields/admin/customer/formfield.customer_edit.php +++ b/lib/formfields/admin/customer/formfield.customer_edit.php @@ -297,6 +297,17 @@ return array( 'value' => array($result['dnsenabled']), 'visible' => (Settings::Get('system.dnsenabled') == '1' ? true : false) ), + 'logviewenabled' => array( + 'label' => $lng['admin']['logviewenabled'] . '?', + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array($result['logviewenabled']) + ) ) ), 'section_d' => array( diff --git a/lib/version.inc.php b/lib/version.inc.php index 195f0938..142c0422 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -19,7 +19,7 @@ $version = '0.10.0'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201811300'; +$dbversion = '201812010'; // Distribution branding-tag (used for Debian etc.) $branding = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index 0e409461..0565eeaa 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2165,3 +2165,5 @@ $lng['mails']['2fa']['subject'] = 'Froxlor - 2FA Code'; $lng['2fa']['2fa_overview_desc'] = 'Here you can activate a two-factor authentication for your account.

You can either use an authenticator-app (time-based one-time password / TOTP) or let froxlor send you an email to your account-address after each successful login with a one-time password.'; $lng['2fa']['2fa_email_desc'] = 'Your account is set up to use one-time passwords via e-mail. To deactivate, click on "'.$lng['2fa']['2fa_delete'].'"'; $lng['2fa']['2fa_ga_desc'] = 'Your account is set up to use time-based one-time passwords via authenticator-app. Please scan the QR code below with your desired authenticator app to generate the codes. To deactivate, click on "'.$lng['2fa']['2fa_delete'].'"'; +$lng['admin']['logviewenabled'] = 'Enable access to access/error-logs'; +$lng['panel']['viewlogs'] = 'View logfiles'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 5cb0ef52..3036fd22 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1813,3 +1813,5 @@ $lng['mails']['2fa']['subject'] = 'Froxlor - 2FA Code'; $lng['2fa']['2fa_overview_desc'] = 'Hier kann für das Konto eine Zwei-Faktor-Authentisierung aktiviert werden.

Es kann entweder eine Authenticator-App (time-based one-time password / TOTP) genutzt werden oder ein Einmalpasswort, welches nach erfolgreichem Login an die hinterlegte E-Mail Adresse gesendet wird.'; $lng['2fa']['2fa_email_desc'] = 'Das Konto ist eingerichtet, um Einmalpasswörter per E-Mail zu erhalten. Zum Deaktivieren, klicke auf "'.$lng['2fa']['2fa_delete'].'"'; $lng['2fa']['2fa_ga_desc'] = 'Das Konto ist eingerichtet, um zeitbasierte Einmalpasswörter via Authenticator-App zu erhalten. Um die gewünschte Authenticator-App einzurichten, scanne bitte den untenstehenden QR-Code. Zum Deaktivieren, klicke auf "'.$lng['2fa']['2fa_delete'].'"'; +$lng['admin']['logviewenabled'] = 'Zugriff auf access/error-Logdateien'; +$lng['panel']['viewlogs'] = 'Logdateien einsehen'; diff --git a/logfiles_viewer.php b/logfiles_viewer.php new file mode 100644 index 00000000..3226d25a --- /dev/null +++ b/logfiles_viewer.php @@ -0,0 +1,85 @@ + (2016-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Panel + * + */ + +// This file is being included in admin_domains and customer_domains +// and therefore does not need to require lib/init.php + +// TODO get domain related settings for logfile (speciallogfile) +$domain_id = isset($_GET['domain_id']) ? (int) $_GET['domain_id'] : null; +$last_n = isset($_GET['number_of_lines']) ? (int) $_GET['number_of_lines'] : 100; + +// user's with logviewenabled = false +if (AREA != 'admin' && $userinfo['logviewenabled'] != '1') { + // back to domain overview + redirectTo($filename, array( + 'page' => 'domains', + 's' => $s + )); +} + +if (function_exists('exec')) { + + // get domain-info + try { + $json_result = SubDomains::getLocal($userinfo, array( + 'id' => $domain_id + ))->get(); + } catch (Exception $e) { + dynamic_error($e->getMessage()); + } + $domain = json_decode($json_result, true)['data']; + + $speciallogfile = ''; + if ($domain['speciallogfile'] == '1') { + if ($domain['parentdomainid'] == '0') { + $speciallogfile = '-' . $domain['domain']; + } else { + $speciallogfile = '-' . $domain['parentdomain']; + } + } + // The normal access/error - logging is enabled + $error_log = makeCorrectFile(Settings::Get('system.logfiles_directory') . getCustomerDetail($domain['customerid'], 'loginname') . $speciallogfile . '-error.log'); + $access_log = makeCorrectFile(Settings::Get('system.logfiles_directory') . getCustomerDetail($domain['customerid'], 'loginname') . $speciallogfile . '-access.log'); + + // error log + if (file_exists($error_log)) { + $result = safe_exec('tail -n ' . $last_n . ' ' . escapeshellarg($error_log)); + $error_log_content = implode("\n", $result) . ""; + } else { + $error_log_content = "Error-Log" . (AREA == 'admin' ? " '" . $error_log . "'" : "") . " does not seem to exist"; + } + + // access log + if (file_exists($access_log)) { + $result = safe_exec('tail -n ' . $last_n . ' ' . escapeshellarg($access_log)); + $access_log_content = implode("\n", $result); + } else { + $access_log_content = "Access-Log" . (AREA == 'admin' ? " '" . $access_log . "'" : "") . " does not seem to exist"; + } + + eval("echo \"" . getTemplate("logfiles_viewer/index", true) . "\";"); +} else { + if (AREA == 'admin') { + dynamic_error('You need to allow the exec() function in the froxlor-vhost php-config'); + } else { + dynamic_error('Required function exec() is not allowed. Pllease contact the system administrator.'); + } +} diff --git a/templates/Sparkle/admin/domains/domains_domain.tpl b/templates/Sparkle/admin/domains/domains_domain.tpl index 8e9140c5..a00ecab6 100644 --- a/templates/Sparkle/admin/domains/domains_domain.tpl +++ b/templates/Sparkle/admin/domains/domains_domain.tpl @@ -20,6 +20,9 @@ {$lng['panel']['edit']} + + {$lng['panel']['viewlogs']} +   {$lng['dnseditor']['edit']} diff --git a/templates/Sparkle/assets/css/main.css b/templates/Sparkle/assets/css/main.css index 7783092c..c78c430d 100644 --- a/templates/Sparkle/assets/css/main.css +++ b/templates/Sparkle/assets/css/main.css @@ -1640,7 +1640,7 @@ table thead th.tablesorter-headerDesc { margin-bottom: 20px; } -.shell, .filecontent { +.shell, .filecontent .logcontent { font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace; border: 1px solid #d1d5d8; diff --git a/templates/Sparkle/customer/domains/domains_domain.tpl b/templates/Sparkle/customer/domains/domains_domain.tpl index 89ae2c60..e4e10181 100644 --- a/templates/Sparkle/customer/domains/domains_domain.tpl +++ b/templates/Sparkle/customer/domains/domains_domain.tpl @@ -20,6 +20,11 @@ {$lng['panel']['edit']}   + + + {$lng['panel']['viewlogs']} + + {$lng['panel']['delete']} diff --git a/templates/Sparkle/logfiles_viewer/index.tpl b/templates/Sparkle/logfiles_viewer/index.tpl new file mode 100644 index 00000000..1fb819f7 --- /dev/null +++ b/templates/Sparkle/logfiles_viewer/index.tpl @@ -0,0 +1,19 @@ +$header +
+
+

+   + {$lng['panel']['viewlogs']} ({$domain['domain']}) [{$lng['menue']['domains']['domains']}] +

+
+ +
+

Error-Log

+ +

Access-Log

+ +
+ +
+ +$footer