protected function dispatchWebhooks(string $type, $detail): void
{
$webhooks = Webhook::query()
- ->whereHas('trackedEvents', function(Builder $query) use ($type) {
+ ->whereHas('trackedEvents', function (Builder $query) use ($type) {
$query->where('event', '=', $type)
->orWhere('event', '=', 'all');
})
return $newActivity;
}
-
-}
\ No newline at end of file
+}
class DispatchWebhookJob implements ShouldQueue
{
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+ use Dispatchable;
+ use InteractsWithQueue;
+ use Queueable;
+ use SerializesModels;
/**
* @var Webhook
$textParts[] = '"' . $this->detail->name . '"';
}
- $data = [
- 'event' => $this->event,
- 'text' => implode(' ', $textParts),
- 'triggered_at' => Carbon::createFromTimestampUTC($this->initiatedTime)->toISOString(),
- 'triggered_by' => $this->initiator->attributesToArray(),
+ $data = [
+ 'event' => $this->event,
+ 'text' => implode(' ', $textParts),
+ 'triggered_at' => Carbon::createFromTimestampUTC($this->initiatedTime)->toISOString(),
+ 'triggered_by' => $this->initiator->attributesToArray(),
'triggered_by_profile_url' => $this->initiator->getProfileUrl(),
- 'webhook_id' => $this->webhook->id,
- 'webhook_name' => $this->webhook->name,
+ 'webhook_id' => $this->webhook->id,
+ 'webhook_name' => $this->webhook->name,
];
if (method_exists($this->detail, 'getUrl')) {
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
- * @property int $id
- * @property string $name
- * @property string $endpoint
+ * @property int $id
+ * @property string $name
+ * @property string $endpoint
* @property Collection $trackedEvents
- * @property bool $active
+ * @property bool $active
*/
class Webhook extends Model implements Loggable
{
use Illuminate\Database\Eloquent\Model;
/**
- * @property int $id
- * @property int $webhook_id
+ * @property int $id
+ * @property int $webhook_id
* @property string $event
*/
class WebhookTrackedEvent extends Model
namespace BookStack\Http\Controllers;
-use Activity;
use BookStack\Actions\ActivityQueries;
use BookStack\Actions\View;
use BookStack\Entities\Models\Book;
->orderBy('name', 'desc')
->with('trackedEvents')
->get();
+
return view('settings.webhooks.index', ['webhooks' => $webhooks]);
}
public function store(Request $request)
{
$validated = $this->validate($request, [
- 'name' => ['required', 'max:150'],
+ 'name' => ['required', 'max:150'],
'endpoint' => ['required', 'url', 'max:500'],
- 'events' => ['required', 'array'],
- 'active' => ['required'],
+ 'events' => ['required', 'array'],
+ 'active' => ['required'],
]);
$webhook = new Webhook($validated);
$webhook->updateTrackedEvents(array_values($validated['events']));
$this->logActivity(ActivityType::WEBHOOK_CREATE, $webhook);
+
return redirect('/settings/webhooks');
}
public function update(Request $request, string $id)
{
$validated = $this->validate($request, [
- 'name' => ['required', 'max:150'],
+ 'name' => ['required', 'max:150'],
'endpoint' => ['required', 'url', 'max:500'],
- 'events' => ['required', 'array'],
- 'active' => ['required'],
+ 'events' => ['required', 'array'],
+ 'active' => ['required'],
]);
/** @var Webhook $webhook */
$webhook->updateTrackedEvents($validated['events']);
$this->logActivity(ActivityType::WEBHOOK_UPDATE, $webhook);
+
return redirect('/settings/webhooks');
}
{
/** @var Webhook $webhook */
$webhook = Webhook::query()->findOrFail($id);
+
return view('settings.webhooks.delete', ['webhook' => $webhook]);
}
$webhook->delete();
$this->logActivity(ActivityType::WEBHOOK_DELETE, $webhook);
+
return redirect('/settings/webhooks');
}
}
class WebhookFactory extends Factory
{
-
protected $model = Webhook::class;
/**
public function definition()
{
return [
- 'name' => 'My webhook for ' . $this->faker->country(),
+ 'name' => 'My webhook for ' . $this->faker->country(),
'endpoint' => $this->faker->url,
- 'active' => true,
+ 'active' => true,
];
}
}
{
return [
'webhook_id' => Webhook::factory(),
- 'event' => ActivityType::all()[array_rand(ActivityType::all())],
+ 'event' => ActivityType::all()[array_rand(ActivityType::all())],
];
}
}
namespace Tests\Actions;
+use function app;
use BookStack\Actions\Activity;
use BookStack\Actions\ActivityLogger;
use BookStack\Actions\ActivityType;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Entities\Tools\TrashCan;
use Carbon\Carbon;
-use Tests\TestCase;
-use function app;
use function config;
+use Tests\TestCase;
class AuditLogTest extends TestCase
{
class WebhookCallTest extends TestCase
{
-
public function test_webhook_listening_to_all_called_on_event()
{
$this->newWebhook([], ['all']);
$this->runEvent(ActivityType::PAGE_UPDATE, $page, $editor);
- Http::assertSent(function(Request $request) use ($editor, $page, $webhook) {
+ Http::assertSent(function (Request $request) use ($editor, $page, $webhook) {
$reqData = $request->data();
+
return $request->isJson()
&& $reqData['event'] === 'page_update'
&& $reqData['text'] === ($editor->name . ' updated page "' . $page->name . '"')
});
}
-
protected function runEvent(string $event, $detail = '', ?User $user = null)
{
if (is_null($user)) {
return $webhook;
}
-
-}
\ No newline at end of file
+}
class WebhookManagementTest extends TestCase
{
-
public function test_index_view()
{
$webhook = $this->newWebhook([
- 'name' => 'My awesome webhook',
+ 'name' => 'My awesome webhook',
'endpoint' => 'https://example.com/donkey/webhook',
], ['all']);
public function test_store()
{
$resp = $this->asAdmin()->post('/settings/webhooks/create', [
- 'name' => 'My first webhook',
+ 'name' => 'My first webhook',
'endpoint' => 'https://example.com/webhook',
- 'events' => ['all'],
- 'active' => 'true'
+ 'events' => ['all'],
+ 'active' => 'true',
]);
$resp->assertRedirect('/settings/webhooks');
$resp->assertSee('Webhook successfully created');
$this->assertDatabaseHas('webhooks', [
- 'name' => 'My first webhook',
+ 'name' => 'My first webhook',
'endpoint' => 'https://example.com/webhook',
- 'active' => true,
+ 'active' => true,
]);
/** @var Webhook $webhook */
$webhook = Webhook::query()->where('name', '=', 'My first webhook')->first();
$this->assertDatabaseHas('webhook_tracked_events', [
'webhook_id' => $webhook->id,
- 'event' => 'all',
+ 'event' => 'all',
]);
}
$webhook = $this->newWebhook();
$resp = $this->asAdmin()->put('/settings/webhooks/' . $webhook->id, [
- 'name' => 'My updated webhook',
+ 'name' => 'My updated webhook',
'endpoint' => 'https://example.com/updated-webhook',
- 'events' => [ActivityType::PAGE_CREATE, ActivityType::PAGE_UPDATE],
- 'active' => 'true'
+ 'events' => [ActivityType::PAGE_CREATE, ActivityType::PAGE_UPDATE],
+ 'active' => 'true',
]);
$resp->assertRedirect('/settings/webhooks');
$resp->assertSee('Webhook successfully updated');
$this->assertDatabaseHas('webhooks', [
- 'id' => $webhook->id,
- 'name' => 'My updated webhook',
+ 'id' => $webhook->id,
+ 'name' => 'My updated webhook',
'endpoint' => 'https://example.com/updated-webhook',
- 'active' => true,
+ 'active' => true,
]);
$trackedEvents = $webhook->trackedEvents()->get();
return $webhook;
}
-
-}
\ No newline at end of file
+}
{
$this->newPage([
'name' => 'Test Page',
- 'html' => '<p>На мен ми трябва нещо добро test</p>'
+ 'html' => '<p>На мен ми трябва нещо добро test</p>',
]);
$search = $this->asEditor()->get('/search?term=' . urlencode('На мен ми трябва нещо добро'));