Retry webhooks

This commit is contained in:
David Bomba 2023-03-17 18:27:26 +11:00
parent 200bcd80b7
commit ab2362e874
7 changed files with 110 additions and 12 deletions

View File

@ -913,7 +913,6 @@ class BaseController extends Controller
* List response
*
* @param mixed $query
* @return void
*/
protected function listResponse($query)
{
@ -1010,7 +1009,6 @@ class BaseController extends Controller
* Item Response
*
* @param mixed $item
* @return void
*/
protected function itemResponse($item)
{

View File

@ -12,19 +12,22 @@
namespace App\Http\Controllers;
use App\Models\Webhook;
use Illuminate\Support\Str;
use Illuminate\Http\Response;
use App\Factory\WebhookFactory;
use App\Filters\WebhookFilters;
use App\Http\Requests\Webhook\CreateWebhookRequest;
use App\Http\Requests\Webhook\DestroyWebhookRequest;
use App\Http\Requests\Webhook\EditWebhookRequest;
use App\Http\Requests\Webhook\ShowWebhookRequest;
use App\Http\Requests\Webhook\StoreWebhookRequest;
use App\Http\Requests\Webhook\UpdateWebhookRequest;
use App\Models\Webhook;
use App\Utils\Traits\MakesHash;
use App\Jobs\Util\WebhookSingle;
use App\Repositories\BaseRepository;
use App\Transformers\WebhookTransformer;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
use App\Http\Requests\Webhook\EditWebhookRequest;
use App\Http\Requests\Webhook\ShowWebhookRequest;
use App\Http\Requests\Webhook\RetryWebhookRequest;
use App\Http\Requests\Webhook\StoreWebhookRequest;
use App\Http\Requests\Webhook\CreateWebhookRequest;
use App\Http\Requests\Webhook\UpdateWebhookRequest;
use App\Http\Requests\Webhook\DestroyWebhookRequest;
class WebhookController extends BaseController
{
@ -487,4 +490,28 @@ class WebhookController extends BaseController
return $this->listResponse(Webhook::withTrashed()->whereIn('id', $this->transformKeys($ids)));
}
public function retry(RetryWebhookRequest $request, Webhook $webhook)
{
match($request->entity) {
'invoice' => $includes ='client',
'payment' => $includes ='invoices,client',
'project' => $includes ='client',
'purchase_order' => $includes ='vendor',
'quote' => $includes ='client',
default => $includes = ''
};
$class = 'App\Models\\'.ucfirst(Str::camel($request->entity));
$entity = $class::withTrashed()->where('id', $this->decodePrimaryKey($request->entity_id))->company()->first();
if(!$entity){
return response()->json(['message' => ctrans('texts.record_not_found')], 400);
}
WebhookSingle::dispatchSync($webhook->id, $entity, auth()->user()->company()->db, $includes);
return $this->itemResponse($webhook);
}
}

View File

@ -0,0 +1,35 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Requests\Webhook;
use App\Http\Requests\Request;
class RetryWebhookRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize(): bool
{
return auth()->user()->isAdmin();
}
public function rules()
{
return [
'entity' => 'required|bail|in:client,credit,invoice,product,task,payment,quote,purchase_order,expense,project,vendor',
'entity_id' => 'required|bail|string',
];
}
}

View File

@ -104,8 +104,10 @@ class WebhookSingle implements ShouldQueue
$resource = new Item($this->entity, $transformer, $this->entity->getEntityType());
$data = $manager->createData($resource)->toArray();
$headers = is_array($subscription->headers) ? $subscription->headers : [];
$this->postData($subscription, $data, $subscription->headers);
$this->postData($subscription, $data, $headers);
}
private function postData($subscription, $data, $headers = [])

View File

@ -5026,6 +5026,7 @@ $LANG = array(
'pre_payment_indefinitely' => 'Continue until cancelled',
'notification_payment_emailed' => 'Payment :payment was emailed to :client',
'notification_payment_emailed_subject' => 'Payment :payment was emailed',
'record_not_found' => 'Record not found',
);

View File

@ -336,6 +336,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
Route::resource('webhooks', WebhookController::class);
Route::post('webhooks/bulk', [WebhookController::class, 'bulk'])->name('webhooks.bulk');
Route::post('webhooks/{webhook}/retry', [WebhookController::class, 'retry'])->name('webhooks.retry');
/*Subscription and Webhook routes */
// Route::post('hooks', [SubscriptionController::class, 'subscribe'])->name('hooks.subscribe');

View File

@ -11,6 +11,7 @@
namespace Tests\Feature;
use App\Jobs\Util\WebhookSingle;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
@ -45,6 +46,39 @@ class WebhookAPITest extends TestCase
$this->withoutExceptionHandling();
}
public function testWebhookRetry()
{
$data = [
'target_url' => 'http://hook.com',
'event_id' => 1, //create client
'format' => 'JSON',
'headers' => []
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson("/api/v1/webhooks", $data);
$response->assertStatus(200);
$arr = $response->json();
$data = [
'entity' => 'client',
'entity_id' => $this->client->hashed_id,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson("/api/v1/webhooks/".$arr['data']['id']."/retry", $data);
$response->assertStatus(200);
}
public function testWebhookGetFilter()
{
$response = $this->withHeaders([