Skip to content

Commit 58b1ebd

Browse files
scott graysonscott grayson
authored andcommitted
permission updates
1 parent 22d6927 commit 58b1ebd

File tree

12 files changed

+273
-223
lines changed

12 files changed

+273
-223
lines changed

src/Models/LibraryItem.php

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,13 @@ class LibraryItem extends Model implements HasMedia
2727
'updated_by',
2828
'external_url',
2929
'link_description',
30-
'inherits_from_parent',
31-
'link_role',
32-
'link_token',
3330
'general_access',
3431
];
3532

3633
protected $casts = [
3734
'created_at' => 'datetime',
3835
'updated_at' => 'datetime',
3936
'deleted_at' => 'datetime',
40-
'inherits_from_parent' => 'boolean',
4137
];
4238

4339
/**
@@ -60,19 +56,24 @@ protected static function boot(): void
6056
});
6157

6258
static::created(function (self $item) {
63-
// Creator gets special status - no need to store in permissions table
64-
// They can never lose access and are always the creator
59+
// Copy parent folder permissions to the new item
60+
if ($item->parent_id) {
61+
$parentPermissions = $item->parent->resourcePermissions()->get();
62+
63+
foreach ($parentPermissions as $permission) {
64+
$item->resourcePermissions()->create([
65+
'user_id' => $permission->user_id,
66+
'role' => $permission->role,
67+
]);
68+
}
69+
}
6570
});
6671

6772
static::updating(function (self $item) {
6873
if ($item->isDirty('name') && ! $item->isDirty('slug')) {
6974
$item->slug = static::generateUniqueSlug($item->name, $item->parent_id, $item->id);
7075
}
7176

72-
// Generate link token when link_role is set for the first time
73-
if ($item->isDirty('link_role') && $item->link_role && !$item->link_token) {
74-
$item->link_token = static::generateLinkToken();
75-
}
7677

7778
// Set updated_by on updates
7879
if (auth()->check()) {
@@ -358,6 +359,11 @@ public function getInheritedGeneralAccessDisplay(): ?string
358359
*/
359360
public function hasPermission($user, string $permission): bool
360361
{
362+
// Admin users always have all permissions
363+
if ($user && $user->hasRole('Admin')) {
364+
return true;
365+
}
366+
361367
$effectiveRole = $this->getEffectiveRole($user);
362368

363369
if (!$effectiveRole) {
@@ -525,17 +531,6 @@ protected static function generateUniqueSlug(string $name, ?int $parentId = null
525531
return $slug;
526532
}
527533

528-
/**
529-
* Generate a unique link token for sharing.
530-
*/
531-
protected static function generateLinkToken(): string
532-
{
533-
do {
534-
$token = Str::random(32);
535-
} while (static::where('link_token', $token)->exists());
536-
537-
return $token;
538-
}
539534

540535
/**
541536
* Get the access control options for the general access select.
@@ -545,8 +540,7 @@ public static function getAccessControlOptions(): array
545540
return [
546541
'inherit' => 'Inherit from parent',
547542
'private' => 'Private (owner only)',
548-
'link_viewer' => 'Anyone with link — Viewer',
549-
'link_editor' => 'Anyone with link — Editor',
543+
'anyone_can_view' => 'Anyone can view',
550544
];
551545
}
552546

@@ -555,22 +549,17 @@ public static function getAccessControlOptions(): array
555549
*/
556550
public function getEffectiveAccessControl(): string
557551
{
558-
if (!$this->inherits_from_parent) {
559-
if ($this->link_role === 'viewer') {
560-
return 'link_viewer';
561-
} elseif ($this->link_role === 'editor') {
562-
return 'link_editor';
563-
} else {
564-
return 'private';
565-
}
552+
// If not inheriting, use the item's own setting
553+
if ($this->general_access && $this->general_access !== 'inherit') {
554+
return $this->general_access;
566555
}
567556

568-
// If inheriting from parent, check parent's setting
557+
// If inheriting from parent, check parent's access control
569558
if ($this->parent_id) {
570559
return $this->parent->getEffectiveAccessControl();
571560
}
572561

573-
// Root level defaults to private
562+
// Root level items default to private
574563
return 'private';
575564
}
576565

src/Resources/Pages/CreatedByMe.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,12 @@ public function getSubheading(): ?string
3434
{
3535
return 'Files and folders you created';
3636
}
37+
38+
public function getBreadcrumbs(): array
39+
{
40+
return [
41+
static::getResource()::getUrl() => 'Library',
42+
'' => 'Created by Me',
43+
];
44+
}
3745
}

src/Resources/Pages/EditFile.php

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,28 @@ protected function getHeaderActions(): array
2222
{
2323
$actions = [];
2424

25-
// Add "View Folder" action if we have a parent
25+
// Add "Up One Level" action if we have a parent
2626
if ($this->getRecord()->parent_id) {
27-
$actions[] = Action::make('view_folder')
28-
->label('View Folder')
27+
$actions[] = Action::make('up_one_level')
28+
->label('Up One Level')
2929
->icon('heroicon-o-arrow-up')
3030
->color('gray')
3131
->url(
3232
fn (): string => static::getResource()::getUrl('index', ['parent' => $this->getRecord()->parent_id])
3333
);
3434
}
3535

36+
// Add "View" action - for folders go to list page, for files/links go to view page
37+
$viewUrl = $this->getRecord()->type === 'folder'
38+
? static::getResource()::getUrl('index', ['parent' => $this->getRecord()->id])
39+
: static::getResource()::getUrl('view', ['record' => $this->getRecord()->id]);
40+
41+
$actions[] = Action::make('view')
42+
->label('View')
43+
->icon('heroicon-o-eye')
44+
->color('gray')
45+
->url($viewUrl);
46+
3647
$actions[] = DeleteAction::make()
3748
->before(function () {
3849
// Store parent_id before deletion
@@ -53,7 +64,6 @@ protected function mutateFormDataBeforeFill(array $data): array
5364
// Remove fields that shouldn't be editable
5465
unset($data['type']);
5566
unset($data['parent_id']);
56-
unset($data['created_by']);
5767

5868
// Load the current file into the media input
5969
$record = $this->getRecord();
@@ -117,6 +127,39 @@ public function form(\Filament\Schemas\Schema $schema): \Filament\Schemas\Schema
117127
return $baseText;
118128
})
119129
->visible(fn () => $this->getRecord()->hasPermission(auth()->user(), 'share')),
130+
131+
// Creator select field
132+
\Filament\Forms\Components\Select::make('created_by')
133+
->label('Creator')
134+
->options(function () {
135+
return \App\Models\User::all()->mapWithKeys(function ($user) {
136+
// Check if 'name' field exists and has a value
137+
if (\Illuminate\Support\Facades\Schema::hasColumn('users', 'name') && $user->name) {
138+
return [$user->id => $user->name . ' (' . $user->email . ')'];
139+
}
140+
141+
// Fall back to first_name/last_name if available
142+
if (\Illuminate\Support\Facades\Schema::hasColumn('users', 'first_name') && \Illuminate\Support\Facades\Schema::hasColumn('users', 'last_name')) {
143+
$firstName = $user->first_name ?? '';
144+
$lastName = $user->last_name ?? '';
145+
$fullName = trim($firstName . ' ' . $lastName);
146+
147+
if ($fullName) {
148+
return [$user->id => $fullName . ' (' . $user->email . ')'];
149+
}
150+
}
151+
152+
// Fall back to email only
153+
return [$user->id => $user->email];
154+
});
155+
})
156+
->searchable()
157+
->preload()
158+
->disabled(function () {
159+
// Only allow changes if user has library admin access (Admin role)
160+
return !auth()->user()?->hasRole('Admin');
161+
})
162+
->helperText('Creator receives owner permissions'),
120163
]);
121164
}
122165

src/Resources/Pages/EditFolder.php

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,28 @@ protected function getHeaderActions(): array
2626
{
2727
$actions = [];
2828

29-
// Add "View Folder" action if we have a parent
29+
// Add "Up One Level" action if we have a parent
3030
if ($this->getRecord()->parent_id) {
31-
$actions[] = Action::make('view_folder')
32-
->label('View Folder')
31+
$actions[] = Action::make('up_one_level')
32+
->label('Up One Level')
3333
->icon('heroicon-o-arrow-up')
3434
->color('gray')
3535
->url(
3636
fn (): string => static::getResource()::getUrl('index', ['parent' => $this->getRecord()->parent_id])
3737
);
3838
}
3939

40+
// Add "View" action - for folders go to list page, for files/links go to view page
41+
$viewUrl = $this->getRecord()->type === 'folder'
42+
? static::getResource()::getUrl('index', ['parent' => $this->getRecord()->id])
43+
: static::getResource()::getUrl('view', ['record' => $this->getRecord()->id]);
44+
45+
$actions[] = Action::make('view')
46+
->label('View')
47+
->icon('heroicon-o-eye')
48+
->color('gray')
49+
->url($viewUrl);
50+
4051
$actions[] = DeleteAction::make()
4152
->before(function () {
4253
// Store parent_id before deletion
@@ -57,7 +68,6 @@ protected function mutateFormDataBeforeFill(array $data): array
5768
// Remove fields that shouldn't be editable
5869
unset($data['type']);
5970
unset($data['parent_id']);
60-
unset($data['created_by']);
6171

6272
return $data;
6373
}
@@ -111,6 +121,39 @@ public function form(\Filament\Schemas\Schema $schema): \Filament\Schemas\Schema
111121
return $baseText;
112122
})
113123
->visible(fn () => $this->getRecord()->hasPermission(auth()->user(), 'share')),
124+
125+
// Creator select field
126+
\Filament\Forms\Components\Select::make('created_by')
127+
->label('Creator')
128+
->options(function () {
129+
return \App\Models\User::all()->mapWithKeys(function ($user) {
130+
// Check if 'name' field exists and has a value
131+
if (\Illuminate\Support\Facades\Schema::hasColumn('users', 'name') && $user->name) {
132+
return [$user->id => $user->name . ' (' . $user->email . ')'];
133+
}
134+
135+
// Fall back to first_name/last_name if available
136+
if (\Illuminate\Support\Facades\Schema::hasColumn('users', 'first_name') && \Illuminate\Support\Facades\Schema::hasColumn('users', 'last_name')) {
137+
$firstName = $user->first_name ?? '';
138+
$lastName = $user->last_name ?? '';
139+
$fullName = trim($firstName . ' ' . $lastName);
140+
141+
if ($fullName) {
142+
return [$user->id => $fullName . ' (' . $user->email . ')'];
143+
}
144+
}
145+
146+
// Fall back to email only
147+
return [$user->id => $user->email];
148+
});
149+
})
150+
->searchable()
151+
->preload()
152+
->disabled(function () {
153+
// Only allow changes if user has library admin access (Admin role)
154+
return !auth()->user()?->hasRole('Admin');
155+
})
156+
->helperText('Creator receives owner permissions'),
114157
]);
115158
}
116159

0 commit comments

Comments
 (0)