Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: split Staff Dev role into separate roles, add CM vanity role #2972

Merged
Merged
7 changes: 6 additions & 1 deletion app/Filament/Pages/AdminTools.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Models\Role;
use App\Models\User;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;

class AdminTools extends Page
{
Expand All @@ -23,7 +24,11 @@ class AdminTools extends Page
public static function canAccess(): bool
{
/** @var User $user */
$user = auth()->user();
$user = Auth::user();

if (!$user) {
return false;
}

return $user->hasAnyRole([Role::MODERATOR, Role::ADMINISTRATOR]);
}
Expand Down
8 changes: 6 additions & 2 deletions app/Filament/Pages/MostReportedGames.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Models\Role;
use App\Models\User;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;

class MostReportedGames extends Page
{
Expand All @@ -21,13 +22,16 @@ class MostReportedGames extends Page
public static function canAccess(): bool
{
/** @var User $user */
$user = auth()->user();
$user = Auth::user();

if (!$user) {
return false;
}

return $user->hasAnyRole([
Role::ADMINISTRATOR,
Role::DEVELOPER,
Role::DEVELOPER_JUNIOR,
Role::DEVELOPER_STAFF,
]);
}
}
38 changes: 38 additions & 0 deletions app/Filament/Resources/UserResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Facades\Auth;

class UserResource extends Resource
{
Expand Down Expand Up @@ -60,6 +61,9 @@ public static function getGloballySearchableAttributes(): array

public static function infolist(Infolist $infolist): Infolist
{
/** @var User $user */
$user = Auth::user();

return $infolist
->columns(1)
->schema([
Expand All @@ -72,6 +76,7 @@ public static function infolist(Infolist $infolist): Infolist
Infolists\Components\ImageEntry::make('avatar_url')
->label('Avatar')
->size(config('media.icon.lg.width')),

Infolists\Components\TextEntry::make('Motto'),
]),
Infolists\Components\Group::make()
Expand All @@ -81,6 +86,7 @@ public static function infolist(Infolist $infolist): Infolist
->formatStateUsing(fn (string $state): string => __('permission.role.' . $state))
->color(fn (string $state): string => Role::toFilamentColor($state))
->hidden(fn ($record) => $record->roles->isEmpty()),

Infolists\Components\TextEntry::make('Permissions')
->label('Permissions (legacy)')
->badge()
Expand Down Expand Up @@ -111,32 +117,39 @@ public static function infolist(Infolist $infolist): Infolist
->schema([
Infolists\Components\TextEntry::make('id')
->label('ID'),

Infolists\Components\TextEntry::make('Created')
->label('Joined')
->dateTime(),

Infolists\Components\TextEntry::make('LastLogin')
->label('Last login at')
->dateTime(),

Infolists\Components\TextEntry::make('DeleteRequested')
->label('Deleted requested at')
->dateTime()
->hidden(fn ($state) => !$state)
->color('warning'),

Infolists\Components\TextEntry::make('Deleted')
->label('Deleted at')
->dateTime()
->hidden(fn ($state) => !$state)
->color('danger'),

Infolists\Components\IconEntry::make('Untracked')
->label('Ranked')
->boolean()
->trueColor('danger')
->trueIcon('heroicon-o-x-circle')
->falseColor('success')
->falseIcon('heroicon-o-check-circle'),

Infolists\Components\IconEntry::make('ManuallyVerified')
->label('Forum verified')
->boolean(),

Infolists\Components\TextEntry::make('muted_until')
->hidden(function ($state) {
if (!$state) {
Expand Down Expand Up @@ -165,6 +178,7 @@ public static function form(Form $form): Form
Forms\Components\TextInput::make('Motto')
->maxLength(50),
]),

Forms\Components\Section::make()
->grow(false)
->schema([
Expand All @@ -185,8 +199,10 @@ public static function form(Form $form): Form
$component->state($formattedDate);
}
}),

Forms\Components\Toggle::make('ManuallyVerified')
->label('Forum verified'),

Forms\Components\Toggle::make('Untracked'),
]),
])->from('md'),
Expand All @@ -200,25 +216,31 @@ public static function table(Table $table): Table
Tables\Columns\ImageColumn::make('avatar_url')
->label('')
->size(config('media.icon.sm.width')),

Tables\Columns\TextColumn::make('ID')
->label('ID')
->searchable()
->sortable(),

Tables\Columns\TextColumn::make('User')
->description(fn (User $record): string => $record->display_name)
->label('Username')
->searchable(),

Tables\Columns\TextColumn::make('display_name')
->searchable()
->toggleable(isToggledHiddenByDefault: true),

// Tables\Columns\TextColumn::make('email_verified_at')
// ->dateTime()
// ->sortable()
// ->toggleable(isToggledHiddenByDefault: true),

Tables\Columns\TextColumn::make('roles.name')
->badge()
->formatStateUsing(fn (string $state): string => __('permission.role.' . $state))
->color(fn (string $state): string => Role::toFilamentColor($state)),

Tables\Columns\TextColumn::make('Permissions')
->label('Legacy permissions')
->badge()
Expand All @@ -231,17 +253,21 @@ public static function table(Table $table): Table
Permissions::Moderator => 'warning',
default => 'gray',
}),

// Tables\Columns\TextColumn::make('country'),
// Tables\Columns\TextColumn::make('timezone'),
// Tables\Columns\TextColumn::make('locale'),

Tables\Columns\IconColumn::make('ManuallyVerified')
->label('Forum verified')
->boolean()
->alignCenter(),

// Tables\Columns\TextColumn::make('forum_verified_at')
// ->dateTime()
// ->sortable()
// ->toggleable(isToggledHiddenByDefault: true),

Tables\Columns\IconColumn::make('Untracked')
->label('Ranked')
->boolean()
Expand All @@ -250,38 +276,47 @@ public static function table(Table $table): Table
->falseColor('success')
->falseIcon('heroicon-o-check-circle')
->alignCenter(),

// Tables\Columns\TextColumn::make('unranked_at')
// ->dateTime()
// ->sortable(),

// Tables\Columns\TextColumn::make('banned_at')
// ->dateTime()
// ->sortable(),

// Tables\Columns\TextColumn::make('muted_until')
// ->dateTime()
// ->sortable(),

Tables\Columns\IconColumn::make('UserWallActive')
->label('Wall active')
->boolean()
->alignCenter(),

Tables\Columns\TextColumn::make('Created')
->label('Created at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),

Tables\Columns\TextColumn::make('LastLogin')
->label('Last login at')
->dateTime()
->sortable(),

Tables\Columns\TextColumn::make('Updated')
->label('Updated at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),

Tables\Columns\TextColumn::make('DeleteRequested')
->label('Deleted requested at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),

Tables\Columns\TextColumn::make('Deleted')
->label('Deleted at')
->dateTime()
Expand All @@ -296,6 +331,7 @@ public static function table(Table $table): Table
collect(Permissions::cases())
->mapWithKeys(fn ($value) => [$value => __(Permissions::toString($value))])
),

Filters\TrashedFilter::make(),
])
->deferFilters()
Expand All @@ -305,9 +341,11 @@ public static function table(Table $table): Table
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])->dropdown(false),

Tables\Actions\Action::make('roles')
->url(fn ($record) => UserResource::getUrl('roles', ['record' => $record]))
->icon('fas-lock'),

Tables\Actions\Action::make('audit-log')
->url(fn ($record) => UserResource::getUrl('audit-log', ['record' => $record]))
->icon('fas-clock-rotate-left'),
Expand Down
44 changes: 33 additions & 11 deletions app/Filament/Resources/UserResource/Pages/Roles.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,21 @@ public function table(Table $table): Table
->authorize(fn () => $user->can('updateRoles', $this->getRecord()))
->recordTitle(fn (Model $record) => __('permission.role.' . $record->name))
->preloadRecordSelect()
->recordSelectOptionsQuery(fn (Builder $query) => $query->whereIn('name', $user->assignableRoles))
->recordSelectOptionsQuery(function (Builder $query) {
/** @var User $targetUser */
$targetUser = $this->getRecord();

// Start with basic role filtering based on user permissions.
$query->whereIn('name', Auth::user()->assignableRoles);

// If trying to assign staff developer roles, ensure the user has Role::DEVELOPER.
$staffRoles = [Role::QUALITY_ASSURANCE, Role::DEV_COMPLIANCE, Role::CODE_REVIEWER];
if (!$targetUser->hasRole(Role::DEVELOPER)) {
$query->whereNotIn('name', $staffRoles);
}

return $query;
})
->after(function ($data) {
/** @var User $targetUser */
$targetUser = $this->getRecord();
Expand All @@ -55,26 +69,19 @@ public function table(Table $table): Table

if ($attachedRole->name === Role::DEVELOPER_JUNIOR) {
$targetUser->removeRole(Role::DEVELOPER);
$targetUser->removeRole(Role::DEVELOPER_STAFF);
$targetUser->removeRole(Role::DEVELOPER_RETIRED);
$this->removeDeveloperStaffRoles($targetUser); // jr devs cannot be staff

$newPermissions = Permissions::JuniorDeveloper;
} elseif ($attachedRole->name === Role::DEVELOPER) {
$targetUser->removeRole(Role::DEVELOPER_JUNIOR);
$targetUser->removeRole(Role::DEVELOPER_STAFF);
$targetUser->removeRole(Role::DEVELOPER_RETIRED);

$newPermissions = Permissions::Developer;
} elseif ($attachedRole->name === Role::DEVELOPER_STAFF) {
$targetUser->removeRole(Role::DEVELOPER_JUNIOR);
$targetUser->removeRole(Role::DEVELOPER);
$targetUser->removeRole(Role::DEVELOPER_RETIRED);

$newPermissions = Permissions::Developer;
} elseif ($attachedRole->name === Role::DEVELOPER_RETIRED) {
$targetUser->removeRole(Role::DEVELOPER_JUNIOR);
$targetUser->removeRole(Role::DEVELOPER);
$targetUser->removeRole(Role::DEVELOPER_STAFF);
$this->removeDeveloperStaffRoles($targetUser); // retired devs cannot be staff

$newPermissions = Permissions::Registered;
} else {
Expand Down Expand Up @@ -104,12 +111,14 @@ public function table(Table $table): Table
if (!in_array($record->name, [
Role::DEVELOPER_JUNIOR,
Role::DEVELOPER,
Role::DEVELOPER_STAFF,
Role::DEVELOPER_RETIRED,
])) {
return;
}

// When manually detaching any dev role, remove all staff dev roles.
$this->removeDeveloperStaffRoles($targetUser);

// Keep legacy permissions in sync.
$currentPermissions = (int) $targetUser->getAttribute('Permissions');
// Don't strip moderation power away if the user already has it.
Expand All @@ -123,4 +132,17 @@ public function table(Table $table): Table
Tables\Actions\BulkActionGroup::make([]),
]);
}

private function removeDeveloperStaffRoles(User $targetUser): void
{
if ($targetUser->hasRole(Role::QUALITY_ASSURANCE)) {
$targetUser->removeRole(Role::QUALITY_ASSURANCE);
}
if ($targetUser->hasRole(Role::DEV_COMPLIANCE)) {
$targetUser->removeRole(Role::DEV_COMPLIANCE);
}
if ($targetUser->hasRole(Role::CODE_REVIEWER)) {
$targetUser->removeRole(Role::CODE_REVIEWER);
}
Jamiras marked this conversation as resolved.
Show resolved Hide resolved
}
}
Loading