RbacSeeder.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. namespace Database\Seeders;
  3. use App\Models\Permission;
  4. use App\Models\Role;
  5. use App\Models\User;
  6. use App\Services\Access\AccessService;
  7. use Illuminate\Database\Seeder;
  8. use Illuminate\Support\Facades\DB;
  9. class RbacSeeder extends Seeder
  10. {
  11. public function run(): void
  12. {
  13. DB::transaction(function () {
  14. $roles = $this->seedRoles();
  15. $permissions = $this->seedPermissions();
  16. $this->backfillUserRoles($roles);
  17. $this->seedRolePermissions($roles, $permissions);
  18. });
  19. app(AccessService::class)->bumpCacheVersion();
  20. }
  21. private function seedRoles(): array
  22. {
  23. $roles = [];
  24. foreach (Role::NAMES as $slug => $name) {
  25. $roles[$slug] = Role::query()->updateOrCreate(
  26. ['slug' => $slug],
  27. [
  28. 'name' => $name,
  29. 'is_system' => true,
  30. 'is_active' => true,
  31. 'sort' => array_search($slug, Role::VALID_ROLES, true) + 10,
  32. ],
  33. );
  34. }
  35. return $roles;
  36. }
  37. private function seedPermissions(): array
  38. {
  39. $permissions = [];
  40. $sort = 10;
  41. foreach (config('access', []) as $module => $definition) {
  42. foreach (($definition['actions'] ?? []) as $action => $name) {
  43. $slug = "{$module}.{$action}";
  44. $permissions[$slug] = Permission::query()->updateOrCreate(
  45. ['slug' => $slug],
  46. [
  47. 'name' => $name,
  48. 'module' => $module,
  49. 'entity' => $definition['entity'] ?? null,
  50. 'field' => null,
  51. 'action' => $action,
  52. 'type' => Permission::TYPE_ACTION,
  53. 'group' => $definition['name'] ?? $module,
  54. 'sort' => $sort++,
  55. 'is_system' => true,
  56. ],
  57. );
  58. }
  59. foreach (($definition['fields'] ?? []) as $field => $name) {
  60. foreach (['view' => 'Просмотр', 'update' => 'Редактирование'] as $action => $actionName) {
  61. $slug = "{$module}.fields.{$field}.{$action}";
  62. $permissions[$slug] = Permission::query()->updateOrCreate(
  63. ['slug' => $slug],
  64. [
  65. 'name' => "{$name}: {$actionName}",
  66. 'module' => $module,
  67. 'entity' => $definition['entity'] ?? null,
  68. 'field' => $field,
  69. 'action' => $action,
  70. 'type' => Permission::TYPE_FIELD,
  71. 'group' => ($definition['name'] ?? $module) . ' / Поля',
  72. 'sort' => $sort++,
  73. 'is_system' => true,
  74. ],
  75. );
  76. }
  77. }
  78. }
  79. return $permissions;
  80. }
  81. private function backfillUserRoles(array $roles): void
  82. {
  83. foreach ($roles as $slug => $role) {
  84. User::query()
  85. ->where('role', $slug)
  86. ->whereNull('role_id')
  87. ->withTrashed()
  88. ->update(['role_id' => $role->id]);
  89. }
  90. }
  91. private function seedRolePermissions(array $roles, array $permissions): void
  92. {
  93. $all = array_keys($permissions);
  94. $auth = [
  95. 'orders.view',
  96. 'orders.photos.upload',
  97. 'orders.documents.generate',
  98. 'orders.chat.create',
  99. 'reclamations.view',
  100. 'reclamations.photos.upload',
  101. 'reclamations.chat.create',
  102. 'schedule.view',
  103. 'profile.view',
  104. 'profile.update',
  105. 'profile.delete',
  106. 'notifications.view',
  107. 'notifications.mark_read',
  108. 'areas.ajax.view',
  109. 'catalog.search',
  110. 'pricing_codes.search',
  111. 'filters.view',
  112. ];
  113. $manager = array_merge($auth, [
  114. 'orders.update',
  115. 'orders.export',
  116. 'orders.documents.upload',
  117. 'orders.documents.delete',
  118. 'orders.documents.generate',
  119. 'orders.photos.delete',
  120. 'reclamations.create',
  121. 'reclamations.update',
  122. 'reclamations.export',
  123. 'reclamations.status.update',
  124. 'reclamations.documents.upload',
  125. 'reclamations.documents.delete',
  126. 'reclamations.documents.generate',
  127. 'reclamations.photos.delete',
  128. 'reclamations.act.upload',
  129. 'reclamations.act.delete',
  130. 'reclamations.spare_parts.manage',
  131. 'catalog.view',
  132. 'catalog.import',
  133. 'maf.view',
  134. 'maf.update',
  135. 'maf.passports.upload',
  136. 'contracts.view',
  137. 'contracts.create',
  138. 'contracts.update',
  139. 'contracts.delete',
  140. 'responsibles.view',
  141. 'responsibles.create',
  142. 'responsibles.update',
  143. 'responsibles.delete',
  144. 'reports.view',
  145. 'spare_parts.view',
  146. 'spare_parts.search',
  147. 'spare_part_orders.view',
  148. 'spare_part_orders.create',
  149. 'spare_part_orders.update',
  150. 'spare_part_orders.ship',
  151. 'spare_part_orders.stock.manage',
  152. 'spare_part_reservations.view',
  153. 'spare_part_reservations.manage',
  154. 'spare_part_reservations.issue',
  155. 'spare_part_reservations.cancel',
  156. 'spare_part_reservations.reassign',
  157. 'spare_part_inventory.view',
  158. 'chat_messages.create',
  159. 'chat_messages.notify',
  160. ]);
  161. $manager = array_merge($manager, $this->fieldPermissions('catalog', ['view'], $permissions));
  162. $brigadier = array_merge($auth, [
  163. 'reclamations.act.upload',
  164. ]);
  165. $warehouseHead = array_merge($auth, [
  166. 'reclamations.act.upload',
  167. ]);
  168. $rolePermissions = [
  169. Role::ADMIN => $all,
  170. Role::ASSISTANT_HEAD => $all,
  171. Role::MANAGER => $manager,
  172. Role::BRIGADIER => $brigadier,
  173. Role::WAREHOUSE_HEAD => $warehouseHead,
  174. ];
  175. foreach ($rolePermissions as $roleSlug => $permissionSlugs) {
  176. $role = $roles[$roleSlug] ?? null;
  177. if (!$role) {
  178. continue;
  179. }
  180. $sync = [];
  181. foreach (array_unique($permissionSlugs) as $permissionSlug) {
  182. if (isset($permissions[$permissionSlug])) {
  183. $sync[$permissions[$permissionSlug]->id] = ['effect' => 'allow'];
  184. }
  185. }
  186. $role->permissions()->sync($sync);
  187. }
  188. }
  189. private function fieldPermissions(string $module, array $actions, array $permissions): array
  190. {
  191. return array_values(array_filter(
  192. array_keys($permissions),
  193. fn (string $slug): bool => str_starts_with($slug, "{$module}.fields.")
  194. && in_array(substr($slug, strrpos($slug, '.') + 1), $actions, true)
  195. ));
  196. }
  197. }