Skip to content

Commit a07abe3

Browse files
Group abilities by groups, list abilities for user roles (#42)
* Introduce ability groups * Add users details page * Add page showing own abilities * Improve UI, add missing ability checks
1 parent 3ab66f2 commit a07abe3

25 files changed

+577
-138
lines changed

app/Http/Controllers/AccountController.php

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public function show(): View
1818
return view('account.account_show');
1919
}
2020

21+
public function showAbilities(): View
22+
{
23+
$this->authorize('viewAbilities', User::class);
24+
25+
return view('account.account_show_abilities');
26+
}
27+
2128
public function edit(): View
2229
{
2330
$this->authorize('editAccount', User::class);

app/Http/Controllers/UserRoleController.php

+9
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ public function store(UserRoleRequest $request): RedirectResponse
4747
return back();
4848
}
4949

50+
public function show(UserRole $userRole): View
51+
{
52+
$this->authorize('view', $userRole);
53+
54+
return view('user_roles.user_role_show', [
55+
'userRole' => $userRole,
56+
]);
57+
}
58+
5059
public function edit(UserRole $userRole): View
5160
{
5261
$this->authorize('update', $userRole);

app/Models/User.php

+15-4
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,25 @@ public function fillAndSave(array $validatedData): bool
198198
}
199199

200200
/**
201-
* @return \Illuminate\Support\Collection<Ability>
201+
* @return Collection<string>
202202
*/
203-
public function getAbilities(): \Illuminate\Support\Collection
203+
public function getAbilitiesAsStrings(): \Illuminate\Support\Collection
204204
{
205205
$abilities = \Illuminate\Support\Collection::empty();
206206
foreach ($this->userRoles as $userRole) {
207207
$abilities->add($userRole->abilities);
208208
}
209209

210210
return $abilities->flatten()
211-
->unique()
211+
->unique();
212+
}
213+
214+
/**
215+
* @return \Illuminate\Support\Collection<Ability>
216+
*/
217+
public function getAbilities(): \Illuminate\Support\Collection
218+
{
219+
return $this->getAbilitiesAsStrings()
212220
->map(static fn (string $ability) => Ability::tryFrom($ability))
213221
->filter()
214222
->values();
@@ -250,6 +258,9 @@ public function loadProfileData(): self
250258
'documents',
251259
'groups',
252260
]),
261+
'responsibleForEvents.eventSeries',
262+
'responsibleForEvents.location',
263+
'responsibleForEvents.parentEvent',
253264
'responsibleForEventSeries' => fn (MorphToMany $eventSeries) => $eventSeries
254265
->withCount([
255266
'documents',
@@ -261,7 +272,7 @@ public function loadProfileData(): self
261272
'events_min_started_at' => 'datetime',
262273
'events_max_started_at' => 'datetime',
263274
]),
264-
'responsibleForOrganizations',
275+
'responsibleForOrganizations.location',
265276
]);
266277

267278
// Set backwards relation for documents.

app/Options/Ability.php

+131-38
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ enum Ability: string
88
{
99
use NamedOption;
1010

11-
case ViewAccount = 'users.view_account';
12-
case EditAccount = 'users.edit_account';
13-
case ManagePersonalAccessTokens = 'personal_access_tokens.manage_own';
14-
11+
// Events
1512
case ViewEvents = 'events.view';
1613
case ViewPrivateEvents = 'events.view_private';
1714
case CreateEvents = 'events.create';
1815
case EditEvents = 'events.edit';
16+
case ViewResponsibilitiesOfEvents = 'events.responsibilities.view';
17+
1918
case ManageBookingOptionsOfEvent = 'events.manage_booking_options';
2019
case ViewBookingsOfEvent = 'events.view_bookings';
2120
case ExportBookingsOfEvent = 'events.export_bookings';
@@ -24,39 +23,45 @@ enum Ability: string
2423
case EditBookingComment = 'events.edit_booking_comment';
2524
case ViewPaymentStatus = 'events.view_payment_status';
2625
case EditPaymentStatus = 'events.edit_payment_status';
26+
2727
case ManageGroupsOfEvent = 'events.manage_groups';
2828
case ExportGroupsOfEvent = 'events.export_groups';
29-
case ViewDocumentsOfEvents = 'events.documents.view';
30-
case AddDocumentsToEvents = 'events.documents.create';
31-
case EditDocumentsOfEvents = 'events.documents.edit';
32-
case DeleteDocumentsOfEvents = 'events.documents.delete';
33-
case ViewResponsibilitiesOfEvents = 'events.responsibilities.view';
3429

3530
case ViewEventSeries = 'event_series.view';
3631
case ViewPrivateEventSeries = 'event_series.view_private';
3732
case CreateEventSeries = 'event_series.create';
3833
case EditEventSeries = 'event_series.edit';
39-
case ViewDocumentsOfEventSeries = 'event_series.documents.view';
40-
case AddDocumentsToEventSeries = 'event_series.documents.create';
41-
case EditDocumentsOfEventSeries = 'event_series.documents.edit';
42-
case DeleteDocumentsOfEventSeries = 'event_series.documents.delete';
4334
case ViewResponsibilitiesOfEventSeries = 'event_series.responsibilities.view';
4435

36+
// Basic data
37+
case ViewOrganizations = 'organizations.view';
38+
case CreateOrganizations = 'organizations.create';
39+
case EditOrganizations = 'organizations.edit';
40+
case ViewResponsibilitiesOfOrganizations = 'organizations.responsibilities.view';
41+
4542
case ViewLocations = 'locations.view';
4643
case CreateLocations = 'locations.create';
4744
case EditLocations = 'locations.edit';
4845

49-
case ViewOrganizations = 'organizations.view';
50-
case CreateOrganizations = 'organizations.create';
51-
case EditOrganizations = 'organizations.edit';
46+
// Documents
47+
case ViewDocuments = 'documents.view';
48+
49+
case ViewDocumentsOfEvents = 'events.documents.view';
50+
case AddDocumentsToEvents = 'events.documents.create';
51+
case EditDocumentsOfEvents = 'events.documents.edit';
52+
case DeleteDocumentsOfEvents = 'events.documents.delete';
53+
54+
case ViewDocumentsOfEventSeries = 'event_series.documents.view';
55+
case AddDocumentsToEventSeries = 'event_series.documents.create';
56+
case EditDocumentsOfEventSeries = 'event_series.documents.edit';
57+
case DeleteDocumentsOfEventSeries = 'event_series.documents.delete';
58+
5259
case ViewDocumentsOfOrganizations = 'organizations.documents.view';
5360
case AddDocumentsToOrganizations = 'organizations.documents.create';
5461
case EditDocumentsOfOrganizations = 'organizations.documents.edit';
5562
case DeleteDocumentsOfOrganizations = 'organizations.documents.delete';
56-
case ViewResponsibilitiesOfOrganizations = 'organizations.responsibilities.view';
57-
58-
case ViewDocuments = 'documents.view';
5963

64+
// Users and abilities
6065
case ViewUsers = 'users.view';
6166
case CreateUsers = 'users.create';
6267
case EditUsers = 'users.edit';
@@ -65,17 +70,84 @@ enum Ability: string
6570
case CreateUserRoles = 'user_roles.create';
6671
case EditUserRoles = 'user_roles.edit';
6772

68-
public function getTranslatedName(): string
73+
case ViewAccount = 'users.view_account';
74+
case ViewAbilities = 'users.view_account.abilities';
75+
case EditAccount = 'users.edit_account';
76+
case ManagePersonalAccessTokens = 'personal_access_tokens.manage_own';
77+
78+
public function getAbilityGroup(): AbilityGroup
6979
{
7080
return match ($this) {
71-
self::ViewAccount => __('View own account'),
72-
self::EditAccount => __('Edit own account'),
73-
self::ManagePersonalAccessTokens => __('Manage personal access tokens'),
81+
// Events
82+
self::ViewEvents,
83+
self::ViewPrivateEvents,
84+
self::CreateEvents,
85+
self::EditEvents,
86+
self::ViewResponsibilitiesOfEvents => AbilityGroup::Events,
87+
self::ManageBookingOptionsOfEvent,
88+
self::ViewBookingsOfEvent,
89+
self::ExportBookingsOfEvent,
90+
self::EditBookingsOfEvent,
91+
self::DeleteAndRestoreBookingsOfEvent,
92+
self::EditBookingComment,
93+
self::ViewPaymentStatus,
94+
self::EditPaymentStatus => AbilityGroup::Bookings,
95+
self::ManageGroupsOfEvent,
96+
self::ExportGroupsOfEvent => AbilityGroup::Groups,
97+
self::ViewEventSeries,
98+
self::ViewPrivateEventSeries,
99+
self::CreateEventSeries,
100+
self::EditEventSeries,
101+
self::ViewResponsibilitiesOfEventSeries => AbilityGroup::EventSeries,
102+
103+
// Basic data
104+
self::ViewOrganizations,
105+
self::CreateOrganizations,
106+
self::EditOrganizations,
107+
self::ViewResponsibilitiesOfOrganizations => AbilityGroup::Organizations,
108+
self::ViewLocations,
109+
self::CreateLocations,
110+
self::EditLocations => AbilityGroup::Locations,
111+
112+
// Documents
113+
self::ViewDocuments => AbilityGroup::Documents,
114+
self::ViewDocumentsOfEvents,
115+
self::AddDocumentsToEvents,
116+
self::EditDocumentsOfEvents,
117+
self::DeleteDocumentsOfEvents => AbilityGroup::DocumentsOfEvents,
118+
self::ViewDocumentsOfEventSeries,
119+
self::AddDocumentsToEventSeries,
120+
self::EditDocumentsOfEventSeries,
121+
self::DeleteDocumentsOfEventSeries => AbilityGroup::DocumentsOfEventSeries,
122+
self::ViewDocumentsOfOrganizations,
123+
self::AddDocumentsToOrganizations,
124+
self::EditDocumentsOfOrganizations,
125+
self::DeleteDocumentsOfOrganizations => AbilityGroup::DocumentsOfOrganizations,
126+
127+
// Users and abilities
128+
self::ViewUsers,
129+
self::CreateUsers,
130+
self::EditUsers => AbilityGroup::Users,
131+
self::ViewUserRoles,
132+
self::CreateUserRoles,
133+
self::EditUserRoles => AbilityGroup::UserRoles,
134+
self::ViewAccount,
135+
self::ViewAbilities,
136+
self::EditAccount,
137+
self::ManagePersonalAccessTokens => AbilityGroup::OwnAccount,
138+
};
139+
}
74140

141+
public function getTranslatedName(): string
142+
{
143+
return match ($this) {
144+
// Events
75145
self::ViewEvents => __('View events'),
76146
self::ViewPrivateEvents => __('View private events'),
77147
self::CreateEvents => __('Create events'),
78148
self::EditEvents => __('Edit events'),
149+
self::ViewResponsibilitiesOfEvents => __('View responsibilities of events'),
150+
79151
self::ManageBookingOptionsOfEvent => __('Manage booking options of event'),
80152
self::ViewBookingsOfEvent => __('View bookings of event'),
81153
self::ExportBookingsOfEvent => __('Export bookings of event'),
@@ -84,46 +156,67 @@ public function getTranslatedName(): string
84156
self::EditBookingComment => __('Edit booking comment'),
85157
self::ViewPaymentStatus => __('View payment status'),
86158
self::EditPaymentStatus => __('Edit payment status'),
159+
87160
self::ManageGroupsOfEvent => __('Manage groups of event'),
88161
self::ExportGroupsOfEvent => __('Export groups of event'),
89-
self::ViewDocumentsOfEvents => __('View documents of events'),
90-
self::AddDocumentsToEvents => __('Add documents to events'),
91-
self::EditDocumentsOfEvents => __('Update documents of events'),
92-
self::DeleteDocumentsOfEvents => __('Delete documents of events'),
93-
self::ViewResponsibilitiesOfEvents => __('View responsibilities of events'),
94162

95163
self::ViewEventSeries => __('View event series'),
96164
self::ViewPrivateEventSeries => __('View private event series'),
97165
self::CreateEventSeries => __('Create event series'),
98166
self::EditEventSeries => __('Edit event series'),
99-
self::ViewDocumentsOfEventSeries => __('View documents of event series'),
100-
self::AddDocumentsToEventSeries => __('Add documents to event series'),
101-
self::EditDocumentsOfEventSeries => __('Update documents of event series'),
102-
self::DeleteDocumentsOfEventSeries => __('Delete documents of event series'),
103167
self::ViewResponsibilitiesOfEventSeries => __('View responsibilities of event series'),
104168

169+
// Basic data
170+
self::ViewOrganizations => __('View organizations'),
171+
self::CreateOrganizations => __('Create organizations'),
172+
self::EditOrganizations => __('Edit organizations'),
173+
self::ViewResponsibilitiesOfOrganizations => __('View responsibilities of organizations'),
174+
105175
self::ViewLocations => __('View locations'),
106176
self::CreateLocations => __('Create locations'),
107177
self::EditLocations => __('Edit locations'),
108178

109-
self::ViewOrganizations => __('View organizations'),
110-
self::CreateOrganizations => __('Create organizations'),
111-
self::EditOrganizations => __('Edit organizations'),
179+
// Documents
180+
self::ViewDocuments => __('View documents'),
181+
182+
self::ViewDocumentsOfEvents => __('View documents of events'),
183+
self::AddDocumentsToEvents => __('Add documents to events'),
184+
self::EditDocumentsOfEvents => __('Update documents of events'),
185+
self::DeleteDocumentsOfEvents => __('Delete documents of events'),
186+
187+
self::ViewDocumentsOfEventSeries => __('View documents of event series'),
188+
self::AddDocumentsToEventSeries => __('Add documents to event series'),
189+
self::EditDocumentsOfEventSeries => __('Update documents of event series'),
190+
self::DeleteDocumentsOfEventSeries => __('Delete documents of event series'),
191+
112192
self::ViewDocumentsOfOrganizations => __('View documents of organizations'),
113193
self::AddDocumentsToOrganizations => __('Add documents to organizations'),
114194
self::EditDocumentsOfOrganizations => __('Update documents of organizations'),
115195
self::DeleteDocumentsOfOrganizations => __('Delete documents of organizations'),
116-
self::ViewResponsibilitiesOfOrganizations => __('View responsibilities of organizations'),
117-
118-
self::ViewDocuments => __('View documents'),
119196

197+
// Users and abilities
120198
self::ViewUsers => __('View users'),
121199
self::CreateUsers => __('Create users'),
122200
self::EditUsers => __('Edit users'),
123201

124202
self::ViewUserRoles => __('View user roles'),
125203
self::CreateUserRoles => __('Create user roles'),
126204
self::EditUserRoles => __('Edit user roles'),
205+
206+
self::ViewAccount => __('View own account'),
207+
self::ViewAbilities => __('View abilities'),
208+
self::EditAccount => __('Edit own account'),
209+
self::ManagePersonalAccessTokens => __('Manage personal access tokens'),
127210
};
128211
}
212+
213+
/**
214+
* @return self[]
215+
*/
216+
public static function apiCases(): array
217+
{
218+
return [
219+
self::EditAccount,
220+
];
221+
}
129222
}

0 commit comments

Comments
 (0)