Skip to content

Commit

Permalink
Merge pull request #2 from dniccum/feature/logging
Browse files Browse the repository at this point in the history
Feature/logging
  • Loading branch information
dniccum authored Mar 4, 2022
2 parents 42bc901 + f2c4be2 commit c00f5fa
Show file tree
Hide file tree
Showing 29 changed files with 722 additions and 32 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package-lock.json
composer.phar
composer.lock
phpunit.xml
.phpunit.result.cache
.DS_Store
Thumbs.db
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ A Laravel Nova tool that allows users to create and manage webhooks based on Elo

A tool for Laravel's Nova administrator panel that enables users to create webhooks that can be customized to fire on specified Eloquent model events (created, updated, etc). This allows applications to communicate with other applications and integrations (Zapier, If This Then That, etc).

This tool also includes a useful logging feature that will log any successful/failed webhooks to help with metrics and debugging.

## Table of Contents

* [Installation](#installation)
Expand All @@ -26,6 +28,7 @@ A tool for Laravel's Nova administrator panel that enables users to create webho
* [Webhook Secret](#webhook-secret)
* [Authorization](#authorization)
* [Testing Action](#testing-action)
* [Logging](#logging)
* [Testing and Development](#testing-and-development)

## Installation
Expand Down Expand Up @@ -104,7 +107,42 @@ public function tools()

Two different configuration files are published with this package; one for this package (`nova-webhooks.php`) and one for the webhook server (`webhook-server.php`) that this package utilizes.

This package relies on [Spatie's webhook server package](https://github.com/spatie/laravel-webhook-server) to dispatch each webhook request. Feel free to configure the server to your needs using the associated documentation.
This package relies on [Spatie's webhook server package](https://github.com/spatie/laravel-webhook-server) to dispatch each webhook request. Feel free to configure the server to your needs using the associated documentation.

### Available Configuration Settings

Available configuration settings for this tool:

```php
return [

/**
* Whether webhooks should be sent
*/
'enabled' => env('NOVA_WEBHOOKS_ENABLED', true),

/**
* If logging should be enabled for each successful/failed request
*/
'logging' => [
'enabled' => env('NOVA_WEBHOOKS_LOGGING_ENABLED', true),
],

/**
* Enter the desired formatting for timestamps that are attached to logging.
* See the official PHP documentation for more information: https://www.php.net/manual/en/datetime.format.php
*/
'date_format' => 'Y-m-d @ G:i',

/**
* The Laravel Nova resource that manages your authenticated users.
*/
'users' => [
'resource' => App\Nova\User::class
]

];
```

## Implementing the Tool

Expand Down Expand Up @@ -270,6 +308,14 @@ Probably the most important part of any webhook is testing and validation that y

When you want execute a test, this package will pull a random entry in the selected model's table in your database and use it as the subject for your webhook. If you don't have any records available yet, the action will throw an error instructing you to add the necessary records before you proceed.

### Logging

Unless specifically configured (as seen above), this tool will log successful and failed webhook operations. Successful events are simply stored for analytics purposes and are then displayed with some simple accompanying charts.

![Resource Analytics](https://github.com/dniccum/nova-webhooks/blob/main/assets/resource-analytics.png?raw=true)

If the desired endpoint that your webhooks are pointed throws an error, this tool will capture the response and log it accordingly. You can then view the associated error message within the Webhook that was created.

## Testing and Development

To perform the necessary PHP Unit tests using the Orchestra Workbench, clone the repository, install the necessary dependencies with `composer install` and run the PHP Unit testing suite:
Expand Down
Binary file added assets/resource-analytics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
"require": {
"php": "^7.4|^8.0",
"bensampo/laravel-enum": "^4.2",
"coroowicaksono/chart-js-integration": "^0.3.5",
"owenmelbz/nova-radio-field": "^1.0",
"spatie/laravel-webhook-server": "^2.0",
"symfony/class-loader": "^3.4"
},
"require-dev": {
"orchestra/testbench": "^6.24",
"phpunit/phpunit": "^9.5"
},
"autoload": {
"psr-4": {
"Dniccum\\NovaWebhooks\\": "src/",
Expand All @@ -46,9 +51,5 @@
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true,
"require-dev": {
"orchestra/testbench": "^6.24",
"phpunit/phpunit": "^9.5"
}
"prefer-stable": true
}
14 changes: 14 additions & 0 deletions config/nova-webhooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@
*/
'enabled' => env('NOVA_WEBHOOKS_ENABLED', true),

/**
* If logging should be enabled for each successful/failed request
*/
'logging' => [

'enabled' => env('NOVA_WEBHOOKS_LOGGING_ENABLED', true),
],

/**
* Enter the desired formatting for timestamps that are attached to logging.
* See the official PHP documentation for more information: https://www.php.net/manual/en/datetime.format.php
*/
'date_format' => 'Y-m-d @ G:i',

/**
* The Laravel Nova resource that manages your authenticated users.
*/
Expand Down
57 changes: 57 additions & 0 deletions database/factories/WebhookLogFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Dniccum\NovaWebhooks\Database\Factories;

use Dniccum\NovaWebhooks\Models\WebhookLog;
use Illuminate\Database\Eloquent\Factories\Factory;

class WebhookLogFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = WebhookLog::class;

/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'successful' => true,
'created_at' => now(),
];
}

/**
* @return WebhookLogFactory|\Dniccum\NovaWebhooks\Database\Factories\WebhookLogFactory.state
*/
public function notFound()
{
return $this->state(function(array $attributes) {
return [
'successful' => false,
'error_code' => '404',
'error_message' => 'Page not found.'
];
});
}

/**
* @return WebhookLogFactory|\Dniccum\NovaWebhooks\Database\Factories\WebhookLogFactory.state
*/
public function failed()
{
return $this->state(function(array $attributes) {
return [
'successful' => false,
'error_code' => '422',
'error_message' => $this->faker->text,
];
});
}
}
33 changes: 33 additions & 0 deletions database/migrations/create_webhook_logs_table.php.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateWebhookLogsTable extends Migration
{
public function up()
{
Schema::create('webhook_logs', function (Blueprint $table) {
$table->id();
$table->boolean('successful')
->default(true);
$table->string('error_code')
->nullable();
$table->text('error_message')
->nullable();
$table->unsignedBigInteger('webhook_id')
->nullable();
$table->foreign('webhook_id')
->references('id')
->on('webhooks');
$table->timestamp('created_at')
->nullable();
});
}

public function down()
{
Schema::dropIfExists('webhook_logs');
}
}
2 changes: 0 additions & 2 deletions database/migrations/create_webhooks_table.php.stub
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?php

namespace Dniccum\NovaWebhooks\Database\Migrations;

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Expand Down
39 changes: 39 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
cacheResult="true"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="true"
stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Feature">
<directory suffix="Test.php">tests/Feature/</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_KEY" value="base64:mIRM5Fpb6DtuRIejBwkqpt3c/ovlFZsSpo66efwo3g0="/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="MAIL_DRIVER" value="array"/>
<env name="MAIL_MAILER" value="array"/>
<env name="NOVA_WEBHOOKS_LOGGING_ENABLED" value="true"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
5 changes: 5 additions & 0 deletions resources/lang/en/logging.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'not_found' => 'The requested endpoint could not be found.'
];
9 changes: 8 additions & 1 deletion resources/lang/en/nova.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@
return [
'available_actions' => 'Available Actions',
'available_actions_help' => 'The events and/or actions that this webhook will queue it\'s payload to the desired endpoint.' ,
'created_at' => 'Created At',
'error_code' => 'Error Code',
'error_message' => 'Error Message',
'failed_calls' => 'Failed Calls',
'last_modified_by' => 'Last Modified By',
'name' => 'Name',
'name_help' => 'Provide a helpful name/label for the webhook you are about to create; like the site and/or application that will consume it.',
'name_placeholder' => 'A helpful title',
'last_modified_by' => 'Last Modified By',
'no_actions_available' => 'You currently do not have any actions available. Please add the necessary traits to your application\'s models to select actions for this webhook.',
'no_models_available' => 'You do not have any records available to test the requested ":model" model. Please either select a different test or add a record.',
'resource_validation_error' => 'Please provide either a valid array or an instance of a JsonResource.',
'secret' => 'Secret',
'secret_help' => 'If necessary provide a secret that will be used to validate this hook. If not, one will be generated for you during creation.',
'select_hook_to_test' => 'Select a webhook to test',
'settings' => 'Settings',
'successful_calls' => 'Successful Calls',
'test' => 'Test',
'test_webhook' => 'Send a Test',
'url' => 'Url',
'url_help' => 'The url or "recipient" of the webhook when it is dispatched by this application.',
'webhook_failure_logs' => 'Webhook Failure Logs',
'webhook_to_test' => 'Webhook to test',
];
11 changes: 9 additions & 2 deletions src/Jobs/DispatchWebhook.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,26 @@ class DispatchWebhook implements ShouldQueue
*/
public $payload;

/**
* @var bool
*/
public bool $isTest = false;

/**
* Create a new job instance.
*
* @param Model $model
* @param string $action
* @param array $payload
* @param bool $isTest
* @return void
*/
public function __construct($model, string $action = ModelEvents::Created, array $payload = [])
public function __construct($model, string $action = ModelEvents::Created, array $payload = [], bool $isTest = false)
{
$this->model = $model;
$this->action = $action;
$this->payload = $payload;
$this->isTest = $isTest;
}

/**
Expand All @@ -55,7 +62,7 @@ public function __construct($model, string $action = ModelEvents::Created, array
*/
public function handle()
{
WebhookUtility::processWebhooks($this->model, $this->action, $this->payload);
WebhookUtility::processWebhooks($this->model, $this->action, $this->payload, $this->isTest);
}

/**
Expand Down
Loading

0 comments on commit c00f5fa

Please sign in to comment.