Changed some Plugin hooks for better handling:

* json.action-pre-call => json.before-{actionname}
* json.action-post-call => json.after-{actionname}
This commit is contained in:
the-djmaze 2022-12-08 09:08:41 +01:00
parent 4397eaed86
commit 477158e54a
6 changed files with 83 additions and 92 deletions

View file

@ -240,6 +240,25 @@ $Plugin->addHook('hook.name', 'functionName');
\RainLoop\Model\Account $oAccount \RainLoop\Model\Account $oAccount
array &$aCache array &$aCache
## Json service actions
Called by RainLoop\ServiceActions::ServiceJson()
### json.before-{actionname}
params: none
### json.after-{actionname}
params:
array &$aResponse
### json.action-post-call
Obsolete, use json.after-{actionname}
### json.action-pre-call
Obsolete, use json.before-{actionname}
### filter.json-response
Obsolete, use json.after-{actionname}
## Others ## Others
### filter.account ### filter.account
@ -285,11 +304,6 @@ $Plugin->addHook('hook.name', 'functionName');
params: params:
array &$aPaths array &$aPaths
### filter.json-response
params:
string $sAction
array &$aResponseItem
### filter.message-html ### filter.message-html
params: params:
\RainLoop\Model\Account $oAccount \RainLoop\Model\Account $oAccount
@ -368,16 +382,7 @@ $Plugin->addHook('hook.name', 'functionName');
### filter.upload-response ### filter.upload-response
params: params:
array &$aResponseItem array &$aResponse
### json.action-post-call
params:
string $sAction
array &$aResponseItem
### json.action-pre-call
params:
string $sAction
### json.attachments ### json.attachments
params: params:
@ -413,7 +418,7 @@ $Plugin->addHook('hook.name', 'functionName');
### main.default-response ### main.default-response
params: params:
string $sActionName string $sActionName
array &$aResponseItem array &$aResponse
### main.default-response-data ### main.default-response-data
params: params:

View file

@ -7,8 +7,8 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
AUTHOR = 'SnappyMail', AUTHOR = 'SnappyMail',
URL = 'https://snappymail.eu/', URL = 'https://snappymail.eu/',
VERSION = '1.4', VERSION = '1.4',
RELEASE = '2022-12-07', RELEASE = '2022-12-08',
REQUIRED = '2.22.4', REQUIRED = '2.23',
CATEGORY = 'Contacts', CATEGORY = 'Contacts',
LICENSE = 'MIT', LICENSE = 'MIT',
DESCRIPTION = 'Show photo of sender in message and messages list (supports BIMI, Gravatar and identicon, Contacts is still TODO)'; DESCRIPTION = 'Show photo of sender in message and messages list (supports BIMI, Gravatar and identicon, Contacts is still TODO)';
@ -25,20 +25,26 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
} }
// https://github.com/the-djmaze/snappymail/issues/714 // https://github.com/the-djmaze/snappymail/issues/714
if ($this->Config()->Get('plugin', 'service', true) || !$this->Config()->Get('plugin', 'delay', true)) { if ($this->Config()->Get('plugin', 'service', true) || !$this->Config()->Get('plugin', 'delay', true)) {
$this->addHook('filter.json-response', 'FilterJsonResponse'); $this->addHook('json.after-message', 'JsonMessage');
$this->addHook('json.after-messagelist', 'JsonMessageList');
} }
} }
public function FilterJsonResponse(string $sAction, array &$aResponseItem) public function JsonMessage(array &$aResponse)
{ {
if ('MessageList' === $sAction && !empty($aResponseItem['Result']['@Collection'])) { if (!empty($aResponse['Result']['From'])) {
foreach ($aResponseItem['Result']['@Collection'] as $id => $message) { $aResponse['Result']['Avatar'] = $this->encryptFrom($aResponse['Result']['From'][0]);
}
}
public function JsonMessageList(array &$aResponse)
{
if (!empty($aResponse['Result']['@Collection'])) {
foreach ($aResponse['Result']['@Collection'] as $id => $message) {
if (!empty($message['From'])) { if (!empty($message['From'])) {
$aResponseItem['Result']['@Collection'][$id]['Avatar'] = $this->encryptFrom($message['From'][0]); $aResponse['Result']['@Collection'][$id]['Avatar'] = $this->encryptFrom($message['From'][0]);
} }
} }
} else if ('Message' === $sAction && !empty($aResponseItem['Result']['From'])) {
$aResponseItem['Result']['Avatar'] = $this->encryptFrom($aResponseItem['Result']['From'][0]);
} }
} }

View file

@ -5,7 +5,7 @@ class DemoAccountPlugin extends \RainLoop\Plugins\AbstractPlugin
const const
NAME = 'Demo Account Extension', NAME = 'Demo Account Extension',
CATEGORY = 'Login', CATEGORY = 'Login',
REQUIRED = '2.14.0', REQUIRED = '2.23',
DESCRIPTION = 'Extension to enable a demo account'; DESCRIPTION = 'Extension to enable a demo account';
/** /**
@ -15,7 +15,7 @@ class DemoAccountPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
$this->addHook('filter.app-data', 'FilterAppData'); $this->addHook('filter.app-data', 'FilterAppData');
$this->addHook('filter.action-params', 'FilterActionParams'); $this->addHook('filter.action-params', 'FilterActionParams');
$this->addHook('json.action-pre-call', 'JsonActionPreCall'); $this->addHook('json.before-accountsetup', 'BeforeAccountSetup');
$this->addHook('filter.send-message', 'FilterSendMessage'); $this->addHook('filter.send-message', 'FilterSendMessage');
$this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('main.fabrica', 'MainFabrica');
} }
@ -78,12 +78,10 @@ class DemoAccountPlugin extends \RainLoop\Plugins\AbstractPlugin
return ($oAccount && $oAccount->Email() === $this->Config()->Get('plugin', 'email')); return ($oAccount && $oAccount->Email() === $this->Config()->Get('plugin', 'email'));
} }
public function JsonActionPreCall($sAction) public function BeforeAccountSetup()
{ {
if ('AccountSetup' === $sAction && $this->isDemoAccount()) {
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DemoAccountError); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DemoAccountError);
} }
}
public function FilterSendMessage($oMessage) public function FilterSendMessage($oMessage)
{ {

View file

@ -6,9 +6,9 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
NAME = 'reCaptcha', NAME = 'reCaptcha',
AUTHOR = 'SnappyMail', AUTHOR = 'SnappyMail',
URL = 'https://snappymail.eu/', URL = 'https://snappymail.eu/',
VERSION = '2.12.1', VERSION = '2.13',
RELEASE = '2022-02-14', RELEASE = '2022-12-08',
REQUIRED = '2.12.1', REQUIRED = '2.23',
CATEGORY = 'General', CATEGORY = 'General',
LICENSE = 'MIT', LICENSE = 'MIT',
DESCRIPTION = 'A CAPTCHA (v2) is a program that can generate and grade tests that humans can pass but current computer programs cannot. For example, humans can read distorted text as the one shown below, but current computer programs can\'t. More info at https://developers.google.com/recaptcha'; DESCRIPTION = 'A CAPTCHA (v2) is a program that can generate and grade tests that humans can pass but current computer programs cannot. For example, humans can read distorted text as the one shown below, but current computer programs can\'t. More info at https://developers.google.com/recaptcha';
@ -22,8 +22,8 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
$this->addJs('js/recaptcha.js'); $this->addJs('js/recaptcha.js');
$this->addHook('json.action-pre-call', 'AjaxActionPreCall'); $this->addHook('json.before-login', 'BeforeLogin');
$this->addHook('filter.json-response', 'FilterAjaxResponse'); $this->addHook('json.after-login', 'AfterLogin');
$this->addHook('main.content-security-policy', 'ContentSecurityPolicy'); $this->addHook('main.content-security-policy', 'ContentSecurityPolicy');
} }
@ -82,12 +82,9 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
} }
} }
/** public function BeforeLogin()
* @param string $sAction
*/
public function AjaxActionPreCall(string $sAction)
{ {
if ('Login' === $sAction && 0 >= $this->getLimit()) { if (0 >= $this->getLimit()) {
$bResult = false; $bResult = false;
$HTTP = \SnappyMail\HTTP\Request::factory(); $HTTP = \SnappyMail\HTTP\Request::factory();
@ -112,18 +109,18 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
/** /**
* @param string $sAction * @param string $sAction
* @param array $aResponseItem * @param array $aResponse
*/ */
public function FilterAjaxResponse(string $sAction, array &$aResponseItem) public function AfterLogin(array &$aResponse)
{ {
if ('Login' === $sAction && $aResponseItem && isset($aResponseItem['Result'])) { if (isset($aResponse['Result'])) {
$oCacher = $this->Manager()->Actions()->Cacher(); $oCacher = $this->Manager()->Actions()->Cacher();
$iConfigLimit = (int) $this->Config()->Get('plugin', 'error_limit', 0); $iConfigLimit = (int) $this->Config()->Get('plugin', 'error_limit', 0);
$sKey = $this->getCaptchaCacherKey(); $sKey = $this->getCaptchaCacherKey();
if (0 < $iConfigLimit && $oCacher && $oCacher->IsInited()) { if (0 < $iConfigLimit && $oCacher && $oCacher->IsInited()) {
if (false === $aResponseItem['Result']) { if (false === $aResponse['Result']) {
$iLimit = 0; $iLimit = 0;
$sLimut = $oCacher->Get($sKey); $sLimut = $oCacher->Get($sKey);
if (\strlen($sLimut) && \is_numeric($sLimut)) { if (\strlen($sLimut) && \is_numeric($sLimut)) {
@ -133,7 +130,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
$oCacher->Set($sKey, ++$iLimit); $oCacher->Set($sKey, ++$iLimit);
if ($iConfigLimit <= $iLimit) { if ($iConfigLimit <= $iLimit) {
$aResponseItem['Captcha'] = true; $aResponse['Captcha'] = true;
} }
} else { } else {
$oCacher->Delete($sKey); $oCacher->Delete($sKey);

View file

@ -9,7 +9,7 @@ class Manager
*/ */
private $oActions; private $oActions;
private private array
$aHooks = array(), $aHooks = array(),
$aCss = array([], []), $aCss = array([], []),
$aJs = array([], []), $aJs = array([], []),
@ -19,10 +19,7 @@ class Manager
$aAdditionalJson = array(), $aAdditionalJson = array(),
$aPlugins = array(); $aPlugins = array();
/** private bool $bIsEnabled;
* @var bool
*/
private $bIsEnabled;
/** /**
* @var \MailSo\Log\Logger * @var \MailSo\Log\Logger
@ -284,16 +281,13 @@ class Manager
*/ */
public function AddHook(string $sHookName, $mCallbak) : self public function AddHook(string $sHookName, $mCallbak) : self
{ {
if ($this->bIsEnabled && \is_callable($mCallbak)) if ($this->bIsEnabled && \is_callable($mCallbak)) {
{ $sHookName = \strtolower($sHookName);
if (!isset($this->aHooks[$sHookName])) if (!isset($this->aHooks[$sHookName])) {
{
$this->aHooks[$sHookName] = array(); $this->aHooks[$sHookName] = array();
} }
$this->aHooks[$sHookName][] = $mCallbak; $this->aHooks[$sHookName][] = $mCallbak;
} }
return $this; return $this;
} }
@ -333,22 +327,17 @@ class Manager
public function RunHook(string $sHookName, array $aArg = array(), bool $bLogHook = true) : self public function RunHook(string $sHookName, array $aArg = array(), bool $bLogHook = true) : self
{ {
if ($this->bIsEnabled) if ($this->bIsEnabled) {
{ $sHookName = \strtolower($sHookName);
if (isset($this->aHooks[$sHookName])) if (isset($this->aHooks[$sHookName])) {
{ if ($bLogHook) {
if ($bLogHook)
{
$this->WriteLog('Hook: '.$sHookName, \LOG_INFO); $this->WriteLog('Hook: '.$sHookName, \LOG_INFO);
} }
foreach ($this->aHooks[$sHookName] as $mCallback) {
foreach ($this->aHooks[$sHookName] as $mCallback)
{
$mCallback(...$aArg); $mCallback(...$aArg);
} }
} }
} }
return $this; return $this;
} }

View file

@ -88,7 +88,7 @@ class ServiceActions
{ {
\ob_start(); \ob_start();
$aResponseItem = null; $aResponse = null;
$oException = null; $oException = null;
$_POST = \json_decode(\file_get_contents('php://input'), true); $_POST = \json_decode(\file_get_contents('php://input'), true);
@ -151,20 +151,20 @@ class ServiceActions
if (\method_exists($this->oActions, $sMethodName) && if (\method_exists($this->oActions, $sMethodName) &&
\is_callable(array($this->oActions, $sMethodName))) \is_callable(array($this->oActions, $sMethodName)))
{ {
$sAction && $this->Plugins()->RunHook('json.action-pre-call', array($sAction)); $sAction && $this->Plugins()->RunHook("json.before-{$sAction}");
$aResponseItem = $this->oActions->{$sMethodName}(); $aResponse = $this->oActions->{$sMethodName}();
$sAction && $this->Plugins()->RunHook('json.action-post-call', array($sAction, &$aResponseItem));
} }
else if ($this->Plugins()->HasAdditionalJson($sMethodName)) else if ($this->Plugins()->HasAdditionalJson($sMethodName))
{ {
$sAction && $this->Plugins()->RunHook('json.action-pre-call', array($sAction)); $sAction && $this->Plugins()->RunHook("json.before-{$sAction}");
$aResponseItem = $this->Plugins()->RunAdditionalJson($sMethodName); $aResponse = $this->Plugins()->RunAdditionalJson($sMethodName);
$sAction && $this->Plugins()->RunHook('json.action-post-call', array($sAction, &$aResponseItem)); }
if ($sAction && \is_array($aResponse)) {
$this->Plugins()->RunHook("json.after-{$sAction}", array(&$aResponse));
} }
} }
if (!\is_array($aResponseItem)) if (!\is_array($aResponse)) {
{
throw new Exceptions\ClientException(Notifications::UnknownError); throw new Exceptions\ClientException(Notifications::UnknownError);
} }
} }
@ -175,22 +175,19 @@ class ServiceActions
\SnappyMail\Log::warning('SERVICE', "- {$e->getMessage()} @ {$e->getFile()}#{$e->getLine()}"); \SnappyMail\Log::warning('SERVICE', "- {$e->getMessage()} @ {$e->getFile()}#{$e->getLine()}");
} }
$aResponseItem = $this->oActions->ExceptionResponse( $aResponse = $this->oActions->ExceptionResponse(
empty($sAction) ? 'Unknown' : $sAction, $oException); empty($sAction) ? 'Unknown' : $sAction, $oException);
} }
if (\is_array($aResponseItem)) if (\is_array($aResponse)) {
{ $aResponse['Time'] = (int) ((\microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000);
$aResponseItem['Time'] = (int) ((\microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000);
} }
$sAction && $this->Plugins()->RunHook('filter.json-response', array($sAction, &$aResponseItem));
if (!\headers_sent()) { if (!\headers_sent()) {
\header('Content-Type: application/json; charset=utf-8'); \header('Content-Type: application/json; charset=utf-8');
} }
$sResult = Utils::jsonEncode($aResponseItem); $sResult = Utils::jsonEncode($aResponse);
$sObResult = \ob_get_clean(); $sObResult = \ob_get_clean();
@ -257,7 +254,7 @@ class ServiceActions
$oConfig = $this->Config(); $oConfig = $this->Config();
\ob_start(); \ob_start();
$aResponseItem = null; $aResponse = null;
try try
{ {
$aFile = null; $aFile = null;
@ -301,27 +298,26 @@ class ServiceActions
$this->oActions->SetActionParams($aActionParams, $sAction); $this->oActions->SetActionParams($aActionParams, $sAction);
$aResponseItem = $this->oActions->{$sAction}(); $aResponse = $this->oActions->{$sAction}();
} }
if (!is_array($aResponseItem)) if (!is_array($aResponse)) {
{
throw new Exceptions\ClientException(Notifications::UnknownError); throw new Exceptions\ClientException(Notifications::UnknownError);
} }
$this->Plugins()->RunHook('filter.upload-response', array(&$aResponse));
} }
catch (\Throwable $oException) catch (\Throwable $oException)
{ {
$aResponseItem = $this->oActions->ExceptionResponse($sAction, $oException); $aResponse = $this->oActions->ExceptionResponse($sAction, $oException);
} }
\header('Content-Type: application/json; charset=utf-8'); \header('Content-Type: application/json; charset=utf-8');
$this->Plugins()->RunHook('filter.upload-response', array(&$aResponseItem)); $sResult = Utils::jsonEncode($aResponse);
$sResult = Utils::jsonEncode($aResponseItem);
$sObResult = \ob_get_clean(); $sObResult = \ob_get_clean();
if (\strlen($sObResult)) if (\strlen($sObResult)) {
{
$this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA'); $this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA');
} }