PHP Classes

File: vendor/jackbooted/admin/Login.php

Recommend this page to a friend!
  Classes of Brett Dutton   JackBooted PHP Framework   vendor/jackbooted/admin/Login.php   Download  
File: vendor/jackbooted/admin/Login.php
Role: Class source
Content type: text/plain
Description: Class source
Class: JackBooted PHP Framework
Web application framework using simplified MVC
Author: By
Last change:
Date: 8 years ago
Size: 15,920 bytes
 

Contents

Class file image Download
<?php namespace Jackbooted\Admin; use \Jackbooted\Config\Cfg; use \Jackbooted\Config\PreferenceLoader; use \Jackbooted\DB\DB; use \Jackbooted\DB\DBMaintenance; use \Jackbooted\Forms\Request; use \Jackbooted\Forms\Response; use \Jackbooted\G; use \Jackbooted\Html\Tag; use \Jackbooted\Html\Validator; use \Jackbooted\Html\WebPage; use \Jackbooted\Security\Privileges; use \Jackbooted\Util\Cookie; use \Jackbooted\Html\Widget; use \Jackbooted\Security\Password; use \Jackbooted\Mail\Mailer; /** * @copyright Confidential and copyright (c) 2016 Jackbooted Software. All rights reserved. * * Written by Brett Dutton of Jackbooted Software * brett at brettdutton dot com * * This software is written and distributed under the GNU General Public * License which means that its source code is freely-distributed and * available to the general public. */ class Login extends WebPage { const LOGIN_NAME = 'RW_4e832b50f61c5e87ec9e7264e6466e1f'; const PASSWORD_NAME = 'RW_99cb4fc2271bcda4c9284aa7b2d8e262'; const SESSHASH_NAME = 'RW_9289b6efa48c4e12633da5057107dfcb'; const LOGIN_FNAME = 'fldLoginID'; const PASSW_FNAME = 'fldPassword'; const DEF = '\Jackbooted\Admin\Login->index()'; private static $completeMenu; private static $userMenu = null; public static function init () { self::$completeMenu = [ 'Logout' => [ 'action' => __CLASS__ . '::logOut()', 'url' => 'ajax.php?' ], Cfg::get('desc') => [ 'action' => __CLASS__ . '::home()' , 'url' => '?' ] ]; } public static function getMenu () { if ( self::$userMenu != null ) return self::$userMenu; self::$userMenu = []; foreach ( self::$completeMenu as $title => $action ) { if ( G::isLoggedIn () ) self::$userMenu[$title] = $action; } return self::$userMenu; } public static function menu () { if ( Privileges::access ( __METHOD__ ) !== true || ! G::isLoggedIn () ) return ''; if ( count ( self::getMenu () ) <= 0 ) return ''; $resp = new Response (); $html = Tag::hTag ( 'b' ) . 'Login Menu' . Tag::_hTag ( 'b' ) . Tag::ul ( [ 'id' => 'menuList' ] ); foreach ( self::getMenu () as $title => $action ) { $html .= Tag::li ( ) . Tag::hRef ( $action['url'] . $resp->action ( $action['action'] )->toUrl (), $title ) . Tag::_li ( ); } $html .= Tag::_ul ( ); return $html; } public static function sendLoginCookie ( $username, $password ) { $hash = self::calculateHash ( $username, $password ); if ( Cfg::get ( 'save_cookies', false ) ) { Cookie::set ( self::LOGIN_NAME, $username ); Cookie::set ( self::PASSWORD_NAME, $password ); Cookie::set ( self::SESSHASH_NAME, $hash ); } G::set ( self::LOGIN_NAME, $username ); G::set ( self::PASSWORD_NAME, $password ); G::set ( self::SESSHASH_NAME, $hash ); } public static function getLoginCookie ( ) { $username = G::get ( self::LOGIN_NAME, '' ); $password = G::get ( self::PASSWORD_NAME, '' ); $hash = G::get ( self::SESSHASH_NAME, '' ); if ( $username == '' || $password == '' || $hash == '' ) { $username = Cookie::get ( self::LOGIN_NAME, '' ); $password = Cookie::get ( self::PASSWORD_NAME, '' ); $hash = Cookie::get ( self::SESSHASH_NAME, '' ); } return [ $username, $password, $hash ]; } public static function loadPreferencesFromCookies ( ) { list ( $username, $password, $hash ) = self::getLoginCookie (); if ( ! self::checkAuthenticated ( $username, $password, $hash ) ) return false; if ( ! isset ( $_SESSION[G::SESS][G::PREFS] ) || ! is_object ( $_SESSION[G::SESS][G::PREFS] ) ) { self::loadPreferences ( $username ); self::sendLoginCookie ( $username, $password ); } return true; } public static function calculateHash ( $username, $password ) { $hashArray = [ $username, $password, $_SERVER['REMOTE_ADDR'], time () ]; return serialize ( $hashArray ); } public static function testHash ( $username, $password, $hash ) { if ( ( $hashArray = @unserialize ( $hash ) ) === false ) return false; else if ( $hashArray[0] != $username ) return self::$log->error ( 'Incorrect username' ); else if ( $hashArray[1] != $password ) return self::$log->error ( 'Incorrect password' ); else if ( $hashArray[2] != $_SERVER['REMOTE_ADDR'] ) return self::$log->error ( 'Login from different IP' ); else if ( time () - $hashArray[3] > Cfg::get ( 'session_timeout', 604800 ) ) { return self::$log->error ( 'Session timeout' ); } else return true; } public static function checkAuthenticated ( $username, $password, $hash=null ) { if ( ! isset( $username ) || ! isset( $password ) || $username == false || $password == false ) return false; if ( $hash != null && ! self::testHash ( $username, $password, $hash ) ) { $sucessfulLogin = false; } else { if ( DB::driver() == DB::MYSQL ) { $sql = <<<SQL SELECT COUNT(*) FROM tblUser WHERE fldPassword=PASSWORD(?) AND fldUser=? AND fldFails<4 SQL; $numEntries = DB::oneValue ( DB::DEF, $sql, [ $password, $username ] ); } else { $sql = <<<SQL SELECT COUNT(*) FROM tblUser WHERE fldPassword=? AND fldUser=? AND fldFails<4 SQL; $numEntries = DB::oneValue ( DB::DEF, $sql, [ hash( 'md5', $password ), $username ] ); } $sucessfulLogin = ( $numEntries == 1 ); if ( ! $sucessfulLogin ) { $params = [ DBMaintenance::dbNextNumber(DB::DEF, 'tblLoginAttempt'), $username, $password, $_SERVER['HTTP_USER_AGENT'], $_SERVER['SERVER_ADDR'] ]; DB::exec ( DB::DEF, 'INSERT INTO tblLoginAttempt VALUES(?,?,?,?,?)', $params ); } } if ( $sucessfulLogin ) { self::updateLastLogin ( $username ); } else { self::incrementFails ( $username ); } return $sucessfulLogin; } public static function updateLastLogin ( $username ) { $sql = 'UPDATE tblUser SET fldLastLogin=?,fldFails=0 WHERE fldUser=?'; DB::exec ( DB::DEF, $sql, [ time(), $username ] ); } public static function incrementFails ( $username ) { DB::exec ( DB::DEF, 'UPDATE tblUser SET fldFails=fldFails+1 WHERE fldUser=?', $username ); return DB::oneValue ( DB::DEF, 'SELECT fldFails FROM tblUser WHERE fldUser=?', $username ); } public static function clearFails () { $up = DB::exec ( DB::DEF, 'UPDATE tblUser SET fldFails=0' ); return [ 0, "Cleared: $up " ]; } public static function loadPreferences ( $user ) { $prefLoader = new PreferenceLoader ( null, $user ); $_SESSION[G::SESS][G::PREFS] = $prefLoader->getPreferences ( ); G::setLoggedIn ( true ); } public static function logOut () { self::killSession (); self::doRedirect (); } public static function initSession () { session_start ( ); if ( ! isset ( $_SESSION[G::SESS] ) ) $_SESSION[G::SESS] = []; // See if there is an encryption key set for this session // If not then set it up if ( ! isset ( $_SESSION[G::SESS][G::CRYPTO] ) ) { $iv = str_shuffle ( Cfg::get ( 'crypto_key', G::IV ) ); $_SESSION[G::SESS][G::CRYPTO] = $iv; } } public static function killSession () { Cookie::clear ( self::LOGIN_NAME ); Cookie::clear ( self::PASSWORD_NAME ); Cookie::clear ( self::SESSHASH_NAME ); $_SESSION[G::SESS][G::PREFS] = null; $_SESSION[G::SESS] = null; unset ( $_SESSION[G::SESS][G::PREFS] ); unset ( $_SESSION[G::SESS] ); session_unset (); session_destroy (); } public static function home () { Request::set ( WebPage::SAVE_URL, Cfg::siteUrl() ); self::doRedirect (); } public static function doRedirect ( ) { $redirectTime = 0; if ( ( $index = Cfg::get ( 'index' ) ) == '' ) { $index = Cfg::siteUrl () . '/index.php'; } $url = Request::get ( WebPage::SAVE_URL, $index ); echo ( sprintf ( '<meta HTTP-EQUIV="REFRESH" content="%s; url=%s">', $redirectTime, $url ) ); exit; } public function __construct () { parent::__construct(); } public function index () { $formName = 'Login_index'; $valid = Validator::factory ( $formName ) ->addExists ( self::LOGIN_FNAME, 'Email field must not be empty' ) ->addExists ( self::PASSW_FNAME, 'Password field must not be empty' ); $mobileAttribs = []; if ( G::isSmartPhone() ) { $mobileAttribs['type'] = 'email'; } $resp = new Response (); $html = '<h2>Login</h2>' . $valid->toHtml ( ) . Tag::form ( [ 'action' => 'ajax.php', 'name' => $formName, 'onSubmit' => $valid->onSubmit() ] ) . $resp->action ( __CLASS__ . '->checkLogin()' )->toHidden() . Tag::table ( ) . Tag::tr ( ) . Tag::td ( ) . 'Email' . Tag::_td ( ) . Tag::td ( ) . Tag::text ( self::LOGIN_FNAME, $mobileAttribs ) . Tag::_td ( ) . Tag::_tr ( ) . Tag::tr ( ) . Tag::td ( ) . 'Password:' . Tag::_td ( ) . Tag::td ( ) . Tag::password ( self::PASSW_FNAME ) . Tag::_td ( ) . Tag::_tr ( ) . Tag::tr ( ) . Tag::td ( ) . Tag::submit ( 'Login' ) . Tag::_td ( ) . Tag::td ( [ 'align' => 'right' ] ) . Tag::linkButton('?' . $resp->action ( __CLASS__ . '->forgotPassword()' )->toUrl(), 'Forgot Password' ) . Tag::_td ( ) . Tag::_tr ( ) . Tag::_table ( ) . Tag::_form ( ); return $html; } public function forgotPassword ( ) { // Initialise the $msg and $action and $disclaimer variables $formName = 'Login_forgotPassword'; $valid = Validator::factory ( $formName, 'FP' ) ->addExists ( 'fldEmail', 'Email field is empty. Please insert valid email and resubmit' ) ->addEmail ( 'fldEmail', 'Email is in valid format. Must be of the form a@b.com' ); $html = '<h2>Password Reset</h2>' . $valid->toHtml () . Tag::form ( [ 'id' => $formName, 'name' => $formName, 'onSubmit' => $valid->onSubmit() ] ) . Response::factory()->action ( __CLASS__ . '->sendPW()' )->toHidden() . Tag::table ( ) . Tag::tr () . Tag::td () . 'Email' . Tag::_td () . Tag::td () . Tag::text ( 'fldEmail', [ 'title' => 'Your Password will be reset and sent to you via email you have provided' ] ) . Tag::_td () . Tag::_tr () . Tag::tr ( ) . Tag::td ( [ 'align' => 'left' ] ) . Tag::submit ( 'Reset PW' ) . Tag::_td ( ) . Tag::td ( [ 'align' => 'right' ] ) . Tag::linkButton('?' . Response::factory()->action ( __CLASS__ . '->index()' )->toUrl(), 'Back to Login' ) . Tag::_td ( ) . Tag::_tr ( ) . Tag::_table () . Tag::_form(); return $html; } public function sendPW () { $sql = 'SELECT fldUserID FROM tblUser WHERE fldUser=?'; if ( ( $id = DB::oneValue ( DB::DEF, $sql, Request::get ( 'fldEmail' ) ) ) === false ) { return $this->forgotPassword() . Widget::popupWrapper('This email does not exist on this system.', -1 ); } $pw = Password::passGen ( 10, Password::MEDIUM ); if ( DB::driver() == DB::MYSQL ) { $sql = 'UPDATE tblUser SET fldPassword=PASSWORD(?),fldFails=0 WHERE fldUserID=?'; DB::exec ( DB::DEF, $sql, [ $pw, $id ] ); } else { $sql = 'UPDATE tblUser SET fldPassword=?,fldFails=0 WHERE fldUserID=?'; DB::exec ( DB::DEF, $sql, [ hash( 'md5', $pw ), $id ] ); } // Update the Database with the new Password combo $boss = Cfg::get ('boss'); $desc = Cfg::get ('desc'); // create the email message to notify about a password request $body = '<h3>User requested password<br>Email: <b>%s</b></h3><br>From %s'; Mailer::envelope()->format ( Mailer::HTML_TEXT ) ->from ( Request::get ( 'fldEmail' ) ) ->to ( $boss ) ->subject ( 'User requested password' ) ->body ( sprintf ( $body, Request::get ( 'fldEmail' ), $desc ) ) ->send (); $body = <<<TXT Message from %s Here is your new password Password: %s Regards %s TXT; // create the email message to notify the user of his/her login details Mailer::envelope()->from ( $boss ) ->to ( Request::get ( 'fldEmail' ) ) ->subject ( 'Login Request ' . $desc ) ->body ( sprintf ( $body, $desc, $pw, $desc ) ) ->send (); $msg = 'Soon you will receive an email that will contain your login details.'; return $this->index() . Widget::popupWrapper( $msg, -1 ); } public function checkLogin () { $username = Request::get ( self::LOGIN_FNAME ); $password = Request::get ( self::PASSW_FNAME ); if ( ! isset( $username ) || $username == false || ! isset( $password ) || $password == false ) return false; if ( self::checkAuthenticated ( $username, $password ) ) { self::$log->debug ( 'Killing old session id: ' . session_id () ); @session_regenerate_id ( true ); self::$log->debug ( 'New session has taken over id: ' . session_id () ); self::loadPreferences ( $username ); self::sendLoginCookie ( $username, $password ); self::doRedirect (); } else { return 'Invalid Login Details' . $this->index (); } } protected function getDisplayName ( ) { $name = G::get ( 'fldFirstName' ) . ' ' . G::get ( 'fldLastName' ); if ( G::isLoggedIn () && G::accessLevel ( Privileges::getSecurityLevel ( 'SITE ADMIN' ) ) ) { $uName = Tag::hRef ( 'superadmin.php', $name, [ 'class' => 'admin' ] ); } else { $uName = Tag::e ( $name ); } return $uName; } }