diff --git a/app/Http/Controllers/API/GroupController.php b/app/Http/Controllers/API/GroupController.php index c4b5abfc21..feb077ef0b 100644 --- a/app/Http/Controllers/API/GroupController.php +++ b/app/Http/Controllers/API/GroupController.php @@ -383,7 +383,59 @@ public static function listTagsv2(Request $request) { */ public static function getGroupv2(Request $request, $idgroups) { $group = Group::findOrFail($idgroups); - return \App\Http\Resources\Group::make($group); + + // This endpoint is not behind auth:api, so the request may be anonymous. Try session auth first (the + // group view page is loaded via a normal browser session), then fall back to API token auth. If there is + // no authenticated user at all, every permission flag is false. + $user = Auth::user(); + if (! $user) { + $user = auth('api')->user(); + } + + $permissions = self::groupPermissionsFor($user, $group); + + return \App\Http\Resources\Group::make($group)->additional([ + 'data' => [ + 'permissions' => $permissions, + ], + ]); + } + + /** + * Compute the UI show/hide permission flags for a given (possibly null) user against a group. + * + * These flags are for UI purposes only - the actual edit/delete/archive endpoints enforce their own + * authorization independently. Mirrors the logic previously computed server-side in group/view.blade.php. + */ + private static function groupPermissionsFor(?User $user, Group $group): array + { + if (! $user) { + return [ + 'can_edit' => false, + 'can_demote' => false, + 'can_see_delete' => false, + 'can_perform_delete' => false, + 'can_perform_archive' => false, + ]; + } + + $isAdministrator = Fixometer::hasRole($user, 'Administrator'); + $isCoordinatorForGroup = $user->isCoordinatorForGroup($group); + $isHostOfGroup = Fixometer::userHasEditGroupPermission($group->idgroups, $user->id); + + $canEdit = $isAdministrator || $isCoordinatorForGroup || $isHostOfGroup; + $canDemote = $isAdministrator || $isCoordinatorForGroup; + $canSeeDelete = $isAdministrator; + $canPerformDelete = $canSeeDelete && $group->canDelete(); + $canPerformArchive = $isAdministrator || $isCoordinatorForGroup; + + return [ + 'can_edit' => $canEdit, + 'can_demote' => $canDemote, + 'can_see_delete' => $canSeeDelete, + 'can_perform_delete' => $canPerformDelete, + 'can_perform_archive' => $canPerformArchive, + ]; } /** diff --git a/app/Http/Resources/Group.php b/app/Http/Resources/Group.php index 7066ae67fc..fe42f444b3 100644 --- a/app/Http/Resources/Group.php +++ b/app/Http/Resources/Group.php @@ -260,6 +260,42 @@ * title="archived_at", * description="If present, this group has been archived and is no longer active.", * format="date-time", + * ), + * @OA\Property( + * property="permissions", + * title="permissions", + * description="UI show/hide permission flags for the currently authenticated user (only present on the single-group endpoint). These are for UI purposes only - the edit/delete/archive endpoints enforce their own authorization independently. When there is no authenticated user, every flag is false.", + * format="object", + * @OA\Property( + * property="can_edit", + * title="can_edit", + * description="Whether the user can see group editing controls (administrator, network coordinator for the group, or host of the group).", + * type="boolean", + * ), + * @OA\Property( + * property="can_demote", + * title="can_demote", + * description="Whether the user can demote/manage volunteer roles (administrator or network coordinator for the group).", + * type="boolean", + * ), + * @OA\Property( + * property="can_see_delete", + * title="can_see_delete", + * description="Whether the user can see the delete-group control (administrator only).", + * type="boolean", + * ), + * @OA\Property( + * property="can_perform_delete", + * title="can_perform_delete", + * description="Whether the group can actually be deleted by this user (can_see_delete and the group has no events with devices).", + * type="boolean", + * ), + * @OA\Property( + * property="can_perform_archive", + * title="can_perform_archive", + * description="Whether the user can archive the group (administrator or network coordinator for the group).", + * type="boolean", + * ), * ) * ) */ diff --git a/resources/js/components/GroupPage.vue b/resources/js/components/GroupPage.vue index 49b2a14360..7928b0442c 100644 --- a/resources/js/components/GroupPage.vue +++ b/resources/js/components/GroupPage.vue @@ -48,6 +48,9 @@ +
+
{{ __('partials.loading') }}...
+