mirror of
https://github.com/Froxlor/Froxlor.git
synced 2024-09-21 10:27:29 +00:00
Allow access to webserver logs via weinterface, if activated for customer; todo: view more content dynamically; fixes #603
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
parent
1bd4c00631
commit
8291c7d2ab
@ -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)
|
||||
|
@ -496,4 +496,7 @@ if ($page == 'overview') {
|
||||
|
||||
require_once __DIR__.'/ssl_certificates.php';
|
||||
|
||||
}
|
||||
} elseif ($page == 'logfiles') {
|
||||
|
||||
require_once __DIR__.'/logfiles_viewer.php';
|
||||
}
|
||||
|
@ -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`;
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -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(
|
||||
|
@ -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 = '';
|
||||
|
@ -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.<br><br>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';
|
||||
|
@ -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.<br><br>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';
|
||||
|
85
logfiles_viewer.php
Normal file
85
logfiles_viewer.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
if (! defined('AREA')) {
|
||||
header("Location: index.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2016 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (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) . "</textarea>";
|
||||
} 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.');
|
||||
}
|
||||
}
|
@ -20,6 +20,9 @@
|
||||
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}">
|
||||
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
|
||||
</a>
|
||||
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'logfiles', 'domain_id' => $row['id']))}">
|
||||
<img src="templates/{$theme}/assets/img/icons/view.png" alt="{$lng['panel']['viewlogs']}" title="{$lng['panel']['viewlogs']}" />
|
||||
</a>
|
||||
<if $row['isbinddomain'] == '1' && Settings::Get('system.bind_enable') == '1' && Settings::Get('system.dnsenabled') == '1'>
|
||||
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domaindnseditor', 'domain_id' => $row['id']))}">
|
||||
<img src="templates/{$theme}/assets/img/icons/dns_edit.png" alt="{$lng['dnseditor']['edit']}" title="{$lng['dnseditor']['edit']}" />
|
||||
|
2
templates/Sparkle/assets/css/main.css
vendored
2
templates/Sparkle/assets/css/main.css
vendored
@ -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;
|
||||
|
@ -20,6 +20,11 @@
|
||||
<img src="templates/{$theme}/assets/img/icons/edit.png" alt="{$lng['panel']['edit']}" title="{$lng['panel']['edit']}" />
|
||||
</a>
|
||||
</if>
|
||||
<if $userinfo['logviewenabled'] == '1'>
|
||||
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'logfiles', 'domain_id' => $row['id']))}">
|
||||
<img src="templates/{$theme}/assets/img/icons/view.png" alt="{$lng['panel']['viewlogs']}" title="{$lng['panel']['viewlogs']}" />
|
||||
</a>
|
||||
</if>
|
||||
<if $row['parentdomainid'] != '0' && !(isset($row['domainaliasid']) && $row['domainaliasid'] != 0)>
|
||||
<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domains', 'action' => 'delete', 'id' => $row['id']))}">
|
||||
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />
|
||||
|
19
templates/Sparkle/logfiles_viewer/index.tpl
vendored
Normal file
19
templates/Sparkle/logfiles_viewer/index.tpl
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
$header
|
||||
<article>
|
||||
<header>
|
||||
<h2>
|
||||
<img src="templates/{$theme}/assets/img/icons/view.png" alt="" />
|
||||
{$lng['panel']['viewlogs']} (<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domains', 'action' => 'edit', 'id' => $domain_id))}">{$domain['domain']}</a>) [<a href="{$linker->getLink(array('section' => 'domains', 'page' => 'domains'))}">{$lng['menue']['domains']['domains']}</a>]
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<h3>Error-Log</h3>
|
||||
<textarea rows="20" class="logcontent" readonly>{$error_log_content}</textarea>
|
||||
<h3>Access-Log</h3>
|
||||
<textarea rows="20" class="logcontent" readonly>{$access_log_content}</textarea>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
|
||||
$footer
|
Loading…
Reference in New Issue
Block a user