Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\WebhookBundle\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Controller\AjaxController as CommonAjaxController;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Helper\PathsHelper;
|
||||
use Mautic\WebhookBundle\Exception\PrivateAddressException;
|
||||
use Mautic\WebhookBundle\Http\Client;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class AjaxController extends CommonAjaxController
|
||||
{
|
||||
public function sendHookTestAction(Request $request, Client $client, PathsHelper $pathsHelper): JsonResponse
|
||||
{
|
||||
try {
|
||||
return $this->processWebhookTest($request, $client, $pathsHelper);
|
||||
} catch (PrivateAddressException) {
|
||||
return $this->createErrorResponse(
|
||||
'mautic.webhook.error.private_address'
|
||||
);
|
||||
} catch (\Exception) {
|
||||
return $this->createErrorResponse(
|
||||
'mautic.webhook.label.warning'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function processWebhookTest(Request $request, Client $client, PathsHelper $pathsHelper): JsonResponse
|
||||
{
|
||||
$url = $this->validateUrl($request);
|
||||
if (!$url) {
|
||||
return $this->createErrorResponse('mautic.webhook.label.no.url');
|
||||
}
|
||||
|
||||
$selectedTypes = InputHelper::cleanArray($request->request->all()['types']) ?? [];
|
||||
$payloadPaths = $this->getPayloadPaths($selectedTypes, $pathsHelper);
|
||||
$payload = $this->loadPayloads($payloadPaths);
|
||||
$payload['timestamp'] = (new \DateTimeImmutable())->format('c');
|
||||
$secret = InputHelper::string($request->request->get('secret'));
|
||||
|
||||
$response = $client->post($url, $payload, $secret);
|
||||
|
||||
return $this->createResponseFromStatusCode($response->getStatusCode());
|
||||
}
|
||||
|
||||
private function validateUrl(Request $request): ?string
|
||||
{
|
||||
$url = InputHelper::url($request->request->get('url'));
|
||||
|
||||
return '' !== $url ? $url : null;
|
||||
}
|
||||
|
||||
private function createResponseFromStatusCode(int $statusCode): JsonResponse
|
||||
{
|
||||
$isSuccess = str_starts_with((string) $statusCode, '2');
|
||||
$message = $isSuccess
|
||||
? 'mautic.webhook.label.success'
|
||||
: 'mautic.webhook.label.warning';
|
||||
|
||||
$cssClass = $isSuccess ? 'has-success' : 'has-error';
|
||||
|
||||
return $this->createJsonResponse($message, $cssClass);
|
||||
}
|
||||
|
||||
private function createErrorResponse(string $message): JsonResponse
|
||||
{
|
||||
return $this->createJsonResponse($message, 'has-error', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
private function createJsonResponse(
|
||||
string $message,
|
||||
string $cssClass,
|
||||
int $status = Response::HTTP_OK,
|
||||
): JsonResponse {
|
||||
$html = sprintf(
|
||||
'<div class="%s"><span class="help-block">%s</span></div>',
|
||||
$cssClass,
|
||||
$this->translator->trans($message)
|
||||
);
|
||||
|
||||
return $this->sendJsonResponse(
|
||||
['html' => $html],
|
||||
$status
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get an array of all the payload paths we need to load
|
||||
*
|
||||
* @param $types array
|
||||
* @return array
|
||||
*/
|
||||
/**
|
||||
* @return non-falsy-string[]
|
||||
*/
|
||||
public function getPayloadPaths($types, PathsHelper $pathsHelper): array
|
||||
{
|
||||
$payloadPaths = [];
|
||||
|
||||
foreach ($types as $type) {
|
||||
// takes an input like mautic.lead_on_something
|
||||
// converts to array pieces using _
|
||||
$typePath = explode('_', $type);
|
||||
|
||||
// pull the prefix into its own variable
|
||||
$prefix = $typePath[0];
|
||||
|
||||
// now that we have the remove it from the array
|
||||
unset($typePath[0]);
|
||||
|
||||
// build the event name by putting the pieces back together
|
||||
$eventName = implode('_', $typePath);
|
||||
|
||||
// default the path to core
|
||||
$payloadPath = $pathsHelper->getSystemPath('bundles', true);
|
||||
|
||||
// if plugin is in first part of the string this is an addon
|
||||
// input is plugin.bundlename or mautic.bundlename
|
||||
if (strpos('plugin.', $prefix)) {
|
||||
$payloadPath = $pathsHelper->getSystemPath('plugins', true);
|
||||
}
|
||||
|
||||
$prefixParts = explode('.', $prefix);
|
||||
|
||||
$bundleName = array_pop($prefixParts);
|
||||
|
||||
$payloadPath .= '/'.ucfirst($bundleName).'Bundle/Assets/WebhookPayload/'.$bundleName.'_'.$eventName.'.json';
|
||||
|
||||
$payloadPaths[$type] = $payloadPath;
|
||||
}
|
||||
|
||||
return $payloadPaths;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate through the paths and get the json payloads
|
||||
*
|
||||
* @param $paths array
|
||||
* @return $payload array
|
||||
*/
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function loadPayloads($paths): array
|
||||
{
|
||||
$payloads = [];
|
||||
|
||||
foreach ($paths as $key => $path) {
|
||||
if (file_exists($path)) {
|
||||
$payloads[$key] = json_decode(file_get_contents($path), true);
|
||||
}
|
||||
}
|
||||
|
||||
return $payloads;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\WebhookBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\WebhookBundle\Entity\Webhook;
|
||||
use Mautic\WebhookBundle\Model\WebhookModel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @extends CommonApiController<Webhook>
|
||||
*/
|
||||
class WebhookApiController extends CommonApiController
|
||||
{
|
||||
/**
|
||||
* @var WebhookModel|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
public function __construct(
|
||||
CorePermissions $security,
|
||||
Translator $translator,
|
||||
EntityResultHelper $entityResultHelper,
|
||||
RouterInterface $router,
|
||||
FormFactoryInterface $formFactory,
|
||||
AppVersion $appVersion,
|
||||
private RequestStack $requestStack,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
) {
|
||||
$webhookModel = $modelFactory->getModel('webhook');
|
||||
\assert($webhookModel instanceof WebhookModel);
|
||||
|
||||
$this->model = $webhookModel;
|
||||
$this->entityClass = Webhook::class;
|
||||
$this->entityNameOne = 'hook';
|
||||
$this->entityNameMulti = 'hooks';
|
||||
$this->serializerGroups = ['hookDetails', 'categoryList', 'publishDetails'];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives child controllers opportunity to analyze and do whatever to an entity before going through serializer.
|
||||
*/
|
||||
protected function preSerializeEntity(object $entity, string $action = 'view'): void
|
||||
{
|
||||
// We have to use this hack to have a simple array instead of the one the serializer gives us
|
||||
$entity->buildTriggers();
|
||||
}
|
||||
|
||||
protected function preSaveEntity(&$entity, $form, $parameters, $action = 'edit')
|
||||
{
|
||||
$eventsToKeep = [];
|
||||
|
||||
// Build webhook events from the triggers
|
||||
if (isset($parameters['triggers']) && is_array($parameters['triggers'])) {
|
||||
$entity->setTriggers($parameters['triggers']);
|
||||
$eventsToKeep = $parameters['triggers'];
|
||||
}
|
||||
|
||||
// Remove events missing in the PUT request
|
||||
if ('PUT' === $this->requestStack->getCurrentRequest()->getMethod()) {
|
||||
foreach ($entity->getEvents() as $event) {
|
||||
if (!in_array($event->getEventType(), $eventsToKeep)) {
|
||||
$entity->removeEvent($event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getTriggersAction()
|
||||
{
|
||||
return $this->handleView(
|
||||
$this->view(
|
||||
[
|
||||
'triggers' => $this->model->getEvents(),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\WebhookBundle\Controller;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\CoreBundle\Controller\FormController;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Service\FlashBag;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Helper\FormFieldHelper;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class WebhookController extends FormController
|
||||
{
|
||||
public function __construct(FormFactoryInterface $formFactory, FormFieldHelper $fieldHelper, ManagerRegistry $doctrine, ModelFactory $modelFactory, UserHelper $userHelper, CoreParametersHelper $coreParametersHelper, EventDispatcherInterface $dispatcher, Translator $translator, FlashBag $flashBag, RequestStack $requestStack, CorePermissions $security)
|
||||
{
|
||||
$this->setStandardParameters(
|
||||
'webhook.webhook', // model name
|
||||
'webhook:webhooks', // permission base
|
||||
'mautic_webhook', // route base
|
||||
'mautic_webhook', // session base
|
||||
'mautic.webhook', // lang string base
|
||||
'@MauticWebhook/Webhook', // template base
|
||||
'mautic_webhook', // activeLink
|
||||
'mauticWebhook' // mauticContent
|
||||
);
|
||||
|
||||
parent::__construct($formFactory, $fieldHelper, $doctrine, $modelFactory, $userHelper, $coreParametersHelper, $dispatcher, $translator, $flashBag, $requestStack, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $page
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function indexAction(Request $request, $page = 1): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
return parent::indexStandard($request, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new form and processes post data.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function newAction(Request $request)
|
||||
{
|
||||
return parent::newStandard($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates edit form and processes post data.
|
||||
*
|
||||
* @param int $objectId
|
||||
* @param bool $ignorePost
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function editAction(Request $request, $objectId, $ignorePost = false)
|
||||
{
|
||||
return parent::editStandard($request, $objectId, $ignorePost);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays details on a Focus.
|
||||
*
|
||||
* @return array|\Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function viewAction(Request $request, $objectId)
|
||||
{
|
||||
return $this->viewStandard($request, $objectId, 'webhook', 'webhook', null, 'item');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone an entity.
|
||||
*
|
||||
* @param int $objectId
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function cloneAction(Request $request, $objectId)
|
||||
{
|
||||
return parent::cloneStandard($request, $objectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the entity.
|
||||
*
|
||||
* @param int $objectId
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function deleteAction(Request $request, $objectId)
|
||||
{
|
||||
return parent::deleteStandard($request, $objectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a group of entities.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function batchDeleteAction(Request $request)
|
||||
{
|
||||
return parent::batchDeleteStandard($request);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user