Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: oauth integration #58

Open
wants to merge 7 commits into
base: release/v12
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 85 additions & 20 deletions Classes/CleverReach/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
*/


use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Uri;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use WapplerSystems\Cleverreach\Domain\Model\Receiver;
Expand Down Expand Up @@ -38,6 +44,7 @@ class Api

public const MODE_OPTOUT = 'optout';

private const CACHE_KEY = 'ws_cleverreach_token_storage';

public function __construct(ConfigurationService $configurationService)
{
Expand All @@ -56,16 +63,19 @@ public function connect()
$this->rest = new Rest($this->configurationService->getRestUrl());

try {
//skip this part if you have an OAuth access token
$token = $this->rest->post('/login',
[
'client_id' => $this->configurationService->getClientId(),
'login' => $this->configurationService->getLoginName(),
'password' => $this->configurationService->getPassword()
]
);
if ($this->configurationService->getAuthMode() === 'oauth') {
$token = $this->authenticateViaOAuth();
} else {
$token = $this->rest->post('/login',
[
'client_id' => $this->configurationService->getClientId(),
'login' => $this->configurationService->getLoginName(),
'password' => $this->configurationService->getPassword(),
]
);
}
$this->rest->setAuthMode('bearer', $token);
} catch (\Exception $ex) {
} catch (\Exception | GuzzleException $ex) {
$this->log($ex);
}

Expand Down Expand Up @@ -103,7 +113,7 @@ public function addReceiversToGroup($receivers, $groupId = null)
}

try {
$return = $this->rest->post('/groups.json/' . $groupId . '/receivers/insert',
$return = $this->rest->post('/groups.json/'.$groupId.'/receivers/insert',
$aReceivers
);
if (\is_object($return) && $return->status === 'insert success') {
Expand Down Expand Up @@ -133,7 +143,7 @@ public function removeReceiversFromGroup($receivers, $groupId = null)
}

try {
$this->rest->delete('/groups.json/' . $groupId . '/receivers/' . $receivers);
$this->rest->delete('/groups.json/'.$groupId.'/receivers/'.$receivers);
} catch (\Exception $ex) {
$this->log($ex);
}
Expand All @@ -155,7 +165,7 @@ public function disableReceiversInGroup($receivers, $groupId = null)
}

try {
$this->rest->put('/groups.json/' . $groupId . '/receivers/' . $receivers . '/setinactive');
$this->rest->put('/groups.json/'.$groupId.'/receivers/'.$receivers.'/setinactive');
} catch (\Exception $ex) {
$this->log($ex);
}
Expand All @@ -177,7 +187,7 @@ public function activateReceiversInGroup($receivers, $groupId = null)
}

try {
$this->rest->put('/groups.json/' . $groupId . '/receivers/' . $receivers . '/setactive');
$this->rest->put('/groups.json/'.$groupId.'/receivers/'.$receivers.'/setactive');
} catch (\Exception $ex) {
$this->log($ex);
}
Expand All @@ -197,7 +207,7 @@ public function getGroup($groupId = null)
}

try {
return $this->rest->get('/groups.json/' . $groupId);
return $this->rest->get('/groups.json/'.$groupId);
} catch (\Exception $ex) {
$this->log($ex);
}
Expand All @@ -219,13 +229,15 @@ public function isReceiverOfGroup($id, $groupId = null): bool
}

try {
$this->rest->get('/groups.json/' . $groupId . '/receivers/' . $id);
$this->rest->get('/groups.json/'.$groupId.'/receivers/'.$id);

return true;
} catch (\Exception $ex) {
if ($ex->getCode() !== 404) {
$this->log($ex);
}
}

return false;
}

Expand All @@ -244,13 +256,15 @@ public function getReceiverOfGroup($id, $groupId = null): ?Receiver
}

try {
$return = $this->rest->get('/groups.json/' . $groupId . '/receivers/' . $id);
$return = $this->rest->get('/groups.json/'.$groupId.'/receivers/'.$id);

return Receiver::createInstance($return);
} catch (\Exception $ex) {
if ($ex->getCode() !== 404) {
$this->log($ex);
}
}

return null;
}

Expand All @@ -266,6 +280,7 @@ public function isReceiverOfGroupAndActive($id, $groupId = null): bool
if ($receiver !== null) {
return $receiver->isActive();
}

return false;
}

Expand Down Expand Up @@ -293,7 +308,7 @@ public function sendSubscribeMail($email, $formId = null, $groupId = null): void
];

try {
$this->rest->post('/forms.json/' . $formId . '/send/activate',
$this->rest->post('/forms.json/'.$formId.'/send/activate',
[
'email' => $email,
'groups_id' => $groupId,
Expand Down Expand Up @@ -339,7 +354,7 @@ public function sendUnsubscribeMail($email, $formId = null, $groupId = null): vo
];

try {
$this->rest->post('/forms.json/' . $formId . '/send/deactivate',
$this->rest->post('/forms.json/'.$formId.'/send/deactivate',
[
'email' => $email,
'groups_id' => $groupId,
Expand All @@ -366,7 +381,7 @@ public function setAttributeOfReceiver($email, $attributeId, $value): void
{
$this->connect();
try {
$this->rest->put('/receivers.json/' . $email . '/attributes/' . $attributeId,
$this->rest->put('/receivers.json/'.$email.'/attributes/'.$attributeId,
[
'value' => $value,
]
Expand All @@ -382,7 +397,7 @@ public function deleteReceiver($email, $groupId = null): void
{
$this->connect();
try {
$this->rest->delete('/receivers.json/' . $email . '',
$this->rest->delete('/receivers.json/'.$email.'',
[
'group_id' => $groupId,
]
Expand All @@ -393,5 +408,55 @@ public function deleteReceiver($email, $groupId = null): void

}

/**
* @throws NoSuchCacheException
* @throws GuzzleException
* @throws \Exception
*/
protected function authenticateViaOAuth(): string
{
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
$cache = $cacheManager->getCache('hash');

if ($cachedAccessToken = $cache->get(self::CACHE_KEY)) {
return $cachedAccessToken;
}

$uri = new Uri($this->configurationService->getOauthTokenUrl());

$arguments = [
'grant_type' => 'client_credentials',
'client_id' => $this->configurationService->getOauthClientId(),
'client_secret' => $this->configurationService->getOAuthClientSecret(),
];

$request = new Request(
'POST',
$uri,
[
'Content-Type' => 'application/json; charset=utf-8',
],
\GuzzleHttp\json_encode($arguments)
);

$client = new Client();
$rawResponse = $client->send($request, ['http_errors' => false]);
$responseData = json_decode($rawResponse->getBody()->getContents(), true);

if (200 !== $rawResponse->getStatusCode()) {
$errorMessage = $responseData['error']['message'] ?? 'Error message not specified';

throw new \Exception(sprintf('CleverReach Api Error: %s', $errorMessage), 1706886072);
}

if (empty($responseData['access_token'])) {
throw new \Exception('CleverReach oAuth failed: %s', 1706886133);
}

// cache result for expire time minus 2 minutes buffer
$cache->set(self::CACHE_KEY, $responseData['access_token'], [], ($responseData['expires_in']) - 120);

return $responseData['access_token'];
}

}
2 changes: 1 addition & 1 deletion Classes/Form/Validator/OptinValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class OptinValidator extends AbstractValidator
* @param mixed $value The value that should be validated
* @api
*/
public function isValid($value)
public function isValid(mixed $value): void
{

/** @var ConfigurationService $configurationService */
Expand Down
2 changes: 1 addition & 1 deletion Classes/Form/Validator/OptoutValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class OptoutValidator extends AbstractValidator
* @param mixed $value The value that should be validated
* @api
*/
public function isValid($value)
public function isValid(mixed $value): void
{

/** @var ConfigurationService $configurationService */
Expand Down
65 changes: 56 additions & 9 deletions Classes/Service/ConfigurationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,82 +19,129 @@
class ConfigurationService
{


public function getConfiguration()
public function getConfiguration(): array
{

$configurationManager = GeneralUtility::makeInstance(ConfigurationManagerInterface::class);
$settings = $configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
'cleverreach'
);

return $settings['plugin.']['tx_cleverreach.']['settings.'];
}

/**
* @return string
*/
public function getRestUrl()
public function getRestUrl(): string
{

$config = $this->getConfiguration();

return $config['restUrl'];
}

/**
* @return string
*/
public function getClientId()
public function getClientId(): string
{

$config = $this->getConfiguration();

return $config['clientId'];

}

/**
* @return string
*/
public function getLoginName()
public function getLoginName(): string
{
$config = $this->getConfiguration();

return $config['login'];
}

/**
* @return string
*/
public function getPassword()
public function getPassword(): string
{
$config = $this->getConfiguration();

return $config['password'];
}

/**
* @return int
*/
public function getGroupId()
public function getGroupId(): string
{
$config = $this->getConfiguration();

return (int)$config['groupId'];
}

/**
* @return int
*/
public function getFormId()
public function getFormId(): string
{
$config = $this->getConfiguration();

return (int)$config['formId'];
}

/**
* @return string
*/
public function getUnsubscribeMethod()
public function getUnsubscribeMethod(): string
{
$config = $this->getConfiguration();

return $config['unsubscribemethod'];
}

/**
* @return string
*/
public function getAuthMode(): string
{
return $this->getConfiguration()['authMode'];
}

/**
* @return string
*/
public function getOauthTokenUrl(): string
{
return $this->getConfiguration()['oauthTokenUrl'];
}

/**
* @return string
*/
public function getOauthClientId(): string
{
return $this->getConfiguration()['oauthClientId'];
}

/**
* @return string
*/
public function getOauthClientSecret(): string
{
return $this->getConfiguration()['oauthClientSecret'];
}

/**
* @return string
*/
public function getOauthClientCode(): string
{
return $this->getConfiguration()['oauthClientCode'];
}

}
Loading