restricting server list for regular users, moving user-server relations

to own table
This commit is contained in:
Pepijn Over 2014-03-16 02:04:49 +01:00
parent d625dafa9e
commit c47c33c0eb
11 changed files with 385 additions and 148 deletions

View File

@ -25,6 +25,10 @@
* @link http://www.phpservermonitor.org/
**/
if(php_sapi_name() != 'cli') {
die('This script can only be run from the command line.');
}
// include main configuration and functionality
require_once dirname(__FILE__) . '/../src/bootstrap.php';
@ -35,54 +39,12 @@ $time = time();
if(psm_get_conf('cron_running') == 1 && ($time - psm_get_conf('cron_running_time') < PSM_CRON_TIMEOUT)) {
die('Cron is already running. Exiting.');
}
psm_update_conf('cron_running', 1);
if(!PSM_DEBUG) {
psm_update_conf('cron_running', 1);
}
psm_update_conf('cron_running_time', $time);
// get the active servers from database
$servers = $db->select(
PSM_DB_PREFIX.'servers',
array('active' => 'yes'),
array('server_id', 'ip', 'port', 'label', 'type', 'pattern', 'status', 'active', 'email', 'sms')
);
$updater = new \psm\Util\Updater\Status();
foreach ($servers as $server) {
$status_org = $server['status'];
// remove the old status from the array to avoid confusion between the new and old status
unset($server['status']);
$updater->setServer($server, $status_org);
// check server status
// it returns the new status, and performs the update check automatically.
$status_new = $updater->getStatus();
// notify the nerds if applicable
$updater->notify();
// update server status
$save = array(
'last_check' => date('Y-m-d H:i:s'),
'status' => $status_new,
'error' => $updater->getError(),
'rtime' => $updater->getRtime(),
);
// if the server is on, add the last_online value
if($save['status'] == 'on') {
$save['last_online'] = date('Y-m-d H:i:s');
}
$db->save(
PSM_DB_PREFIX . 'servers',
$save,
array('server_id' => $server['server_id'])
);
$log_status = ($status_new == 'on') ? 1 : 0;
psm_log_uptime($server['server_id'], $log_status, $updater->getRtime());
}
$autorun = new \psm\Util\Updater\Autorun($db);
$autorun->run();
psm_update_conf('cron_running', 0);
?>

View File

@ -0,0 +1,78 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor 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 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor 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 PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Pepijn Over <pep@neanderthal-technology.com>
* @copyright Copyright (c) 2008-2014 Pepijn Over <pep@neanderthal-technology.com>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 2.2.0
**/
namespace psm\Module\Server\Controller;
use psm\Module\AbstractController;
use psm\Service\Database;
use psm\Service\Template;
abstract class AbstractServerController extends AbstractController {
function __construct(Database $db, Template $tpl) {
parent::__construct($db, $tpl);
}
/**
* Get all servers for the current user
* @return array
*/
public function getServers() {
$sql_join = '';
if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) {
// restrict by user_id
$sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON (
`us`.`user_id`={$this->user->getUserId()}
AND `us`.`server_id`=`s`.`server_id`
)";
}
$sql = "SELECT
`s`.`server_id`,
`s`.`ip`,
`s`.`port`,
`s`.`type`,
`s`.`label`,
`s`.`pattern`,
`s`.`status`,
`s`.`error`,
`s`.`rtime`,
IF(`s`.`last_check`='0000-00-00 00:00:00', 'never', DATE_FORMAT(`s`.`last_check`, '%d-%m-%y %H:%i')) AS `last_check`,
IF(`s`.`last_online`='0000-00-00 00:00:00', 'never', DATE_FORMAT(`s`.`last_online`, '%d-%m-%y %H:%i')) AS `last_online`,
`s`.`active`,
`s`.`email`,
`s`.`sms`
FROM `".PSM_DB_PREFIX."servers` AS `s`
{$sql_join}
ORDER BY `active` ASC, `status` DESC, `type` ASC, `label` ASC";
$servers = $this->db->query($sql);
return $servers;
}
}

View File

@ -26,14 +26,13 @@
**/
namespace psm\Module\Server\Controller;
use psm\Module\AbstractController;
use psm\Service\Database;
use psm\Service\Template;
/**
* Log module. Create the page to view previous log messages
*/
class LogController extends AbstractController {
class LogController extends AbstractServerController {
function __construct(Database $db, Template $tpl) {
parent::__construct($db, $tpl);
@ -104,6 +103,14 @@ class LogController extends AbstractController {
* @return array
*/
public function getEntries($type) {
$sql_join = '';
if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) {
// restrict by user_id
$sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON (
`us`.`user_id`={$this->user->getUserId()}
AND `us`.`server_id`=`servers`.`server_id`
)";
}
$entries = $this->db->query(
'SELECT '.
'`servers`.`label`, '.
@ -118,9 +125,10 @@ class LogController extends AbstractController {
'`log`.`datetime`, '.
'\'%H:%i:%s %d-%m-%y\''.
') AS `datetime_format`, '.
'`user_id` '.
'`log`.`user_id` '.
'FROM `'.PSM_DB_PREFIX.'log` AS `log` '.
'JOIN `'.PSM_DB_PREFIX.'servers` AS `servers` ON (`servers`.`server_id`=`log`.`server_id`) '.
$sql_join .
'WHERE `log`.`type`=\''.$type.'\' '.
'ORDER BY `datetime` DESC '.
'LIMIT 0,20'
@ -142,7 +150,7 @@ class LogController extends AbstractController {
'label_type' => psm_get_lang('log', 'type'),
'label_message' => psm_get_lang('system', 'message'),
'label_date' => psm_get_lang('system', 'date'),
'label_users' => ucfirst(psm_get_lang('menu', 'users')),
'label_users' => ucfirst(psm_get_lang('menu', 'user')),
)
);

View File

@ -26,14 +26,13 @@
**/
namespace psm\Module\Server\Controller;
use psm\Module\AbstractController;
use psm\Service\Database;
use psm\Service\Template;
/**
* Server module. Add/edit/delete servers, show a list of all servers etc.
*/
class ServerController extends AbstractController {
class ServerController extends AbstractServerController {
function __construct(Database $db, Template $tpl) {
parent::__construct($db, $tpl);
@ -70,35 +69,7 @@ class ServerController extends AbstractController {
// we need an array for our template magic (see below):
$html_actions = array('html_actions' => $html_actions);
// get servers from database
$servers = $this->db->query(
'SELECT '.
'`server_id`, '.
'`ip`, '.
'`port`, '.
'`type`, '.
'`label`, '.
'`pattern`, '.
'`status`, '.
'`error`, '.
'`rtime`, '.
'IF('.
'`last_check`=\'0000-00-00 00:00:00\', '.
'\'never\', '.
'DATE_FORMAT(`last_check`, \'%d-%m-%y %H:%i\') '.
') AS `last_check`, '.
'IF('.
'`last_online`=\'0000-00-00 00:00:00\', '.
'\'never\', '.
'DATE_FORMAT(`last_online`, \'%d-%m-%y %H:%i\') '.
') AS `last_online`, '.
'`active`, '.
'`email`, '.
'`sms` '.
'FROM `'.PSM_DB_PREFIX.'servers` '.
'ORDER BY `active` ASC, `status` DESC, `type` ASC, `label` ASC'
);
$servers = $this->getServers();
$server_count = count($servers);
for ($x = 0; $x < $server_count; $x++) {
@ -223,12 +194,11 @@ class ServerController extends AbstractController {
if(isset($_GET['id'])) {
$id = intval($_GET['id']);
// do delete
$this->db->delete(
PSM_DB_PREFIX . 'servers',
array(
'server_id' => $id,
)
);
$res = $this->db->delete(PSM_DB_PREFIX . 'servers', array('server_id' => $id));
if($res->rowCount() == 1) {
$this->db->delete(PSM_DB_PREFIX.'log', array('server_id' => $id));
$this->db->delete(PSM_DB_PREFIX.'users_servers', array('server_id' => $id));
}
$this->addMessage(psm_get_lang('system', 'deleted'));
}
$this->initializeAction('index');

View File

@ -27,14 +27,13 @@
**/
namespace psm\Module\Server\Controller;
use psm\Module\AbstractController;
use psm\Service\Database;
use psm\Service\Template;
/**
* Status module
*/
class StatusController extends AbstractController {
class StatusController extends AbstractServerController {
function __construct(Database $db, Template $tpl) {
parent::__construct($db, $tpl);
@ -51,11 +50,7 @@ class StatusController extends AbstractController {
$this->addFooter(false);
// get the active servers from database
$servers = $this->db->select(
PSM_DB_PREFIX.'servers',
array('active' => 'yes'),
array('server_id', 'label', 'status', 'last_online', 'last_check', 'rtime')
);
$servers = $this->getServers();
$offline = array();
$online = array();
@ -73,6 +68,9 @@ class StatusController extends AbstractController {
$this->tpl->addTemplateData($this->getTemplateId(), $tpl_data);
foreach ($servers as $server) {
if($server['active'] == 'no') {
continue;
}
$server['last_checked_nice'] = psm_timespan($server['last_check']);
$server['last_online_nice'] = psm_timespan($server['last_online']);

View File

@ -41,11 +41,10 @@ class UpdateController extends AbstractController {
}
protected function executeIndex() {
// fuck globals. but hey, dirty fixes, like you've done it.
global $db;
$autorun = new \psm\Util\Updater\Autorun($this->db);
$autorun->setUser($this->user);
$autorun->run();
require PSM_PATH_SRC . '../cron/status.cron.php';
// redirect user to regular status page
header('Location: ' . psm_build_url(array(
'mod' => 'server_status'
), true, false));

View File

@ -55,7 +55,11 @@ class UserController extends AbstractController {
public function initialize() {
$this->user_validator = new \psm\Util\User\UserValidator($this->user);
$this->servers = $this->db->select(PSM_DB_PREFIX.'servers', null, array('server_id', 'label'));
$servers = $this->db->select(PSM_DB_PREFIX.'servers', null, array('server_id', 'label'));
// change the indexes to reflect their server ids
foreach($servers as $server) {
$this->servers[$server['server_id']] = $server;
}
return parent::initialize();
}
@ -75,23 +79,21 @@ class UserController extends AbstractController {
$users = $this->db->select(
PSM_DB_PREFIX.'users',
null,
array('user_id', 'user_name', 'level', 'server_id', 'name', 'mobile', 'email'),
array('user_id', 'user_name', 'level', 'name', 'mobile', 'email'),
null,
array('name')
);
foreach($users as $x => &$user) {
$user_servers = $this->getUserServers($user['user_id']);
$user['class'] = ($x & 1) ? 'odd' : 'even';
$user['emp_servers'] = '';
// fix server list
$user_servers = explode(',', $user['server_id']);
if(empty($user_servers)) continue;
foreach($user_servers as $server) {
if (!isset($servers_labels[$server])) continue;
$user['emp_servers'] .= $servers_labels[$server] . '<br/>';
foreach($user_servers as $server_id) {
if (!isset($servers_labels[$server_id])) continue;
$user['emp_servers'] .= $servers_labels[$server_id] . '<br/>';
}
$user['emp_servers'] = substr($user['emp_servers'], 0, -5);
}
@ -137,7 +139,7 @@ class UserController extends AbstractController {
$lvl_selected = $edit_user->level;
// select servers for this user
$user_servers = explode(',', $edit_user->server_id);
$user_servers = $this->getUserServers($user_id);
foreach($this->servers as &$server) {
if(in_array($server['server_id'], $user_servers)) {
@ -180,13 +182,10 @@ class UserController extends AbstractController {
}
$user_id = (isset($_GET['id'])) ? intval($_GET['id']) : 0;
$fields = array('name', 'user_name', 'password', 'password_repeat', 'level', 'mobile', 'email', 'server_id');
$fields = array('name', 'user_name', 'password', 'password_repeat', 'level', 'mobile', 'email');
$clean = array();
foreach($fields as $field) {
if(isset($_POST[$field])) {
if(is_array($_POST[$field])) {
$_POST[$field] = implode(',', $_POST[$field]);
}
$clean[$field] = trim(strip_tags($_POST[$field]));
} else {
$clean[$field] = '';
@ -229,6 +228,24 @@ class UserController extends AbstractController {
if(isset($password)) {
$this->user->changePassword($user_id, $password);
}
// update servers
$server_idc = psm_POST('server_id', array());
$server_idc_save = array();
foreach($server_idc as $server_id) {
$server_idc_save[] = array(
'user_id' => $user_id,
'server_id' => intval($server_id),
);
}
// delete all existing records
$this->db->delete(PSM_DB_PREFIX.'users_servers', array('user_id' => $user_id));
if(!empty($server_idc_save)) {
// add all new servers
$this->db->insertMultiple(PSM_DB_PREFIX.'users_servers', $server_idc_save);
}
return $this->executeIndex();
}
@ -241,10 +258,8 @@ class UserController extends AbstractController {
try {
$this->user_validator->userId($id);
$this->db->delete(
PSM_DB_PREFIX . 'users',
array('user_id' => $id,)
);
$this->db->delete(PSM_DB_PREFIX . 'users', array('user_id' => $id,));
$this->db->delete(PSM_DB_PREFIX.'users_servers', array('user_id' => $id));
$this->addMessage(psm_get_lang('system', 'deleted'), 'success');
} catch(\InvalidArgumentException $e) {
$this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error');
@ -282,4 +297,23 @@ class UserController extends AbstractController {
return parent::createHTMLLabels();
}
/**
* Get all server ids for a user
* @param int $user_id
* @return array with ids only
* @todo we should probably find a central place for this kind of stuff
*/
protected function getUserServers($user_id) {
$servers = $this->db->select(
PSM_DB_PREFIX.'users_servers',
array('user_id' => $user_id),
array('server_id')
);
$result = array();
foreach($servers as $server) {
$result[] = $server['server_id'];
}
return $result;
}
}

View File

@ -71,23 +71,26 @@ class User {
public function __construct(Database $db) {
$this->db_connection = $db->pdo();
session_start();
if(php_sapi_name() != 'cli') {
if(!$this->isSessionStarted()) {
session_start();
}
// check the possible login actions:
// 1. login via session data (happens each time user opens a page on your php project AFTER he has successfully logged in via the login form)
// 2. login via cookie
// 3. logout (happen when user clicks logout button)
// check the possible login actions:
// 1. logout (happen when user clicks logout button)
// 2. login via session data (happens each time user opens a page on your php project AFTER he has successfully logged in via the login form)
// 3. login via cookie
// if user has an active session on the server
if(!$this->loginWithSessionData()) {
$this->loginWithCookieData();
}
// if user has an active session on the server
if(!$this->loginWithSessionData()) {
$this->loginWithCookieData();
}
if(isset($_GET["logout"])) {
$this->doLogout();
// logged out, redirect to login
header('Location: ' . psm_build_url());
die();
if(isset($_GET["logout"])) {
$this->doLogout();
// logged out, redirect to login
header('Location: ' . psm_build_url());
die();
}
}
}
@ -422,4 +425,19 @@ class User {
return PSM_USER_ANONYMOUS;
}
}
/**
* Check if the session has already started
* @return boolean
*/
public function isSessionStarted() {
if(php_sapi_name() !== 'cli') {
if(version_compare(phpversion(), '5.4.0', '>=')) {
return session_status() === PHP_SESSION_ACTIVE ? true : false;
} else {
return session_id() === '' ? false : true;
}
}
return false;
}
}

View File

@ -144,13 +144,17 @@ class Installer {
`password_reset_timestamp` bigint(20) DEFAULT NULL COMMENT 'timestamp of the password reset request',
`rememberme_token` varchar(64) DEFAULT NULL COMMENT 'user''s remember-me cookie token',
`level` tinyint(2) unsigned NOT NULL DEFAULT '20',
`server_id` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`mobile` varchar(15) NOT NULL,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `unique_username` (`user_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;",
PSM_DB_PREFIX . 'users_servers' => "CREATE TABLE `" . PSM_DB_PREFIX . "users_servers` (
`user_id` INT( 11 ) UNSIGNED NOT NULL ,
`server_id` INT( 11 ) UNSIGNED NOT NULL ,
PRIMARY KEY ( `user_id` , `server_id` )
) ENGINE = MYISAM ;",
PSM_DB_PREFIX . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` (
`log_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`server_id` int(11) unsigned NOT NULL,
@ -267,6 +271,32 @@ class Installer {
KEY `server_id` (`server_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
$queries[] = "CREATE TABLE `" . PSM_DB_PREFIX . "users_servers` (
`user_id` INT( 11 ) UNSIGNED NOT NULL ,
`server_id` INT( 11 ) UNSIGNED NOT NULL ,
PRIMARY KEY ( `user_id` , `server_id` )
) ENGINE = MYISAM ;";
$this->execSQL($queries);
// from 2.2 all user-server relations are in a separate table
$users = $this->db->select(PSM_DB_PREFIX . 'users', null, array('user_id', 'server_id'));
foreach($users as $user) {
$idc = array();
if($user['server_id'] == '') {
continue;
}
if(strpos($user['server_id'], ',') === false) {
$idc[] = $user['server_id'];
} else {
$idc = explode(',', $user['server_id']);
}
foreach($idc as $id) {
$this->db->save(PSM_DB_PREFIX . 'users_servers', array(
'user_id' => $user['user_id'],
'server_id' => $id,
));
}
}
$this->execSQL("ALTER TABLE `".PSM_DB_PREFIX."users` DROP `server_id`;");
}
}

View File

@ -0,0 +1,125 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor 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 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor 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 PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Pepijn Over <pep@neanderthal-technology.com>
* @copyright Copyright (c) 2008-2014 Pepijn Over <pep@neanderthal-technology.com>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 2.2.0
**/
namespace psm\Util\Updater;
use psm\Service\Database;
use psm\Service\User;
/**
* Run an update on all servers.
*
* If you provide a User service instance it will be
* restricted to that user only.
*/
class Autorun {
/**
* Database service
* @var \psm\Service\Database $db
*/
protected $db;
/**
* User service
* @var \psm\Service\User $user
*/
protected $user;
function __construct(Database $db) {
$this->db = $db;
}
/**
* Go :-)
*/
public function run() {
// check if we need to restrict the servers to a certain user
$sql_join = '';
if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) {
// restrict by user_id
$sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON (
`us`.`user_id`={$this->user->getUserId()}
AND `us`.`server_id`=`s`.`server_id`
)";
}
$sql = "SELECT `s`.`server_id`,`s`.`ip`,`s`.`port`,`s`.`label`,`s`.`type`,`s`.`pattern`,`s`.`status`,`s`.`active`,`s`.`email`,`s`.`sms`
FROM `".PSM_DB_PREFIX."servers` AS `s`
{$sql_join}
WHERE `active`='yes' ";
$servers = $this->db->query($sql);
$updater = new Status($this->db);
foreach($servers as $server) {
$status_org = $server['status'];
// remove the old status from the array to avoid confusion between the new and old status
unset($server['status']);
$updater->setServer($server, $status_org);
// check server status
// it returns the new status, and performs the update check automatically.
$status_new = $updater->getStatus();
// notify the nerds if applicable
$updater->notify();
// update server status
$save = array(
'last_check' => date('Y-m-d H:i:s'),
'status' => $status_new,
'error' => $updater->getError(),
'rtime' => $updater->getRtime(),
);
// if the server is on, add the last_online value
if($save['status'] == 'on') {
$save['last_online'] = date('Y-m-d H:i:s');
}
$this->db->save(
PSM_DB_PREFIX . 'servers',
$save,
array('server_id' => $server['server_id'])
);
$log_status = ($status_new == 'on') ? 1 : 0;
psm_log_uptime($server['server_id'], $log_status, $updater->getRtime());
}
}
/**
* Set a user to restrict the servers being updated
* @param \psm\Service\User $user
*/
public function setUser(User $user) {
$this->user = $user;
}
}

View File

@ -25,7 +25,16 @@
* @link http://www.phpservermonitor.org/
**/
/**
* The status class is for checking a server and notifying if necessary.
*
* You will need to provide an array with all
* server information to the setServer() method, run update() and notify() if you want to.
* If you are looking for a check-all, see the Autorun class.
* @see \psm\Util\Updater\Autorun
*/
namespace psm\Util\Updater;
use psm\Service\Database;
class Status {
public $error;
@ -37,9 +46,8 @@ class Status {
public $db;
function __construct() {
// add database handler
$this->db = $GLOBALS['db'];
function __construct(Database $db) {
$this->db = $db;
}
/**
@ -241,12 +249,7 @@ class Status {
protected function notifyByEmail() {
$userlist = array();
// find all the users with this server listed
$users = $this->db->select(
PSM_DB_PREFIX . 'users',
'FIND_IN_SET(\''.$this->server['server_id'].'\', `server_id`) AND `email` != \'\'',
array('user_id', 'name', 'email')
);
$users = $this->getUsers($this->server['server_id']);
if (empty($users)) {
return false;
@ -283,11 +286,7 @@ class Status {
*/
protected function notifyByTxtMsg() {
// send sms to all users for this server using defined gateway
$users = $this->db->select(
PSM_DB_PREFIX . 'users',
'FIND_IN_SET(\''.$this->server['server_id'].'\', `server_id`) AND `mobile` != \'\'',
array('user_id', 'name', 'mobile')
);
$users = $this->getUsers($this->server['server_id']);
if (empty($users)) {
return false;
@ -369,6 +368,22 @@ class Status {
$this->status_org = false;
$this->status_new = false;
}
}
?>
/**
* Get all users for the provided server id
* @param int $server_id
* @return array
*/
public function getUsers($server_id) {
// find all the users with this server listed
$users = $this->db->query("
SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile`
FROM `".PSM_DB_PREFIX."users` AS `u`
JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON (
`us`.`user_id`=`u`.`user_id`
AND `us`.`server_id` = {$server_id}
)
");
return $users;
}
}