issue #11: adding login module, adding user authentication to user
module issue #11: adding user authentication to installerpull/26/head
parent
f8f3b38708
commit
26f8fedffe
|
@ -4,6 +4,7 @@
|
|||
# ?, 2014
|
||||
#
|
||||
#########################
|
||||
- User login system
|
||||
- Switched from mysql_* to PDO.
|
||||
- Added SMTP support.
|
||||
- Updated PHPMailer package to v5.2.6.
|
||||
|
|
|
@ -98,15 +98,6 @@ The config file has actually been renamed since 2.0, but if you keep it there wh
|
|||
* Remove the old config.inc.php file
|
||||
|
||||
|
||||
## Security
|
||||
|
||||
By default the PHP Server Monitor does not (yet) come with any security methods. After uploading these files to
|
||||
your public html folder these will be visible to everyone on the web. It is recommended to put a password
|
||||
on this folder to prevent other people from playing with your tool. An example .htaccess login script can
|
||||
be found in the example/ dir. To create your own username and password for the .htpasswd file, see
|
||||
<http://www.htaccesstools.com/htpasswd-generator/>
|
||||
|
||||
|
||||
## Setting up a cronjob
|
||||
|
||||
In order to keep the server monitor up to date, the monitor.php file has to run regularly.
|
||||
|
|
24
index.php
24
index.php
|
@ -29,13 +29,21 @@ require 'src/bootstrap.php';
|
|||
|
||||
psm_no_cache();
|
||||
|
||||
if(isset($_GET['action']) && $_GET['action'] == 'check') {
|
||||
require 'cron/status.cron.php';
|
||||
header('Location: index.php');
|
||||
$type = (!isset($_GET['type'])) ? 'servers' : $_GET['type'];
|
||||
|
||||
// if user is not logged in, load login module
|
||||
$user = new \psm\Service\User($db);
|
||||
if(!$user->isUserLoggedIn()) {
|
||||
$type = 'login';
|
||||
}
|
||||
|
||||
$type = (!isset($_GET['type'])) ? 'servers' : $_GET['type'];
|
||||
$allowed_types = array('servers', 'users', 'log', 'config', 'status');
|
||||
if($type == 'update') {
|
||||
require 'cron/status.cron.php';
|
||||
header('Location: ' . psm_build_url());
|
||||
die();
|
||||
}
|
||||
|
||||
$allowed_types = array('servers', 'users', 'log', 'config', 'status', 'login');
|
||||
|
||||
// make sure user selected a valid type. if so, include the file and add to template
|
||||
if(!in_array($type, $allowed_types)) {
|
||||
|
@ -44,7 +52,9 @@ if(!in_array($type, $allowed_types)) {
|
|||
$tpl = new \psm\Service\Template();
|
||||
|
||||
eval('$mod = new psm\Module\\'.ucfirst($type).'($db, $tpl);');
|
||||
if($user->getUserLevel() > $mod->getMinUserLevelRequired()) {
|
||||
die('You do not have the privileges to view this page.');
|
||||
}
|
||||
$mod->setUser($user);
|
||||
// let the module prepare it's HTML code
|
||||
$mod->initialize();
|
||||
|
||||
?>
|
|
@ -29,11 +29,11 @@ define('PSM_INSTALL', true);
|
|||
|
||||
require 'src/bootstrap.php';
|
||||
|
||||
psm_no_cache();
|
||||
|
||||
$type = 'install';
|
||||
$tpl = new \psm\Service\Template();
|
||||
$user = new \psm\Service\User($db);
|
||||
$mod = new psm\Module\Install($db, $tpl);
|
||||
$mod->setUser($user);
|
||||
$mod->initialize();
|
||||
|
||||
?>
|
|
@ -21,12 +21,11 @@
|
|||
* @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: phpservermon 2.1.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://www.phpservermonitor.org/
|
||||
* @since phpservermon 2.1.0
|
||||
**/
|
||||
|
||||
define('PSM_VERSION', '2.2.0-dev');
|
||||
// Include paths
|
||||
define('PSM_PATH_SRC', dirname(__FILE__) . DIRECTORY_SEPARATOR);
|
||||
define('PSM_PATH_VENDOR', PSM_PATH_SRC . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR);
|
||||
|
@ -34,6 +33,11 @@ define('PSM_PATH_INC', PSM_PATH_SRC . 'includes' . DIRECTORY_SEPARATOR);
|
|||
define('PSM_PATH_TPL', PSM_PATH_SRC . 'templates' . DIRECTORY_SEPARATOR);
|
||||
define('PSM_PATH_LANG', PSM_PATH_SRC . 'lang' . DIRECTORY_SEPARATOR);
|
||||
|
||||
// user levels
|
||||
define('PSM_USER_ADMIN', 10);
|
||||
define('PSM_USER_USER', 20);
|
||||
define('PSM_USER_ANONYMOUS', 30);
|
||||
|
||||
// find config file
|
||||
$path_conf = PSM_PATH_SRC . '../config.php';
|
||||
if(file_exists($path_conf)) {
|
||||
|
|
|
@ -369,6 +369,34 @@ function psm_build_url($params = array(), $urlencode = true) {
|
|||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try existence of a GET var, if not return the alternative
|
||||
* @param string $key
|
||||
* @param string $alt
|
||||
* @return mixed
|
||||
*/
|
||||
function psm_GET($key, $alt = null) {
|
||||
if(isset($_GET[$key])) {
|
||||
return $_GET[$key];
|
||||
} else {
|
||||
return $alt;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try existence of a GET var, if not return the alternative
|
||||
* @param string $key
|
||||
* @param string $alt
|
||||
* @return mixed
|
||||
*/
|
||||
function psm_POST($key, $alt = null) {
|
||||
if(isset($_POST[$key])) {
|
||||
return $_POST[$key];
|
||||
} else {
|
||||
return $alt;
|
||||
}
|
||||
}
|
||||
|
||||
###############################################
|
||||
#
|
||||
# Debug functions
|
||||
|
@ -396,5 +424,3 @@ function psm_no_cache() {
|
|||
header("Cache-Control: no-cache, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,246 @@
|
|||
<?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 Anthony Ferrara <ircmaxell@php.net>
|
||||
* @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
|
||||
**/
|
||||
|
||||
/**
|
||||
* A Compatibility library with PHP 5.5's simplified password hashing API.
|
||||
*
|
||||
* @author Anthony Ferrara <ircmaxell@php.net>
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @copyright 2012 The Authors
|
||||
*/
|
||||
|
||||
if (!defined('PASSWORD_DEFAULT')) {
|
||||
|
||||
define('PASSWORD_BCRYPT', 1);
|
||||
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
|
||||
|
||||
/**
|
||||
* Hash the password using the specified algorithm
|
||||
*
|
||||
* @param string $password The password to hash
|
||||
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants)
|
||||
* @param array $options The options for the algorithm to use
|
||||
*
|
||||
* @return string|false The hashed password, or false on error.
|
||||
*/
|
||||
function password_hash($password, $algo, array $options = array()) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_string($password)) {
|
||||
trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_int($algo)) {
|
||||
trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
// Note that this is a C constant, but not exposed to PHP, so we don't define it here.
|
||||
$cost = 10;
|
||||
if (isset($options['cost'])) {
|
||||
$cost = $options['cost'];
|
||||
if ($cost < 4 || $cost > 31) {
|
||||
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// The length of salt to generate
|
||||
$raw_salt_len = 16;
|
||||
// The length required in the final serialization
|
||||
$required_salt_len = 22;
|
||||
$hash_format = sprintf("$2y$%02d$", $cost);
|
||||
break;
|
||||
default:
|
||||
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (isset($options['salt'])) {
|
||||
switch (gettype($options['salt'])) {
|
||||
case 'NULL':
|
||||
case 'boolean':
|
||||
case 'integer':
|
||||
case 'double':
|
||||
case 'string':
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
case 'object':
|
||||
if (method_exists($options['salt'], '__tostring')) {
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
}
|
||||
case 'array':
|
||||
case 'resource':
|
||||
default:
|
||||
trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (strlen($salt) < $required_salt_len) {
|
||||
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
|
||||
return null;
|
||||
} elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
|
||||
$salt = str_replace('+', '.', base64_encode($salt));
|
||||
}
|
||||
} else {
|
||||
$buffer = '';
|
||||
$buffer_valid = false;
|
||||
if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
|
||||
$buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
|
||||
$buffer = openssl_random_pseudo_bytes($raw_salt_len);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && is_readable('/dev/urandom')) {
|
||||
$f = fopen('/dev/urandom', 'r');
|
||||
$read = strlen($buffer);
|
||||
while ($read < $raw_salt_len) {
|
||||
$buffer .= fread($f, $raw_salt_len - $read);
|
||||
$read = strlen($buffer);
|
||||
}
|
||||
fclose($f);
|
||||
if ($read >= $raw_salt_len) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
|
||||
$bl = strlen($buffer);
|
||||
for ($i = 0; $i < $raw_salt_len; $i++) {
|
||||
if ($i < $bl) {
|
||||
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
|
||||
} else {
|
||||
$buffer .= chr(mt_rand(0, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
$salt = str_replace('+', '.', base64_encode($buffer));
|
||||
}
|
||||
$salt = substr($salt, 0, $required_salt_len);
|
||||
|
||||
$hash = $hash_format . $salt;
|
||||
|
||||
$ret = crypt($password, $hash);
|
||||
|
||||
if (!is_string($ret) || strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the password hash. Returns an array of the information
|
||||
* that was used to generate the password hash.
|
||||
*
|
||||
* array(
|
||||
* 'algo' => 1,
|
||||
* 'algoName' => 'bcrypt',
|
||||
* 'options' => array(
|
||||
* 'cost' => 10,
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @param string $hash The password hash to extract info from
|
||||
*
|
||||
* @return array The array of information about the hash.
|
||||
*/
|
||||
function password_get_info($hash) {
|
||||
$return = array(
|
||||
'algo' => 0,
|
||||
'algoName' => 'unknown',
|
||||
'options' => array(),
|
||||
);
|
||||
if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
|
||||
$return['algo'] = PASSWORD_BCRYPT;
|
||||
$return['algoName'] = 'bcrypt';
|
||||
list($cost) = sscanf($hash, "$2y$%d$");
|
||||
$return['options']['cost'] = $cost;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the password hash needs to be rehashed according to the options provided
|
||||
*
|
||||
* If the answer is true, after validating the password using password_verify, rehash it.
|
||||
*
|
||||
* @param string $hash The hash to test
|
||||
* @param int $algo The algorithm used for new password hashes
|
||||
* @param array $options The options array passed to password_hash
|
||||
*
|
||||
* @return boolean True if the password needs to be rehashed.
|
||||
*/
|
||||
function password_needs_rehash($hash, $algo, array $options = array()) {
|
||||
$info = password_get_info($hash);
|
||||
if ($info['algo'] != $algo) {
|
||||
return true;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
$cost = isset($options['cost']) ? $options['cost'] : 10;
|
||||
if ($cost != $info['options']['cost']) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password against a hash using a timing attack resistant approach
|
||||
*
|
||||
* @param string $password The password to verify
|
||||
* @param string $hash The hash to verify against
|
||||
*
|
||||
* @return boolean If the password matches the hash
|
||||
*/
|
||||
function password_verify($password, $hash) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$ret = crypt($password, $hash);
|
||||
if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = 0;
|
||||
for ($i = 0; $i < strlen($ret); $i++) {
|
||||
$status |= (ord($ret[$i]) ^ ord($hash[$i]));
|
||||
}
|
||||
|
||||
return $status === 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?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
|
||||
**/
|
||||
|
||||
/**
|
||||
* Current PSM version
|
||||
*/
|
||||
define('PSM_VERSION', '2.2.0-dev');
|
||||
|
||||
/**
|
||||
* Configuration for: Hashing strength
|
||||
* This is the place where you define the strength of your password hashing/salting
|
||||
*
|
||||
* To make password encryption very safe and future-proof, the PHP 5.5 hashing/salting functions
|
||||
* come with a clever so called COST FACTOR. This number defines the base-2 logarithm of the rounds of hashing,
|
||||
* something like 2^12 if your cost factor is 12. By the way, 2^12 would be 4096 rounds of hashing, doubling the
|
||||
* round with each increase of the cost factor and therefore doubling the CPU power it needs.
|
||||
* Currently, in 2013, the developers of this functions have chosen a cost factor of 10, which fits most standard
|
||||
* server setups. When time goes by and server power becomes much more powerful, it might be useful to increase
|
||||
* the cost factor, to make the password hashing one step more secure. Have a look here
|
||||
* (@see https://github.com/panique/php-login/wiki/Which-hashing-&-salting-algorithm-should-be-used-%3F)
|
||||
* in the BLOWFISH benchmark table to get an idea how this factor behaves. For most people this is irrelevant,
|
||||
* but after some years this might be very very useful to keep the encryption of your database up to date.
|
||||
*
|
||||
* Remember: Every time a user registers or tries to log in (!) this calculation will be done.
|
||||
* Don't change this if you don't know what you do.
|
||||
*
|
||||
* To get more information about the best cost factor please have a look here
|
||||
* @see http://stackoverflow.com/q/4443476/1114320
|
||||
*
|
||||
* This constant will be used in the login and the registration class.
|
||||
*/
|
||||
define("PSM_LOGIN_HASH_COST_FACTOR", "10");
|
||||
|
||||
/**
|
||||
* Configuration for: Cookies
|
||||
* Please note: The COOKIE_DOMAIN needs the domain where your app is,
|
||||
* in a format like this: .mydomain.com
|
||||
* Note the . in front of the domain. No www, no http, no slash here!
|
||||
* For local development .127.0.0.1 or .localhost is fine, but when deploying you should
|
||||
* change this to your real domain, like '.mydomain.com' ! The leading dot makes the cookie available for
|
||||
* sub-domains too.
|
||||
* @see http://stackoverflow.com/q/9618217/1114320
|
||||
* @see http://www.php.net/manual/en/function.setcookie.php
|
||||
*
|
||||
* COOKIE_RUNTIME: How long should a cookie be valid ? 1209600 seconds = 2 weeks
|
||||
* COOKIE_DOMAIN: The domain where the cookie is valid for, like '.mydomain.com'
|
||||
* COOKIE_SECRET_KEY: Put a random value here to make your app more secure. When changed, all cookies are reset.
|
||||
*/
|
||||
define("PSM_LOGIN_COOKIE_RUNTIME", 1209600);
|
||||
define("PSM_LOGIN_COOKIE_DOMAIN", null);
|
||||
define("PSM_LOGIN_COOKIE_SECRET_KEY", "4w900de52e3ap7y77y8675jy6c594286");
|
||||
|
||||
/**
|
||||
* Number of seconds the reset link is valid after sending it to the user.
|
||||
*/
|
||||
define('PSM_LOGIN_RESET_RUNTIME', 3600);
|
|
@ -50,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => 'Добави нов',
|
||||
'update_available' => 'Налична е нова версия. Може да я свалите от <a href="http://phpservermon.sourceforge.net" target="_blank">тук</a>.',
|
||||
'back_to_top' => 'Нагоре',
|
||||
'go_back' => 'Go back',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => 'Потребител',
|
||||
'name' => 'Име',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => 'Мобилен телефон',
|
||||
'email' => 'Имейл',
|
||||
'updated' => 'Информацията за потребителя е обновена.',
|
||||
'inserted' => 'Потребителят е добавен.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Записи в лога',
|
||||
|
@ -149,6 +166,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => 'Връзката до \'%LABEL%\' е ВЪЗСТАНОВЕНА',
|
||||
'on_email_body' => "Връзката до '%LABEL%' беше ВЪЗСТАНОВЕНА:<br/><br/>Сървър: %LABEL%<br/>IP адрес: %IP%<br/>Порт: %PORT%<br/>Днес: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
||||
|
|
|
@ -50,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => 'Adicionar novo?',
|
||||
'update_available' => 'Uma atualização disponível em <a href="http://phpservermon.sourceforge.net" target="_blank">http://phpservermon.sourceforge.net</a>.',
|
||||
'back_to_top' => 'Voltar ao topo',
|
||||
'go_back' => 'Go back',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => 'usuário',
|
||||
'name' => 'Nome',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => 'Celular',
|
||||
'email' => 'Email',
|
||||
'updated' => 'Usuário atualizado.',
|
||||
'inserted' => 'Usuário adicionado.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Entradas do Log',
|
||||
|
@ -149,6 +166,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => 'IMPORTANTE: Servidor \'%LABEL%\' esta ONLINE',
|
||||
'on_email_body' => "Servidor '%LABEL%' esta ONLINE novamente:<br/><br/>Servidor: %LABEL%<br/>IP: %IP%<br/>Porta: %PORT%<br/>Data: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -50,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => 'Neuen Eintrag erstellen?',
|
||||
'update_available' => 'Ein neues Update ist verfügbar auf <a href="http://phpservermon.sourceforge.net" target="_blank">http://phpservermon.sourceforge.net</a>.',
|
||||
'back_to_top' => 'Back to top',
|
||||
'go_back' => 'Go back',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => 'Benutzer',
|
||||
'name' => 'Name',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => 'Mobil',
|
||||
'email' => 'Email',
|
||||
'updated' => 'Benutzer bearbeitet.',
|
||||
'inserted' => 'Benutzer eingetragen.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Log Einträge',
|
||||
|
@ -149,6 +166,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => 'Wichtig: Server \'%LABEL%\' ist wieder Online',
|
||||
'on_email_body' => "Server '%LABEL%' läuft wieder:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Datum: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -50,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => 'Add new?',
|
||||
'update_available' => 'A new update is available from <a href="http://phpservermon.sourceforge.net" target="_blank">http://phpservermon.sourceforge.net</a>.',
|
||||
'back_to_top' => 'Back to top',
|
||||
'go_back' => 'Go back',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => 'user',
|
||||
'name' => 'Name',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => 'Mobile',
|
||||
'email' => 'Email',
|
||||
'updated' => 'User updated.',
|
||||
'inserted' => 'User added.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Log entries',
|
||||
|
@ -149,6 +166,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => 'IMPORTANT: Server \'%LABEL%\' is RUNNING',
|
||||
'on_email_body' => "Server '%LABEL%' is running again:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -50,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => 'Rajouter un nouveau serveur?',
|
||||
'update_available' => 'Une nouvelle version est disponible à l adresse <a href="http://phpservermon.sourceforge.net" target="_blank">http://phpservermon.sourceforge.net</a>.',
|
||||
'back_to_top' => 'Haut de page',
|
||||
'go_back' => 'Go back',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => 'Utilisateur',
|
||||
'name' => 'Nom',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => 'Mobile',
|
||||
'email' => 'Email',
|
||||
'updated' => 'Utilisateur mis à jour.',
|
||||
'inserted' => 'Utilisateur ajouté.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Evenements',
|
||||
|
@ -122,7 +139,6 @@ $sm_lang = array(
|
|||
'Vous recevrez une seule notification à 1 heure du matin et uniquement celle-ci.<br/>'.
|
||||
'<br/><b>Toujours: </b>'.
|
||||
'Vous recevrez une notification à chaque passage de la tache planifiée si le site est en statut ETEINT ',
|
||||
|
||||
'alert_type_status' => 'Changement de statut',
|
||||
'alert_type_offline' => 'Eteint',
|
||||
'alert_type_always' => 'Toujours',
|
||||
|
@ -149,6 +165,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => 'IMPORTANT: Le Serveur \'%LABEL%\' est OK',
|
||||
'on_email_body' => "Le Serveur '%LABEL%' est de nouveau OK:<br/><br/>Serveur: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -23,7 +23,6 @@
|
|||
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
|
||||
* @version Release: @package_version@
|
||||
* @link http://www.phpservermonitor.org/
|
||||
* @since phpservermon 2.1
|
||||
**/
|
||||
|
||||
$sm_lang = array(
|
||||
|
@ -51,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => '새계정 추가',
|
||||
'update_available' => '새로운 업데이트가 있습니다. 다음사이트를 방문 해 주십시오. <a href="http://phpservermon.sourceforge.net" target="_blank">http://phpservermon.sourceforge.net</a>.',
|
||||
'back_to_top' => 'Back to top',
|
||||
'go_back' => 'Go back',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => '사용자',
|
||||
'name' => '이름',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => '휴대폰',
|
||||
'email' => 'Email',
|
||||
'updated' => '수정되었습니다.',
|
||||
'inserted' => '추가되었습니다.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Log entries',
|
||||
|
@ -148,6 +164,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => '중요: 서버(\'%LABEL%\')가 가동중입니다.',
|
||||
'on_email_body' => "서버('%LABEL%')가 재가동됩니다.:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Port: %PORT%<br/>Date: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -50,14 +50,31 @@ $sm_lang = array(
|
|||
'add_new' => 'Voeg toe?',
|
||||
'update_available' => 'Een nieuwe update is beschikbaar op <a href="http://phpservermon.sourceforge.net" target="_blank">http://phpservermon.sourceforge.net</a>.',
|
||||
'back_to_top' => 'Terug naar boven',
|
||||
'go_back' => 'Terug',
|
||||
),
|
||||
'users' => array(
|
||||
'user' => 'gebruiker',
|
||||
'name' => 'Naam',
|
||||
'user_name' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Password repeat',
|
||||
'password_leave_blank' => 'Leave blank to keep unchanged',
|
||||
'level' => 'Level',
|
||||
'level_10' => 'Administrator',
|
||||
'level_20' => 'User',
|
||||
'mobile' => 'Mobiel',
|
||||
'email' => 'Email',
|
||||
'updated' => 'Gebruiker gewijzigd.',
|
||||
'inserted' => 'Gebruiker toegevoegd.',
|
||||
'error_user_name_bad_length' => 'Usernames must be between 2 and 64 characters.',
|
||||
'error_user_name_invalid' => 'It may only contain alphabetic characters (a-z, A-Z), digits (0-9) and underscores (_).',
|
||||
'error_user_name_exists' => 'The given username already exists in the database.',
|
||||
'error_user_email_bad_length' => 'Email addresses must be between 5 and 255 characters.',
|
||||
'error_user_email_invalid' => 'The email address is invalid.',
|
||||
'error_user_level_invalid' => 'The given user level is invalid.',
|
||||
'error_user_no_match' => 'The user could not be found in the database.',
|
||||
'error_user_password_invalid' => 'The entered password is invalid.',
|
||||
'error_user_password_no_match' => 'The entered passwords do not match.',
|
||||
),
|
||||
'log' => array(
|
||||
'title' => 'Log entries',
|
||||
|
@ -148,6 +165,27 @@ $sm_lang = array(
|
|||
'on_email_subject' => 'BELANGRIJK: Server %LABEL% is RUNNING',
|
||||
'on_email_body' => "Server %LABEL% is weer online:<br/><br/>Server: %LABEL%<br/>IP: %IP%<br/>Poort: %PORT%<br/>Datum: %DATE%",
|
||||
),
|
||||
'login' => array(
|
||||
'welcome_usermenu' => 'Welcome, %user_name%',
|
||||
'title_sign_in' => 'Please sign in',
|
||||
'title_forgot' => 'Forgot your password?',
|
||||
'title_reset' => 'Reset your password',
|
||||
'submit' => 'Submit',
|
||||
'remember_me' => 'Remember me',
|
||||
'login' => 'Login',
|
||||
'logout' => 'Logout',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'password_repeat' => 'Repeat password',
|
||||
'password_forgot' => 'Forgot password?',
|
||||
'password_reset' => 'Reset password',
|
||||
'password_reset_email_subject' => 'Reset your password for PHP Server Monitor',
|
||||
'password_reset_email_body' => 'Please use the following link to reset your password. Please note it expires in 1 hour.<br/><br/>%link%',
|
||||
'error_user_incorrect' => 'The provided username could not be found.',
|
||||
'error_login_incorrect' => 'The information is incorrect.',
|
||||
'error_login_passwords_nomatch' => 'The provided passwords do not match.',
|
||||
'error_reset_invalid_link' => 'The reset link you provided is invalid.',
|
||||
'success_password_forgot' => 'An email has been sent to you with information how to reset your password.',
|
||||
'success_password_reset' => 'Your password has been reset successfully. Please login.',
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -76,7 +76,7 @@ abstract class AbstractModule implements ModuleInterface {
|
|||
/**
|
||||
* Messages to show the user
|
||||
* @var array $messages
|
||||
* @see getMessage()
|
||||
* @see addMessage()
|
||||
*/
|
||||
protected $messages = array();
|
||||
|
||||
|
@ -99,6 +99,19 @@ abstract class AbstractModule implements ModuleInterface {
|
|||
*/
|
||||
protected $tpl_id;
|
||||
|
||||
/**
|
||||
* User service
|
||||
* @var \psm\Service\User $user
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Required user level for this module
|
||||
* @var int $user_level_required
|
||||
* @see setMinUserLevelRequired()
|
||||
*/
|
||||
protected $user_level_required = PSM_USER_USER;
|
||||
|
||||
function __construct(Database $db, Template $tpl) {
|
||||
$this->db = $db;
|
||||
$this->tpl = $tpl;
|
||||
|
@ -153,13 +166,14 @@ abstract class AbstractModule implements ModuleInterface {
|
|||
// user wants updates, lets see what we can do
|
||||
$this->createHTMLUpdateAvailable();
|
||||
}
|
||||
$tpl_data = array(
|
||||
'message' => (empty($this->messages)) ? ' ' : implode('<br/>', $this->messages),
|
||||
);
|
||||
$tpl_data = array();
|
||||
|
||||
if(!empty($this->messages)) {
|
||||
$this->tpl->addTemplateDataRepeat('main', 'messages', $this->messages);
|
||||
}
|
||||
// add menu to page?
|
||||
if($this->add_menu) {
|
||||
$this->tpl->newTemplate('main_menu', 'main.tpl.html');
|
||||
$tpl_data['html_menu'] = $this->tpl->getTemplate('main_menu');
|
||||
$tpl_data['html_menu'] = $this->createHTMLMenu();
|
||||
}
|
||||
// add footer to page?
|
||||
if($this->add_footer) {
|
||||
|
@ -181,15 +195,69 @@ abstract class AbstractModule implements ModuleInterface {
|
|||
echo $this->tpl->display($this->getTemplateId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create HTML code for the menu
|
||||
* @return string
|
||||
*/
|
||||
protected function createHTMLMenu() {
|
||||
// @todo globals..? seriously..?
|
||||
global $type;
|
||||
|
||||
$ulvl = ($this->user) ? $this->user->getUserLevel() : PSM_USER_ANONYMOUS;
|
||||
|
||||
$tpl_id = 'main_menu';
|
||||
$this->tpl->newTemplate($tpl_id, 'main.tpl.html');
|
||||
|
||||
$tpl_data = array(
|
||||
'label_help' => psm_get_lang('system', 'help'),
|
||||
'label_logout' => psm_get_lang('login', 'logout'),
|
||||
'url_logout' => psm_build_url(array('logout' => 1)),
|
||||
);
|
||||
|
||||
switch($ulvl) {
|
||||
case PSM_USER_ADMIN:
|
||||
$items = array('servers', 'users', 'log', 'status', 'config', 'update');
|
||||
break;
|
||||
case PSM_USER_USER:
|
||||
$items = array('servers', 'log', 'status', 'update');
|
||||
break;
|
||||
default:
|
||||
$items = array();
|
||||
break;
|
||||
}
|
||||
$menu = array();
|
||||
foreach($items as $key) {
|
||||
$menu[] = array(
|
||||
'active' => ($key == $type) ? 'active' : '',
|
||||
'url' => psm_build_url(array('type' => $key)),
|
||||
'label' => psm_get_lang('system', $key),
|
||||
);
|
||||
}
|
||||
if(!empty($menu)) {
|
||||
$this->tpl->addTemplateDataRepeat($tpl_id, 'menu', $menu);
|
||||
}
|
||||
|
||||
if($ulvl != PSM_USER_ANONYMOUS) {
|
||||
$user = $this->user->getUser();
|
||||
$tpl_data['label_usermenu'] = str_replace(
|
||||
'%user_name%',
|
||||
$user->name,
|
||||
psm_get_lang('login', 'welcome_usermenu')
|
||||
);
|
||||
}
|
||||
$this->tpl->addTemplateData($tpl_id, $tpl_data);
|
||||
|
||||
return $this->tpl->getTemplate($tpl_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* First check if an update is available, if there is add a message
|
||||
* to the main template
|
||||
*/
|
||||
protected function createHTMLUpdateAvailable() {
|
||||
// check for updates?
|
||||
|
||||
if(psm_check_updates()) {
|
||||
// yay, new update available =D
|
||||
// @todo perhaps find a way to make the message more persistent?
|
||||
$this->addMessage(psm_get_lang('system', 'update_available'));
|
||||
}
|
||||
}
|
||||
|
@ -207,14 +275,6 @@ abstract class AbstractModule implements ModuleInterface {
|
|||
array(
|
||||
'title' => strtoupper(psm_get_lang('system', 'title')),
|
||||
'subtitle' => psm_get_lang('system', $type),
|
||||
'active_' . $type => 'active',
|
||||
'label_servers' => psm_get_lang('system', 'servers'),
|
||||
'label_users' => psm_get_lang('system', 'users'),
|
||||
'label_log' => psm_get_lang('system', 'log'),
|
||||
'label_status' => psm_get_lang('system', 'status'),
|
||||
'label_config' => psm_get_lang('system', 'config'),
|
||||
'label_update' => psm_get_lang('system', 'update'),
|
||||
'label_help' => psm_get_lang('system', 'help'),
|
||||
'label_back_to_top' => psm_get_lang('system', 'back_to_top'),
|
||||
)
|
||||
);
|
||||
|
@ -298,15 +358,50 @@ abstract class AbstractModule implements ModuleInterface {
|
|||
/**
|
||||
* Add one or multiple message to the stack to be displayed to the user
|
||||
* @param string|array $msg
|
||||
* @param string $status success/warning/error
|
||||
* @return \psm\Module\AbstractModule
|
||||
*/
|
||||
public function addMessage($msg) {
|
||||
public function addMessage($msg, $status = 'info') {
|
||||
if(!is_array($msg)) {
|
||||
$msg = array($msg);
|
||||
}
|
||||
$this->messages = array_merge($this->messages, $msg);
|
||||
if($status == 'error') {
|
||||
$shortcode = 'important';
|
||||
} else {
|
||||
$shortcode = $status;
|
||||
}
|
||||
|
||||
foreach($msg as $m) {
|
||||
$this->messages[] = array(
|
||||
'message' => $m,
|
||||
'status' => ($status == null) ? '' : strtoupper($status),
|
||||
'shortcode' => $shortcode,
|
||||
);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
/**
|
||||
* Set user service
|
||||
* @param \psm\Service\User $user
|
||||
*/
|
||||
public function setUser(\psm\Service\User $user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum required user level for this module
|
||||
* @param int $level
|
||||
*/
|
||||
public function setMinUserLevelRequired($level) {
|
||||
$this->user_level_required = intval($level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum required user level for this module
|
||||
* @return int
|
||||
*/
|
||||
public function getMinUserLevelRequired() {
|
||||
return $this->user_level_required;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,13 +32,6 @@ use psm\Service\Template;
|
|||
|
||||
class Install extends AbstractModule {
|
||||
|
||||
/**
|
||||
* Result messages to add to the main template
|
||||
* @var array $install_results
|
||||
* @see addResult()
|
||||
*/
|
||||
protected $install_results = array();
|
||||
|
||||
/**
|
||||
* Full path to config file
|
||||
* @var string $path_config
|
||||
|
@ -54,6 +47,8 @@ class Install extends AbstractModule {
|
|||
function __construct(Database $db, Template $tpl) {
|
||||
parent::__construct($db, $tpl);
|
||||
|
||||
$this->addMenu(false);
|
||||
|
||||
$this->path_config = PSM_PATH_SRC . '../config.php';
|
||||
$this->path_config_old = PSM_PATH_SRC . '../config.inc.php';
|
||||
|
||||
|
@ -63,18 +58,18 @@ class Install extends AbstractModule {
|
|||
}
|
||||
|
||||
protected function createHTML() {
|
||||
$tpl_id_custom = $this->getTemplateId();
|
||||
$this->setTemplateId('install', 'install.tpl.html');
|
||||
$html_install = ($tpl_id_custom) ? $this->tpl->getTemplate($tpl_id_custom) : '';
|
||||
|
||||
$html_results = '';
|
||||
if(!empty($this->install_results)) {
|
||||
if(!empty($this->messages)) {
|
||||
$this->tpl->newTemplate('install_results', 'install.tpl.html');
|
||||
$this->tpl->addTemplateDataRepeat('install_results', 'resultmsgs', $this->install_results);
|
||||
$this->tpl->addTemplateDataRepeat('install_results', 'resultmsgs', $this->messages);
|
||||
$html_results = $this->tpl->getTemplate('install_results');
|
||||
$this->messages = array();
|
||||
}
|
||||
$tpl_id = $this->getTemplateId();
|
||||
$this->setTemplateId('install', 'install.tpl.html');
|
||||
|
||||
$this->tpl->addTemplateData($this->getTemplateId(), array(
|
||||
'html_install' => $html_install,
|
||||
'html_install' => $this->tpl->getTemplate($tpl_id),
|
||||
'html_results' => $html_results,
|
||||
));
|
||||
|
||||
|
@ -82,11 +77,10 @@ class Install extends AbstractModule {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generate the main install page with prerequisites
|
||||
* Say hi to our new user
|
||||
*/
|
||||
protected function executeIndex() {
|
||||
$this->addMenu(false);
|
||||
$tpl_data = array();
|
||||
$this->setTemplateId('install_index', 'install.tpl.html');
|
||||
|
||||
// build prerequisites
|
||||
$errors = 0;
|
||||
|
@ -94,30 +88,22 @@ class Install extends AbstractModule {
|
|||
$phpv = phpversion();
|
||||
if(version_compare($phpv, '5.3.0', '<')) {
|
||||
$errors++;
|
||||
$this->addResult('PHP 5.3+ is required to run PHP Server Monitor.', 'error');
|
||||
$this->addMessage('PHP 5.3+ is required to run PHP Server Monitor.', 'error');
|
||||
} else {
|
||||
$this->addResult('PHP version: ' . $phpv);
|
||||
$this->addMessage('PHP version: ' . $phpv, 'success');
|
||||
}
|
||||
if(!function_exists('curl_init')) {
|
||||
$this->addResult('PHP is installed without the cURL module. Please install cURL.', 'warning');
|
||||
$this->addMessage('PHP is installed without the cURL module. Please install cURL.', 'warning');
|
||||
} else {
|
||||
$this->addResult('cURL installed');
|
||||
$this->addMessage('PHP cURL module found', 'success');
|
||||
}
|
||||
if(!in_array('mysql', \PDO::getAvailableDrivers())) {
|
||||
$errors++;
|
||||
$this->addResult('The PDO MySQL driver needs to be installed.', 'error');
|
||||
$this->addMessage('The PDO MySQL driver needs to be installed.', 'error');
|
||||
}
|
||||
|
||||
if($errors > 0) {
|
||||
// cannot continue
|
||||
$this->addResult($errors . ' error(s) have been encountered. Please fix them and refresh this page.', 'error');
|
||||
} else {
|
||||
if(defined('PSM_CONFIG')) {
|
||||
$this->addResult('Configuration file found.');
|
||||
return $this->executeInstall();
|
||||
} else {
|
||||
return $this->executeConfig();
|
||||
}
|
||||
$this->addMessage($errors . ' error(s) have been encountered. Please fix them and refresh this page.', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,110 +111,163 @@ class Install extends AbstractModule {
|
|||
* Help the user create a new config file
|
||||
*/
|
||||
protected function executeConfig() {
|
||||
if(defined('PSM_CONFIG')) {
|
||||
return $this->executeInstall();
|
||||
}
|
||||
// first detect "old" config file (2.0)
|
||||
if(file_exists($this->path_config_old)) {
|
||||
// oldtimer huh
|
||||
$this->addResult('Configuration file for v2.0 found.');
|
||||
$this->addResult(
|
||||
'The location of the config file has been changed since the previous version.<br/>' .
|
||||
'We will attempt to create a new config file for you.'
|
||||
, 'warning');
|
||||
$values = $this->parseConfig20();
|
||||
} else {
|
||||
// fresh install
|
||||
$values = $_POST;
|
||||
}
|
||||
|
||||
$config = array(
|
||||
'host' => 'localhost',
|
||||
'name' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'prefix' => 'psm_',
|
||||
);
|
||||
$this->setTemplateId('install_config_new', 'install.tpl.html');
|
||||
$tpl_data = array();
|
||||
|
||||
$changed = false;
|
||||
foreach($config as $ckey => &$cvalue) {
|
||||
if(isset($values[$ckey])) {
|
||||
$changed = true;
|
||||
$cvalue = $values[$ckey];
|
||||
if(!defined('PSM_CONFIG')) {
|
||||
// first detect "old" config file (2.0)
|
||||
if(file_exists($this->path_config_old)) {
|
||||
// oldtimer huh
|
||||
$this->addMessage('Configuration file for v2.0 found.', 'success');
|
||||
$this->addMessage(
|
||||
'The location of the config file has been changed since v2.0.<br/>' .
|
||||
'We will attempt to create a new config file for you.'
|
||||
, 'warning');
|
||||
$values = $this->parseConfig20();
|
||||
} else {
|
||||
// fresh install
|
||||
$values = $_POST;
|
||||
}
|
||||
}
|
||||
// add config to template data for prefilling the form
|
||||
$tpl_data = $config;
|
||||
|
||||
if($changed) {
|
||||
// test db connection
|
||||
$this->db = new \psm\Service\Database(
|
||||
$config['host'],
|
||||
$config['user'],
|
||||
$config['pass'],
|
||||
$config['name']
|
||||
$config = array(
|
||||
'host' => 'localhost',
|
||||
'name' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'prefix' => 'psm_',
|
||||
);
|
||||
|
||||
if($this->db->status()) {
|
||||
$this->addResult('Connection to MySQL successful.');
|
||||
$config_php = $this->writeConfigFile($config);
|
||||
if($config_php === true) {
|
||||
$this->addResult('Configuration file written successfully.');
|
||||
return $this->executeInstall();
|
||||
} else {
|
||||
$this->addResult('Config file is not writable, we cannot save it for you.', 'error');
|
||||
$this->tpl->newTemplate('install_config_new_copy', 'install.tpl.html');
|
||||
$tpl_data['html_config_copy'] = $this->tpl->getTemplate('install_config_new_copy');
|
||||
$tpl_data['php_config'] = $config_php;
|
||||
$changed = false;
|
||||
foreach($config as $ckey => &$cvalue) {
|
||||
if(isset($values[$ckey])) {
|
||||
$changed = true;
|
||||
$cvalue = $values[$ckey];
|
||||
}
|
||||
}
|
||||
// add config to template data for prefilling the form
|
||||
$tpl_data = $config;
|
||||
|
||||
if($changed) {
|
||||
// test db connection
|
||||
$this->db = new \psm\Service\Database(
|
||||
$config['host'],
|
||||
$config['user'],
|
||||
$config['pass'],
|
||||
$config['name']
|
||||
);
|
||||
|
||||
if($this->db->status()) {
|
||||
$this->addMessage('Connection to MySQL successful.', 'success');
|
||||
$config_php = $this->writeConfigFile($config);
|
||||
if($config_php === true) {
|
||||
$this->addMessage('Configuration file written successfully.', 'success');
|
||||
} else {
|
||||
$this->addMessage('Config file is not writable, we cannot save it for you.', 'error');
|
||||
$this->tpl->newTemplate('install_config_new_copy', 'install.tpl.html');
|
||||
$tpl_data['html_config_copy'] = $this->tpl->getTemplate('install_config_new_copy');
|
||||
$tpl_data['php_config'] = $config_php;
|
||||
}
|
||||
} else {
|
||||
$this->addMessage('Unable to connect to MySQL. Please check your information.', 'error');
|
||||
}
|
||||
} else {
|
||||
$this->addResult('Unable to connect to MySQL. Please check your information.', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
if(defined('PSM_CONFIG')) {
|
||||
if($this->db->status()) {
|
||||
if($this->isUpgrade()) {
|
||||
// upgrade
|
||||
if(version_compare($version_from, '2.2.0', '<')) {
|
||||
// upgrade from before 2.2, does not have passwords yet.. create new user first
|
||||
$this->addMessage('PLEASE CREATE A USER!', 'warning');
|
||||
$this->setTemplateId('install_config_new_user', 'install.tpl.html');
|
||||
} else {
|
||||
$this->setTemplateId('install_config_upgrade', 'install.tpl.html');
|
||||
$tpl_data['version'] = PSM_VERSION;
|
||||
}
|
||||
} else {
|
||||
// fresh install ahead
|
||||
$this->setTemplateId('install_config_new_user', 'install.tpl.html');
|
||||
|
||||
$tpl_data['username'] = (isset($_POST['username'])) ? $_POST['username'] : '';
|
||||
$tpl_data['email'] = (isset($_POST['email'])) ? $_POST['email'] : '';
|
||||
}
|
||||
} else {
|
||||
$this->addMessage('Configuration file found, but unable to connect to MySQL. Please check your information.', 'error');
|
||||
}
|
||||
}
|
||||
$this->tpl->addTemplateData($this->getTemplateId(), $tpl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the 2.0 config file for prefilling
|
||||
* @return array
|
||||
*/
|
||||
protected function parseConfig20() {
|
||||
$config_old = file_get_contents($this->path_config_old);
|
||||
$vars = array(
|
||||
'prefix' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'name' => '',
|
||||
'host' => '',
|
||||
);
|
||||
$pattern = "/define\('SM_DB_{key}', '(.*?)'/u";
|
||||
|
||||
foreach($vars as $key => $value) {
|
||||
$pattern_key = str_replace('{key}', strtoupper($key), $pattern);
|
||||
preg_match($pattern_key, $config_old, $value_matches);
|
||||
$vars[$key] = (isset($value_matches[1])) ? $value_matches[1] : '';
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the upgrade process to a newer version
|
||||
* Execute the install and upgrade process to a newer version
|
||||
*/
|
||||
protected function executeInstall() {
|
||||
if(!defined('PSM_CONFIG')) {
|
||||
$this->addResult('No valid configuration found.', 'error');
|
||||
if(!defined('PSM_CONFIG') || !$this->db->status()) {
|
||||
return $this->executeConfig();
|
||||
}
|
||||
if(!$this->db->status()) {
|
||||
$this->addResult('MySQL connection failed.', 'error');
|
||||
return;
|
||||
}
|
||||
$logger = array($this, 'addResult');
|
||||
// check if user submitted username + password in previous step
|
||||
// this would only be the case for new installs, and install from
|
||||
// before 2.2
|
||||
$new_user = array(
|
||||
'user_name' => psm_POST('username'),
|
||||
'name' => psm_POST('username'),
|
||||
'password' => psm_POST('password'),
|
||||
'password_repeat' => psm_POST('password_repeat'),
|
||||
'email' => psm_POST('email', ''),
|
||||
'level' => PSM_USER_ADMIN,
|
||||
);
|
||||
|
||||
$validator = new \psm\Util\User\UserValidator($this->user);
|
||||
|
||||
$logger = array($this, 'addMessage');
|
||||
$installer = new \psm\Util\Install\Installer($this->db, $logger);
|
||||
$installer->install();
|
||||
|
||||
if($this->isUpgrade()) {
|
||||
$this->addMessage('Upgrade process started.', 'info');
|
||||
|
||||
$version_from = $this->getPreviousVersion();
|
||||
if($version_from === false) {
|
||||
$this->addMessage('Unable to locate your previous version. Please run a fresh install.', 'error');
|
||||
} else {
|
||||
if(version_compare($version_from, PSM_VERSION, '=')) {
|
||||
$this->addMessage('Your installation is already at the latest version.', 'success');
|
||||
} elseif(version_compare($version_from, PSM_VERSION, '>')) {
|
||||
$this->addMessage('This installer does not support downgrading, sorry.', 'error');
|
||||
} else {
|
||||
$this->addMessage('Upgrading from ' . $version_from . ' to ' . PSM_VERSION, 'info');
|
||||
$installer->upgrade($version_from, PSM_VERSION);
|
||||
|
||||
}
|
||||
if(version_compare($version_from, '2.2.0', '<')) {
|
||||
$add_user = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// validate the lot
|
||||
try {
|
||||
$validator->email($new_user['email']);
|
||||
$validator->password($new_user['password'], $new_user['password_repeat']);
|
||||
} catch(\InvalidArgumentException $e) {
|
||||
$this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error');
|
||||
return $this->executeConfig();
|
||||
}
|
||||
|
||||
$this->addMessage('Installation process started.', 'success');
|
||||
$installer->install();
|
||||
// add user
|
||||
$add_user = true;
|
||||
}
|
||||
|
||||
if($add_user) {
|
||||
unset($new_user['password_repeat']);
|
||||
$user_id = $this->db->save(PSM_DB_PREFIX.'users', $new_user);
|
||||
if(intval($user_id) > 0) {
|
||||
$this->addMessage('User account has been created successfully.');
|
||||
} else {
|
||||
$this->addMessage('There was an error adding your user account.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->setTemplateId('install_success', 'install.tpl.html');
|
||||
}
|
||||
|
@ -262,30 +301,63 @@ class Install extends AbstractModule {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add install result to be added to the main template
|
||||
* @param string|array $msg
|
||||
* @param string $status success/warning/error
|
||||
* @return \psm\Module\Install
|
||||
* Parse the 2.0 config file for prefilling
|
||||
* @return array
|
||||
*/
|
||||
public function addResult($msg, $status = 'success') {
|
||||
if(!is_array($msg)) {
|
||||
$msg = array($msg);
|
||||
}
|
||||
if($status == 'error') {
|
||||
$shortcode = 'important';
|
||||
} else {
|
||||
$shortcode = $status;
|
||||
protected function parseConfig20() {
|
||||
$config_old = file_get_contents($this->path_config_old);
|
||||
$vars = array(
|
||||
'prefix' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'name' => '',
|
||||
'host' => '',
|
||||
);
|
||||
$pattern = "/define\('SM_DB_{key}', '(.*?)'/u";
|
||||
|
||||
foreach($vars as $key => $value) {
|
||||
$pattern_key = str_replace('{key}', strtoupper($key), $pattern);
|
||||
preg_match($pattern_key, $config_old, $value_matches);
|
||||
$vars[$key] = (isset($value_matches[1])) ? $value_matches[1] : '';
|
||||
}
|
||||
|
||||
foreach($msg as $m) {
|
||||
$this->install_results[] = array(
|
||||
'message' => $m,
|
||||
'status' => strtoupper($status),
|
||||
'shortcode' => $shortcode,
|
||||
);
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it an upgrade or install?
|
||||
*/
|
||||
protected function isUpgrade() {
|
||||
if(!$this->db->status()) {
|
||||
return false;
|
||||
}
|
||||
$confExists = $this->db->query("SHOW TABLES LIKE '".PSM_DB_PREFIX."config';", false)->rowCount();
|
||||
|
||||
if($confExists > 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous version from the config table
|
||||
* @return boolean|string FALSE on failure, string otherwise
|
||||
*/
|
||||
protected function getPreviousVersion() {
|
||||
if(!$this->isUpgrade()) {
|
||||
return false;
|
||||
}
|
||||
$version_conf = $this->db->selectRow(PSM_DB_PREFIX . 'config', array('key' => 'version'), array('value'));
|
||||
if(empty($version_conf)) {
|
||||
return false;
|
||||
} else {
|
||||
$version_from = $version_conf['value'];
|
||||
if(strpos($version_from, '.') === false) {
|
||||
// yeah, my bad.. previous version did not follow proper naming scheme
|
||||
$version_from = rtrim(chunk_split($version_from, 1, '.'), '.');
|
||||
}
|
||||
return $version_from;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,182 @@
|
|||
<?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;
|
||||
use psm\Service\Database;
|
||||
use psm\Service\Template;
|
||||
|
||||
class Login extends AbstractModule {
|
||||
|
||||
function __construct(Database $db, Template $tpl) {
|
||||
parent::__construct($db, $tpl);
|
||||
|
||||
$this->setMinUserLevelRequired(PSM_USER_ANONYMOUS);
|
||||
|
||||
$this->setActions(array(
|
||||
'login', 'forgot', 'reset',
|
||||
), 'login');
|
||||
|
||||
$this->addMenu(false);
|
||||
}
|
||||
|
||||
protected function executeLogin() {
|
||||
$this->setTemplateId('login', 'login.tpl.html');
|
||||
|
||||
if(isset($_POST['user_name']) && isset($_POST['user_password'])) {
|
||||
$rememberme = (isset($_POST['user_rememberme'])) ? true : false;
|
||||
$result = $this->user->loginWithPostData(
|
||||
$_POST['user_name'],
|
||||
$_POST['user_password'],
|
||||
$rememberme
|
||||
);
|
||||
|
||||
if($result) {
|
||||
// success login, redirect
|
||||
header('Location: ' . $_SERVER['REQUEST_URI']);
|
||||
die();
|
||||
} else {
|
||||
$this->addMessage(psm_get_lang('login', 'error_login_incorrect'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$tpl_data = array(
|
||||
'title_sign_in' => psm_get_lang('login', 'title_sign_in'),
|
||||
'label_username' => psm_get_lang('login', 'username'),
|
||||
'label_password' => psm_get_lang('login', 'password'),
|
||||
'label_remember_me' => psm_get_lang('login', 'remember_me'),
|
||||
'label_login' => psm_get_lang('login', 'login'),
|
||||
'label_password_forgot' => psm_get_lang('login', 'password_forgot'),
|
||||
'value_user_name' => (isset($_POST['user_name'])) ? $_POST['user_name'] : '',
|
||||
'value_rememberme' => (isset($rememberme) && $rememberme) ? 'checked="checked"' : '',
|
||||
);
|
||||
|
||||
$this->tpl->addTemplateData($this->getTemplateId(), $tpl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show/process the password forgot form (before the mail)
|
||||
*/
|
||||
protected function executeForgot() {
|
||||
$this->setTemplateId('login_forgot', 'login.tpl.html');
|
||||
|
||||
if(isset($_POST['user_name'])) {
|
||||
$user = $this->user->getUserByUsername($_POST['user_name']);
|
||||
|
||||
if(!empty($user)) {
|
||||
$token = $this->user->generatePasswordResetToken($user->user_id);
|
||||
// we have a token, send it along
|
||||
$this->sendPasswordForgotMail(
|
||||
$user->user_id,
|
||||
$user->email,
|
||||
$token
|
||||
);
|
||||
|
||||
$this->addMessage(psm_get_lang('login', 'success_password_forgot'), 'success');
|
||||
return $this->executeLogin();
|
||||
} else {
|
||||
$this->addMessage(psm_get_lang('login', 'error_user_incorrect'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$tpl_data = array(
|
||||
'title_forgot' => psm_get_lang('login', 'title_forgot'),
|
||||
'label_username' => psm_get_lang('login', 'username'),
|
||||
'label_submit' => psm_get_lang('login', 'submit'),
|
||||
'label_go_back' => psm_get_lang('system', 'go_back'),
|
||||
);
|
||||
|
||||
$this->tpl->addTemplateData($this->getTemplateId(), $tpl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show/process the password reset form (after the mail)
|
||||
*/
|
||||
protected function executeReset() {
|
||||
$this->setTemplateId('login_reset', 'login.tpl.html');
|
||||
|
||||
$user_id = (isset($_GET['user_id'])) ? intval($_GET['user_id']) : 0;
|
||||
$token = (isset($_GET['token'])) ? $_GET['token'] : '';
|
||||
|
||||
if(!$this->user->verifyPasswordResetToken($user_id, $token)) {
|
||||
$this->addMessage(psm_get_lang('login', 'error_reset_invalid_link'), 'error');
|
||||
return $this->executeLogin();
|
||||
}
|
||||
|
||||
if(!empty($_POST['user_password_new']) && !empty($_POST['user_password_repeat'])) {
|
||||
if($_POST['user_password_new'] !== $_POST['user_password_repeat']) {
|
||||
$this->addMessage(psm_get_lang('login', 'error_login_passwords_nomatch'), 'error');
|
||||
} else {
|
||||
$result = $this->user->changePassword($user_id, $_POST['user_password_new']);
|
||||
|
||||
if($result) {
|
||||
$this->addMessage(psm_get_lang('login', 'success_password_reset'), 'success');
|
||||
return $this->executeLogin();
|
||||
} else {
|
||||
$this->addMessage(psm_get_lang('login', 'error_login_incorrect'), 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
$user = $this->user->getUser($user_id);
|
||||
|
||||
$tpl_data = array(
|
||||
'title_reset' => psm_get_lang('login', 'title_reset'),
|
||||
'label_username' => psm_get_lang('login', 'username'),
|
||||
'label_password' => psm_get_lang('login', 'password'),
|
||||
'label_password_repeat' => psm_get_lang('login', 'password_repeat'),
|
||||
'label_reset' => psm_get_lang('login', 'password_reset'),
|
||||
'label_go_back' => psm_get_lang('system', 'go_back'),
|
||||
'value_user_name' => $user->user_name,
|
||||
);
|
||||
|
||||
$this->tpl->addTemplateData($this->getTemplateId(), $tpl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the password-reset-email.
|
||||
* @param int $user_id
|
||||
* @param string $user_email
|
||||
* @param string $user_password_reset_hash
|
||||
*/
|
||||
protected function sendPasswordForgotMail($user_id, $user_email, $user_password_reset_hash) {
|
||||
$mail = psm_build_mail();
|
||||
$mail->Subject = psm_get_lang('login' ,'password_reset_email_subject');
|
||||
|
||||
$url = psm_build_url(array(
|
||||
'action' => 'reset',
|
||||
'user_id' => $user_id,
|
||||
'token' => $user_password_reset_hash,
|
||||
));
|
||||
$body = psm_get_lang('login', 'password_reset_email_body');
|
||||
$body = str_replace('%link%', $url, $body);
|
||||
$mail->Body = $body;
|
||||
$mail->AltBody = str_replace('<br/>', "\n", $body);
|
||||
|
||||
$mail->AddAddress($user_email);
|
||||
$mail->Send();
|
||||
}
|
||||
}
|
|
@ -36,77 +36,27 @@ use psm\Service\Template;
|
|||
class Users extends AbstractModule {
|
||||
public $servers;
|
||||
|
||||
/**
|
||||
* User data validator
|
||||
* @var \psm\Util\User\UserValidator $user_validator
|
||||
*/
|
||||
protected $user_validator;
|
||||
|
||||
function __construct(Database $db, Template $tpl) {
|
||||
parent::__construct($db, $tpl);
|
||||
|
||||
$this->setMinUserLevelRequired(PSM_USER_ADMIN);
|
||||
|
||||
$this->setActions(array(
|
||||
'index', 'edit', 'delete', 'save',
|
||||
), 'index');
|
||||
|
||||
$this->servers = $this->db->select(PSM_DB_PREFIX.'servers', null, array('server_id', 'label'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the template to show the update screen for a user
|
||||
*/
|
||||
protected function executeEdit() {
|
||||
$this->setTemplateId('users_update', 'users.tpl.html');
|
||||
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'));
|
||||
|
||||
$user_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||
|
||||
$tpl_data = array();
|
||||
$servers_count = count($this->servers);
|
||||
|
||||
switch((int) $user_id) {
|
||||
case 0:
|
||||
// insert mode
|
||||
$tpl_data['titlemode'] = psm_get_lang('system', 'insert');
|
||||
$tpl_data['edit_user_id'] = '0';
|
||||
|
||||
// add inactive class to all servers
|
||||
for ($i = 0; $i < $servers_count; $i++) {
|
||||
$this->servers[$i]['class'] = 'inactive';
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// edit mode
|
||||
$edit_user = $this->db->selectRow(
|
||||
PSM_DB_PREFIX.'users',
|
||||
array('user_id' => $user_id)
|
||||
);
|
||||
if (empty($edit_user)) {
|
||||
$this->addMessage('Invalid user.');
|
||||
return $this->initializeAction('index');
|
||||
}
|
||||
|
||||
$tpl_data = array_merge($tpl_data, array(
|
||||
'titlemode' => psm_get_lang('system', 'edit') . ' ' . $edit_user['name'],
|
||||
'edit_user_id' => $edit_user['user_id'],
|
||||
'edit_value_name' => $edit_user['name'],
|
||||
'edit_value_mobile' => $edit_user['mobile'],
|
||||
'edit_value_email' => $edit_user['email'],
|
||||
));
|
||||
|
||||
// select servers for this user
|
||||
$user_servers = explode(',', $edit_user['server_id']);
|
||||
|
||||
for ($h = 0; $h < $servers_count; $h++) {
|
||||
if(in_array($this->servers[$h]['server_id'], $user_servers)) {
|
||||
$this->servers[$h]['edit_checked'] = 'checked="checked"';
|
||||
$this->servers[$h]['class'] = 'active';
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$this->tpl->addTemplateData(
|
||||
$this->getTemplateId(),
|
||||
$tpl_data
|
||||
);
|
||||
// add servers to template for the edit form
|
||||
$this->tpl->addTemplateDataRepeat('users_update', 'servers', $this->servers);
|
||||
return parent::initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,66 +71,164 @@ class Users extends AbstractModule {
|
|||
$servers_labels[$server['server_id']] = $server['label'];
|
||||
}
|
||||
|
||||
// get users from database
|
||||
$users = $this->db->select(
|
||||
PSM_DB_PREFIX.'users',
|
||||
null,
|
||||
null,
|
||||
array('user_id', 'user_name', 'level', 'server_id', 'name', 'mobile', 'email'),
|
||||
null,
|
||||
array('name')
|
||||
);
|
||||
|
||||
$user_count = count($users);
|
||||
foreach($users as $x => &$user) {
|
||||
$user['class'] = ($x & 1) ? 'odd' : 'even';
|
||||
|
||||
for ($x = 0; $x < $user_count; $x++) {
|
||||
$users[$x]['class'] = ($x & 1) ? 'odd' : 'even';
|
||||
|
||||
$users[$x]['emp_servers'] = '';
|
||||
$user['emp_servers'] = '';
|
||||
|
||||
// fix server list
|
||||
$user_servers = explode(',', $users[$x]['server_id']);
|
||||
if (empty($user_servers)) continue;
|
||||
$user_servers = explode(',', $user['server_id']);
|
||||
if(empty($user_servers)) continue;
|
||||
|
||||
foreach ($user_servers as $server) {
|
||||
foreach($user_servers as $server) {
|
||||
if (!isset($servers_labels[$server])) continue;
|
||||
$users[$x]['emp_servers'] .= $servers_labels[$server] . '<br/>';
|
||||
$user['emp_servers'] .= $servers_labels[$server] . '<br/>';
|
||||
}
|
||||
$users[$x]['emp_servers'] = substr($users[$x]['emp_servers'], 0, -5);
|
||||
$user['emp_servers'] = substr($user['emp_servers'], 0, -5);
|
||||
}
|
||||
// add servers to template
|
||||
$this->tpl->addTemplateDataRepeat($this->getTemplateId(), 'users', $users);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the template to show the update screen for a user
|
||||
*/
|
||||
protected function executeEdit() {
|
||||
$this->setTemplateId('users_update', 'users.tpl.html');
|
||||
|
||||
$user_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||
$fields_prefill = array('name', 'user_name', 'mobile', 'email');
|
||||
|
||||
if($user_id == 0) {
|
||||
// insert mode
|
||||
$title = psm_get_lang('system', 'insert');
|
||||
$placeholder_password = '';
|
||||
$lvl_selected = PSM_USER_USER; // default level is regular user
|
||||
|
||||
// attempt to prefill previously posted fields
|
||||
$edit_user = new \stdClass();
|
||||
foreach($fields_prefill as $field) {
|
||||
$edit_user->$field = (isset($_POST[$field])) ? $_POST[$field] : '';
|
||||
}
|
||||
|
||||
// add inactive class to all servers
|
||||
foreach($this->servers as &$server) {
|
||||
$server['class'] = 'inactive';
|
||||
}
|
||||
} else {
|
||||
// edit mode
|
||||
try {
|
||||
$this->user_validator->userId($user_id);
|
||||
} catch(\InvalidArgumentException $e) {
|
||||
$this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error');
|
||||
return $this->executeIndex();
|
||||
}
|
||||
$edit_user = $this->user->getUser($user_id);
|
||||
$title = psm_get_lang('system', 'edit') . ' ' . $edit_user->name;
|
||||
$placeholder_password = psm_get_lang('users', 'password_leave_blank');
|
||||
$lvl_selected = $edit_user->level;
|
||||
|
||||
// select servers for this user
|
||||
$user_servers = explode(',', $edit_user->server_id);
|
||||
|
||||
foreach($this->servers as &$server) {
|
||||
if(in_array($server['server_id'], $user_servers)) {
|
||||
$server['edit_checked'] = 'checked="checked"';
|
||||
$server['class'] = 'active';
|
||||
}
|
||||
}
|
||||
}
|
||||
$tpl_data = array(
|
||||
'titlemode' => $title,
|
||||
'placeholder_password' => $placeholder_password,
|
||||
'edit_user_id' => $user_id,
|
||||
);
|
||||
foreach($fields_prefill as $field) {
|
||||
if(isset($edit_user->$field)) {
|
||||
$tpl_data['edit_value_' . $field] = $edit_user->$field;
|
||||
}
|
||||
}
|
||||
|
||||
$ulvls_tpl = array();
|
||||
foreach($this->user_validator->getUserLevels() as $lvl) {
|
||||
$ulvls_tpl[] = array(
|
||||
'value' => $lvl,
|
||||
'label' => psm_get_lang('users', 'level_' . $lvl),
|
||||
'selected' => ($lvl == $lvl_selected) ? 'selected="selected"' : '',
|
||||
);
|
||||
}
|
||||
$this->tpl->addTemplateDataRepeat($this->getTemplateId(), 'levels', $ulvls_tpl);
|
||||
$this->tpl->addTemplateDataRepeat($this->getTemplateId(), 'servers', $this->servers);
|
||||
$this->tpl->addTemplateData($this->getTemplateId(), $tpl_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the saving of a user
|
||||
*/
|
||||
protected function executeSave() {
|
||||
// check for add/edit mode
|
||||
if (isset($_POST['name']) && isset($_POST['mobile']) && isset($_POST['email'])) {
|
||||
$clean = array(
|
||||
'name' => $_POST['name'],
|
||||
'mobile' => $_POST['mobile'],
|
||||
'email' => $_POST['email'],
|
||||
'server_id' => (isset($_POST['server_id'])) ? implode(',', $_POST['server_id']) : ''
|
||||
);
|
||||
$id = (isset($_GET['id'])) ? intval($_GET['id']) : 0;
|
||||
if(empty($_POST)) {
|
||||
// dont process anything if no data has been posted
|
||||
return $this->executeIndex();
|
||||
}
|
||||
$user_id = (isset($_GET['id'])) ? intval($_GET['id']) : 0;
|
||||
|
||||
// check for edit or add
|
||||
if ((int) $id > 0) {
|
||||
// edit
|
||||
$this->db->save(
|
||||
PSM_DB_PREFIX.'users',
|
||||
$clean,
|
||||
array('user_id' => $id)
|
||||
);
|
||||
$this->addMessage(psm_get_lang('users', 'updated'));
|
||||
$fields = array('name', 'user_name', 'password', 'password_repeat', 'level', 'mobile', 'email', 'server_id');
|
||||
$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 {
|
||||
// add
|
||||
$this->db->save(PSM_DB_PREFIX.'users', $clean);
|
||||
$this->addMessage(psm_get_lang('users', 'inserted'));
|
||||
$clean[$field] = '';
|
||||
}
|
||||
}
|
||||
$this->initializeAction('index');
|
||||
|
||||
// validate the lot
|
||||
try {
|
||||
$this->user_validator->username($clean['user_name'], $user_id);
|
||||
$this->user_validator->email($clean['email']);
|
||||
$this->user_validator->level($clean['level']);
|
||||
|
||||
// always validate password for new users,
|
||||
// but only validate it for existing users when they change it.
|
||||
if($user_id == 0 || ($user_id > 0 && $clean['password'] != '')) {
|
||||
$this->user_validator->password($clean['password'], $clean['password_repeat']);
|
||||
}
|
||||
if($user_id > 0) {
|
||||
$this->user_validator->userId($user_id);
|
||||
}
|
||||
} catch(\InvalidArgumentException $e) {
|
||||
$this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error');
|
||||
return $this->executeEdit();
|
||||
}
|
||||
if(!empty($clean['password'])) {
|
||||
$password = $clean['password'];
|
||||
$clean['password'] = '';
|
||||
}
|
||||
unset($clean['password_repeat']);
|
||||
|
||||
if($user_id > 0) {
|
||||
// edit user
|
||||
$this->db->save(PSM_DB_PREFIX.'users', $clean, array('user_id' => $user_id));
|
||||
$this->addMessage(psm_get_lang('users', 'updated'), 'success');
|
||||
} else {
|
||||
// add user
|
||||
$user_id = $this->db->save(PSM_DB_PREFIX.'users', $clean);
|
||||
$this->addMessage(psm_get_lang('users', 'inserted'), 'success');
|
||||
}
|
||||
if(isset($password)) {
|
||||
$this->user->changePassword($user_id, $password);
|
||||
}
|
||||
return $this->executeIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,16 +237,19 @@ class Users extends AbstractModule {
|
|||
protected function executeDelete() {
|
||||
$id = (isset($_GET['id'])) ? intval($_GET['id']) : 0;
|
||||
|
||||
if($id > 0) {
|
||||
try {
|
||||
$this->user_validator->userId($id);
|
||||
|
||||
$this->db->delete(
|
||||
PSM_DB_PREFIX . 'users',
|
||||
array(
|
||||
'user_id' => $id,
|
||||
)
|
||||
array('user_id' => $id,)
|
||||
);
|
||||
$this->addMessage(psm_get_lang('system', 'deleted'));
|
||||
$this->addMessage(psm_get_lang('system', 'deleted'), 'success');
|
||||
} catch(\InvalidArgumentException $e) {
|
||||
$this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error');
|
||||
}
|
||||
$this->initializeAction('index');
|
||||
|
||||
return $this->executeIndex();
|
||||
}
|
||||
|
||||
// override parent::createHTMLLabels()
|
||||
|
@ -208,11 +259,19 @@ class Users extends AbstractModule {
|
|||
array(
|
||||
'label_users' => psm_get_lang('system', 'users'),
|
||||
'label_name' => psm_get_lang('users', 'name'),
|
||||
'label_user_name' => psm_get_lang('users', 'user_name'),
|
||||
'label_password' => psm_get_lang('users', 'password'),
|
||||
'label_password_repeat' => psm_get_lang('users', 'password_repeat'),
|
||||
'label_level' => psm_get_lang('users', 'level'),
|
||||
'label_level_10' => psm_get_lang('users', 'level_10'),
|
||||
'label_level_20' => psm_get_lang('users', 'level_20'),
|
||||
'label_level_30' => psm_get_lang('users', 'level_30'),
|
||||
'label_mobile' => psm_get_lang('users', 'mobile'),
|
||||
'label_email' => psm_get_lang('users', 'email'),
|
||||
'label_servers' => psm_get_lang('system', 'servers'),
|
||||
'label_action' => psm_get_lang('system', 'action'),
|
||||
'label_save' => psm_get_lang('system', 'save'),
|
||||
'label_go_back' => psm_get_lang('system', 'go_back'),
|
||||
'label_edit' => psm_get_lang('system', 'edit') . ' ' . psm_get_lang('users', 'user'),
|
||||
'label_delete' => psm_get_lang('system', 'delete') . ' ' . psm_get_lang('users', 'user'),
|
||||
'label_add_new' => psm_get_lang('system', 'add_new'),
|
||||
|
@ -222,5 +281,3 @@ class Users extends AbstractModule {
|
|||
return parent::createHTMLLabels();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,423 @@
|
|||
<?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 Panique <https://github.com/panique/php-login-advanced/>
|
||||
* @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\Service;
|
||||
|
||||
/**
|
||||
* This is a heavily modified version of the php-login-advanced project by Panique.
|
||||
*
|
||||
* @author Panique
|
||||
* @author Pepijn Over
|
||||
* @link http://www.php-login.net
|
||||
* @link https://github.com/panique/php-login-advanced/
|
||||
* @license http://opensource.org/licenses/MIT MIT License
|
||||
*/
|
||||
class User {
|
||||
|
||||
/**
|
||||
* The database connection
|
||||
* @var \PDO $db_connection
|
||||
*/
|
||||
protected $db_connection = null;
|
||||
|
||||
/**
|
||||
* Local cache of user data
|
||||
* @var array $user_data
|
||||
*/
|
||||
protected $user_data = array();
|
||||
|
||||
/**
|
||||
* Current user id
|
||||
* @var int $user_id
|
||||
*/
|
||||
protected $user_id;
|
||||
|
||||
/**
|
||||
* The user's login status
|
||||
* @var boolean $user_is_logged_in
|
||||
*/
|
||||
protected $user_is_logged_in = false;
|
||||
|
||||
/**
|
||||
* the function "__construct()" automatically starts whenever an object of this class is created,
|
||||
* you know, when you do "$login = new Login();"
|
||||
*/
|
||||
public function __construct(Database $db) {
|
||||
$this->db_connection = $db->pdo();
|
||||
|
||||
session_start();
|
||||
|
||||
// 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(isset($_GET["logout"])) {
|
||||
$this->doLogout();
|
||||
// logged out, redirect to login
|
||||
header('Location: ' . psm_build_url());
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user by id, or get current user.
|
||||
* @return object|boolean FALSE if user not found, object otherwise
|
||||
*/
|
||||
public function getUser($user_id = null) {
|
||||
if($user_id == null) {
|
||||
if(!$this->isUserLoggedIn()) {
|
||||
return false;
|
||||
} else {
|
||||
$user_id = $this->getUserId();
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($this->user_data[$user_id])) {
|
||||
$query_user = $this->db_connection->prepare('SELECT * FROM '.PSM_DB_PREFIX.'users WHERE user_id = :user_id');
|
||||
$query_user->bindValue(':user_id', $user_id, \PDO::PARAM_INT);
|
||||
$query_user->execute();
|
||||
// get result row (as an object)
|
||||
$this->user_data[$user_id] = $query_user->fetchObject();
|
||||
}
|
||||
return $this->user_data[$user_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search into database for the user data of user_name specified as parameter
|
||||
* @return object|boolean user data as an object if existing user
|
||||
*/
|
||||
public function getUserByUsername($user_name) {
|
||||
// database query, getting all the info of the selected user
|
||||
$query_user = $this->db_connection->prepare('SELECT * FROM '.PSM_DB_PREFIX.'users WHERE user_name = :user_name');
|
||||
$query_user->bindValue(':user_name', $user_name, \PDO::PARAM_STR);
|
||||
$query_user->execute();
|
||||
// get result row (as an object)
|
||||
return $query_user->fetchObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in with S_SESSION data.
|
||||
*/
|
||||
private function loginWithSessionData() {
|
||||
if(empty($_SESSION) || !isset($_SESSION['user_id'])) {
|
||||
return false;
|
||||
}
|
||||
$user = $this->getUser($_SESSION['user_id']);
|
||||
|
||||
if(!empty($user)) {
|
||||
$this->setUserLoggedIn($user->user_id);
|
||||
return true;
|
||||
} else {
|
||||
// user no longer exists in database
|
||||
// call logout to clean up session vars
|
||||
$this->doLogout();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in via the Cookie
|
||||
* @return bool success state of cookie login
|
||||
*/
|
||||
private function loginWithCookieData() {
|
||||
if (isset($_COOKIE['rememberme'])) {
|
||||
// extract data from the cookie
|
||||
list ($user_id, $token, $hash) = explode(':', $_COOKIE['rememberme']);
|
||||
// check cookie hash validity
|
||||
if ($hash == hash('sha256', $user_id . ':' . $token . PSM_LOGIN_COOKIE_SECRET_KEY) && !empty($token)) {
|
||||
// cookie looks good, try to select corresponding user
|
||||
// get real token from database (and all other data)
|
||||
$user = $this->getUser($user_id);
|
||||
|
||||
if(!empty($user) && $token === $user->rememberme_token) {
|
||||
$this->setUserLoggedIn($user->user_id, true);
|
||||
|
||||
// Cookie token usable only once
|
||||
$this->newRememberMeCookie();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// call logout to remove invalid cookie
|
||||
$this->doLogout();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in with the data provided in $_POST, coming from the login form
|
||||
* @param string $user_name
|
||||
* @param string $user_password
|
||||
* @param boolean $user_rememberme
|
||||
* @return boolean
|
||||
*/
|
||||
public function loginWithPostData($user_name, $user_password, $user_rememberme = false) {
|
||||
$user_name = trim($user_name);
|
||||
$user_password = trim($user_password);
|
||||
|
||||
if(empty($user_name) && empty($user_password)) {
|
||||
return false;
|
||||
}
|
||||
$user = $this->getUserByUsername($user_name);
|
||||
|
||||
// using PHP 5.5's password_verify() function to check if the provided passwords fits to the hash of that user's password
|
||||
if(!isset($user->user_id)) {
|
||||
password_verify($user_password, 'dummy_call_against_timing');
|
||||
return false;
|
||||
} else if (! password_verify($user_password, $user->password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setUserLoggedIn($user->user_id, true);
|
||||
|
||||
// if user has check the "remember me" checkbox, then generate token and write cookie
|
||||
if ($user_rememberme) {
|
||||
$this->newRememberMeCookie();
|
||||
}
|
||||
|
||||
// recalculate the user's password hash
|
||||
// DELETE this if-block if you like, it only exists to recalculate users's hashes when you provide a cost factor,
|
||||
// by default the script will use a cost factor of 10 and never change it.
|
||||
// check if the have defined a cost factor in config/hashing.php
|
||||
if (defined('PSM_LOGIN_HASH_COST_FACTOR')) {
|
||||
// check if the hash needs to be rehashed
|
||||
if (password_needs_rehash($user->password, PASSWORD_DEFAULT, array('cost' => PSM_LOGIN_HASH_COST_FACTOR))) {
|
||||
$this->changePassword($user->user_id, $user_password);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user logged in
|
||||
* @param int $user_id
|
||||
* @param boolean $regenerate regenerate session id against session fixation?
|
||||
*/
|
||||
protected function setUserLoggedIn($user_id, $regenerate = false) {
|
||||
if($regenerate) {
|
||||
session_regenerate_id();
|
||||
}
|
||||
$_SESSION['user_id'] = $user_id;
|
||||
$_SESSION['user_logged_in'] = 1;
|
||||
|
||||
// declare user id, set the login status to true
|
||||
$this->user_id = $user_id;
|
||||
$this->user_is_logged_in = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create all data needed for remember me cookie connection on client and server side
|
||||
*/
|
||||
private function newRememberMeCookie() {
|
||||
// generate 64 char random string and store it in current user data
|
||||
$random_token_string = hash('sha256', mt_rand());
|
||||
$sth = $this->db_connection->prepare('UPDATE '.PSM_DB_PREFIX.'users SET rememberme_token = :user_rememberme_token WHERE user_id = :user_id');
|
||||
$sth->execute(array(':user_rememberme_token' => $random_token_string, ':user_id' => $this->getUserId()));
|
||||
|
||||
// generate cookie string that consists of userid, randomstring and combined hash of both
|
||||
$cookie_string_first_part = $this->getUserId() . ':' . $random_token_string;
|
||||
$cookie_string_hash = hash('sha256', $cookie_string_first_part . PSM_LOGIN_COOKIE_SECRET_KEY);
|
||||
$cookie_string = $cookie_string_first_part . ':' . $cookie_string_hash;
|
||||
|
||||
// set cookie
|
||||
setcookie('rememberme', $cookie_string, time() + PSM_LOGIN_COOKIE_RUNTIME, "/", PSM_LOGIN_COOKIE_DOMAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data needed for remember me cookie connection on client and server side
|
||||
*/
|
||||
private function deleteRememberMeCookie() {
|
||||
// Reset rememberme token
|
||||
if(isset($_SESSION['user_id'])) {
|
||||
$sth = $this->db_connection->prepare('UPDATE '.PSM_DB_PREFIX.'users SET rememberme_token = NULL WHERE user_id = :user_id');
|
||||
$sth->execute(array(':user_id' => $_SESSION['user_id']));
|
||||
}
|
||||
|
||||
// set the rememberme-cookie to ten years ago (3600sec * 365 days * 10).
|
||||
// that's obivously the best practice to kill a cookie via php
|
||||
// @see http://stackoverflow.com/a/686166/1114320
|
||||
setcookie('rememberme', false, time() - (3600 * 3650), '/', PSM_LOGIN_COOKIE_DOMAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the logout, resetting the session
|
||||
*/
|
||||
public function doLogout() {
|
||||
$this->deleteRememberMeCookie();
|
||||
|
||||
$_SESSION = array();
|
||||
session_destroy();
|
||||
session_start();
|
||||
session_regenerate_id();
|
||||
|
||||
$this->user_is_logged_in = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply return the current state of the user's login
|
||||
* @return bool user's login status
|
||||
*/
|
||||
public function isUserLoggedIn() {
|
||||
return $this->user_is_logged_in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a random token into the database (that will verify the user when he/she comes back via the link
|
||||
* in the email) and returns it
|
||||
* @param int $user_id
|
||||
* @return string|boolean FALSE on error, string otherwise
|
||||
*/
|
||||
public function generatePasswordResetToken($user_id) {
|
||||
$user_id = intval($user_id);
|
||||
|
||||
if($user_id == 0) {
|
||||
return false;
|
||||
}
|
||||
// generate timestamp (to see when exactly the user (or an attacker) requested the password reset mail)
|
||||
$temporary_timestamp = time();
|
||||
// generate random hash for email password reset verification (40 char string)
|
||||
$user_password_reset_hash = sha1(uniqid(mt_rand(), true));
|
||||
|
||||
$query_update = $this->db_connection->prepare('UPDATE '.PSM_DB_PREFIX.'users SET password_reset_hash = :user_password_reset_hash,
|
||||
password_reset_timestamp = :user_password_reset_timestamp
|
||||
WHERE user_id = :user_id');
|
||||
$query_update->bindValue(':user_password_reset_hash', $user_password_reset_hash, \PDO::PARAM_STR);
|
||||
$query_update->bindValue(':user_password_reset_timestamp', $temporary_timestamp, \PDO::PARAM_INT);
|
||||
$query_update->bindValue(':user_id', $user_id, \PDO::PARAM_INT);
|
||||
$query_update->execute();
|
||||
|
||||
// check if exactly one row was successfully changed:
|
||||
if ($query_update->rowCount() == 1) {
|
||||
return $user_password_reset_hash;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the verification string in the account verification mail is valid and matches to the user.
|
||||
*
|
||||
* Please note it is valid for 1 hour.
|
||||
* @param int $user_id
|
||||
* @param string $token
|
||||
* @return boolean
|
||||
*/
|
||||
public function verifyPasswordResetToken($user_id, $token) {
|
||||
$user_id = intval($user_id);
|
||||
|
||||
if(empty($user_id) || empty($token)) {
|
||||
return false;
|
||||
}
|
||||
$user = $this->getUser($user_id);
|
||||
|
||||
if(isset($user->user_id) && $user->password_reset_hash == $token) {
|
||||
$runtime = (defined('PSM_LOGIN_RESET_RUNTIME')) ? PSM_LOGIN_RESET_RUNTIME : 3600;
|
||||
$timestamp_max_interval = time() - $runtime;
|
||||
|
||||
if($user->password_reset_timestamp > $timestamp_max_interval) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the password of a user
|
||||
* @param int $user_id
|
||||
* @param string $password
|
||||
* @return boolean TRUE on success, FALSE on failure
|
||||
*/
|
||||
public function changePassword($user_id, $password) {
|
||||
$user_id = intval($user_id);
|
||||
|
||||
if(empty($user_id) || empty($password)) {
|
||||
return false;
|
||||
}
|
||||
// now it gets a little bit crazy: check if we have a constant PSM_LOGIN_HASH_COST_FACTOR defined (in src/includes/psmconfig.inc.php),
|
||||
// if so: put the value into $hash_cost_factor, if not, make $hash_cost_factor = null
|
||||
$hash_cost_factor = (defined('PSM_LOGIN_HASH_COST_FACTOR') ? PSM_LOGIN_HASH_COST_FACTOR : null);
|
||||
|
||||
// crypt the user's password with the PHP 5.5's password_hash() function, results in a 60 character hash string
|
||||
// the PASSWORD_DEFAULT constant is defined by the PHP 5.5, or if you are using PHP 5.3/5.4, by the password hashing
|
||||
// compatibility library. the third parameter looks a little bit shitty, but that's how those PHP 5.5 functions
|
||||
// want the parameter: as an array with, currently only used with 'cost' => XX.
|
||||
$user_password_hash = password_hash($password, PASSWORD_DEFAULT, array('cost' => $hash_cost_factor));
|
||||
|
||||
// write users new hash into database
|
||||
$query_update = $this->db_connection->prepare('UPDATE '.PSM_DB_PREFIX.'users SET password = :user_password_hash,
|
||||
password_reset_hash = NULL, password_reset_timestamp = NULL
|
||||
WHERE user_id = :user_id');
|
||||
$query_update->bindValue(':user_password_hash', $user_password_hash, \PDO::PARAM_STR);
|
||||
$query_update->bindValue(':user_id', $user_id, \PDO::PARAM_STR);
|
||||
$query_update->execute();
|
||||
|
||||
// check if exactly one row was successfully changed:
|
||||
if ($query_update->rowCount() == 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user id
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId() {
|
||||
return $this->user_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username
|
||||
* @return string
|
||||
*/
|
||||
public function getUsername() {
|
||||
$user = $this->getUser();
|
||||
return (isset($user->user_name) ? $user->user_name : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user level
|
||||
* @return int
|
||||
*/
|
||||
public function getUserLevel() {
|
||||
$user = $this->getUser();
|
||||
|
||||
if(isset($user->level)) {
|
||||
return $user->level;
|
||||
} else {
|
||||
return PSM_USER_ANONYMOUS;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -100,23 +100,30 @@ class Installer {
|
|||
public function install() {
|
||||
$this->installTables();
|
||||
|
||||
$version_conf = $this->db->selectRow(PSM_DB_PREFIX . 'config', array('key' => 'version'), array('key', 'value'));
|
||||
|
||||
if(empty($version_conf)) {
|
||||
// fresh install
|
||||
$version_from = null;
|
||||
} else {
|
||||
// existing install
|
||||
$version_from = $version_conf['value'];
|
||||
if(strpos($version_from, '.') === false) {
|
||||
// yeah, my bad.. previous version did not follow proper naming scheme
|
||||
$version_from = rtrim(chunk_split($version_from, 1, '.'), '.');
|
||||
}
|
||||
}
|
||||
$this->upgrade(PSM_VERSION, $version_from);
|
||||
|
||||
|
||||
$this->log('Installation finished!');
|
||||
$this->log('Populating database...');
|
||||
$queries = array();
|
||||
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "servers` (`ip`, `port`, `label`, `type`, `status`, `error`, `rtime`, `last_online`, `last_check`, `active`, `email`, `sms`) VALUES ('http://sourceforge.net/index.php', 80, 'SourceForge', 'website', 'on', '', '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 'yes', 'yes', 'yes'), ('smtp.gmail.com', 465, 'Gmail SMTP', 'service', 'on', '', '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 'yes', 'yes', 'yes')";
|
||||
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE
|
||||
('language', 'en'),
|
||||
('email_status', '1'),
|
||||
('email_from_email', 'monitor@example.org'),
|
||||
('email_from_name', 'Server Monitor'),
|
||||
('sms_status', '1'),
|
||||
('sms_gateway', 'mollie'),
|
||||
('sms_gateway_username', 'username'),
|
||||
('sms_gateway_password', 'password'),
|
||||
('sms_from', '1234567890'),
|
||||
('alert_type', 'status'),
|
||||
('log_status', '1'),
|
||||
('log_email', '1'),
|
||||
('log_sms', '1'),
|
||||
('version', '" . PSM_VERSION . "'),
|
||||
('auto_refresh_servers', '0'),
|
||||
('show_update', '1'),
|
||||
('last_update_check', '0'),
|
||||
('cron_running', '0'),
|
||||
('cron_running_time', '0');";
|
||||
$this->execSQL($queries);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,14 +131,21 @@ class Installer {
|
|||
*/
|
||||
protected function installTables() {
|
||||
$tables = array(
|
||||
PSM_DB_PREFIX . 'users' => "CREATE TABLE `" . PSM_DB_PREFIX . "users` (
|
||||
`user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`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`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;",
|
||||
PSM_DB_PREFIX . 'users' => "CREATE TABLE IF NOT EXISTS `monitor_users` (
|
||||
`user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`user_name` varchar(64) NOT NULL COMMENT 'user''s name, unique',
|
||||
`password` varchar(255) NOT NULL COMMENT 'user''s password in salted and hashed format',
|
||||
`password_reset_hash` char(40) DEFAULT NULL COMMENT 'user''s password reset code',
|
||||
`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 . 'log' => "CREATE TABLE `" . PSM_DB_PREFIX . "log` (
|
||||
`log_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`server_id` int(11) unsigned NOT NULL,
|
||||
|
@ -179,50 +193,19 @@ class Installer {
|
|||
|
||||
/**
|
||||
* Populate the tables and perform upgrades if necessary
|
||||
* @param string $version
|
||||
* @param string $version_from
|
||||
* @param string $version_to
|
||||
*/
|
||||
public function upgrade($version, $version_from = null) {
|
||||
if($version_from === null) {
|
||||
$this->log('Populating database...');
|
||||
$queries = array();
|
||||
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "users` (`server_id`, `name`, `mobile`, `email`) VALUES ('1,2', 'example_user', '0123456789', 'user@example.com')";
|
||||
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "servers` (`ip`, `port`, `label`, `type`, `status`, `error`, `rtime`, `last_online`, `last_check`, `active`, `email`, `sms`) VALUES ('http://sourceforge.net/index.php', 80, 'SourceForge', 'website', 'on', '', '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 'yes', 'yes', 'yes'), ('smtp.gmail.com', 465, 'Gmail SMTP', 'service', 'on', '', '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 'yes', 'yes', 'yes')";
|
||||
$queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE
|
||||
('language', 'en'),
|
||||
('email_status', '1'),
|
||||
('email_from_email', 'monitor@example.org'),
|
||||
('email_from_name', 'Server Monitor'),
|
||||
('sms_status', '1'),
|
||||
('sms_gateway', 'mollie'),
|
||||
('sms_gateway_username', 'username'),
|
||||
('sms_gateway_password', 'password'),
|
||||
('sms_from', '1234567890'),
|
||||
('alert_type', 'status'),
|
||||
('log_status', '1'),
|
||||
('log_email', '1'),
|
||||
('log_sms', '1'),
|
||||
('version', '{$version}'),
|
||||
('auto_refresh_servers', '0'),
|
||||
('show_update', '1'),
|
||||
('last_update_check', '0'),
|
||||
('cron_running', '0'),
|
||||
('cron_running_time', '0');";
|
||||
$this->execSQL($queries);
|
||||
} else {
|
||||
if(version_compare($version_from, $version, '<')) {
|
||||
$this->log('Upgrade detected, upgrading from ' . $version_from . ' to ' . $version);
|
||||
if(version_compare($version_from, '2.1.0', '<')) {
|
||||
// upgrade to 2.1.0
|
||||
$this->upgrade210();
|
||||
}
|
||||
if(version_compare($version_from, '2.2.0', '<')) {
|
||||
// upgrade to 2.2.0
|
||||
$this->upgrade220();
|
||||
}
|
||||
}
|
||||
$this->execSQL("UPDATE `" . PSM_DB_PREFIX . "config` SET `value` = '{$version}' WHERE `key` = 'version';");
|
||||
public function upgrade($version_from, $version_to) {
|
||||
if(version_compare($version_from, '2.1.0', '<')) {
|
||||
// upgrade to 2.1.0
|
||||
$this->upgrade210();
|
||||
}
|
||||
if(version_compare($version_from, '2.2.0', '<')) {
|
||||
// upgrade to 2.2.0
|
||||
$this->upgrade220();
|
||||
}
|
||||
$this->db->save(PSM_DB_PREFIX . 'config', array('value' => $version_from), array('key' => 'version'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -254,6 +237,17 @@ class Installer {
|
|||
$queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "log` CHANGE `server_id` `server_id` INT( 11 ) UNSIGNED NOT NULL;";
|
||||
$queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` CHANGE `server_id` `server_id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;";
|
||||
$queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` CHANGE `user_id` `user_id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;";
|
||||
$queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users`
|
||||
ADD `user_name` varchar(64) COLLATE utf8_general_ci NOT NULL COMMENT 'user\'s name, unique' AFTER `user_id`,
|
||||
ADD `password` varchar(255) COLLATE utf8_general_ci NOT NULL COMMENT 'user\'s password in salted and hashed format' AFTER `user_name`,
|
||||
ADD `password_reset_hash` char(40) COLLATE utf8_general_ci DEFAULT NULL COMMENT 'user\'s password reset code' AFTER `password`,
|
||||
ADD `password_reset_timestamp` bigint(20) DEFAULT NULL COMMENT 'timestamp of the password reset request' AFTER `password_reset_hash`,
|
||||
ADD `rememberme_token` varchar(64) COLLATE utf8_general_ci DEFAULT NULL COMMENT 'user\'s remember-me cookie token' AFTER `password_reset_timestamp`,
|
||||
ADD `level` TINYINT( 2 ) UNSIGNED NOT NULL DEFAULT '20' AFTER `rememberme_token`;";
|
||||
// make sure all current users are admins (previously we didnt have non-admins):
|
||||
$queries[] = "UPDATE `" . PSM_DB_PREFIX . "users` SET `user_name`=`email`, `level`=10;";
|
||||
$queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` ADD UNIQUE `unique_username` ( `user_name` );";
|
||||
|
||||
$queries[] = "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "uptime` (
|
||||
`server_id` INT( 11 ) NOT NULL,
|
||||
`date` DATETIME NOT NULL ,
|
||||
|
@ -264,5 +258,3 @@ class Installer {
|
|||
$this->execSQL($queries);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,145 @@
|
|||
<?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\User;
|
||||
|
||||
/**
|
||||
* The UserValidator helps you to check input data for user accounts.
|
||||
*/
|
||||
class UserValidator {
|
||||
|
||||
/**
|
||||
* Available editable user levels
|
||||
* @var array $user_levels
|
||||
*/
|
||||
protected $user_levels = array(PSM_USER_ADMIN, PSM_USER_USER);
|
||||
|
||||
/**
|
||||
* User service
|
||||
* @var \psm\Service\User $user
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
public function __construct(\psm\Service\User $user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user id exists
|
||||
* @param int $user_id
|
||||
* @return boolean
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function userId($user_id) {
|
||||
$user = $this->user->getUser($user_id);
|
||||
if(empty($user)) {
|
||||
throw new \InvalidArgumentException('user_no_match');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check username on:
|
||||
*
|
||||
* - Length (2-64 chars)
|
||||
* - Contents (alphabetic chars and digits only)
|
||||
* - Unique
|
||||
* @param string $username
|
||||
* @param int $user_id to check whether the username is unique
|
||||
* @return boolean
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function username($username, $user_id = 0) {
|
||||
if(strlen($username) > 64 || strlen($username) < 2) {
|
||||
throw new \InvalidArgumentException('user_name_bad_length');
|
||||
}
|
||||
if (!preg_match('/^[a-zA-Z\d_]{2,64}$/i', $username)) {
|
||||
throw new \InvalidArgumentException('user_name_invalid');
|
||||
}
|
||||
$user_exists = $this->user->getUserByUsername($username);
|
||||
|
||||
if(!empty($user_exists) && ($user_id == 0 || $user_id != $user_exists->user_id)) {
|
||||
throw new \InvalidArgumentException('user_name_exists');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check user password
|
||||
* @param string $password
|
||||
* @param string $password_repeat
|
||||
* @return boolean
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function password($password, $password_repeat) {
|
||||
if(empty($password) || empty($password_repeat)) {
|
||||
throw new \InvalidArgumentException('user_password_invalid');
|
||||
}
|
||||
if($password !== $password_repeat) {
|
||||
throw new \InvalidArgumentException('user_password_no_match');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check email
|
||||
* @param string $email
|
||||
* @return boolean
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function email($email) {
|
||||
if(strlen($email) > 255 || strlen($email) < 5) {
|
||||
throw new \InvalidArgumentException('user_email_bad_length');
|
||||
}
|
||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new \InvalidArgumentException('user_email_invalid');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check user level
|
||||
* @param int $level
|
||||
* @return boolean
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function level($level) {
|
||||
if(!in_array($level, $this->user_levels)) {
|
||||
throw new \InvalidArgumentException('user_level_invalid');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of all available user levels
|
||||
* @return array
|
||||
*/
|
||||
public function getUserLevels() {
|
||||
return $this->user_levels;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,82 @@
|
|||
<!--%tpl_install-->
|
||||
<div class="hero-unit">
|
||||
<h1><img class="pull-right" src="static/opensource.png" width="100" alt="" /> PHP Server Monitor</h1>
|
||||
<h2><a href="http://www.phpservermonitor.org/"><img class="pull-right" src="static/opensource.png" width="100" alt="" /></a> PHP Server Monitor</h2>
|
||||
<p> </p>
|
||||
<p>
|
||||
<a class="btn btn-primary btn-large" target="_blank" href="http://www.phpservermonitor.org/">PHP Server Monitor</a>
|
||||
<a class="btn btn-large" target="_blank" href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a>
|
||||
</p>
|
||||
<p>PHP Server Monitor is a script that checks whether the servers on your list are up and running on the selected ports. It comes with a web based user interface where you can add and remove servers or websites from the MySQL database, and you can manage users for each server with a mobile number and email address.</p>
|
||||
<p>To install PHP Server Monitor, please follow the instructions below.</p>
|
||||
{html_install}
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">{html_results}</div>
|
||||
</div>
|
||||
{html_install}
|
||||
<!--%%tpl_install-->
|
||||
|
||||
<!--%tpl_install_index-->
|
||||
<p>Welcome to the installation of PHP Server Monitor. This page will guide you through the steps to install or upgrade your monitor.</p>
|
||||
<p>Before we start, we need to verify your system meets the requirements.
|
||||
If you see any errors in the list below, you may still continue, but PHP Server Monitor may not work correctly.
|
||||
It is recommended you fix any errors before continuing.
|
||||
</p>
|
||||
{html_results}
|
||||
<p> </p>
|
||||
<p>
|
||||
<a class="btn btn-primary btn-large" href="install.php?action=config">Let's go</a>
|
||||
</p>
|
||||
<!--%%tpl_install_index-->
|
||||
|
||||
<!--%tpl_install_config_upgrade-->
|
||||
<p>We have discovered a previous version.</p>
|
||||
<p>In the next step we will upgrade your database to the latest version.</p>
|
||||
{html_results}
|
||||
<p> </p>
|
||||
<p><a class="btn btn-primary btn-large" href="install.php?action=install">Upgrade to {version}</a></p>
|
||||
<!--%%tpl_install_config_upgrade-->
|
||||
|
||||
<!--%tpl_install_config_new_user-->
|
||||
<p>Sweet, your database connection is up and running!</p>
|
||||
<p>Next, please set up a new account to access your monitor:</p>
|
||||
{html_results}
|
||||
<p> </p>
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<form id="psm_config" class="form-horizontal" action="install.php?action=install" method="post">
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="username">Username</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="username" name="username" value="{username}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password">Password</label>
|
||||
<div class="controls">
|
||||
<input type="password" id="password" name="password" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password_repeat">Password repeat</label>
|
||||
<div class="controls">
|
||||
<input type="password" id="password_repeat" name="password_repeat" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="email">Email</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="email" name="email" value="{email}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn btn-primary btn-large">Install</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{html_config_copy}
|
||||
</div>
|
||||
<!--%%tpl_install_config_new_user-->
|
||||
|
||||
<!--%tpl_install_config_new-->
|
||||
<div class="row-fluid">
|
||||
<div class="span12">{html_results}</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<form id="psm_config" class="form-horizontal" action="install.php" method="post">
|
||||
<!--<input type="hidden" name="action" value="config" />-->
|
||||
<form id="psm_config" class="form-horizontal" action="install.php?action=config" method="post">
|
||||
<h3>Please enter your database info:</h3>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="host">Database host</label>
|
||||
|
@ -66,7 +123,8 @@
|
|||
<div class="span6">
|
||||
<h3>Your config file:</h3>
|
||||
<div class="alert alert-error">Unable to save your configuration.</div>
|
||||
<p>Please create a new file in the project directory called "config.php" and copy the information below.</p>
|
||||
<p>Your database information is valid, however we are unable to create the configuration file automatically.
|
||||
Please create a new file in the project directory called "config.php" and copy the information below.</p>
|
||||
<p>After you have copied the configuration, press the button to continue.</p>
|
||||
<p class="pull-left"><textarea rows="10">{php_config}</textarea></p>
|
||||
<p class="offset2"><input type="submit" class="btn btn-primary" value="I have saved the configuration" onclick="location.reload(true);" /></p>
|
||||
|
@ -74,11 +132,19 @@
|
|||
<!--%%tpl_install_config_new_copy-->
|
||||
|
||||
<!--%tpl_install_success-->
|
||||
<div class="row-fluid">
|
||||
<div class="span12">{html_results}</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
The installation is complete. Please check above if errors have occured.<br/>
|
||||
If no errors have occurred, you are good to go.<br><br>
|
||||
<a class="btn btn-primary" href="index.php">Click here to go to the monitor</a>
|
||||
<p> </p>
|
||||
<p>The installation is complete. Please check above if errors have occurred.<br>
|
||||
If no errors have occurred, you are good to go.<br><br></p>
|
||||
<p>
|
||||
<a class="btn btn-primary btn-large" href="index.php">Go to your monitor</a>
|
||||
<a class="btn btn-large" target="_blank" href="http://www.phpservermonitor.org/">PHP Server Monitor</a>
|
||||
<a class="btn btn-large" target="_blank" href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!--%%tpl_install_success-->
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<!--%tpl_login-->
|
||||
<div class="container">
|
||||
<form class="form-signin" method="post">
|
||||
<h2 class="form-signin-heading">{title_sign_in}</h2>
|
||||
<input type="text" name="user_name" class="input-block-level" placeholder="{label_username}" value="{value_user_name}" required>
|
||||
<input type="password" name="user_password" class="input-block-level" placeholder="{label_password}" required>
|
||||
<input type="hidden" name="action" value="login">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="user_rememberme" value="1" {value_rememberme}> {label_remember_me}
|
||||
</label>
|
||||
<button class="btn btn-large btn-primary" type="submit">{label_login}</button>
|
||||
<a class="btn btn-large" href="?action=forgot">{label_password_forgot}</a>
|
||||
</form>
|
||||
</div>
|
||||
<!--%%tpl_login-->
|
||||
|
||||
<!--%tpl_login_forgot-->
|
||||
<div class="container">
|
||||
<form class="form-signin" method="post">
|
||||
<h2 class="form-signin-heading">{title_forgot}</h2>
|
||||
<input type="text" name="user_name" class="input-block-level" placeholder="{label_username}" value="{value_user_name}" required>
|
||||
<button class="btn btn-large btn-primary" type="submit">{label_submit}</button>
|
||||
<a class="btn btn-large" href="?">{label_go_back}</a>
|
||||
</form>
|
||||
</div>
|
||||
<!--%%tpl_login_forgot-->
|
||||
|
||||
<!--%tpl_login_reset-->
|
||||
<div class="container">
|
||||
<form class="form-signin" method="post">
|
||||
<h2 class="form-signin-heading">{title_reset}</h2>
|
||||
<input type="text" name="user_name" class="input-block-level" placeholder="{label_username}" value="{value_user_name}" required disabled="disabled">
|
||||
<input type="password" name="user_password_new" class="input-block-level" placeholder="{label_password}" required autocomplete="off">
|
||||
<input type="password" name="user_password_repeat" class="input-block-level" placeholder="{label_password_repeat}" required autocomplete="off">
|
||||
<button class="btn btn-large btn-primary" type="submit">{label_reset}</button>
|
||||
<a class="btn btn-large" href="?">{label_go_back}</a>
|
||||
</form>
|
||||
</div>
|
||||
<!--%%tpl_login_reset-->
|
|
@ -53,11 +53,18 @@
|
|||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div id="flashmessage" class="alert alert-info hide">{message}</div>
|
||||
<div id="flashmessage" class="alert alert-info hide">
|
||||
<!--%tpl_repeat_messages-->
|
||||
<div>
|
||||
<p class="pull-left span1"><span class="label label-{shortcode}">{status}</span></p>
|
||||
<p>{message}</p>
|
||||
</div>
|
||||
<!--%%tpl_repeat_messages-->
|
||||
{messages}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">{content}</div>
|
||||
|
||||
{html_footer}
|
||||
</div>
|
||||
<!-- /container -->
|
||||
|
@ -67,25 +74,21 @@
|
|||
|
||||
<!--%tpl_main_menu-->
|
||||
<div class="nav-collapse">
|
||||
<ul class="nav pull-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{label_usermenu} <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{url_logout}">{label_logout}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav">
|
||||
<li id="nav_option_servers" class="{active_servers}">
|
||||
<a href="index.php?type=servers">{label_servers}</a>
|
||||
</li>
|
||||
<li id="nav_option_users" class="{active_users}">
|
||||
<a href="index.php?type=users">{label_users}</a>
|
||||
</li>
|
||||
<li id="nav_option_log" class="{active_log}">
|
||||
<a href="index.php?type=log">{label_log}</a>
|
||||
</li>
|
||||
<li id="nav_option_status" class="{active_status}">
|
||||
<a href="index.php?type=status">{label_status}</a>
|
||||
</li>
|
||||
<li id="nav_option_config" class="{active_config}">
|
||||
<a href="index.php?type=config">{label_config}</a>
|
||||
</li>
|
||||
<li id="nav_option_update">
|
||||
<a href="index.php?action=check">{label_update}</a>
|
||||
<!--%tpl_repeat_menu-->
|
||||
<li id="nav_option_{key}" class="{active}">
|
||||
<a href="{url}">{label}</a>
|
||||
</li>
|
||||
<!--%%tpl_repeat_menu-->
|
||||
{menu}
|
||||
<li id="nav_option_help">
|
||||
<a href="http://www.phpservermonitor.org/" target="_blank">{label_help}</a>
|
||||
</li>
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>{label_name}</th>
|
||||
<th>{label_user_name}</th>
|
||||
<th>{label_level}</th>
|
||||
<th>{label_mobile}</th>
|
||||
<th>{label_email}</th>
|
||||
<th>{label_servers}</th>
|
||||
|
@ -20,6 +22,8 @@
|
|||
<!--%tpl_repeat_users-->
|
||||
<tr>
|
||||
<td>{name}</td>
|
||||
<td>{user_name}</td>
|
||||
<td>{label_level_{level}}</td>
|
||||
<td>{mobile}</td>
|
||||
<td>{email}</td>
|
||||
<td>{emp_servers}</td>
|
||||
|
@ -47,23 +51,52 @@
|
|||
<div class="control-group">
|
||||
<label class="control-label" for="name">{label_name}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="name" value="{edit_value_name}" maxlength="255" />
|
||||
<input type="text" id="name" name="name" value="{edit_value_name}" maxlength="255" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="user_name">{label_user_name}</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="user_name" name="user_name" value="{edit_value_user_name}" maxlength="64" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="level">{label_level}</label>
|
||||
<div class="controls">
|
||||
<select id="level" name="level">
|
||||
<!--%tpl_repeat_levels-->
|
||||
<option value="{value}" {selected}>{label}</option>
|
||||
<!--%%tpl_repeat_levels-->
|
||||
{levels}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password">{label_password}</label>
|
||||
<div class="controls">
|
||||
<input type="password" id="password" name="password" maxlength="255" placeholder="{placeholder_password}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password_repeat">{label_password_repeat}</label>
|
||||
<div class="controls">
|
||||
<input type="password" id="password_repeat" name="password_repeat" maxlength="255" placeholder="{placeholder_password}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="mobile">{label_mobile}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="mobile" value="{edit_value_mobile}" maxlength="15" />
|
||||
<input type="text" id="mobile" name="mobile" value="{edit_value_mobile}" maxlength="15" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="name">{label_email}</label>
|
||||
<label class="control-label" for="email">{label_email}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="email" value="{edit_value_email}" maxlength="255" />
|
||||
<input type="text" id="email" name="email" value="{edit_value_email}" maxlength="255" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="name">{label_servers}</label>
|
||||
<label class="control-label" for="servers[]">{label_servers}</label>
|
||||
<div class="controls">
|
||||
<!--%tpl_repeat_servers-->
|
||||
<label class="checkbox">
|
||||
|
@ -78,8 +111,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-success" type="submit">Save</button>
|
||||
<button class="btn" onclick="history.back();return false;" >Cancel</button>
|
||||
<button class="btn btn-success" type="submit">{label_save}</button>
|
||||
<button class="btn" onclick="history.back();return false;" >{label_go_back}</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
body{
|
||||
padding-top:70px;
|
||||
}
|
||||
}
|
||||
body.install{
|
||||
padding-top:20px;
|
||||
padding-top:20px;
|
||||
}
|
||||
.label-status-on{
|
||||
background-color: #468847;
|
||||
|
@ -34,4 +34,29 @@ legend{
|
|||
}
|
||||
.form-actions {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.form-signin {
|
||||
max-width: 300px;
|
||||
padding: 19px 29px 29px;
|
||||
margin: 0 auto 20px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #e5e5e5;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
|
||||
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05);
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.05);
|
||||
}
|
||||
.form-signin .form-signin-heading,
|
||||
.form-signin .checkbox {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.form-signin input[type="text"],
|
||||
.form-signin input[type="password"] {
|
||||
font-size: 16px;
|
||||
height: auto;
|
||||
margin-bottom: 15px;
|
||||
padding: 7px 9px;
|
||||
}
|
Loading…
Reference in New Issue