Rework the webhooks table, allow to update exists webhooks

This commit is contained in:
ErickSkrauch
2020-06-14 01:20:31 +03:00
parent 17f1794a4e
commit fb452901b8
10 changed files with 131 additions and 104 deletions

View File

@@ -7,15 +7,46 @@ use common\models\WebHook;
use console\models\WebHookForm;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\helpers\Console;
use yii\console\widgets\Table;
use yii\helpers\Console as C;
class WebhooksController extends Controller {
public function actionCreate(): int {
$form = new WebHookForm(new WebHook());
public $defaultAction = 'list';
$url = Console::prompt('Enter webhook url:', [
public function actionList(): void {
$rows = [];
/** @var WebHook $webHook */
foreach (WebHook::find()->with('events')->all() as $webHook) {
$rows[] = [$webHook->id, $webHook->url, $webHook->secret, implode(', ', $webHook->events)];
}
echo (new Table([
'headers' => ['id', 'url', 'secret', 'events'],
'rows' => $rows,
]))->run();
}
public function actionCreate(): int {
return $this->runForm(new WebHookForm(new WebHook()));
}
public function actionUpdate(int $id): int {
/** @var WebHook|null $webHook */
$webHook = WebHook::findOne(['id' => $id]);
if ($webHook === null) {
C::error("Entity with id {$id} isn't found.");
return ExitCode::DATAERR;
}
return $this->runForm(new WebHookForm($webHook));
}
private function runForm(WebHookForm $form): int {
C::prompt(C::ansiFormat('Enter webhook url:', [C::FG_GREY]), [
'required' => true,
'default' => $form->url,
'validator' => function(string $input, ?string &$error) use ($form): bool {
$form->url = $input;
if (!$form->validate('url')) {
@@ -26,34 +57,48 @@ class WebhooksController extends Controller {
return true;
},
]);
$secret = Console::prompt('Enter webhook secret (empty to no secret):');
$options = $form::getEvents();
$options[''] = 'Finish input'; // It's needed to allow finish input cycle
$events = [];
do {
$availableOptions = array_diff($options, $events);
$eventIndex = Console::select('Choose wanted events (submit no input to finish):', $availableOptions);
if ($eventIndex !== '') {
$events[] = $options[$eventIndex];
}
} while ($eventIndex !== '' || empty($events));
$form->url = $url;
$form->events = $events;
$secret = C::prompt(C::ansiFormat('Enter webhook secret (empty to no secret):', [C::FG_GREY]), [
'default' => $form->secret,
]);
if ($secret !== '') {
$form->secret = $secret;
}
$allEvents = WebHookForm::getEvents();
do {
$options = [];
foreach ($allEvents as $id => $option) {
if (in_array($option, $form->events, true)) {
$options["-{$id}"] = $option; // Cast to string to create "-0" index
} else {
$options[$id] = $option;
}
}
$options[''] = 'Finish input'; // This needed to allow finish input cycle
$eventIndex = C::select(
C::ansiFormat('Choose wanted events (submit no input to finish):', [C::FG_GREY]),
$options,
);
if ($eventIndex === '') {
continue;
}
if ($eventIndex[0] === '-') {
unset($form->events[array_search($options[$eventIndex], $form->events, true)]);
} else {
$form->events[] = $options[$eventIndex];
}
} while ($eventIndex !== '' || empty($form->events));
if (!$form->save()) {
Console::error('Unable to create new webhook. Check errors list below' . PHP_EOL . Console::errorSummary($form));
C::error('Unable to create new webhook. Check errors list below' . PHP_EOL . C::errorSummary($form));
return ExitCode::UNSPECIFIED_ERROR;
}
return ExitCode::OK;
}
// TODO: add action to modify the webhook events
}

View File

@@ -0,0 +1,51 @@
<?php
use console\db\Migration;
class m200613_204832_remove_webhooks_events_table extends Migration {
public function safeUp() {
$this->addColumn('webhooks', 'events', $this->json()->toString('events') . ' AFTER `secret`');
$webhooksIds = $this->db->createCommand('SELECT id FROM webhooks')->queryColumn();
foreach ($webhooksIds as $webhookId) {
$events = $this->db->createCommand("SELECT event_type FROM webhooks_events WHERE webhook_id = {$webhookId}")->queryColumn();
if (empty($events)) {
continue;
}
$this->execute('UPDATE webhooks SET events = JSON_ARRAY("' . implode('","', $events) . '")');
}
$this->dropTable('webhooks_events');
}
public function safeDown() {
$this->createTable('webhooks_events', [
'webhook_id' => $this->db->getTableSchema('webhooks')->getColumn('id')->dbType . ' NOT NULL',
'event_type' => $this->string()->notNull(),
$this->primary('webhook_id', 'event_type'),
]);
$this->addForeignKey('FK_webhook_event_to_webhook', 'webhooks_events', 'webhook_id', 'webhooks', 'id', 'CASCADE', 'CASCADE');
$webhooks = $this->db->createCommand('SELECT id, `events` FROM webhooks')->queryAll();
foreach ($webhooks as $webhook) {
if (empty($webhook['events'])) {
continue;
}
$events = json_decode($webhook['events'], true);
if (empty($events)) {
continue;
}
$this->batchInsert(
'webhooks_events',
['webhook_id', 'event_type'],
array_map(fn($event) => [$webhook['id'], $event], $events),
);
}
$this->dropColumn('webhooks', 'events');
}
}

View File

@@ -4,9 +4,7 @@ declare(strict_types=1);
namespace console\models;
use common\models\WebHook;
use common\models\WebHookEvent;
use Webmozart\Assert\Assert;
use Yii;
use yii\base\Model;
class WebHookForm extends Model {
@@ -22,6 +20,9 @@ class WebHookForm extends Model {
public function __construct(WebHook $webHook, array $config = []) {
parent::__construct($config);
$this->webHook = $webHook;
$this->url = $webHook->url;
$this->secret = $webHook->secret;
$this->events = (array)$webHook->events;
}
public function rules(): array {
@@ -38,22 +39,12 @@ class WebHookForm extends Model {
return false;
}
$transaction = Yii::$app->db->beginTransaction();
$webHook = $this->webHook;
$webHook->url = $this->url;
$webHook->secret = $this->secret;
$webHook->events = array_values($this->events); // Drop the keys order
Assert::true($webHook->save(), 'Cannot save webhook.');
foreach ($this->events as $event) {
$eventModel = new WebHookEvent();
$eventModel->webhook_id = $webHook->id;
$eventModel->event_type = $event;
Assert::true($eventModel->save(), 'Cannot save webhook event.');
}
$transaction->commit();
return true;
}