<?php
namespace EADPlataforma\Services\Aws;
use Aws\EventBridge\EventBridgeClient;
use Aws\Exception\AwsException;
use EADPlataforma\Services\Aws\Aws;
use EADPlataforma\Services\GeneralService;
use EADPlataforma\Enum\ServicesEnum;
/**
* AwsEventBridge
*/
class AwsEventBridge extends Aws
{
/**
* @var Aws\EventBridge\EventBridgeClient
*/
protected $eventBridgeClient = [];
/**
* @var GeneralService
*/
protected $generalService;
/**
* @var AwsIAM
*/
protected $awsIam;
/**
* @var ConfigurationService
*/
protected $configuration;
/**
* @var string
*/
protected $connection;
/**
* @var Client
*/
protected $client;
/**
* @var string
*/
protected $clientHash;
/**
* @var object
*/
protected $info;
/**
* Constructor
*
* @param GeneralService $generalService
*/
public function __construct(GeneralService $generalService)
{
$this->generalService = $generalService;
$info = $this->generalService->getServiceAccess(ServicesEnum::AWS_EVENT_BRIDGE);
$this->info = $info;
$this->connection = $this->info->connection;
$this->awsIam = $this->generalService->getService('Aws\\AwsIAM');
$this->configuration = $this->generalService->getService('ConfigurationService');
$this->client = $this->configuration->getClient();
$this->clientHash = "client-{$this->client->getClientId()}-cron";
}
public function setClientHash(string $clientHash)
{
$this->clientHash = $clientHash;
return $this;
}
public function getRegion()
{
$clientConfig = $this->configuration->getClientConfiguration();
$region = $clientConfig->getServiceCronRegion();
return (!empty($region) ? $region : "us-east-1");
}
public function getEventBridgeClient()
{
if(!isset($this->eventBridgeClient[$this->getRegion()])){
$this->eventBridgeClient[$this->getRegion()] = new EventBridgeClient(
$this->getCredentials(
$this->getRegion(),
$this->info->key,
$this->info->secret
)
);
}
return $this->eventBridgeClient[$this->getRegion()];
}
public function createByTypeApiDestination(int $cronType)
{
$arnTypeSave = $this->configuration->get("config_cron_arn_destination_{$cronType}");
if(!empty($arnTypeSave)){
return;
}
$arrUrl = [
ServicesEnum::CRON_GENERAL => "/general/",
ServicesEnum::CRON_QUEUE => "/email/queue/",
ServicesEnum::CRON_PROCCESS_SUBSCRIPTION => "/user/subscription/",
ServicesEnum::CRON_WEBHOOK_QUEUE => "/webhook/queue/send/",
ServicesEnum::CRON_TRASH => "/delete/trash/all/",
];
$horaGeneral = rand(5,7);
$minGeneral = rand(10,59);
$horaSub = rand(5,7);
$minSub = rand(10,59);
$horaTrash = rand(5,7);
$minTrash = rand(10,59);
$arrTime = [
ServicesEnum::CRON_GENERAL => "cron({$horaGeneral} {$minGeneral} * * ? *)",
ServicesEnum::CRON_QUEUE => "rate(1 minute)",
ServicesEnum::CRON_PROCCESS_SUBSCRIPTION => "cron({$horaSub} {$minSub} * * ? *)",
ServicesEnum::CRON_WEBHOOK_QUEUE => "rate(1 minute)",
ServicesEnum::CRON_TRASH => "cron({$horaTrash} {$minTrash} * * ? *)",
];
$clientConfiguration = $this->configuration->getClientConfiguration();
$token = $clientConfiguration->getToken();
$this->createApiDestination(
$cronType,
"https://{$this->client->getDomainPrimary()}{$arrUrl[$cronType]}{$token}",
$arrTime[$cronType]
);
}
public function createApiDestination(int $cronType, string $url, string $time)
{
$cronName = "{$this->clientHash}-{$cronType}";
$idConn = $this->connection->{$this->getRegion()};
$awsId = $this->info->awsAccountId;
$arnConn = "arn:aws:events:{$this->getRegion()}:{$awsId}:connection/{$idConn}";
try{
$result = $this->getEventBridgeClient()->createApiDestination([
'ConnectionArn' => $arnConn, // REQUIRED
'HttpMethod' => 'GET', // REQUIRED
'InvocationEndpoint' => $url, // REQUIRED
'InvocationRateLimitPerSecond' => 1,
'Name' => $cronName, // REQUIRED
]);
$this->putRule($cronName, $result['ApiDestinationArn'], $cronType, $time);
}catch(Exception $e){
print_r($e->getMessage());
}
}
public function putRule(string $cronName, string $arnDestination,
int $cronType, string $time)
{
try{
$arnPolicy = $this->awsIam->createPolicyApiDestination(
"policy-{$cronName}",
$arnDestination
);
$arnRole = $this->awsIam->createRole(
"role-{$cronName}",
$arnDestination,
$arnPolicy
);
$result = $this->getEventBridgeClient()->putRule([
'EventBusName' => 'default',
'Name' => "rule-{$cronName}", // REQUIRED
'ScheduleExpression' => $time,
'State' => 'ENABLED',
]);
$this->getEventBridgeClient()->putTargets([
'EventBusName' => 'default',
'Rule' => "rule-{$cronName}",
'Targets' => [
[
"Arn" => $arnDestination,
"Id" => "id-{$cronName}",
"RoleArn" => $arnRole,
]
]
]);
$this->configuration->setMany([
"config_cron_arn_destination_{$cronType}" => $arnDestination,
"config_cron_arn_policy_{$cronType}" => $arnPolicy,
"config_cron_arn_role_{$cronType}" => $arnRole,
"config_cron_arn_rule_{$cronType}" => $result['RuleArn']
]);
}catch(AwsException $e){
print_r($e->getMessage());
}
}
public function deleteRule(string $ruleName, string $targetId){
try{
$this->getEventBridgeClient()->removeTargets([
'EventBusName' => 'default',
'Force' => true,
'Ids' => [ $targetId ], // REQUIRED
'Rule' => $ruleName, // REQUIRED
]);
$this->getEventBridgeClient()->deleteRule([
'EventBusName' => 'default',
'Force' => true,
'Name' => $ruleName, // REQUIRED
]);
}catch(AwsException $e){
}
}
public function deleteApiDestination(int $cronType)
{
$arnPolicy = $this->configuration->get("config_cron_arn_policy_{$cronType}");
if(empty($arnPolicy)){
return;
}
if($this->deleteApiDestinationByCronName($cronType)){
$this->configuration->setMany([
"config_cron_arn_destination_{$cronType}" => "",
"config_cron_arn_policy_{$cronType}" => "",
"config_cron_arn_role_{$cronType}" => "",
"config_cron_arn_rule_{$cronType}" => ""
]);
}
}
public function deleteApiDestinationByCronName(int $cronType)
{
if(empty($cronType)){
return false;
}
$clientHash = $this->clientHash;
if($cronType == ServicesEnum::CRON_GENERAL){
$clientId = (int)$this->client->getClientId();
$clientId = str_pad($clientId, 6, '0', STR_PAD_LEFT);
$clientHash = "client-{$clientId}-cron";
}
$cronName = "{$clientHash}-{$cronType}";
try{
$this->deleteRule("rule-{$cronName}", "id-{$cronName}");
}catch(AwsException $e){
if(
!strpos($e->getMessage(), 'does not exist') &&
!strpos($e->getMessage(), 'cannot be found') &&
!strpos($e->getMessage(), 'was not found')
){
return false;
}
}
try{
$this->getEventBridgeClient()->deleteApiDestination([
'Name' => $cronName, // REQUIRED
]);
}catch(AwsException $e){
if(
!strpos($e->getMessage(), 'does not exist') &&
!strpos($e->getMessage(), 'cannot be found') &&
!strpos($e->getMessage(), 'was not found')
){
return false;
}
}
$arnPolicy = "arn:aws:iam::{$this->info->awsAccountId}:policy/policy-{$cronName}";
try{
$this->awsIam->deleteRole("role-{$cronName}", $arnPolicy);
}catch(AwsException $e){
if(
!strpos($e->getMessage(), 'does not exist') &&
!strpos($e->getMessage(), 'cannot be found') &&
!strpos($e->getMessage(), 'was not found')
){
return false;
}
}
try{
$this->awsIam->deletePolicy($arnPolicy);
}catch(AwsException $e){
if(
!strpos($e->getMessage(), 'does not exist') &&
!strpos($e->getMessage(), 'cannot be found') &&
!strpos($e->getMessage(), 'was not found')
){
return false;
}
}
return true;
}
public function updateApiDestinationNewDomain($newDomain)
{
$clientConfiguration = $this->configuration->getClientConfiguration();
$clientToken = $clientConfiguration->getToken();
$newDomain = str_replace('http://', '', $newDomain);
$newDomain = str_replace('https://', '', $newDomain);
$newDomain = str_replace('/', '', $newDomain);
$arrUrl = [
ServicesEnum::CRON_GENERAL => "/general/",
ServicesEnum::CRON_QUEUE => "/email/queue/",
ServicesEnum::CRON_PROCCESS_SUBSCRIPTION => "/user/subscription/",
ServicesEnum::CRON_WEBHOOK_QUEUE => "/webhook/queue/send/",
ServicesEnum::CRON_TRASH => "/delete/trash/all/",
];
foreach ($arrUrl as $type => $action) {
try {
$cronName = "{$this->clientHash}-{$type}";
$awsId = $this->info->awsAccountId;
$idConn = $this->connection->{$this->getRegion()};
$arnConn = "arn:aws:events:{$this->getRegion()}:{$awsId}:connection/{$idConn}";
$this->getEventBridgeClient()->updateApiDestination([
'ConnectionArn' => $arnConn, // REQUIRED
'HttpMethod' => 'GET', // REQUIRED
'InvocationEndpoint' => "https://{$newDomain}{$action}{$clientToken}",
'InvocationRateLimitPerSecond' => 1,
'Name' => $cronName, // REQUIRED
]);
} catch (\Exception $e) {
}
}
}
}