diff --git a/app/Models/DocumentTemplate.php b/app/Models/DocumentTemplate.php index c7024c0..e9c66ed 100644 --- a/app/Models/DocumentTemplate.php +++ b/app/Models/DocumentTemplate.php @@ -48,4 +48,11 @@ public function getTemplatingMode(): TemplatingMode return TemplatingMode::from($rawMode); } + + public static function getByUuidOrKey(string $value): DocumentTemplate + { + return DocumentTemplate::where(function ($q) use ($value) { + $q->orWhere('uuid', $value)->orWhere('key', $value); + })->firstOrFail(); + } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 7edd912..c8cc8f5 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -44,14 +44,15 @@ public function boot(): void protected function configureRateLimiting(): void { RateLimiter::for('api', function (Request $request) { - return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); + return Limit::perMinute(600)->by($request->user()?->id ?: $request->ip()); }); } private function registerModelBindings(): void { Route::model('documentFile', DocumentFile::class); - Route::model('documentTemplate', DocumentTemplate::class); Route::model('font', Font::class); + + Route::bind('documentTemplateUuidKey', DocumentTemplate::getByUuidOrKey(...)); } } diff --git a/routes/api.php b/routes/api.php index 01d58d4..67ad2c7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,22 +18,28 @@ Route::get('access', [AuthController::class, 'access']); Route::resource('document-templates', DocumentTemplateController::class) - ->parameter('document-template', 'documentTemplate') + ->parameter('document-templates', 'documentTemplateUuidKey') ->except([ 'create', 'edit', ]); Route::post( - 'document-templates/{documentTemplate}/preview-html', + 'document-templates/{documentTemplateUuidKey}/preview-html', [DocumentTemplateController::class, 'previewHtml'] ); Route::post( - 'document-templates/{documentTemplate}/duplicate', + 'document-templates/{documentTemplateUuidKey}/duplicate', [DocumentTemplateController::class, 'duplicate'] ); - Route::post('document-templates/{documentTemplate}/pdfs', [PdfRenderController::class, 'render']); - Route::post('document-templates/{documentTemplate}/pdfs-async', [PdfRenderController::class, 'renderAsync']); + Route::post( + 'document-templates/{documentTemplateUuidKey}/pdfs', + [PdfRenderController::class, 'render'] + ); + Route::post( + 'document-templates/{documentTemplateUuidKey}/pdfs-async', + [PdfRenderController::class, 'renderAsync'] + ); Route::get('document-files', [DocumentFileController::class, 'index']); Route::get('document-files/{documentFile}', [DocumentFileController::class, 'show']); diff --git a/tests/Feature/DocumentTemplateControllerTest.php b/tests/Feature/DocumentTemplateControllerTest.php index 705b8a6..763ffff 100644 --- a/tests/Feature/DocumentTemplateControllerTest.php +++ b/tests/Feature/DocumentTemplateControllerTest.php @@ -72,6 +72,23 @@ public function testShowReturnsASingleTemplate() ]); } + public function testShowReturnsASingleTemplateUseKey() + { + $template = DocumentTemplate::factory()->create([ + 'key' => 'seth-tran-key', + ]); + + $this->json('GET', 'api/v1/document-templates/seth-tran-key') + ->assertOk() + ->assertJsonFragment([ + 'uuid' => $template->uuid, + 'key' => $template->key, + 'category' => $template->category, + 'title' => $template->title, + 'template' => $template->template, + ]); + } + public function testStoreCreateNewTemplate() { Event::fake([ @@ -136,6 +153,45 @@ public function testUpdateUpdatesASingleTemplate() ); } + public function testUpdateUpdatesASingleTemplateUseKey() + { + Event::fake([ + DocumentTemplateUpdated::class, + ]); + + $template = DocumentTemplate::factory()->create(); + + $this->json('PUT', 'api/v1/document-templates/' . $template->key, [ + 'category' => 'Hihi', + 'title' => 'Funny template', + 'template' => '

Hello {{ $name }}

', + 'default_variables' => [ + 'name' => 'DocKing', + ], + 'metadata' => [ + 'driver' => 'gotenberg', + ], + ]) + ->assertOk() + ->assertJsonFragment([ + 'uuid' => $template->uuid, + ]); + + $this->assertDatabaseHas('document_templates', [ + 'uuid' => $template->uuid, + 'category' => 'Hihi', + 'title' => 'Funny template', + 'template' => '

Hello {{ $name }}

', + 'default_variables->name' => 'DocKing', + 'metadata->driver' => 'gotenberg', + ]); + + Event::assertDispatched( + DocumentTemplateUpdated::class, + fn (DocumentTemplateUpdated $event) => $event->template->is($template) + ); + } + public function testDestroySoftDeletesTheTemplate() { Event::fake([