Cleanup some classes and improve the Accounts and Contacts

This commit is contained in:
djmaze 2021-11-10 21:24:19 +01:00
parent 7ea4365ccb
commit ef4790d04e
25 changed files with 159 additions and 192 deletions

View file

@ -11,7 +11,7 @@
namespace MailSo\Imap\Commands;
use \MailSo\Imap\Responses\ACL as ACLResponse;
use MailSo\Imap\Responses\ACL as ACLResponse;
/**
* @category MailSo

View file

@ -11,7 +11,7 @@
namespace MailSo\Imap;
use \MailSo\Imap\Enumerations\ResponseType;
use MailSo\Imap\Enumerations\ResponseType;
/**
* @category MailSo

View file

@ -11,9 +11,9 @@
namespace MailSo\Imap\Traits;
use \MailSo\Imap\Response;
use \MailSo\Imap\Enumerations\ResponseType;
use \MailSo\Imap\Exceptions\ResponseNotFoundException;
use MailSo\Imap\Response;
use MailSo\Imap\Enumerations\ResponseType;
use MailSo\Imap\Exceptions\ResponseNotFoundException;
/**
* @category MailSo

View file

@ -11,7 +11,7 @@
namespace MailSo\Mail;
use \MailSo\Imap\Enumerations\FolderResponseStatus;
use MailSo\Imap\Enumerations\FolderResponseStatus;
/**
* @category MailSo

View file

@ -245,8 +245,6 @@ class Actions
$mResult = new Providers\AddressBook\PdoAddressBook($sDsn, $sUser, $sPassword, $sDsnType);
break;
case 'identities':
$mResult = [];
break;
case 'suggestions':
$mResult = [];
break;
@ -1117,52 +1115,6 @@ class Actions
);
}
public function GetAccounts(Model\Account $oAccount): array
{
if ($this->GetCapa(false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
$sAccounts = $this->StorageProvider()->Get($oAccount,
Providers\Storage\Enumerations\StorageType::CONFIG,
'accounts'
);
$aAccounts = array();
if ('' !== $sAccounts && '{' === \substr($sAccounts, 0, 1)) {
$aAccounts = \json_decode($sAccounts, true);
}
if (\is_array($aAccounts) && \count($aAccounts)) {
if (1 === \count($aAccounts)) {
$this->SetAccounts($oAccount, array());
} else if (1 < \count($aAccounts)) {
$sOrder = $this->StorageProvider()->Get($oAccount,
Providers\Storage\Enumerations\StorageType::CONFIG,
'accounts_identities_order'
);
$aOrder = empty($sOrder) ? array() : \json_decode($sOrder, true);
if (isset($aOrder['Accounts']) && \is_array($aOrder['Accounts']) &&
1 < \count($aOrder['Accounts'])) {
$aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts);
$aAccounts = \array_filter($aAccounts, function ($sHash) {
return 5 < \strlen($sHash);
});
}
}
return $aAccounts;
}
}
$aAccounts = array();
if (!$oAccount->IsAdditionalAccount()) {
$aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken();
}
return $aAccounts;
}
public function GetIdentityByID(Model\Account $oAccount, string $sID, bool $bFirstOnEmpty = false): ?Model\Identity
{
$aIdentities = $this->GetIdentities($oAccount);
@ -1176,24 +1128,6 @@ class Actions
return $bFirstOnEmpty && isset($aIdentities[0]) ? $aIdentities[0] : null;
}
public function SetAccounts(Model\Account $oAccount, array $aAccounts = array()): void
{
$sParentEmail = $oAccount->ParentEmailHelper();
if (!$aAccounts ||
(1 === \count($aAccounts) && !empty($aAccounts[$sParentEmail]))) {
$this->StorageProvider()->Clear($oAccount,
Providers\Storage\Enumerations\StorageType::CONFIG,
'accounts'
);
} else {
$this->StorageProvider()->Put($oAccount,
Providers\Storage\Enumerations\StorageType::CONFIG,
'accounts',
\json_encode($aAccounts)
);
}
}
/**
* @throws \MailSo\Base\Exceptions\Exception
*/

View file

@ -8,11 +8,72 @@ use RainLoop\Model\Account;
use RainLoop\Model\Identity;
use RainLoop\Notifications;
use RainLoop\Providers\Storage\Enumerations\StorageType;
use function trim;
trait Accounts
{
public function GetAccounts(Account $oAccount): array
{
if ($this->GetCapa(false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
$sAccounts = $this->StorageProvider()->Get($oAccount,
StorageType::CONFIG,
'accounts'
);
$aAccounts = $sAccounts ? \json_decode($sAccounts, true) : array();
if (\is_array($aAccounts) && \count($aAccounts)) {
if (1 === \count($aAccounts)) {
$this->SetAccounts($oAccount, array());
} else if (1 < \count($aAccounts)) {
$sOrder = $this->StorageProvider()->Get($oAccount,
StorageType::CONFIG,
'accounts_identities_order'
);
$aOrder = empty($sOrder) ? array() : \json_decode($sOrder, true);
if (isset($aOrder['Accounts']) && \is_array($aOrder['Accounts']) && 1 < \count($aOrder['Accounts'])) {
$aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts);
$aAccounts = \array_filter($aAccounts, function ($sHash) {
return 5 < \strlen($sHash);
});
}
}
return $aAccounts;
}
}
$aAccounts = array();
if (!$oAccount->IsAdditionalAccount()) {
$aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken();
}
return $aAccounts;
}
protected function SetAccounts(Account $oAccount, array $aAccounts = array()): void
{
$sParentEmail = $oAccount->ParentEmailHelper();
if (!$aAccounts ||
(1 === \count($aAccounts) && !empty($aAccounts[$sParentEmail]))) {
$this->StorageProvider()->Clear(
$oAccount,
StorageType::CONFIG,
'accounts'
);
} else {
$this->StorageProvider()->Put(
$oAccount,
StorageType::CONFIG,
'accounts',
\json_encode($aAccounts)
);
}
}
/**
* @throws \MailSo\Base\Exceptions\Exception
*/
@ -28,7 +89,7 @@ trait Accounts
$aAccounts = $this->GetAccounts($oAccount);
$sEmail = trim($this->GetActionParam('Email', ''));
$sEmail = \trim($this->GetActionParam('Email', ''));
$sPassword = $this->GetActionParam('Password', '');
$bNew = '1' === (string)$this->GetActionParam('New', '1');
@ -63,7 +124,7 @@ trait Accounts
}
$sParentEmail = $oAccount->ParentEmailHelper();
$sEmailToDelete = trim($this->GetActionParam('EmailToDelete', ''));
$sEmailToDelete = \trim($this->GetActionParam('EmailToDelete', ''));
$sEmailToDelete = \MailSo\Base\Utils::IdnToAscii($sEmailToDelete, true);
$aAccounts = $this->GetAccounts($oAccount);
@ -93,7 +154,7 @@ trait Accounts
{
$oAccount = $this->getAccountFromToken();
$oIdentity = new \RainLoop\Model\Identity();
$oIdentity = new Identity();
if (!$oIdentity->FromJSON($this->GetActionParams(), true)) {
throw new ClientException(Notifications::InvalidInputArgument);
}
@ -113,7 +174,7 @@ trait Accounts
return $this->FalseResponse(__FUNCTION__);
}
$sId = trim($this->GetActionParam('IdToDelete', ''));
$sId = \trim($this->GetActionParam('IdToDelete', ''));
if (empty($sId)) {
throw new ClientException(Notifications::UnknownError);
}
@ -137,7 +198,7 @@ trait Accounts
}
return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order',
StorageType::CONFIG, 'accounts_identities_order',
\json_encode(array(
'Accounts' => \is_array($aAccounts) ? $aAccounts : array(),
'Identities' => \is_array($aIdentities) ? $aIdentities : array()

View file

@ -2,12 +2,12 @@
namespace RainLoop\Actions;
use \RainLoop\Enumerations\Capa;
use \RainLoop\Enumerations\PluginPropertyType;
use \RainLoop\Exceptions\ClientException;
use \RainLoop\KeyPathHelper;
use \RainLoop\Notifications;
use \RainLoop\Utils;
use RainLoop\Enumerations\Capa;
use RainLoop\Enumerations\PluginPropertyType;
use RainLoop\Exceptions\ClientException;
use RainLoop\KeyPathHelper;
use RainLoop\Notifications;
use RainLoop\Utils;
trait Admin
{

View file

@ -22,20 +22,13 @@ trait Contacts
$mData = $this->getContactsSyncData($oAccount);
$sPassword = APP_DUMMY === $sPassword && isset($mData['Password'])
? $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword);
$bResult = $this->StorageProvider()->Put(
$oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
'contacts_sync',
\json_encode(array(
'Enable' => $bEnabled,
'User' => $sUser,
'Password' => $sPassword ? \SnappyMail\Crypt::EncryptToJSON($sPassword, $oAccount->PasswordHash()) : null,
'Url' => $sUrl
))
);
$bResult = $this->setContactsSyncData(array(
'Enable' => $bEnabled,
'User' => $sUser,
'Password' => APP_DUMMY === $sPassword && isset($mData['Password'])
? $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword),
'Url' => $sUrl
));
return $this->DefaultResponse(__FUNCTION__, $bResult);
}
@ -241,6 +234,20 @@ trait Contacts
return $this->DefaultResponse(__FUNCTION__, $mResponse);
}
protected function setContactsSyncData(\RainLoop\Model\Account $oAccount, array $aData) : bool
{
if ($aData['Password']) {
$aData['Password'] = \SnappyMail\Crypt::EncryptToJSON($aData['Password'], $oAccount->PasswordHash());
}
$aData['PasswordHMAC'] = $aData['Password'] ? \hash_hmac('sha1', $aData['Password'], $oAccount->PasswordHash()) : null;
return $this->StorageProvider()->Put(
$oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
'contacts_sync',
\json_encode($aData)
);
}
protected function getContactsSyncData(\RainLoop\Model\Account $oAccount) : ?array
{
$sData = $this->StorageProvider()->Get($oAccount,
@ -251,10 +258,17 @@ trait Contacts
$aData = \json_decode($sData);
if ($aData) {
if ($aData['Password']) {
$aData['Password'] = \SnappyMail\Crypt::DecryptFromJSON(
$aData['Password'],
$oAccount->PasswordHash()
);
// Verify oAccount password hasn't changed so that Password can be decrypted
if ($aData['PasswordHMAC'] !== \hash_hmac('sha1', $aData['Password'], $oAccount->PasswordHash())) {
// Failed
$aData['Password'] = null;
} else {
// Success
$aData['Password'] = \SnappyMail\Crypt::DecryptFromJSON(
$aData['Password'],
$oAccount->PasswordHash()
);
}
}
return $aData;
}
@ -262,6 +276,7 @@ trait Contacts
// Try the old
$aData = \RainLoop\Utils::DecodeKeyValues($sData);
if ($aData) {
$this->setContactsSyncData($oAccount, $aData);
return array(
'Enable' => isset($aData['Enable']) ? !!$aData['Enable'] : false,
'Url' => isset($aData['Url']) ? \trim($aData['Url']) : '',

View file

@ -2,7 +2,7 @@
namespace RainLoop\Actions;
use \RainLoop\Enumerations\Capa;
use RainLoop\Enumerations\Capa;
trait Filters
{

View file

@ -2,10 +2,10 @@
namespace RainLoop\Actions;
use \RainLoop\Enumerations\Capa;
use \RainLoop\Exceptions\ClientException;
use \RainLoop\Notifications;
use \MailSo\Imap\Enumerations\FolderType;
use RainLoop\Enumerations\Capa;
use RainLoop\Exceptions\ClientException;
use RainLoop\Notifications;
use MailSo\Imap\Enumerations\FolderType;
trait Folders
{

View file

@ -2,10 +2,10 @@
namespace RainLoop\Actions;
use \RainLoop\Enumerations\Capa;
use \RainLoop\Exceptions\ClientException;
use \RainLoop\Model\Account;
use \RainLoop\Notifications;
use RainLoop\Enumerations\Capa;
use RainLoop\Exceptions\ClientException;
use RainLoop\Model\Account;
use RainLoop\Notifications;
trait Messages
{

View file

@ -2,9 +2,9 @@
namespace RainLoop\Actions;
use \RainLoop\Enumerations\Capa;
use \RainLoop\Notifications;
use \RainLoop\Utils;
use RainLoop\Enumerations\Capa;
use RainLoop\Notifications;
use RainLoop\Utils;
trait Response
{

View file

@ -2,10 +2,10 @@
namespace RainLoop\Actions;
use \RainLoop\Enumerations\Capa;
use \RainLoop\Exceptions\ClientException;
use \RainLoop\Notifications;
use \RainLoop\Utils;
use RainLoop\Enumerations\Capa;
use RainLoop\Exceptions\ClientException;
use RainLoop\Notifications;
use RainLoop\Utils;
trait User
{

View file

@ -2,11 +2,11 @@
namespace RainLoop\Actions;
use \RainLoop\Notifications;
use \RainLoop\Utils;
use \RainLoop\Model\Account;
use \RainLoop\Providers\Storage\Enumerations\StorageType;
use \RainLoop\Exceptions\ClientException;
use RainLoop\Notifications;
use RainLoop\Utils;
use RainLoop\Model\Account;
use RainLoop\Providers\Storage\Enumerations\StorageType;
use RainLoop\Exceptions\ClientException;
trait UserAuth
{
@ -145,12 +145,7 @@ trait UserAuth
*/
public function GetAccountFromCustomToken(string $sToken): ?Account
{
return empty($sToken) ? null
: Account::NewInstanceFromTokenArray(
$this,
Utils::DecodeKeyValues($sToken),
false
);
return empty($sToken) ? null : Account::NewInstanceFromAuthToken($sToken);
}
/**

View file

@ -2,8 +2,8 @@
namespace RainLoop\Model;
use \RainLoop\Utils;
use \RainLoop\Exceptions\ClientException;
use RainLoop\Utils;
use RainLoop\Exceptions\ClientException;
class Account implements \JsonSerializable
{
@ -187,6 +187,19 @@ class Account implements \JsonSerializable
*/
}
/**
* @throws \RainLoop\Exceptions\ClientException
*/
public static function NewInstanceFromAuthToken(\RainLoop\Actions $oActions, string $sToken): ?Account
{
return empty($sToken) ? null
: static::NewInstanceFromTokenArray(
$oActions,
Utils::DecodeKeyValues($sToken),
false
);
}
public static function NewInstanceByLogin(\RainLoop\Actions $oActions, string $sEmail, string $sLogin, string $sPassword, string $sClientCert = '', bool $bThrowException = false): ?self
{
$oAccount = null;

View file

@ -2,10 +2,9 @@
namespace RainLoop\Model;
use JsonSerializable;
use MailSo\Base\Utils;
class Identity implements JsonSerializable
class Identity implements \JsonSerializable
{
/**
* @var string

View file

@ -2,7 +2,7 @@
namespace RainLoop\Providers;
use \RainLoop\Providers\AddressBook\Enumerations\PropertyType as PropertyType;
use RainLoop\Providers\AddressBook\Enumerations\PropertyType as PropertyType;
class AddressBook extends \RainLoop\Providers\AbstractProvider
{

View file

@ -2,7 +2,7 @@
namespace RainLoop\Providers\AddressBook;
use \SnappyMail\DAV\Client as DAVClient;
use SnappyMail\DAV\Client as DAVClient;
trait CardDAV
{

View file

@ -2,7 +2,7 @@
namespace RainLoop\Providers\AddressBook;
use \RainLoop\Providers\AddressBook\Enumerations\PropertyType;
use RainLoop\Providers\AddressBook\Enumerations\PropertyType;
class PdoAddressBook
extends \RainLoop\Common\PdoAbstract

View file

@ -1,47 +0,0 @@
<?php
namespace RainLoop\Providers\Identities;
use RainLoop\Exceptions\Exception;
use RainLoop\Model\Account;
use RainLoop\Model\Identity;
class TestIdentities implements IIdentities
{
/**
* @param Account $account
* @return Identity[]
*/
public function GetIdentities(Account $account): array
{
$oIdentity = new Identity('', $account->Email());
$oIdentity->SetName("Test Name");
return [$oIdentity];
}
/**
* @param Account $account
* @param Identity[] $identities
*
* @return void
* @throws Exception
*/
public function SetIdentities(Account $account, array $identities): void
{
throw new Exception("Not implemented");
}
/**
* @return bool
*/
public function SupportsStore(): bool
{
return false;
}
public function Name(): string
{
return "Test";
}
}

View file

@ -2,7 +2,7 @@
namespace RainLoop\Providers\Storage;
use \RainLoop\Providers\Storage\Enumerations\StorageType;
use RainLoop\Providers\Storage\Enumerations\StorageType;
class FileStorage implements \RainLoop\Providers\Storage\IStorage
{

View file

@ -811,10 +811,11 @@ class ServiceActions
return '';
}
private function changeAction()
public function ServiceChange() : string
{
$this->oHttp->ServerNoCache();
// $oAccount = $this->oActions->getAccountFromToken(false);
$oAccount = $this->oActions->GetAccount();
if ($oAccount && $this->oActions->GetCapa(false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount))
@ -837,11 +838,7 @@ class ServiceActions
$this->oActions->SetAuthToken($oAccountToLogin);
}
}
}
public function ServiceChange() : string
{
$this->changeAction();
$this->oActions->Location('./');
return '';
}

View file

@ -2,7 +2,7 @@
namespace SnappyMail\HTTP\Request;
use \SnappyMail\HTTP\Response;
use SnappyMail\HTTP\Response;
class CURL extends \SnappyMail\HTTP\Request
{

View file

@ -2,7 +2,7 @@
namespace SnappyMail\HTTP\Request;
use \SnappyMail\HTTP\Response;
use SnappyMail\HTTP\Response;
class Socket extends \SnappyMail\HTTP\Request
{

View file

@ -44,7 +44,7 @@ if (defined('APP_VERSION'))
unset($sSite);
$sPrivateDataFolderInternalName = defined('MULTIDOMAIN') ? APP_SITE : '';
define('APP_PRIVATE_DATA_NAME', 0 === strlen($sPrivateDataFolderInternalName) ? '_default_' : $sPrivateDataFolderInternalName);
define('APP_PRIVATE_DATA_NAME', $sPrivateDataFolderInternalName ?: '_default_');
define('APP_DUMMY', '********');
define('APP_DEV_VERSION', '0.0.0');