OnlineStateTimeout = 600; // in seconds
$this->PasswordHash = new PasswordHash();
$this->User = array('Id' => null, 'Member' => null);
}
function Check()
{
$SID = session_id();
// Lookup user record
$Query = $this->Database->select('UserOnline', '*', 'SessionId="'.$SID.'"');
if ($Query->num_rows > 0)
{
// Refresh time of last access
$this->Database->update('UserOnline', '`SessionId`="'.$SID.'"', array('ActivityTime' => 'NOW()'));
} else $this->Database->insert('UserOnline', array('SessionId' => $SID,
'User' => null, 'LoginTime' => 'NOW()', 'ActivityTime' => 'NOW()',
'IpAddress' => GetRemoteAddress(), 'HostName' => gethostbyaddr(GetRemoteAddress()),
'ScriptName' => $_SERVER['PHP_SELF'], 'StayLogged' => 0, 'StayLoggedHash' => ''));
// Logged permanently?
if (array_key_exists('LoginHash', $_COOKIE))
{
$DbResult = $this->Database->query('SELECT * FROM `UserOnline` WHERE `User`='.$_COOKIE['LoginUserId'].
' AND `StayLogged`=1 AND SessionId!="'.$SID.'"');
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_assoc();
if (sha1($_COOKIE['LoginUserId'].$DbRow['StayLoggedHash']) == $_COOKIE['LoginHash'])
{
$this->Database->query('DELETE FROM `UserOnline` WHERE `SessionId`="'.$SID.'"');
$this->Database->query('UPDATE `UserOnline` SET `SessionId`="'.$SID.'" WHERE `Id`='.$DbRow['Id']);
}
}
}
// Check login
$Query = $this->Database->select('UserOnline', '*', '`SessionId`="'.$SID.'"');
$Row = $Query->fetch_assoc();
if ($Row['User'] != '')
{
$Query = $this->Database->query('SELECT `User`.* FROM `User` '.
' WHERE `User`.`Id`='.$Row['User']);
$this->User = $Query->fetch_assoc();
$Result = USER_LOGGED;
} else
{
$Query = $this->Database->select('User', '*', 'Id IS NULL');
$this->User = array('Id' => null, 'Member' => null);
$Result = USER_NOT_LOGGED;
}
// Remove nonactive users
$DbResult = $this->Database->select('UserOnline', '`Id`, `User`', '(`ActivityTime` < DATE_SUB(NOW(), INTERVAL '.$this->OnlineStateTimeout.' SECOND)) AND (`StayLogged` = 0)');
while ($DbRow = $DbResult->fetch_array())
{
$this->Database->delete('UserOnline', 'Id='.$DbRow['Id']);
if (($DbRow['User'] != null) and $this->System->ModuleManager->ModulePresent('Log'))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'Logout');
}
//$this->LoadPermission($this->User['Role']);
// Role and permission
//$this->LoadRoles();
}
function Register($Login, $Password, $Password2, $Email, $Name)
{
if (($Email == '') || ($Login == '') || ($Password == '') || ($Password2 == '') || ($Name == '')) $Result = DATA_MISSING;
else if ($Password != $Password2) $Result = PASSWORDS_UNMATCHED;
else
{
// Is user registred yet?
$Query = $this->Database->select('User', '*', 'Login = "'.$Login.'"');
if ($Query->num_rows > 0) $Result = LOGIN_USED;
else
{
$Query = $this->Database->select('User', '*', 'Name = "'.$Name.'"');
if ($Query->num_rows > 0) $Result = NAME_USED;
else
{
$Query = $this->Database->select('User', '*', 'Email = "'.$Email.'"');
if ($Query->num_rows > 0) $Result = EMAIL_USED;
else
{
$PasswordHash = new PasswordHash();
$Salt = $PasswordHash->GetSalt();
$this->Database->insert('User', array('Name' => $Name, 'Login' => $Login,
'Password' => $PasswordHash->Hash($Password, $Salt), 'Salt' => $Salt,
'Email' => $Email, 'RegistrationTime' => 'NOW()',
'Locked' => 1));
$UserId = $this->Database->insert_id;
$this->Database->insert('PermissionUserAssignment', array('User' => $UserId,
'AssignedGroup' => DEFAULT_GROUP));
$NewPassword = substr(sha1(strtoupper($Login)), 0, 7);
// Send activation mail to user email
$ServerURL = 'http://'.Core::Cast($this->System)->Config['Web']['Host'].Core::Cast($this->System)->Config['Web']['RootFolder'];
$Mail = new Mail();
$Mail->Subject = 'Registrace nového účtu';
$Mail->AddBody('Provedli jste registraci nového účtu na serveru '.$ServerURL.'".'.
'
\nPokud jste tak neučinili, měli by jste tento email ignorovat.
\n\n'.
'Váš účet je: '.$Login."\n
Pro dokončení registrace klikněte na tento odkaz: ".''.$ServerURL.'/?Action=UserRegisterConfirm&User='.
$UserId.'&H='.$NewPassword.'.'."\n
\n\n'.
'
Na tento email neodpovídejte.", 'text/html');
$Mail->AddTo($Email, $Name);
$Mail->From = Core::Cast($this->System)->Config['Web']['Title'].' ';
$Mail->Send();
$Result = USER_REGISTRATED;
if ($this->System->ModuleManager->ModulePresent('Log'))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'NewRegistration', $Login);
}
}
}
}
return $Result;
}
function RegisterConfirm($Id, $Hash)
{
$DbResult = $this->Database->select('User', 'Id, Login, Password', 'Id = '.$Id);
if ($DbResult->num_rows > 0)
{
$Row = $DbResult->fetch_array();
$NewPassword = substr(sha1(strtoupper($Row['Login'])), 0, 7);
if ($Hash == $NewPassword)
{
$this->Database->update('User', 'Id='.$Row['Id'], array('Locked' => 0));
$Output = USER_REGISTRATION_CONFIRMED;
if ($this->System->ModuleManager->ModulePresent('Log'))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'RegisterConfirm', 'Login='.
$Row['Login'].', Id='.$Row['Id']);
} else $Output = PASSWORDS_UNMATCHED;
} else $Output = USER_NOT_FOUND;
return $Output;
}
function Login($Login, $Password, $StayLogged = false)
{
if ($StayLogged) $StayLogged = 1; else $StayLogged = 0;
$SID = session_id();
$Query = $this->Database->select('User', '*', 'Login="'.$Login.'"');
if ($Query->num_rows > 0)
{
$Row = $Query->fetch_assoc();
$PasswordHash = new PasswordHash();
if (!$PasswordHash->Verify($Password, $Row['Salt'], $Row['Password'])) $Result = BAD_PASSWORD;
else if ($Row['Locked'] == 1) $Result = ACCOUNT_LOCKED;
else
{
$this->Database->update('User', 'Id='.$Row['Id'], array('LastLoginTime' => 'NOW()',
'LastIpAddress' => GetRemoteAddress()));
$Hash = new PasswordHash();
$StayLoggedSalt = $Hash->GetSalt();
$this->Database->update('UserOnline', 'SessionId="'.$SID.'"', array(
'User' => $Row['Id'], 'StayLogged' => $StayLogged, 'StayLoggedHash' => $StayLoggedSalt));
if ($StayLogged)
{
setcookie('LoginUserId', $Row['Id'], time()+365*24*60*60, $this->System->Link('/'));
setcookie('LoginHash', sha1($Row['Id'].$StayLoggedSalt), time()+365*24*60*60, $this->System->Link('/'));
} else {
setcookie('LoginUserId', '', time() - 3600, $this->System->Link('/'));
setcookie('LoginHash', '', time() - 3600, $this->System->Link('/'));
}
$Result = USER_LOGGED_IN;
$this->Check();
if (array_key_exists('Log', $this->System->ModuleManager->Modules))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'Login', 'Login='.$Login.',Host='.gethostbyaddr(GetRemoteAddress()));
}
} else $Result = USER_NOT_REGISTRED;
return $Result;
}
function Logout()
{
$SID = session_id();
$this->Database->update('UserOnline', 'SessionId="'.$SID.'"', array('User' => null));
if ($this->System->ModuleManager->ModulePresent('Log'))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'Logout', $this->User['Login']);
$this->Check();
return USER_LOGGED_OUT;
}
function LoadRoles()
{
$this->Roles = array();
$DbResult = $this->Database->select('UserRole', '*');
while ($DbRow = $DbResult->fetch_array())
$this->Roles[] = $DbRow;
}
function LoadPermission($Role)
{
$this->User['Permission'] = array();
$DbResult = $this->Database->query('SELECT `UserRolePermission`.*, `PermissionOperation`.`Description` FROM `UserRolePermission` JOIN `PermissionOperation` ON `PermissionOperation`.`Id` = `UserRolePermission`.`Operation` WHERE `UserRolePermission`.`Role` = '.$Role);
if ($DbResult->num_rows > 0)
while ($DbRow = $DbResult->fetch_array())
$this->User['Permission'][$DbRow['Operation']] = $DbRow;
}
function PermissionMatrix()
{
$Result = array();
$DbResult = $this->Database->query('SELECT `UserRolePermission`.*, `PermissionOperation`.`Description`, `UserRole`.`Title` FROM `UserRolePermission` LEFT JOIN `PermissionOperation` ON `PermissionOperation`.`Id` = `UserRolePermission`.`Operation` LEFT JOIN `UserRole` ON `UserRole`.`Id` = `UserRolePermission`.`Role`');
while ($DbRow = $DbResult->fetch_array())
{
$Value = '';
if ($DbRow['Read']) $Value .= 'R';
if ($DbRow['Write']) $Value .= 'W';
$Result[$DbRow['Description']][$DbRow['Title']] = $Value;
}
return $Result;
}
function CheckGroupPermission($GroupId, $OperationId)
{
$PermissionExists = false;
// First try to check cache group-group relation
if (array_key_exists($GroupId, $this->PermissionGroupCache))
{
$PermissionExists = true;
} else
{
// If no permission combination exists in cache, do new check of database items
$DbResult = $this->Database->select('PermissionGroupAssignment', '*', '(`Group`="'.$GroupId.
'") AND (`AssignedGroup` IS NOT NULL)');
$DbRow = array();
while ($DbRow[] = $DbResult->fetch_array());
$this->PermissionGroupCache[$GroupId] = $DbRow;
$PermissionExists = true;
}
if ($PermissionExists)
{
foreach ($this->PermissionGroupCache[$GroupId] as $DbRow)
{
if ($DbRow['AssignedGroup'] != '')
if ($this->CheckGroupPermission($DbRow['AssignedGroup'], $OperationId) == true) return true;
}
}
// Check group-operation relation
if (array_key_exists($GroupId.','.$OperationId, $this->PermissionGroupCacheOp))
{
$PermissionExists = true;
} else
{
// If no permission combination exists in cache, do new check of database items
$DbResult = $this->Database->select('PermissionGroupAssignment', '*', '`Group`="'.$GroupId.'" AND `AssignedOperation`="'.$OperationId.'"');
if ($DbResult->num_rows > 0) $this->PermissionGroupCacheOp[$GroupId.','.$OperationId] = true;
else $this->PermissionGroupCacheOp[$GroupId.','.$OperationId] = false;
$PermissionExists = true;
}
if ($PermissionExists)
{
return $this->PermissionGroupCacheOp[$GroupId.','.$OperationId];
}
return false;
}
function CheckPermission($Module, $Operation, $ItemType = '', $ItemIndex = 0)
{
// Get module id
$DbResult = $this->Database->select('Module', 'Id', '`Name`="'.$Module.'"');
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_assoc();
$ModuleId = $DbRow['Id'];
} else return false;
// First try to check cache
if (in_array(array($Module, $Operation, $ItemType, $ItemType), $this->PermissionCache))
{
$OperationId = array_search(array($Module, $Operation, $ItemType, $ItemIndex), $this->PermissionCache);
$PermissionExists = is_numeric($OperationId);
} else
{
// If no permission combination exists in cache, do new check of database items
$DbResult = $this->Database->select('PermissionOperation', 'Id', '(`Module`="'.$ModuleId.
'") AND (`Item`="'.$ItemType.'") AND (`ItemId`='.$ItemIndex.') AND (`Operation`="'.$Operation.'")');
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_array();
$OperationId = $DbRow['Id'];
$this->PermissionCache[$DbRow['Id']] = array($Module, $Operation, $ItemType, $ItemIndex);
$PermissionExists = true;
} else
{
$this->PermissionCache[count($this->PermissionCache).'_'] = array($Module, $Operation, $ItemType, $ItemIndex);
$PermissionExists = false;
}
}
if ($PermissionExists)
{
if ($this->User['Id'] == null) $UserCondition = '(`User` IS NULL)';
else $UserCondition = '(`User`="'.$this->User['Id'].'")';
// Check user-operation relation
$DbResult = $this->Database->select('PermissionUserAssignment', '*', $UserCondition.' AND (`AssignedOperation`="'.$OperationId.'")');
if ($DbResult->num_rows > 0) return true;
// Check user-group relation
$DbResult = $this->Database->select('PermissionUserAssignment', 'AssignedGroup', $UserCondition);
while ($DbRow = $DbResult->fetch_array())
{
if ($this->CheckGroupPermission($DbRow['AssignedGroup'], $OperationId) == true) return true;
}
return false;
} else return false;
}
function PasswordRecoveryRequest($Login, $Email)
{
$DbResult = $this->Database->select('User', 'Login, Name, Id, Email, Password', '`Login`="'.$Login.'" AND `Email`="'.$Email.'"');
if ($DbResult->num_rows > 0)
{
$Row = $DbResult->fetch_array();
$NewPassword = substr(sha1(strtoupper($Row['Login'])), 0, 7);
$ServerURL = 'http://'.Core::Cast($this->System)->Config['Web']['Host'].Core::Cast($this->System)->Config['Web']['RootFolder'];
$Mail = new Mail();
$Mail->Subject = 'Obnova hesla';
$Mail->From = Core::Cast($this->System)->Config['Web']['Title'].' ';
$Mail->AddTo($Row['Email'], $Row['Name']);
$Mail->AddBody('Požádali jste o zaslání nového hesla na serveru '.$ServerURL.'".
\n'.
"Pokud jste tak neučinili, měli by jste tento email ignorovat.
\n\nVaše nové heslo k účtu ".
$Row['Login'].' je: '.$NewPassword."\n
".
'Pro aktivaci tohoto hesla klikněte na tento odkaz.'."\n
".
"Po přihlášení si prosím změňte heslo na nové.\n\n
Na tento email neodpovídejte.", 'text/html');
$Mail->Send();
$Output = USER_PASSWORD_RECOVERY_SUCCESS;
if ($this->System->ModuleManager->ModulePresent('Log'))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'PasswordRecoveryRequest', 'Login='.$Login.',Email='.$Email);
} else $Output = USER_PASSWORD_RECOVERY_FAIL;
return $Output;
}
function PasswordRecoveryConfirm($Id, $Hash, $NewPassword)
{
$DbResult = $this->Database->select('User', 'Id, Login, Password', 'Id = '.$Id);
if ($DbResult->num_rows > 0)
{
$Row = $DbResult->fetch_array();
$NewPassword2 = substr(sha1(strtoupper($Row['Login'])), 0, 7);
if (($NewPassword == $NewPassword2) and ($Hash == $Row['Password']))
{
$PasswordHash = new PasswordHash();
$Salt = $PasswordHash->GetSalt();
$this->Database->update('User', 'Id='.$Row['Id'], array('Password' => $PasswordHash->Hash($NewPassword, $Salt),
'Salt' => $Salt, 'Locked' => 0));
if ($this->System->ModuleManager->ModulePresent('Log'))
$this->System->ModuleManager->Modules['Log']->NewRecord('User', 'PasswordRecoveryConfirm', 'Login='.$Row['Login']);
} else $Output = PASSWORDS_UNMATCHED;
} else $Output = USER_NOT_FOUND;
return $Output;
}
function CheckToken($Module, $Operation, $Token)
{
$DbResult = $this->Database->select('APIToken', 'User', '`Token`="'.$Token.'"');
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_assoc();
$User = new User($this->System);
$User->User = array('Id' => $DbRow['User']);
return $User->CheckPermission($Module, $Operation);
} else return false;
}
}