Last active
October 1, 2018 12:53
-
-
Save kongondo/cbc6ddc0471b53c6a38388869bec3fbd to your computer and use it in GitHub Desktop.
ProcessWire: Restrict logins for users so that one user cannot be loggedin in more than once simultaneously
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace ProcessWire; | |
// code goes in ready.php | |
// Hook into login/logout sessions | |
wire()->addHookAfter('Session::loginSuccess', null, 'checkLoggedIn'); | |
wire()->addHookBefore('Session::logout', null, 'removeLoggedIn');// Hook before to get $user->id | |
/** | |
* Check if a user is already logged in | |
* | |
* If user logged in, take an action (notify,logout,etc). | |
* Else, cache user as logged in to check for duplicate logins. | |
* | |
* @param HookEvent $event The object (Session::loginSuccess) we are hooking into. | |
* @return void | |
* | |
*/ | |
function checkLoggedIn(HookEvent $event) { | |
$user = $event->arguments('user'); | |
$session = wire('session'); | |
$userDuplicateLogin = checkUserDuplicateLogin($user);// returns boolean | |
// if user logged in, do something. Here, we log them out and redirect to home page | |
// you could make an exception for Superusers, or exception by role, permission, etc | |
if($userDuplicateLogin) { | |
$session->logout(); | |
$session->redirect('/'); | |
} | |
// set cache | |
else setLoggedInUserCache($user); | |
/* @note: testing only | |
$log = wire('log'); | |
$log->save("user-logs","Successful login for '$user->name'"); */ | |
} | |
/** | |
* Check if a user is logged in more than once. | |
* | |
* @param User $user The user to whose logins to check. | |
* @return Boolean $duplicateLogIn True if user already logged in, else false. | |
* | |
*/ | |
function checkUserDuplicateLogin(User $user) { | |
$cache = wire('cache'); | |
$duplicateLogIn = false; | |
$userID = $user->id; | |
$cachedUsersIDs = $cache->get('loggedInUserIDs');// array OR null | |
if(is_array($cachedUsersIDs) && isset($cachedUsersIDs[$userID])) $duplicateLogIn = true; | |
return $duplicateLogIn; | |
} | |
/** | |
* Create or update cache for logged in user. | |
* | |
* @param User $user The user whose cache to set. | |
* @return void | |
* | |
*/ | |
function setLoggedInUserCache(User $user) { | |
$cache = wire('cache'); | |
$userID = $user->id; | |
$cachedUsersIDs = $cache->get('loggedInUserIDs'); | |
// cache does not exist, create empty array ready to cache | |
if(!count($cachedUsersIDs) || is_null($cachedUsersIDs)) $cachedUsersIDs = array(); | |
// save/update cache | |
// for value, can use whatever, even $user->name; doesn't matter, key is the important thing here | |
// outer array: we use $user->id to group same user; | |
// in inner array, we use session_id() to ensure uniqueness when removing cache | |
$cachedUsersIDs[$userID][session_id()] = $userID; | |
$cachedUsersIDsStr = json_encode($cachedUsersIDs);// JSON to save as cache | |
$cache->save('loggedInUserIDs',$cachedUsersIDsStr);// @note: set expiration of cache if you wish to | |
} | |
/** | |
* Remove a logged out user's cache. | |
* | |
* This to allow subsequent logins. | |
* | |
* @param HookEvent $event The object (Session::logout) we are hooking into. | |
* @return void | |
* | |
*/ | |
function removeLoggedIn(HookEvent $event) { | |
$user = wire('user'); | |
removeLoggedInUserCache($user); | |
/* @note: for testing only | |
$log = wire('log'); | |
$log->save("user-logs","Successful logout for '$user->name'"); */ | |
} | |
/** | |
* Remove the cache for a user who has logged out. | |
* | |
* @param User $user The user whose logged-in cache we are removing. | |
* @return void | |
* | |
*/ | |
function removeLoggedInUserCache(User $user) { | |
$cache = wire('cache'); | |
$userID = $user->id; | |
$cachedUsersIDs = $cache->get('loggedInUserIDs'); | |
// cache does not exist/empty, nothing to do | |
if(!count($cachedUsersIDs) || is_null($cachedUsersIDs)) return; | |
// save/update cache | |
// @note: we check for current logged in user but we remove the whole user group (outer array) | |
// this is because the user logged in 'validly' is logging out. | |
if(isset($cachedUsersIDs[$userID][session_id()])) unset($cachedUsersIDs[$userID]); | |
$cachedUsersIDsStr = json_encode($cachedUsersIDs); | |
// save updated cached | |
$cache->save('loggedInUserIDs',$cachedUsersIDsStr);// @note: set expiration of cache if you wish to | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment