mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-11 00:14:50 +03:00
Improved account login/switch handling
This commit is contained in:
parent
3af8652175
commit
abe2af153d
7 changed files with 45 additions and 101 deletions
|
|
@ -79,7 +79,7 @@ trait Accounts
|
|||
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||
}
|
||||
|
||||
$oNewAccount = $this->LoginProcess($sEmail, $sPassword, false, $oMainAccount);
|
||||
$oNewAccount = $this->LoginProcess($sEmail, $sPassword, false, false);
|
||||
|
||||
$aAccounts[$oNewAccount->Email()] = $oNewAccount->asTokenArray($oMainAccount);
|
||||
$this->SetAccounts($oMainAccount, $aAccounts);
|
||||
|
|
|
|||
|
|
@ -200,14 +200,9 @@ trait User
|
|||
|
||||
public function DoLogout() : array
|
||||
{
|
||||
$oAccount = $this->getAccountFromToken(false);
|
||||
if ($oAccount) {
|
||||
if ($oAccount instanceof \RainLoop\Model\MainAccount) {
|
||||
$this->ClearSignMeData();
|
||||
Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
}
|
||||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
}
|
||||
$bMain = empty($_COOKIE[self::AUTH_ADDITIONAL_TOKEN_KEY]);
|
||||
$this->Logout($bMain);
|
||||
$bMain && $this->ClearSignMeData();
|
||||
return $this->TrueResponse(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ trait UserAuth
|
|||
/**
|
||||
* @throws \RainLoop\Exceptions\ClientException
|
||||
*/
|
||||
public function LoginProcess(string &$sEmail, string &$sPassword, bool $bSignMe = false, Account $oMainAccount = null): Account
|
||||
public function LoginProcess(string &$sEmail, string &$sPassword, bool $bSignMe = false, bool $bMainAccount = true): Account
|
||||
{
|
||||
$sInputEmail = $sEmail;
|
||||
|
||||
|
|
@ -114,10 +114,10 @@ trait UserAuth
|
|||
$oAccount = null;
|
||||
$sClientCert = \trim($this->Config()->Get('ssl', 'client_cert', ''));
|
||||
try {
|
||||
if ($oMainAccount) {
|
||||
$oAccount = AdditionalAccount::NewInstanceByLogin($this, $sEmail, $sLogin, $sPassword, $sClientCert, true);
|
||||
if ($bMainAccount) {
|
||||
$oAccount = MainAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $sPassword, $sClientCert, true);
|
||||
} else {
|
||||
$oAccount = MainAccount::NewInstanceByLogin($this, $sEmail, $sLogin, $sPassword, $sClientCert, true);
|
||||
$oAccount = AdditionalAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $sPassword, $sClientCert, true);
|
||||
}
|
||||
|
||||
if (!$oAccount) {
|
||||
|
|
@ -131,7 +131,7 @@ trait UserAuth
|
|||
|
||||
try {
|
||||
$this->CheckMailConnection($oAccount, true);
|
||||
if (!$oMainAccount) {
|
||||
if ($bMainAccount) {
|
||||
$bSignMe && $this->SetSignMeToken($oAccount);
|
||||
$this->StorageProvider()->Put($oAccount, StorageType::SESSION, Utils::GetSessionToken(), 'true');
|
||||
}
|
||||
|
|
@ -144,6 +144,18 @@ trait UserAuth
|
|||
return $oAccount;
|
||||
}
|
||||
|
||||
private static function SetAccountCookie(string $sName, ?Account $oAccount)
|
||||
{
|
||||
if ($oAccount) {
|
||||
Utils::SetCookie(
|
||||
$sName,
|
||||
\MailSo\Base\Utils::UrlSafeBase64Encode(\SnappyMail\Crypt::EncryptToJSON($oAccount))
|
||||
);
|
||||
} else {
|
||||
Utils::ClearCookie($sName);
|
||||
}
|
||||
}
|
||||
|
||||
public function switchAccount(string $sEmail) : bool
|
||||
{
|
||||
$this->Http()->ServerNoCache();
|
||||
|
|
@ -165,6 +177,9 @@ trait UserAuth
|
|||
if (!$oAccountToLogin) {
|
||||
throw new ClientException(Notifications::AccountSwitchFailed);
|
||||
}
|
||||
|
||||
// $this->CheckMailConnection($oAccountToLogin);
|
||||
|
||||
$this->SetAdditionalAuthToken($oAccountToLogin);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -233,12 +248,10 @@ trait UserAuth
|
|||
} 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);
|
||||
$this->Logout(true);
|
||||
}
|
||||
} else {
|
||||
Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
$this->Logout(true);
|
||||
}
|
||||
} else {
|
||||
$oAccount = $this->GetAccountFromSignMeToken();
|
||||
|
|
@ -252,7 +265,7 @@ trait UserAuth
|
|||
}
|
||||
|
||||
if ($this->oMainAuthAccount) {
|
||||
$this->StorageProvider()->Put($this->oMainAuthAccount, StorageType::SESSION, $sToken, 'true');
|
||||
$this->StorageProvider()->Put($this->oMainAuthAccount, StorageType::SESSION, Utils::GetSessionToken(), 'true');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -263,17 +276,13 @@ trait UserAuth
|
|||
{
|
||||
$this->oAdditionalAuthAccount = false;
|
||||
$this->oMainAuthAccount = $oAccount;
|
||||
Utils::SetSecureCookie(self::AUTH_SPEC_TOKEN_KEY, $oAccount);
|
||||
static::SetAccountCookie(self::AUTH_SPEC_TOKEN_KEY, $oAccount);
|
||||
}
|
||||
|
||||
public function SetAdditionalAuthToken(?AdditionalAccount $oAccount): void
|
||||
{
|
||||
$this->oAdditionalAuthAccount = $oAccount ?: false;
|
||||
if ($oAccount) {
|
||||
Utils::SetSecureCookie(self::AUTH_ADDITIONAL_TOKEN_KEY, $oAccount);
|
||||
} else {
|
||||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
}
|
||||
static::SetAccountCookie(self::AUTH_ADDITIONAL_TOKEN_KEY, $oAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -288,7 +297,6 @@ trait UserAuth
|
|||
if (isset($aResult['e'], $aResult['u']) && \SnappyMail\UUID::isValid($aResult['u'])) {
|
||||
return $aResult;
|
||||
}
|
||||
Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -350,10 +358,10 @@ trait UserAuth
|
|||
catch (\Throwable $oException)
|
||||
{
|
||||
}
|
||||
|
||||
$this->ClearSignMeData();
|
||||
}
|
||||
|
||||
$this->ClearSignMeData();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -362,8 +370,8 @@ trait UserAuth
|
|||
$aTokenData = static::GetSignMeToken();
|
||||
if ($aTokenData) {
|
||||
$this->StorageProvider()->Clear($aTokenData['e'], StorageType::SIGN_ME, $aTokenData['u']);
|
||||
Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY);
|
||||
}
|
||||
Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -391,6 +399,12 @@ trait UserAuth
|
|||
Utils::SetCookie(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY, $sMessage);
|
||||
}
|
||||
|
||||
protected function Logout(bool $bMain) : void
|
||||
{
|
||||
Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY);
|
||||
$bMain && Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RainLoop\Exceptions\ClientException
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -143,20 +143,7 @@ abstract class Account implements \JsonSerializable
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RainLoop\Exceptions\ClientException
|
||||
*/
|
||||
public static function NewInstanceFromAuthToken(\RainLoop\Actions $oActions, string $sToken): ?self
|
||||
{
|
||||
return empty($sToken) ? null
|
||||
: static::NewInstanceFromTokenArray(
|
||||
$oActions,
|
||||
Utils::DecodeKeyValues($sToken),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
public static function NewInstanceByLogin(\RainLoop\Actions $oActions,
|
||||
public static function NewInstanceFromCredentials(\RainLoop\Actions $oActions,
|
||||
string $sEmail, string $sLogin, string $sPassword, string $sClientCert = '',
|
||||
bool $bThrowException = false): ?self
|
||||
{
|
||||
|
|
@ -176,7 +163,7 @@ abstract class Account implements \JsonSerializable
|
|||
$oActions->Plugins()->RunHook('filter.account', array($oAccount));
|
||||
|
||||
if ($bThrowException && !$oAccount) {
|
||||
throw new ClientException(Notifications::AuthError);
|
||||
throw new ClientException(Notifications::AccountFilterError);
|
||||
}
|
||||
} else if ($bThrowException) {
|
||||
throw new ClientException(Notifications::AccountNotAllowed);
|
||||
|
|
@ -195,7 +182,7 @@ abstract class Account implements \JsonSerializable
|
|||
bool $bThrowExceptionOnFalse = false): ?self
|
||||
{
|
||||
if (!empty($aAccountHash[0]) && 'account' === $aAccountHash[0] && 7 <= \count($aAccountHash)) {
|
||||
$oAccount = static::NewInstanceByLogin(
|
||||
$oAccount = static::NewInstanceFromCredentials(
|
||||
$oActions,
|
||||
$aAccountHash[1] ?: '',
|
||||
$aAccountHash[2] ?: '',
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class Notifications
|
|||
const AccountAlreadyExists = 801;
|
||||
const AccountDoesNotExist = 802;
|
||||
const AccountSwitchFailed = 803;
|
||||
const AccountFilterError = 804;
|
||||
|
||||
const MailServerError = 901;
|
||||
const ClientViewError = 902;
|
||||
|
|
|
|||
|
|
@ -717,7 +717,7 @@ class ServiceActions
|
|||
|
||||
$this->oActions->SetAuthToken($oAccount);
|
||||
|
||||
$bLogout = !($oAccount instanceof Model\Account);
|
||||
$bLogout = !($oAccount instanceof Model\MainAccount);
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
|
|
@ -751,7 +751,7 @@ class ServiceActions
|
|||
{
|
||||
$oAccount = $this->oActions->LoginProcess($sEmail, $sPassword);
|
||||
$this->oActions->SetAuthToken($oAccount);
|
||||
$bLogout = !($oAccount instanceof Model\Account);
|
||||
$bLogout = !($oAccount instanceof Model\MainAccount);
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
|
|
@ -768,49 +768,6 @@ class ServiceActions
|
|||
return '';
|
||||
}
|
||||
|
||||
public function ServiceExternalLogin() : string
|
||||
{
|
||||
$this->oHttp->ServerNoCache();
|
||||
|
||||
$oException = null;
|
||||
$oAccount = null;
|
||||
$bLogout = true;
|
||||
|
||||
switch (\strtolower($_REQUEST['Output'] ?? 'Redirect'))
|
||||
{
|
||||
case 'json':
|
||||
|
||||
\header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$aResult = array(
|
||||
'Action' => 'ExternalLogin',
|
||||
'Result' => $oAccount instanceof Model\Account ? true : false,
|
||||
'ErrorCode' => 0
|
||||
);
|
||||
|
||||
if (!$aResult['Result'])
|
||||
{
|
||||
if ($oException instanceof Exceptions\ClientException)
|
||||
{
|
||||
$aResult['ErrorCode'] = $oException->getCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult['ErrorCode'] = Notifications::AuthError;
|
||||
}
|
||||
}
|
||||
|
||||
return \MailSo\Base\Utils::Php2js($aResult, $this->Logger());
|
||||
|
||||
case 'redirect':
|
||||
default:
|
||||
$this->oActions->Location('./');
|
||||
break;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class Utils
|
|||
$sToken = static::GetCookie(self::SESSION_TOKEN, null);
|
||||
if (!$sToken) {
|
||||
$sToken = \MailSo\Base\Utils::Sha1Rand(APP_SALT);
|
||||
static::SetCookie(self::SESSION_TOKEN, $sToken, 0);
|
||||
static::SetCookie(self::SESSION_TOKEN, $sToken);
|
||||
}
|
||||
|
||||
return \sha1('Session'.APP_SALT.$sToken.'Token'.APP_SALT);
|
||||
|
|
@ -149,16 +149,6 @@ class Utils
|
|||
));
|
||||
}
|
||||
|
||||
public static function SetSecureCookie(string $sName, $mValue, int $iExpire = 0, bool $bHttpOnly = true)
|
||||
{
|
||||
static::SetCookie(
|
||||
$sName,
|
||||
\MailSo\Base\Utils::UrlSafeBase64Encode(\SnappyMail\Crypt::EncryptToJSON($mValue)),
|
||||
$iExpire,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public static function ClearCookie(string $sName)
|
||||
{
|
||||
if (isset($_COOKIE[$sName])) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue