diff --git a/app/Console/Commands/ProcessScheduledPosts.php b/app/Console/Commands/ProcessScheduledPosts.php index acc3d7b3..37a4789e 100644 --- a/app/Console/Commands/ProcessScheduledPosts.php +++ b/app/Console/Commands/ProcessScheduledPosts.php @@ -4,6 +4,7 @@ namespace App\Console\Commands; +use App\Enums\Post\Status as PostStatus; use App\Jobs\PublishPost; use App\Models\Post; use Illuminate\Console\Command; @@ -18,9 +19,13 @@ public function handle(): void { Post::query() ->due() - ->with(['postPlatforms.socialAccount', 'postPlatforms.media']) - ->chunk(100, function ($posts) { - foreach ($posts as $post) { + ->each(function (Post $post) { + // Atomically claim the post — only dispatch if we successfully change its status + $claimed = Post::where('id', $post->id) + ->where('status', PostStatus::Scheduled) + ->update(['status' => PostStatus::Publishing]); + + if ($claimed) { PublishPost::dispatch($post); } }); diff --git a/app/Http/Controllers/App/MediaController.php b/app/Http/Controllers/App/MediaController.php index 7e587cd4..c0227873 100644 --- a/app/Http/Controllers/App/MediaController.php +++ b/app/Http/Controllers/App/MediaController.php @@ -9,6 +9,8 @@ use App\Models\Media; use App\Models\Post; use App\Models\PostPlatform; +use App\Models\User; +use App\Models\Workspace; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Http\JsonResponse; @@ -162,6 +164,16 @@ private function authorizeModelOwnership(Model $model, Request $request): void if ($model->workspace_id !== $workspace->id) { abort(403); } + } elseif ($model instanceof Workspace) { + if ($model->id !== $workspace->id) { + abort(403); + } + } elseif ($model instanceof User) { + if ($model->id !== $request->user()->id) { + abort(403); + } + } else { + abort(403); } } diff --git a/app/Models/SocialAccount.php b/app/Models/SocialAccount.php index 8e2a47f4..9a2ccfc9 100644 --- a/app/Models/SocialAccount.php +++ b/app/Models/SocialAccount.php @@ -136,6 +136,7 @@ public function markAsTokenExpired(string $errorMessage): void $this->update([ 'status' => Status::TokenExpired, 'error_message' => $errorMessage, + 'disconnected_at' => $this->disconnected_at ?? now(), ]); }