new: [wip] eventblocklists migration

pull/9060/head
Luciano Righetti 2023-05-04 16:34:18 +02:00
parent cda28789f1
commit 385a1dabd4
7 changed files with 530 additions and 1 deletions

View File

@ -0,0 +1,203 @@
<?php
namespace App\Controller\Component;
use Cake\Controller\Component;
class BlocklistComponent extends Component
{
public $settings = array();
public $defaultModel = '';
public $components = array('RestResponse');
public function index($rest = false, $filters = array())
{
if (!empty($filters)) {
$this->controller->paginate['conditions'] = $filters;
}
if ($rest) {
$data = $this->controller->{$this->defaultModel}->find('all', array(
'recursive' => -1,
'conditions' => isset($this->controller->paginate['conditions']) ? $this->controller->paginate['conditions'] : []
));
$blocklist = [];
foreach ($data as $item) {
$blocklist[] = $item[$this->defaultModel];
}
return $this->RestResponse->viewData($blocklist);
} else {
$this->controller->set('response', $this->controller->paginate());
}
}
public function add($rest = false)
{
if ($this->controller->getRequest()->is('post')) {
if ($rest) {
if ($this->controller->getResponse()->type() === 'application/json') {
$isJson = true;
$data = $this->controller->getRequest()->input('json_decode', true);
} else {
$data = $this->controller->getRequest()->getData();
}
if (isset($data['request'])) {
$data = $data['request'];
}
} else {
$data = $this->controller->getRequest()->getData();
}
if (!isset($data[$this->defaultModel])) {
$data = [$this->defaultModel => $data];
}
if (!isset($data[$this->defaultModel])) {
throw new InvalidArgumentException(__('Pass a list of uuids via the "uuids" key in the request object.'));
}
if (is_array($data[$this->defaultModel]['uuids'])) {
$uuids = $data[$this->defaultModel]['uuids'];
} else {
$uuids = explode(PHP_EOL, trim($data[$this->defaultModel]['uuids']));
}
$successes = array();
$fails = array();
foreach ($uuids as $uuid) {
$uuid = trim($uuid);
if (strlen($uuid) == 36) {
$object = $this->controller->{$this->defaultModel}->newEmptyEntity();
foreach ($this->controller->{$this->defaultModel}->blocklistFields as $f) {
if ($f === $this->controller->{$this->defaultModel}->blocklistTarget . '_uuid') {
$object[$f] = $uuid;
} else {
$object[$f] = !empty($data[$this->defaultModel][$f]) ? $data[$this->defaultModel][$f] : '';
}
}
if ($this->controller->{$this->defaultModel}->save($object)) {
$successes[] = $uuid;
} else {
$fails[] = $uuid;
}
} else {
$fails[] = $uuid;
}
}
$message = sprintf(__('Done. Added %d new entries to the blocklist. %d entries could not be saved.'), count($successes), count($fails));
if ($rest) {
$result = [
'result' => [
'successes' => $successes,
'fails' => $fails
],
'message' => $message
];
return $this->RestResponse->viewData($result);
} else {
$this->controller->Flash->success($message);
$this->controller->redirect(array('action' => 'index'));
}
}
}
public function edit($id, $rest = false)
{
if (Validation::uuid($id)) {
$blockEntry = $this->controller->{$this->defaultModel}->find('first', [
'conditions' => array(
$this->controller->{$this->defaultModel}->blocklistTarget . '_uuid' => $id
)
]);
} else {
$blockEntry = $this->controller->{$this->defaultModel}->find('first', array('conditions' => array('id' => $id)));
}
if (empty($blockEntry)) {
throw new NotFoundException(__('Blocklist item not found.'));
}
$this->controller->set('blockEntry', $blockEntry);
if ($this->controller->getRequest()->is('post')) {
if ($rest) {
if ($this->controller->getResponse()->type() === 'application/json') {
$data = $this->controller->getRequest()->input('json_decode', true);
} else {
$data = $this->controller->getRequest()->getData();
}
if (isset($data['request'])) {
$data = $data['request'];
}
if (!isset($data[$this->defaultModel])) {
$data = [$this->defaultModel => $data];
}
} else {
$data = $this->controller->getRequest()->getData();
}
$fields = $this->controller->{$this->defaultModel}->blocklistFields;
foreach ($fields as $f) {
if ($f == 'uuid') {
continue;
}
if (isset($data[$this->defaultModel][$f])) {
$blockEntry[$this->defaultModel][$f] = $data[$this->defaultModel][$f];
}
}
if ($this->controller->{$this->defaultModel}->save($blockEntry)) {
if ($rest) {
return $this->RestResponse->viewData(
$this->controller->{$this->defaultModel}->find('first', [
'recursive' => -1,
'conditions' => [
'id' => $this->controller->{$this->defaultModel}->id
]
])
);
} else {
$this->controller->Flash->success(__('Blocklist item added.'));
$this->controller->redirect(array('action' => 'index'));
}
} else {
if ($rest) {
throw new MethodNotAllowedException('Could not save the blocklist item.');
} else {
$this->controller->Flash->error(__('Could not save the blocklist item'));
$this->controller->redirect(array('action' => 'index'));
}
}
}
}
public function delete($id, $rest = false)
{
if (Validation::uuid($id)) {
$blockEntry = $this->controller->{$this->defaultModel}->find('first', [
'conditions' => array(
$this->controller->{$this->defaultModel}->blocklistTarget . '_uuid' => $id
)
]);
} else {
$blockEntry = $this->controller->{$this->defaultModel}->find('first', array('conditions' => array('id' => $id)));
}
if (empty($blockEntry)) {
throw new NotFoundException(__('Invalid blocklist entry'));
}
if ($this->controller->{$this->defaultModel}->delete($blockEntry[$this->defaultModel]['id'])) {
$message = __('Blocklist entry removed');
if ($rest) {
return $this->RestResponse->saveSuccessResponse($this->defaultModel, 'delete', $id, false, $message);
}
$this->controller->Flash->success($message);
} else {
$message = __('Could not remove the blocklist entry');
if ($rest) {
return $this->RestResponse->saveFailResponse($this->defaultModel, 'delete', $id, $message);
}
$this->controller->error($message);
}
$this->controller->redirect(array('action' => 'index'));
}
public $controller;
public function initialize(array $config): void
{
$this->controller = $config['controller'];
$this->defaultModel = $config['table'];
}
}

View File

@ -0,0 +1,86 @@
<?php
namespace App\Controller;
use App\Controller\AppController;
class EventBlocklistsController extends AppController
{
public $quickFilterFields = ['event_uuid', 'comment', 'event_info', 'event_orgc'];
public $filterFields = ['event_uuid', 'comment', 'event_info', 'event_orgc'];
public function initialize(): void
{
parent::initialize();
$this->loadComponent('BlockList', [
'controller' => $this,
'table' => $this->modelClass,
]);
}
public function index()
{
$this->CRUD->index([
'filters' => $this->filterFields,
'quickFilters' => $this->quickFilterFields
]);
$responsePayload = $this->CRUD->getResponsePayload();
if (!empty($responsePayload)) {
return $responsePayload;
}
}
public function add()
{
return $this->BlockList->add($this->ParamHandler->isRest());
}
public function edit($id)
{
return $this->BlockList->edit($id, $this->ParamHandler->isRest());
}
public function delete($id)
{
return $this->BlockList->delete($id, $this->ParamHandler->isRest());
}
public function massDelete()
{
if ($this->request->is('post') || $this->request->is('put')) {
if (!isset($this->request->data['EventBlocklist'])) {
$this->request->data = array('EventBlocklist' => $this->request->data);
}
$ids = $this->request->data['EventBlocklist']['ids'];
$event_ids = json_decode($ids, true);
if (empty($event_ids)) {
throw new NotFoundException(__('Invalid event IDs.'));
}
$result = $this->EventBlocklist->deleteAll(array('EventBlocklist.id' => $event_ids));
if ($result) {
if ($this->ParamHandler->isRest()) {
return $this->RestResponse->saveSuccessResponse('EventBlocklist', 'Deleted', $ids, $this->response->type());
} else {
$this->Flash->success('Blocklist entry removed');
$this->redirect(array('controller' => 'eventBlocklists', 'action' => 'index'));
}
} else {
$error = __('Failed to delete Event from EventBlocklist. Error: ') . PHP_EOL . h($result);
if ($this->ParamHandler->isRest()) {
return $this->RestResponse->saveFailResponse('EventBlocklist', 'Deleted', false, $error, $this->response->type());
} else {
$this->Flash->error($error);
$this->redirect(array('controller' => 'eventBlocklists', 'action' => 'index'));
}
}
} else {
$ids = json_decode($this->request->query('ids'), true);
if (empty($ids)) {
throw new NotFoundException(__('Invalid event blocklist IDs.'));
}
$this->set('event_ids', $ids);
}
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Model\Entity;
use App\Model\Entity\AppModel;
class EventBlocklist extends AppModel
{
protected $_accessible = [
'*' => true,
'id' => false
];
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Model\Table;
use App\Model\Table\AppTable;
use Cake\Validation\Validator;
use Cake\ORM\RulesChecker;
use Cake\Event\EventInterface;
use Cake\Datasource\EntityInterface;
use ArrayObject;
class EventBlocklistsTable extends AppTable
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->addBehavior('AuditLog');
}
public $blocklistFields = array('event_uuid', 'comment', 'event_info', 'event_orgc');
public $blocklistTarget = 'event';
public function validationDefault(Validator $validator): Validator
{
$validator
->requirePresence('event_uuid')
->notEmptyString('event_uuid')
->uuid('event_uuid');
return $validator;
}
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->isUnique(['event_uuid']));
return $rules;
}
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
if (empty($data['id'])) {
$entity->created = date('Y-m-d H:i:s');
}
if (empty($data['comment'])) {
$entity->comment = '';
}
return true;
}
/**
* @param array $eventArray
*/
public function removeBlockedEvents(array &$eventArray)
{
// When event array contains a lot events, it is more efficient to fetch all blocked events
$conditions = (count($eventArray) > 10000) ? [] : ['EventBlocklist.event_uuid' => array_column($eventArray, 'uuid')];
$blocklistHits = $this->find('column', [
'conditions' => $conditions,
'fields' => ['EventBlocklist.event_uuid'],
]);
if (empty($blocklistHits)) {
return;
}
$blocklistHits = array_flip($blocklistHits);
foreach ($eventArray as $k => $event) {
if (isset($blocklistHits[$event['uuid']])) {
unset($eventArray[$k]);
}
}
}
/**
* @param string $eventUuid
* @return bool
*/
public function isBlocked($eventUuid)
{
return $this->hasAny(['event_uuid' => $eventUuid]);
}
}

View File

@ -0,0 +1,49 @@
<?php
// if ($isSiteAdmin) {
// echo $this->element('/genericElements/SideMenu/side_menu', ['menuList' => 'admin', 'menuItem' => 'eventBlocklistsAdd']);
// } else {
// echo $this->element('/genericElements/SideMenu/side_menu', ['menuList' => 'event-collection', 'menuItem' => 'eventBlocklistsAdd']);
// }
echo $this->element('genericElements/Form/genericForm', [
'data' => [
'title' => __('Add Event Blocklist Entries'),
'description' => __('Simply paste a list of all the event UUIDs that you wish to block from being entered.'),
'fields' => [
[
'field' => 'uuids',
'label' => __('UUIDs'),
'div' => 'input clear',
'class' => 'input-xxlarge',
'type' => 'textarea',
'placeholder' => __('Enter a single or a list of UUIDs'),
],
[
'field' => 'event_orgc',
'label' => __('Creating organisation'),
'class' => 'input-xxlarge',
'placeholder' => __('(Optional) The organisation that the event is associated with')
],
[
'field' => 'event_info',
'label' => __('Event info'),
'type' => 'textarea',
'div' => 'input clear',
'class' => 'input-xxlarge',
'placeholder' => __('(Optional) the event info of the event that you would like to block. It\'s best to leave this empty if you are adding a list of UUIDs.')
],
[
'field' => 'comment',
'label' => __('Comment'),
'type' => 'textarea',
'div' => 'input clear',
'class' => 'input-xxlarge',
'placeholder' => __('(Optional) Any comments you would like to add regarding this (or these) entries.')
],
],
'submit' => [
'action' => $this->request->getParam('action'),
'ajaxSubmit' => 'submitGenericFormInPlace();'
]
]
]);

View File

@ -0,0 +1,96 @@
<?php
if ($isSiteAdmin) {
$this->set('menuData', ['menuList' => 'admin', 'menuItem' => 'eventBlocklists']);
} else {
$this->set('menuData', ['menuList' => 'event-collection', 'menuItem' => 'eventBlocklists']);
}
echo $this->element('genericElements/IndexTable/index_table', [
'data' => [
'data' => $data,
'top_bar' => [
'pull' => 'right',
'children' => [
[
'children' => [
[
'class' => 'hidden mass-select',
'fa-icon' => 'trash',
'onClick' => "multiSelectDeleteEventBlocklist",
'onClickParams' => ['1', '0']
]
]
],
[
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'searchKey' => 'searchall',
]
]
],
'fields' => [
[
'element' => 'selector',
'class' => 'short',
'data' => [
'id' => [
'value_path' => 'id'
]
]
],
[
'name' => 'Id',
'sort' => 'id',
'data_path' => 'id'
],
[
'name' => 'Organisation name',
'sort' => 'org_name',
'data_path' => 'event_orgc'
],
[
'name' => 'UUID',
'sort' => 'event_uuid',
'data_path' => 'event_uuid'
],
[
'name' => 'Created',
'sort' => 'created',
'data_path' => 'created',
'element' => 'datetime'
],
[
'name' => 'Event Info',
'sort' => 'event_info',
'data_path' => 'event_info',
'class' => 'bitwider'
],
[
'name' => 'Comment',
'sort' => 'comment',
'data_path' => 'comment',
'class' => 'bitwider'
],
],
'title' => empty($ajax) ? __('Event Blocklists') : false,
'pull' => 'right',
'actions' => [
[
'url' => $baseurl . '/event_blocklists/edit',
'url_params_data_paths' => [
'id'
],
'icon' => 'edit',
'title' => 'Edit Blocklist',
],
[
'url' => $baseurl . '/event_blocklists/delete',
'url_params_data_paths' => [
'id'
],
'icon' => 'trash',
'title' => 'Delete Blocklist',
]
]
]
]);

View File

@ -12,7 +12,7 @@ class AuthKeysFixture extends TestFixture
public $connection = 'test';
public const ADMIN_API_ID = 1;
public const ADMIN_API_KEY = 'd033e22ae348aeb5660fc2140aec35850c4da997';
public const ADMIN_API_KEY = 'sL9hrjIyY405RyGQHLx5DoCAM92BNmmGa8P4ck1E';
public const SYNC_API_ID = 2;