From 85ec9df2dd350a98bb573612d283c937c7972b03 Mon Sep 17 00:00:00 2001 From: mubbasher-ahmed Date: Wed, 6 Aug 2025 01:38:47 +0500 Subject: [PATCH 1/2] docs: updated todo list --- README.md | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 426377a..425cd9c 100644 --- a/README.md +++ b/README.md @@ -371,40 +371,58 @@ Based on the defined roles and permissions, the following admin and management A - **NextJS Client App** - Complete NextJS App to integrate all these APIs, it will be separate REPO once i complete the APIs -- **Admin APIs** - - User management: list, create, update, delete, ban, block, restore users - - Role management: assign roles, manage roles, manage permissions - - View user activity logs - - Approve/ban/restore users - - Manage site-wide settings and options +- **Role Management** + - Assign roles, manage roles, manage permissions + - Role CRUD operations + - Permission assignment and management + - User role assignment - **Article/Post Management** - - Approve, feature, pin, archive, restore, trash, and report posts (admin/editor) - - Edit/delete others' posts (admin/editor) + - Create, update, delete articles + - Pin, archive, restore, trash articles + - Like/dislike articles + - Article status management (draft, published, archived) - **Comment Management** - - Moderate, approve, edit, delete, and report comments (admin/editor) + - Create, update, delete comments + - Report comments + - User comment management - **Taxonomy Management** - Manage categories and tags (admin/editor) - -- **Newsletter Management** - - View/manage newsletter subscribers (admin/editor) - -- **Notification Management** - - View/manage/send notifications (admin/editor) + - Category CRUD operations + - Tag CRUD operations + - Hierarchical category management - **Media Management** - Upload, delete, and manage media (admin/editor) + - File upload system + - Media library management + - Image optimization and storage + +- **Newsletter Management** + - Newsletter subscription endpoints + - User notification management + - Email subscription handling - **Analytics & Settings** - View analytics dashboard (admin only) - Manage site settings (admin only) + - Site statistics and metrics + - User activity tracking + +- **Social/Community Features** + - User follow/unfollow system + - User profile management + - Social interaction features - **General** - Ensure all permission checks are enforced in controllers/routes - Add missing API endpoints for all permissions listed in `PermissionSeeder` and `RolePermissionSeeder` - - Add integration and feature tests for all admin/management APIs + - Add integration and feature tests for all remaining APIs + - Implement rate limiting for all public endpoints + - Optimize database queries and add proper indexing + - Implement caching strategies for better performance > _Review the permissions in `database/seeders/PermissionSeeder.php` and `RolePermissionSeeder.php` to ensure all are mapped to actual API endpoints and controller logic._ From e5a88445a0d394b0098140ce5a7edfbab9b008ed Mon Sep 17 00:00:00 2001 From: mubbasher-ahmed Date: Wed, 6 Aug 2025 02:11:59 +0500 Subject: [PATCH 2/2] feat: add more permissions - added more permissions - improved roles and permissions queries --- database/seeders/DatabaseSeeder.php | 13 +- database/seeders/PermissionSeeder.php | 228 +++++++++++------ database/seeders/RolePermissionSeeder.php | 293 ++++++++++++++-------- database/seeders/RoleSeeder.php | 54 +++- 4 files changed, 392 insertions(+), 196 deletions(-) diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index a414354..abf73a3 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -6,17 +6,26 @@ use Illuminate\Database\Seeder; -final class DatabaseSeeder extends Seeder +class DatabaseSeeder extends Seeder { /** * Seed the application's database. */ public function run(): void { + // Seed permissions first (required for roles) $this->call([ - RoleSeeder::class, PermissionSeeder::class, + ]); + + // Seed roles and assign permissions + $this->call([ + RoleSeeder::class, RolePermissionSeeder::class, + ]); + + // Seed other data + $this->call([ UserSeeder::class, ]); } diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php index c4677ee..98f91db 100644 --- a/database/seeders/PermissionSeeder.php +++ b/database/seeders/PermissionSeeder.php @@ -1,90 +1,162 @@ + */ + private const PERMISSIONS = [ + // User & Account Management + 'view_users', + 'create_users', + 'edit_users', + 'delete_users', + 'ban_users', + 'block_users', + 'restore_users', + 'assign_roles', + 'manage_roles', + 'manage_permissions', + 'edit_profile', + 'view_user_activity', + 'register_user', + 'view_own_profile', + + // Article/Post Management + 'view_posts', + 'create_posts', + 'edit_posts', + 'delete_posts', + 'publish_posts', + 'edit_others_posts', + 'delete_others_posts', + 'approve_posts', + 'feature_posts', + 'pin_posts', + 'archive_posts', + 'restore_posts', + 'trash_posts', + 'report_posts', + 'like_posts', + 'dislike_posts', + 'view_own_posts', + 'schedule_posts', + + // Comment Management + 'comment_moderate', + 'create_comments', + 'edit_comments', + 'delete_comments', + 'approve_comments', + 'report_comments', + 'view_comments', + 'edit_own_comments', + 'delete_own_comments', + + // Taxonomy Management + 'manage_categories', + 'create_categories', + 'edit_categories', + 'delete_categories', + 'view_categories', + 'manage_tags', + 'create_tags', + 'edit_tags', + 'delete_tags', + 'view_tags', + + // Newsletter + 'view_newsletter_subscribers', + 'manage_newsletter_subscribers', + 'subscribe_newsletter', + 'unsubscribe_newsletter', + 'send_newsletter', + + // Notifications + 'view_notifications', + 'manage_notifications', + 'send_notifications', + 'read_notifications', + 'delete_notifications', + + // Media Management + 'upload_media', + 'delete_media', + 'manage_media', + 'view_media', + 'edit_media', + + // Analytics & Settings + 'view_analytics', + 'manage_settings', + 'view_dashboard', + 'export_data', + + // Social/Community + 'follow_users', + 'unfollow_users', + 'view_user_profiles', + 'send_messages', + + // General + 'manage_options', + 'read', + 'access_api', + 'view_logs', + ]; + + /** + * Run the database seeds. + */ + public function run(): void { - $permissions = [ - // User & Account Management - 'view_users', - 'create_users', - 'edit_users', - 'delete_users', - 'ban_users', - 'block_users', - 'restore_users', - 'assign_roles', - 'manage_roles', - 'manage_permissions', - 'edit_profile', - 'view_user_activity', - - // Article/Post Management - 'view_posts', - 'edit_posts', - 'delete_posts', - 'publish_posts', - 'edit_others_posts', - 'delete_others_posts', - 'approve_posts', - 'feature_posts', - 'pin_posts', - 'archive_posts', - 'restore_posts', - 'trash_posts', - 'report_posts', - 'like_posts', - 'dislike_posts', - - // Comment Management - 'comment_moderate', - 'edit_comments', - 'delete_comments', - 'approve_comments', - 'report_comments', - - // Taxonomy Management - 'manage_categories', - 'manage_tags', - - // Newsletter - 'view_newsletter_subscribers', - 'manage_newsletter_subscribers', - 'subscribe_newsletter', - - // Notifications - 'view_notifications', - 'manage_notifications', - 'send_notifications', - - // Media Management - 'upload_media', - 'delete_media', - 'manage_media', - - // Analytics & Settings - 'view_analytics', - 'manage_settings', - - // Social/Community - 'follow_users', - - // General - 'manage_options', - 'read', - ]; - - foreach ($permissions as $permission) { - $slug = strtolower(str_replace([' ', '_'], '-', $permission)); - Permission::firstOrCreate([ - 'name' => $permission, - 'slug' => $slug, - ]); + $this->command->info('Starting permission creation...'); + + try { + $createdCount = 0; + $existingCount = 0; + + foreach (self::PERMISSIONS as $permission) { + $slug = strtolower(str_replace([' ', '_'], '-', $permission)); + + $existingPermission = Permission::where('name', $permission)->first(); + + if ($existingPermission) { + $existingCount++; + $this->command->line("Permission '{$permission}' already exists"); + + continue; + } + + Permission::create([ + 'name' => $permission, + 'slug' => $slug, + ]); + + $createdCount++; + $this->command->info("Created permission: {$permission}"); + } + + $this->command->info("Permission seeding completed. Created: {$createdCount}, Existing: {$existingCount}"); + + } catch (\Throwable $e) { + $this->command->error('Failed to create permissions: '.$e->getMessage()); + throw $e; } } } diff --git a/database/seeders/RolePermissionSeeder.php b/database/seeders/RolePermissionSeeder.php index 38443cb..9a29177 100644 --- a/database/seeders/RolePermissionSeeder.php +++ b/database/seeders/RolePermissionSeeder.php @@ -1,121 +1,202 @@ > + */ + private const ROLE_PERMISSIONS = [ + UserRole::ADMINISTRATOR->value => [ + // User & Account Management + 'view_users', 'create_users', 'edit_users', 'delete_users', 'ban_users', 'block_users', 'restore_users', + 'assign_roles', 'manage_roles', 'manage_permissions', 'edit_profile', 'view_user_activity', + 'register_user', 'view_own_profile', + // Article/Post Management + 'view_posts', 'create_posts', 'edit_posts', 'delete_posts', 'publish_posts', 'edit_others_posts', 'delete_others_posts', + 'approve_posts', 'feature_posts', 'pin_posts', 'archive_posts', 'restore_posts', 'trash_posts', 'report_posts', + 'like_posts', 'dislike_posts', 'view_own_posts', 'schedule_posts', + // Comment Management + 'comment_moderate', 'create_comments', 'edit_comments', 'delete_comments', 'approve_comments', 'report_comments', + 'view_comments', 'edit_own_comments', 'delete_own_comments', + // Taxonomy Management + 'manage_categories', 'create_categories', 'edit_categories', 'delete_categories', 'view_categories', + 'manage_tags', 'create_tags', 'edit_tags', 'delete_tags', 'view_tags', + // Newsletter + 'view_newsletter_subscribers', 'manage_newsletter_subscribers', 'subscribe_newsletter', + 'unsubscribe_newsletter', 'send_newsletter', + // Notifications + 'view_notifications', 'manage_notifications', 'send_notifications', + 'read_notifications', 'delete_notifications', + // Media Management + 'upload_media', 'delete_media', 'manage_media', 'view_media', 'edit_media', + // Analytics & Settings + 'view_analytics', 'manage_settings', 'view_dashboard', 'export_data', + // Social/Community + 'follow_users', 'unfollow_users', 'view_user_profiles', 'send_messages', + // General + 'manage_options', 'read', 'access_api', 'view_logs', + ], + UserRole::EDITOR->value => [ + // User & Account Management + 'view_users', 'edit_profile', 'view_own_profile', + // Article/Post Management + 'view_posts', 'create_posts', 'edit_posts', 'delete_posts', 'publish_posts', 'edit_others_posts', 'delete_others_posts', + 'feature_posts', 'pin_posts', 'archive_posts', 'restore_posts', 'trash_posts', 'report_posts', + 'like_posts', 'dislike_posts', 'view_own_posts', 'schedule_posts', + // Comment Management + 'comment_moderate', 'create_comments', 'edit_comments', 'delete_comments', 'approve_comments', 'report_comments', + 'view_comments', 'edit_own_comments', 'delete_own_comments', + // Taxonomy Management + 'manage_categories', 'create_categories', 'edit_categories', 'delete_categories', 'view_categories', + 'manage_tags', 'create_tags', 'edit_tags', 'delete_tags', 'view_tags', + // Newsletter + 'view_newsletter_subscribers', 'subscribe_newsletter', 'unsubscribe_newsletter', + // Notifications + 'view_notifications', 'read_notifications', + // Media Management + 'upload_media', 'delete_media', 'manage_media', 'view_media', 'edit_media', + // Analytics & Settings + 'view_analytics', 'view_dashboard', + // Social/Community + 'follow_users', 'unfollow_users', 'view_user_profiles', + // General + 'read', 'access_api', + ], + UserRole::AUTHOR->value => [ + // User & Account Management + 'edit_profile', 'view_own_profile', + // Article/Post Management + 'view_posts', 'create_posts', 'edit_posts', 'delete_posts', 'publish_posts', 'archive_posts', 'restore_posts', 'trash_posts', 'report_posts', + 'like_posts', 'dislike_posts', 'view_own_posts', 'schedule_posts', + // Comment Management + 'create_comments', 'edit_comments', 'delete_comments', 'report_comments', + 'view_comments', 'edit_own_comments', 'delete_own_comments', + // Newsletter + 'subscribe_newsletter', 'unsubscribe_newsletter', + // Media Management + 'upload_media', 'view_media', + // Social/Community + 'follow_users', 'unfollow_users', 'view_user_profiles', + // General + 'read', 'access_api', + ], + UserRole::CONTRIBUTOR->value => [ + // User & Account Management + 'edit_profile', 'view_own_profile', + // Article/Post Management + 'view_posts', 'create_posts', 'edit_posts', 'delete_posts', 'trash_posts', 'report_posts', 'like_posts', 'dislike_posts', + 'view_own_posts', + // Comment Management + 'create_comments', 'edit_comments', 'delete_comments', 'report_comments', + 'view_comments', 'edit_own_comments', 'delete_own_comments', + // Newsletter + 'subscribe_newsletter', 'unsubscribe_newsletter', + // Media Management + 'upload_media', 'view_media', + // Social/Community + 'follow_users', 'unfollow_users', 'view_user_profiles', + // General + 'read', 'access_api', + ], + UserRole::SUBSCRIBER->value => [ + // User & Account Management + 'edit_profile', 'view_own_profile', + // Article/Post Management + 'view_posts', 'report_posts', 'like_posts', 'dislike_posts', + // Comment Management + 'create_comments', 'report_comments', 'view_comments', 'edit_own_comments', 'delete_own_comments', + // Newsletter + 'subscribe_newsletter', 'unsubscribe_newsletter', + // Social/Community + 'follow_users', 'unfollow_users', 'view_user_profiles', + // General + 'read', 'access_api', + ], + ]; + + /** + * Run the database seeds. + */ + public function run(): void { - $rolePermissions = [ - UserRole::ADMINISTRATOR->value => [ - // User & Account Management - 'view_users', 'create_users', 'edit_users', 'delete_users', 'ban_users', 'block_users', 'restore_users', - 'assign_roles', 'manage_roles', 'manage_permissions', 'edit_profile', 'view_user_activity', - // Article/Post Management - 'view_posts', 'edit_posts', 'delete_posts', 'publish_posts', 'edit_others_posts', 'delete_others_posts', - 'approve_posts', 'feature_posts', 'pin_posts', 'archive_posts', 'restore_posts', 'trash_posts', 'report_posts', - 'like_posts', 'dislike_posts', - // Comment Management - 'comment_moderate', 'edit_comments', 'delete_comments', 'approve_comments', 'report_comments', - // Taxonomy Management - 'manage_categories', 'manage_tags', - // Newsletter - 'view_newsletter_subscribers', 'manage_newsletter_subscribers', 'subscribe_newsletter', - // Notifications - 'view_notifications', 'manage_notifications', 'send_notifications', - // Media Management - 'upload_media', 'delete_media', 'manage_media', - // Analytics & Settings - 'view_analytics', 'manage_settings', - // Social/Community - 'follow_users', - // General - 'manage_options', 'read', - ], - UserRole::EDITOR->value => [ - // User & Account Management - 'view_users', 'edit_profile', - // Article/Post Management - 'view_posts', 'edit_posts', 'delete_posts', 'publish_posts', 'edit_others_posts', 'delete_others_posts', - 'feature_posts', 'pin_posts', 'archive_posts', 'restore_posts', 'trash_posts', 'report_posts', - 'like_posts', 'dislike_posts', - // Comment Management - 'comment_moderate', 'edit_comments', 'delete_comments', 'approve_comments', 'report_comments', - // Taxonomy Management - 'manage_categories', 'manage_tags', - // Newsletter - 'view_newsletter_subscribers', 'subscribe_newsletter', - // Notifications - 'view_notifications', - // Media Management - 'upload_media', 'delete_media', 'manage_media', - // Analytics & Settings - 'view_analytics', - // Social/Community - 'follow_users', - // General - 'read', - ], - UserRole::AUTHOR->value => [ - // User & Account Management - 'edit_profile', - // Article/Post Management - 'view_posts', 'edit_posts', 'delete_posts', 'publish_posts', 'archive_posts', 'restore_posts', 'trash_posts', 'report_posts', - 'like_posts', 'dislike_posts', - // Comment Management - 'edit_comments', 'delete_comments', 'report_comments', - // Newsletter - 'subscribe_newsletter', - // Media Management - 'upload_media', - // Social/Community - 'follow_users', - // General - 'read', - ], - UserRole::CONTRIBUTOR->value => [ - // User & Account Management - 'edit_profile', - // Article/Post Management - 'view_posts', 'edit_posts', 'delete_posts', 'trash_posts', 'report_posts', 'like_posts', 'dislike_posts', - // Comment Management - 'edit_comments', 'delete_comments', 'report_comments', - // Newsletter - 'subscribe_newsletter', - // Media Management - 'upload_media', - // Social/Community - 'follow_users', - // General - 'read', - ], - UserRole::SUBSCRIBER->value => [ - // User & Account Management - 'edit_profile', - // Article/Post Management - 'view_posts', 'report_posts', 'like_posts', 'dislike_posts', - // Comment Management - 'report_comments', - // Newsletter - 'subscribe_newsletter', - // Social/Community - 'follow_users', - // General - 'read', - ], - ]; - - foreach ($rolePermissions as $roleName => $permissions) { - $role = Role::where('name', $roleName)->first(); - if ($role) { - $permissionIds = Permission::whereIn('name', $permissions)->pluck('id')->toArray(); - $role->permissions()->syncWithoutDetaching($permissionIds); + $this->command->info('Starting role permission assignment...'); + + try { + DB::beginTransaction(); + + // Pre-load all permissions for efficiency + $permissions = Permission::all()->keyBy('name'); + $roles = Role::all()->keyBy('name'); + + $this->command->info('Found '.$permissions->count().' permissions and '.$roles->count().' roles'); + + $assignedCount = 0; + $missingPermissions = []; + $missingRoles = []; + + foreach (self::ROLE_PERMISSIONS as $roleName => $permissionNames) { + $role = $roles->get($roleName); + + if (! $role) { + $missingRoles[] = $roleName; + + continue; + } + + $permissionIds = []; + foreach ($permissionNames as $permissionName) { + $permission = $permissions->get($permissionName); + + if (! $permission) { + $missingPermissions[] = $permissionName; + + continue; + } + + $permissionIds[] = $permission->id; + } + + if (! empty($permissionIds)) { + // Use sync instead of syncWithoutDetaching for clean assignment + $role->permissions()->sync($permissionIds); + $assignedCount += count($permissionIds); + + $this->command->info('Assigned '.count($permissionIds)." permissions to role: {$roleName}"); + } } + + if (! empty($missingRoles)) { + $this->command->warn('Missing roles: '.implode(', ', array_unique($missingRoles))); + } + + if (! empty($missingPermissions)) { + $this->command->warn('Missing permissions: '.implode(', ', array_unique($missingPermissions))); + } + + DB::commit(); + $this->command->info("Successfully assigned {$assignedCount} permission-role relationships"); + } catch (\Throwable $e) { + DB::rollBack(); + $this->command->error('Failed to assign role permissions: '.$e->getMessage()); + throw $e; } } } diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php index 58002e4..add9f20 100644 --- a/database/seeders/RoleSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -1,23 +1,57 @@ value)); - Role::firstOrCreate([ - 'name' => $role->value, - 'slug' => $slug, - ]); + $this->command->info('Starting role creation...'); + + try { + $createdCount = 0; + $existingCount = 0; + + foreach (UserRole::cases() as $role) { + $slug = strtolower(str_replace([' ', '_'], '-', $role->value)); + + $existingRole = Role::where('name', $role->value)->first(); + + if ($existingRole) { + $existingCount++; + $this->command->line("Role '{$role->value}' already exists"); + + continue; + } + + Role::create([ + 'name' => $role->value, + 'slug' => $slug, + ]); + + $createdCount++; + $this->command->info("Created role: {$role->value}"); + } + + $this->command->info("Role seeding completed. Created: {$createdCount}, Existing: {$existingCount}"); + } catch (\Throwable $e) { + $this->command->error('Failed to create roles: '.$e->getMessage()); + throw $e; } } }