From b13d79edb2003cef8929467a72cac1f18832330b Mon Sep 17 00:00:00 2001 From: Lapotor <17144397+Lapotor@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:00:08 +0100 Subject: [PATCH] feat(permission): add endpoint for retrieving all and single permission (#109) This adds new endpoints to retrieve all permissions and a single permission. The implementation enhances the system's capability for managing permissions. --------- Signed-off-by: Valentin Sickert <17144397+Lapotor@users.noreply.github.com> Signed-off-by: Lapotor <17144397+Lapotor@users.noreply.github.com> --- .github/assets/swagger.yml | 125 ++++++++++++ app/Http/Controllers/PermissionController.php | 48 +++++ routes/api.php | 1 + routes/api/v1/permission.php | 9 + .../Controllers/PermissionControllerTest.php | 191 ++++++++++++++++++ 5 files changed, 374 insertions(+) create mode 100644 app/Http/Controllers/PermissionController.php create mode 100644 routes/api/v1/permission.php create mode 100644 tests/Feature/Http/Controllers/PermissionControllerTest.php diff --git a/.github/assets/swagger.yml b/.github/assets/swagger.yml index 0d448c32..24240ae4 100644 --- a/.github/assets/swagger.yml +++ b/.github/assets/swagger.yml @@ -657,6 +657,111 @@ paths: security: - BearerAuth: [] + /permissions: + get: + tags: + - Permission + summary: Retrieves all permissions + operationId: getPermissions + parameters: + - name: sort + in: query + schema: + type: string + enum: + - id + - id:asc + - id:desc + - name + - name:asc + - name:desc + default: id + - name: per_page + in: query + schema: + type: integer + default: 25 + maximum: 50 + - name: page + in: query + schema: + type: integer + default: 1 + minimum: 0 + responses: + "200": + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Permission" + "403": + description: + "Forbidden - The server understood the request, but is refusing\ + \ to fulfill it." + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: + "Internal Server Error - A generic error message, given when\ + \ an unexpected condition was encountered and no more specific message\ + \ is suitable." + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + security: + - BearerAuth: [] + + /permissions/{id}: + get: + tags: + - Permission + summary: Retrieves a permission + operationId: getPermission + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + "200": + description: Successful operation + content: + application/json: + schema: + $ref: "#/components/schemas/Permission" + "403": + description: + "Forbidden - The server understood the request, but is refusing\ + \ to fulfill it." + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "404": + description: Not Found - The server cannot find the requested resource. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: + "Internal Server Error - A generic error message, given when\ + \ an unexpected condition was encountered and no more specific message\ + \ is suitable." + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + security: + - BearerAuth: [] + /roles: get: tags: @@ -1187,6 +1292,25 @@ components: role: type: integer nullable: true + + Permission: + type: object + required: + - id + - name + - guard + - created_at + - updated_at + properties: + id: + type: integer + readOnly: true + name: + type: string + readOnly: true + guard: + type: string + readOnly: true created_at: type: string format: date-time @@ -1195,6 +1319,7 @@ components: type: string format: date-time readOnly: true + Role: required: - id diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/PermissionController.php new file mode 100644 index 00000000..b7d093e8 --- /dev/null +++ b/app/Http/Controllers/PermissionController.php @@ -0,0 +1,48 @@ +validate([ + 'sort' => 'string|in:id,id:asc,id:desc,name,name:asc,name:desc', + 'per_page' => 'integer|between:1,50', + ]); + + $perms = Permission::paginate($request->per_page ?? 25); + + if ($request->sort) { + // Sort can be a string like 'id' or 'name:desc' + $sort = explode(':', $request->sort); + $perms = Permission::orderBy($sort[0], $sort[1] ?? 'asc')->paginate($request->per_page ?? 25); + } else { + $perms = Permission::orderBy('id')->paginate($request->per_page ?? 25); + } + + return $perms; + } + + /** + * Display the specified resource. + * + * @param \Spatie\Permission\Models\Permission $permission The permission to be displayed + * @return \App\Http\Responses\ApiSuccessResponse The success response containing the permission + */ + public function show(Permission $permission): ApiSuccessResponse + { + return new ApiSuccessResponse($permission); + } +} diff --git a/routes/api.php b/routes/api.php index 4de97518..2ea2bda2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -24,4 +24,5 @@ require __DIR__ . '/api/v1/auth.php'; require __DIR__ . '/api/v1/user.php'; require __DIR__ . '/api/v1/role.php'; + require __DIR__ . '/api/v1/permission.php'; }); diff --git a/routes/api/v1/permission.php b/routes/api/v1/permission.php new file mode 100644 index 00000000..ca9e4b44 --- /dev/null +++ b/routes/api/v1/permission.php @@ -0,0 +1,9 @@ + 'auth:sanctum'], function () { + Route::get('/permissions', [PermissionController::class, 'index'])->name('api.v1.permissions.index'); + Route::get('/permissions/{permission}', [PermissionController::class, 'show'])->name('api.v1.permissions.show'); +}); diff --git a/tests/Feature/Http/Controllers/PermissionControllerTest.php b/tests/Feature/Http/Controllers/PermissionControllerTest.php new file mode 100644 index 00000000..998909db --- /dev/null +++ b/tests/Feature/Http/Controllers/PermissionControllerTest.php @@ -0,0 +1,191 @@ +create(), + ); + + $response = $this->getJson('/api/v1/permissions'); + + $response->assertStatus(200); + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'guard_name', + 'created_at', + 'updated_at', + ], + ], + 'links' => [ + '*' => [ + 'url', + 'label', + 'active', + ], + ], + 'first_page_url', + 'from', + 'last_page', + 'last_page_url', + 'next_page_url', + 'path', + 'per_page', + 'prev_page_url', + 'to', + 'total' + ]); + } + + public function test_get_paginate_permissions_with_sort(): void + { + Sanctum::actingAs( + User::factory()->create(), + ); + + $response = $this->getJson('/api/v1/permissions?sort=id:desc'); + + $response->assertStatus(200); + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'guard_name', + 'created_at', + 'updated_at', + ], + ], + 'links' => [ + '*' => [ + 'url', + 'label', + 'active', + ], + ], + 'first_page_url', + 'from', + 'last_page', + 'last_page_url', + 'next_page_url', + 'path', + 'per_page', + 'prev_page_url', + 'to', + 'total' + ]); + } + + public function test_get_paginate_permissions_with_per_page(): void + { + Sanctum::actingAs( + User::factory()->create(), + ); + + $response = $this->getJson('/api/v1/permissions?per_page=5'); + + $response->assertStatus(200); + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'guard_name', + 'created_at', + 'updated_at', + ], + ], + 'links' => [ + '*' => [ + 'url', + 'label', + 'active', + ], + ], + 'first_page_url', + 'from', + 'last_page', + 'last_page_url', + 'next_page_url', + 'path', + 'per_page', + 'prev_page_url', + 'to', + 'total' + ]); + } + + public function test_get_paginate_permissions_with_sort_and_per_page(): void + { + Sanctum::actingAs( + User::factory()->create(), + ); + + $response = $this->getJson('/api/v1/permissions?sort=id:desc&per_page=5'); + + $response->assertStatus(200); + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'guard_name', + 'created_at', + 'updated_at', + ], + ], + 'links' => [ + '*' => [ + 'url', + 'label', + 'active', + ], + ], + 'first_page_url', + 'from', + 'last_page', + 'last_page_url', + 'next_page_url', + 'path', + 'per_page', + 'prev_page_url', + 'to', + 'total' + ]); + } + + public function test_get_single_permission(): void + { + Sanctum::actingAs( + User::factory()->create(), + ); + + $response = $this->getJson('/api/v1/permissions/1'); + + $response->assertStatus(200); + $response->assertJsonStructure([ + 'data' => [ + 'id', + 'name', + 'guard_name', + 'created_at', + 'updated_at', + ], + 'status', + 'timestamp' + ]); + } +}