mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 21:19:21 +03:00
parent
40471957ee
commit
5719b63619
5 changed files with 62 additions and 27 deletions
|
|
@ -131,7 +131,10 @@ trait UserAuth
|
|||
|
||||
try {
|
||||
$this->CheckMailConnection($oAccount, true);
|
||||
$bSignMe && $this->SetSignMeToken($oAccount);
|
||||
if (!$oMainAccount) {
|
||||
$bSignMe && $this->SetSignMeToken($oAccount);
|
||||
$this->StorageProvider()->Put($oAccount, StorageType::SESSION, Utils::GetSessionToken(), 'true');
|
||||
}
|
||||
} catch (\Throwable $oException) {
|
||||
$this->loginErrorDelay();
|
||||
|
||||
|
|
@ -177,6 +180,8 @@ trait UserAuth
|
|||
*/
|
||||
public function getAccountFromToken(bool $bThrowExceptionOnFalse = true): ?Account
|
||||
{
|
||||
$this->getMainAccountFromToken($bThrowExceptionOnFalse);
|
||||
|
||||
if (\is_null($this->oAdditionalAuthAccount) && isset($_COOKIE[self::AUTH_ADDITIONAL_TOKEN_KEY])) {
|
||||
$aData = Utils::GetSecureCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
if ($aData) {
|
||||
|
|
@ -191,7 +196,8 @@ trait UserAuth
|
|||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
}
|
||||
}
|
||||
return $this->oAdditionalAuthAccount ?: $this->getMainAccountFromToken($bThrowExceptionOnFalse);
|
||||
|
||||
return $this->oAdditionalAuthAccount ?: $this->oMainAuthAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -205,15 +211,34 @@ trait UserAuth
|
|||
Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY);
|
||||
// Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
// Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
Utils::ClearCookie(Utils::SESSION_TOKEN);
|
||||
}
|
||||
|
||||
$aData = Utils::GetSecureCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
if ($aData) {
|
||||
$this->oMainAuthAccount = MainAccount::NewInstanceFromTokenArray(
|
||||
$this,
|
||||
$aData,
|
||||
$bThrowExceptionOnFalse
|
||||
);
|
||||
/**
|
||||
* Server side control/kickout of logged in sessions
|
||||
* https://github.com/the-djmaze/snappymail/issues/151
|
||||
*/
|
||||
if (isset($_COOKIE[Utils::SESSION_TOKEN])) {
|
||||
$oMainAuthAccount = MainAccount::NewInstanceFromTokenArray(
|
||||
$this,
|
||||
$aData,
|
||||
$bThrowExceptionOnFalse
|
||||
);
|
||||
$sToken = Utils::GetSessionToken();
|
||||
if ($oMainAuthAccount && $this->StorageProvider()->Get($oMainAuthAccount, StorageType::SESSION, $sToken)) {
|
||||
$this->oMainAuthAccount = $oMainAuthAccount;
|
||||
} else {
|
||||
$oMainAuthAccount && $this->StorageProvider()->Clear($oMainAuthAccount, StorageType::SESSION, $sToken);
|
||||
Utils::ClearCookie(Utils::SESSION_TOKEN);
|
||||
Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
}
|
||||
} else {
|
||||
Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
}
|
||||
} else {
|
||||
$oAccount = $this->GetAccountFromSignMeToken();
|
||||
if ($oAccount) {
|
||||
|
|
@ -224,6 +249,10 @@ trait UserAuth
|
|||
if ($bThrowExceptionOnFalse && !$this->oMainAuthAccount) {
|
||||
throw new ClientException(Notifications::AuthError);
|
||||
}
|
||||
|
||||
if ($this->oMainAuthAccount) {
|
||||
$this->StorageProvider()->Put($this->oMainAuthAccount, StorageType::SESSION, $sToken, 'true');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->oMainAuthAccount;
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ class Api
|
|||
public static function LogoutCurrentLogginedUser() : bool
|
||||
{
|
||||
// TODO: kill SignMe data to prevent automatic login?
|
||||
Utils::ClearCookie(Utils::SHORT_TOKEN);
|
||||
Utils::ClearCookie(Utils::SESSION_TOKEN);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@ class StorageType
|
|||
const CONFIG = 2;
|
||||
const NOBODY = 3;
|
||||
const SIGN_ME = 4;
|
||||
const SESSION = 5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
if ($sFileName && \file_exists($sFileName)) {
|
||||
$mValue = \file_get_contents($sFileName);
|
||||
}
|
||||
|
||||
return false === $mValue ? $mDefault : $mValue;
|
||||
}
|
||||
|
||||
|
|
@ -59,13 +58,8 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
*/
|
||||
public function Clear($mAccount, int $iStorageType, string $sKey) : bool
|
||||
{
|
||||
$mResult = true;
|
||||
$sFileName = $this->generateFileName($mAccount, $iStorageType, $sKey);
|
||||
if ($sFileName && \file_exists($sFileName)) {
|
||||
$mResult = \unlink($sFileName);
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
return $sFileName && \file_exists($sFileName) && \unlink($sFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -90,14 +84,20 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
*/
|
||||
protected function generateFileName($mAccount, int $iStorageType, string $sKey, bool $bMkDir = false, bool $bForDeleteAction = false) : string
|
||||
{
|
||||
$sEmail = $sSubEmail = '';
|
||||
$sEmail = $sSubFolder = '';
|
||||
if (null === $mAccount) {
|
||||
$iStorageType = StorageType::NOBODY;
|
||||
} else if ($mAccount instanceof \RainLoop\Model\Account) {
|
||||
$sEmail = $mAccount instanceof \RainLoop\Model\AdditionalAccount ? $mAccount->ParentEmail() : $mAccount->Email();
|
||||
if ($this->bLocal && $mAccount instanceof \RainLoop\Model\AdditionalAccount && !$bForDeleteAction)
|
||||
{
|
||||
$sSubEmail = $mAccount->Email();
|
||||
} else if ($mAccount instanceof \RainLoop\Model\MainAccount) {
|
||||
$sEmail = $mAccount->Email();
|
||||
if (StorageType::SIGN_ME === $iStorageType) {
|
||||
$sSubFolder = '.sign_me';
|
||||
} else if (StorageType::SESSION === $iStorageType) {
|
||||
$sSubFolder = '.sessions';
|
||||
}
|
||||
} else if ($mAccount instanceof \RainLoop\Model\AdditionalAccount) {
|
||||
$sEmail = $mAccount->ParentEmail();
|
||||
if ($this->bLocal && !$bForDeleteAction) {
|
||||
$sSubFolder = $mAccount->Email();
|
||||
}
|
||||
} else if (\is_string($mAccount) && empty($sEmail)) {
|
||||
$sEmail = $mAccount;
|
||||
|
|
@ -110,7 +110,7 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
$sFilePath = $this->sDataPath.'/__nobody__/'.\sha1($sKey ?: \time());
|
||||
break;
|
||||
case StorageType::SIGN_ME:
|
||||
$sSubEmail = '.sign_me';
|
||||
case StorageType::SESSION:
|
||||
case StorageType::CONFIG:
|
||||
if (empty($sEmail)) {
|
||||
return '';
|
||||
|
|
@ -123,7 +123,7 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
$sFilePath = $this->sDataPath
|
||||
.'/'.\RainLoop\Utils::fixName($sDomain ?: 'unknown.tld')
|
||||
.'/'.\RainLoop\Utils::fixName(\implode('@', $aEmail) ?: '.unknown')
|
||||
.'/'.($sSubEmail ? \RainLoop\Utils::fixName($sSubEmail).'/' : '')
|
||||
.'/'.($sSubFolder ? \RainLoop\Utils::fixName($sSubFolder).'/' : '')
|
||||
.($sKey ? \RainLoop\Utils::fixName($sKey) : '');
|
||||
break;
|
||||
default:
|
||||
|
|
@ -138,11 +138,16 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage
|
|||
}
|
||||
}
|
||||
|
||||
// CleanupSignMeData
|
||||
// Cleanup SignMe
|
||||
if (StorageType::SIGN_ME === $iStorageType && $sKey && 0 === \random_int(0, 25) && \is_dir($sFilePath)) {
|
||||
\MailSo\Base\Utils::RecTimeDirRemove(\is_dir($sFilePath), 3600 * 24 * 30); // 30 days
|
||||
}
|
||||
|
||||
// Cleanup sessions
|
||||
if (StorageType::SESSION === $iStorageType && $sKey && 0 === \random_int(0, 25) && \is_dir($sFilePath)) {
|
||||
\MailSo\Base\Utils::RecTimeDirRemove(\is_dir($sFilePath), 3600 * 3); // 3 hours
|
||||
}
|
||||
|
||||
return $sFilePath;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Utils
|
|||
* Session cookie
|
||||
* Used by: EncodeKeyValuesQ, DecodeKeyValuesQ
|
||||
*/
|
||||
SHORT_TOKEN = 'smsession';
|
||||
SESSION_TOKEN = 'smsession';
|
||||
|
||||
public static function EncodeKeyValues(array $aValues, string $sCustomKey = '') : string
|
||||
{
|
||||
|
|
@ -74,10 +74,10 @@ class Utils
|
|||
|
||||
public static function GetSessionToken() : string
|
||||
{
|
||||
$sToken = static::GetCookie(self::SHORT_TOKEN, null);
|
||||
$sToken = static::GetCookie(self::SESSION_TOKEN, null);
|
||||
if (!$sToken) {
|
||||
$sToken = \MailSo\Base\Utils::Sha1Rand(APP_SALT);
|
||||
static::SetCookie(self::SHORT_TOKEN, $sToken, 0);
|
||||
static::SetCookie(self::SESSION_TOKEN, $sToken, 0);
|
||||
}
|
||||
|
||||
return \sha1('Session'.APP_SALT.$sToken.'Token'.APP_SALT);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue