Skip to content

Commit a7cab0a

Browse files
add post policy and change updated_at when post update
1 parent 0aa658b commit a7cab0a

File tree

4 files changed

+90
-11
lines changed

4 files changed

+90
-11
lines changed

app/Http/Controllers/Api/PostController.php

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace App\Http\Controllers\Api;
44

55
use App\Actions\UploadPostImage;
6-
use App\Enums\PostStatus;
76
use App\Filters\Posts\SearchFilter;
87
use App\Filters\Posts\StatusFilter;
98
use App\Filters\Posts\TrashFilter;
@@ -15,16 +14,20 @@
1514
use Illuminate\Http\JsonResponse;
1615
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
1716
use Illuminate\Pipeline\Pipeline;
18-
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
17+
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
1918

2019
class PostController extends Controller
2120
{
21+
use AuthorizesRequests;
22+
2223
public function __construct(
2324
private readonly UploadPostImage $uploadPostImage
2425
) {}
2526

2627
public function index(): AnonymousResourceCollection
2728
{
29+
$this->authorize('viewAny', Post::class);
30+
2831
$posts = Post::query()->with(['author', 'category']);
2932

3033
$posts = app(Pipeline::class)
@@ -43,6 +46,8 @@ public function index(): AnonymousResourceCollection
4346

4447
public function store(StorePostRequest $request): PostResource
4548
{
49+
$this->authorize('create', Post::class);
50+
4651
$data = $request->validated();
4752
$post = auth()->user()->posts()->create($data);
4853

@@ -53,44 +58,45 @@ public function store(StorePostRequest $request): PostResource
5358

5459
public function show(Post $post): PostResource
5560
{
56-
// Only published posts are visible to public, drafts visible to authors
57-
if ($post->status !== PostStatus::PUBLISHED && !auth()->user()?->isAdmin()) {
58-
throw new NotFoundHttpException('Post not found');
59-
}
61+
$this->authorize('view', $post);
6062

6163
return new PostResource($post->load(['author', 'category']));
6264
}
6365

6466
public function update(UpdatePostRequest $request, Post $post): PostResource
6567
{
66-
$post->update($request->validated());
68+
$this->authorize('update', $post);
6769

70+
$post->update($request->validated());
6871
$this->uploadPostImage->execute($post, $request->file('cover_image'));
6972

7073
return new PostResource($post->load(['author', 'category']));
7174
}
7275

7376
public function destroy(Post $post): JsonResponse
7477
{
75-
$post->delete();
78+
$this->authorize('delete', $post);
7679

80+
$post->delete();
7781
return response()->json(['message' => 'Post deleted successfully'], 200);
7882
}
7983

8084
public function restore($id): JsonResponse
8185
{
8286
$post = Post::withTrashed()->findOrFail($id);
83-
$post->restore();
87+
$this->authorize('restore', $post);
8488

89+
$post->restore();
8590
return response()->json(['message' => 'Post restored successfully']);
8691
}
8792

8893
public function forceDelete($id): JsonResponse
8994
{
9095
$post = Post::withTrashed()->findOrFail($id);
96+
$this->authorize('forceDelete', $post);
97+
9198
$post->clearMediaCollection('images');
9299
$post->forceDelete();
93-
94100
return response()->json(['message' => 'Post permanently deleted']);
95101
}
96102
}

app/Models/Post.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class Post extends Model implements HasMedia
2727
'is_featured',
2828
'author_id',
2929
'category_id',
30+
'created_at',
31+
'updated_at',
3032
];
3133

3234
protected function casts(): array

app/Observers/PostObserver.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ public function created(Post $post): void
2020
*/
2121
public function updated(Post $post): void
2222
{
23-
//
23+
$post->updated_at = now();
24+
$post->save();
2425
}
2526

2627
/**

app/Policies/PostPolicy.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace App\Policies;
4+
5+
use App\Models\Post;
6+
use App\Models\User;
7+
use App\Enums\PostStatus;
8+
9+
class PostPolicy
10+
{
11+
/**
12+
* Determine whether the user can view any models.
13+
*/
14+
public function viewAny(?User $user): bool
15+
{
16+
return true;
17+
}
18+
19+
/**
20+
* Determine whether the user can view the model.
21+
*/
22+
public function view(?User $user, Post $post): bool
23+
{
24+
if ($post->status === PostStatus::PUBLISHED) {
25+
return true;
26+
}
27+
28+
return $user && ($user->isAdmin() || $user->id === $post->author_id);
29+
}
30+
31+
/**
32+
* Determine whether the user can create models.
33+
*/
34+
public function create(User $user): bool
35+
{
36+
return $user->isAdmin();
37+
}
38+
39+
/**
40+
* Determine whether the user can update the model.
41+
*/
42+
public function update(User $user, Post $post): bool
43+
{
44+
return $user->isAdmin();
45+
}
46+
47+
/**
48+
* Determine whether the user can delete the model.
49+
*/
50+
public function delete(User $user, Post $post): bool
51+
{
52+
return $user->isAdmin();
53+
}
54+
55+
/**
56+
* Determine whether the user can restore the model.
57+
*/
58+
public function restore(User $user, Post $post): bool
59+
{
60+
return $user->isAdmin();
61+
}
62+
63+
/**
64+
* Determine whether the user can force delete the model.
65+
*/
66+
public function forceDelete(User $user, Post $post): bool
67+
{
68+
return $user->isAdmin();
69+
}
70+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy