diff --git a/app/Filament/Pages/AdminTools.php b/app/Filament/Pages/AdminTools.php index 335b97c935..0f8e00e3af 100644 --- a/app/Filament/Pages/AdminTools.php +++ b/app/Filament/Pages/AdminTools.php @@ -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 { @@ -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]); } diff --git a/app/Filament/Pages/MostReportedGames.php b/app/Filament/Pages/MostReportedGames.php index 52383b1723..2647dc791f 100644 --- a/app/Filament/Pages/MostReportedGames.php +++ b/app/Filament/Pages/MostReportedGames.php @@ -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 { @@ -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, ]); } } diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index 1f70e0fb6e..c9b2714f1b 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -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 { @@ -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([ @@ -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() @@ -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() @@ -111,22 +117,27 @@ 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() @@ -134,9 +145,11 @@ public static function infolist(Infolist $infolist): Infolist ->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) { @@ -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([ @@ -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'), @@ -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() @@ -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() @@ -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() @@ -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() @@ -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'), diff --git a/app/Filament/Resources/UserResource/Pages/Roles.php b/app/Filament/Resources/UserResource/Pages/Roles.php index a6eb3d2424..d49c132f72 100644 --- a/app/Filament/Resources/UserResource/Pages/Roles.php +++ b/app/Filament/Resources/UserResource/Pages/Roles.php @@ -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(); @@ -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 { @@ -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. @@ -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); + } + } } diff --git a/app/Models/Role.php b/app/Models/Role.php index 78ec44c565..f50fc53ccc 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -5,10 +5,12 @@ namespace App\Models; use Fico7489\Laravel\Pivot\Traits\PivotEventTrait; +use Illuminate\Support\Facades\Auth; +use Spatie\Permission\Models\Role as SpatieRole; use Spatie\TypeScriptTransformer\Attributes\TypeScript; #[TypeScript('UserRole')] -class Role extends \Spatie\Permission\Models\Role +class Role extends SpatieRole { /* * Providers Traits @@ -29,7 +31,11 @@ class Role extends \Spatie\Permission\Models\Role public const GAME_HASH_MANAGER = 'game-hash-manager'; - public const DEVELOPER_STAFF = 'developer-staff'; // staff + public const DEV_COMPLIANCE = 'dev-compliance'; + + public const QUALITY_ASSURANCE = 'quality-assurance'; + + public const CODE_REVIEWER = 'code-reviewer'; public const DEVELOPER = 'developer'; @@ -75,6 +81,8 @@ class Role extends \Spatie\Permission\Models\Role // vanity roles assigned by admin + public const COMMUNITY_MANAGER = 'community-manager'; // effectively a moderator + public const DEVELOPER_RETIRED = 'developer-retired'; public static function toFilamentColor(string $role): string @@ -90,7 +98,9 @@ public static function toFilamentColor(string $role): string // creator roles assigned by admin Role::GAME_HASH_MANAGER => 'warning', - Role::DEVELOPER_STAFF => 'success', + Role::DEV_COMPLIANCE => 'success', + Role::QUALITY_ASSURANCE => 'success', + Role::CODE_REVIEWER => 'success', Role::DEVELOPER => 'success', Role::DEVELOPER_JUNIOR => 'success', Role::ARTIST => 'success', @@ -117,7 +127,9 @@ public static function toFilamentColor(string $role): string // vanity roles assigned by admin + Role::COMMUNITY_MANAGER => 'info', // effectively a moderator Role::DEVELOPER_RETIRED => 'primary', + default => 'gray', }; } @@ -132,7 +144,7 @@ public static function boot() if ($relationName === 'users') { foreach ($pivotIds as $pivotId) { $user = User::find($pivotId); - activity()->causedBy(auth()->user())->performedOn($user) + activity()->causedBy(Auth::user())->performedOn($user) ->withProperty('relationships', ['roles' => [$model->id]]) ->withProperty('attributes', ['roles' => [$model->id => []]]) ->event('pivotAttached') @@ -145,7 +157,7 @@ public static function boot() if ($relationName === 'users') { foreach ($pivotIds as $pivotId) { $user = User::find($pivotId); - activity()->causedBy(auth()->user())->performedOn($user) + activity()->causedBy(Auth::user())->performedOn($user) ->withProperty('relationships', ['roles' => [$model->id]]) ->event('pivotDetached') ->log('pivotDetached'); diff --git a/app/Policies/AchievementAuthorPolicy.php b/app/Policies/AchievementAuthorPolicy.php index 449b19b4c4..d46d0eeb44 100644 --- a/app/Policies/AchievementAuthorPolicy.php +++ b/app/Policies/AchievementAuthorPolicy.php @@ -17,7 +17,6 @@ class AchievementAuthorPolicy public function manage(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::MODERATOR, Role::TEAM_ACCOUNT, @@ -53,7 +52,6 @@ public function update(User $user, AchievementAuthor $achievementAuthor): bool public function delete(User $user, AchievementAuthor $achievementAuthor): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::MODERATOR, Role::TEAM_ACCOUNT, ]); @@ -62,7 +60,6 @@ public function delete(User $user, AchievementAuthor $achievementAuthor): bool public function restore(User $user, AchievementAuthor $achievementAuthor): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::MODERATOR, Role::TEAM_ACCOUNT, ]); @@ -77,7 +74,6 @@ public function canUpsertTask(User $user, AchievementAuthorTask $task): bool { // These roles can assign any type of credit. $alwaysAllowed = [ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::MODERATOR, Role::TEAM_ACCOUNT, diff --git a/app/Policies/AchievementPolicy.php b/app/Policies/AchievementPolicy.php index ea7d10fa00..562cb9bdbe 100644 --- a/app/Policies/AchievementPolicy.php +++ b/app/Policies/AchievementPolicy.php @@ -21,7 +21,6 @@ public function manage(User $user): bool /* * developers may at least upload new achievements to the server, create code notes, etc */ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, @@ -76,7 +75,6 @@ public function update(User $user, Achievement $achievement): bool /* * developers may at least upload new achievements to the server, create code notes, etc */ - Role::DEVELOPER_STAFF, Role::DEVELOPER, /* @@ -99,7 +97,6 @@ public function delete(User $user, Achievement $achievement): bool return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -108,7 +105,6 @@ public function restore(User $user, Achievement $achievement): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -124,7 +120,6 @@ public function updateField(User $user, ?Achievement $achievement, string $field $roleFieldPermissions = [ Role::DEVELOPER_JUNIOR => ['Title', 'Description', 'type', 'Points', 'DisplayOrder'], Role::DEVELOPER => ['Title', 'Description', 'Flags', 'type', 'Points', 'DisplayOrder'], - Role::DEVELOPER_STAFF => ['Title', 'Description', 'Flags', 'type', 'Points', 'DisplayOrder'], Role::WRITER => ['Title', 'Description'], ]; diff --git a/app/Policies/AchievementSetAuthorPolicy.php b/app/Policies/AchievementSetAuthorPolicy.php index 78e1ecbf0e..88da518e87 100644 --- a/app/Policies/AchievementSetAuthorPolicy.php +++ b/app/Policies/AchievementSetAuthorPolicy.php @@ -16,7 +16,6 @@ class AchievementSetAuthorPolicy public function manage(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, Role::ARTIST, @@ -36,7 +35,6 @@ public function view(?User $user, AchievementSetAuthor $achievementSetAuthor): b public function create(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::ARTIST, ]); @@ -45,7 +43,6 @@ public function create(User $user): bool public function update(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::ARTIST, ]); @@ -54,7 +51,6 @@ public function update(User $user): bool public function delete(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::ARTIST, ]); @@ -63,7 +59,6 @@ public function delete(User $user): bool public function restore(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::ARTIST, ]); diff --git a/app/Policies/AchievementSetClaimPolicy.php b/app/Policies/AchievementSetClaimPolicy.php index fbce15ca2f..065c3632a9 100644 --- a/app/Policies/AchievementSetClaimPolicy.php +++ b/app/Policies/AchievementSetClaimPolicy.php @@ -16,7 +16,6 @@ class AchievementSetClaimPolicy public function manage(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); @@ -35,7 +34,6 @@ public function view(?User $user, AchievementSetClaim $achievementSetClaim): boo public function create(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); diff --git a/app/Policies/AchievementSetPolicy.php b/app/Policies/AchievementSetPolicy.php index bbf0b9f9b1..085d500596 100644 --- a/app/Policies/AchievementSetPolicy.php +++ b/app/Policies/AchievementSetPolicy.php @@ -17,7 +17,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, // Juniors can see set management, but can't manipulate sets. Role::DEVELOPER_JUNIOR, @@ -38,7 +37,6 @@ public function create(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); @@ -48,7 +46,6 @@ public function update(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -57,7 +54,6 @@ public function delete(User $user, ?AchievementSet $achievementSet = null): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -66,7 +62,6 @@ public function restore(User $user, AchievementSet $achievementSet): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -80,7 +75,6 @@ public function markGameHashAsIncompatible(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } diff --git a/app/Policies/GameAchievementSetPolicy.php b/app/Policies/GameAchievementSetPolicy.php index 810ddef8a8..1f998e506b 100644 --- a/app/Policies/GameAchievementSetPolicy.php +++ b/app/Policies/GameAchievementSetPolicy.php @@ -17,7 +17,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, // Juniors can see set management, but can't manipulate sets. Role::DEVELOPER_JUNIOR, @@ -40,7 +39,6 @@ public function create(User $user): bool // they are not included in this list. return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -49,7 +47,6 @@ public function update(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -58,7 +55,6 @@ public function delete(User $user, ?GameAchievementSet $gameAchievementSet = nul { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -67,7 +63,6 @@ public function restore(User $user, GameAchievementSet $gameAchievementSet): boo { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } diff --git a/app/Policies/GameHashPolicy.php b/app/Policies/GameHashPolicy.php index fd80f1e776..994f585cda 100644 --- a/app/Policies/GameHashPolicy.php +++ b/app/Policies/GameHashPolicy.php @@ -17,7 +17,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -36,7 +35,6 @@ public function create(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -45,7 +43,6 @@ public function update(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -64,7 +61,6 @@ public function forceDelete(User $user, GameHash $gameHash): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } diff --git a/app/Policies/GamePolicy.php b/app/Policies/GamePolicy.php index 3acfa14263..be5655476f 100644 --- a/app/Policies/GamePolicy.php +++ b/app/Policies/GamePolicy.php @@ -18,7 +18,6 @@ public function manage(User $user): bool return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, @@ -33,9 +32,7 @@ public function viewAny(?User $user): bool public function view(?User $user, Game $game): bool { - /* - * TODO: check age gate - */ + // Age gates are handled at the UI level. return true; } @@ -44,7 +41,6 @@ public function create(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - // Role::DEVELOPER_STAFF, // Role::DEVELOPER, ]); } @@ -53,7 +49,6 @@ public function update(User $user, Game $game): bool { $canAlwaysUpdate = $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); @@ -98,7 +93,6 @@ public function updateField(User $user, Game $game, string $fieldName): bool Role::DEVELOPER_JUNIOR => ['GuideURL', 'Developer', 'Publisher', 'Genre', 'released_at', 'released_at_granularity'], Role::DEVELOPER => ['Title', 'GuideURL', 'Developer', 'Publisher', 'Genre', 'released_at', 'released_at_granularity'], - Role::DEVELOPER_STAFF => ['Title', 'sort_title', 'GuideURL', 'Developer', 'Publisher', 'Genre', 'released_at', 'released_at_granularity'], ]; $userRoles = $user->getRoleNames(); @@ -129,28 +123,20 @@ public function createForumTopic(User $user, Game $game): bool } return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::FORUM_MANAGER, Role::MODERATOR, ]); } - // TODO rename to viewActivitylog or use manage() ? public function viewModifications(User $user): bool { - return $user->hasAnyRole([ - Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, - Role::DEVELOPER, - Role::DEVELOPER_JUNIOR, - ]); + return $this->manage($user); } public function manageContributionCredit(User $user, Game $game): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::ARTIST, ]); diff --git a/app/Policies/GameSetPolicy.php b/app/Policies/GameSetPolicy.php index 90f0eaf6b1..9e3c0ac88f 100644 --- a/app/Policies/GameSetPolicy.php +++ b/app/Policies/GameSetPolicy.php @@ -19,7 +19,6 @@ public function manage(User $user): bool Role::GAME_HASH_MANAGER, Role::GAME_EDITOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -43,7 +42,6 @@ public function create(User $user): bool // TODO enable after dropping GameAlternatives // return $user->hasAnyRole([ // Role::ADMINISTRATOR, - // Role::DEVELOPER_STAFF, // Role::GAME_EDITOR, // ]); } @@ -72,7 +70,6 @@ public function toggleHasMatureContent(User $user, GameSet $gameSet): bool { return $user->hasAnyRole([ Role::ADMINISTRATOR, - Role::DEVELOPER_STAFF, ]); } } diff --git a/app/Policies/LeaderboardEntryPolicy.php b/app/Policies/LeaderboardEntryPolicy.php index 2d5d09c856..5b37f31a06 100644 --- a/app/Policies/LeaderboardEntryPolicy.php +++ b/app/Policies/LeaderboardEntryPolicy.php @@ -17,7 +17,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::CHEAT_INVESTIGATOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); @@ -50,7 +49,7 @@ public function delete(User $user, LeaderboardEntry $leaderboardEntry): bool Role::ROOT, Role::ADMINISTRATOR, Role::MODERATOR, - Role::DEVELOPER_STAFF, + Role::DEVELOPER, ]; diff --git a/app/Policies/LeaderboardPolicy.php b/app/Policies/LeaderboardPolicy.php index a095bfa01e..70548371b1 100644 --- a/app/Policies/LeaderboardPolicy.php +++ b/app/Policies/LeaderboardPolicy.php @@ -17,7 +17,6 @@ class LeaderboardPolicy public function manage(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); @@ -40,7 +39,6 @@ public function create(User $user, ?Game $game = null): bool } return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -52,7 +50,6 @@ public function update(User $user, Leaderboard $leaderboard): bool } return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -60,7 +57,6 @@ public function update(User $user, Leaderboard $leaderboard): bool public function delete(User $user, Leaderboard $leaderboard): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -73,7 +69,6 @@ public function restore(User $user, Leaderboard $leaderboard): bool public function forceDelete(User $user, Leaderboard $leaderboard): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -81,7 +76,6 @@ public function forceDelete(User $user, Leaderboard $leaderboard): bool public function resetAllEntries(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } diff --git a/app/Policies/MemoryNotePolicy.php b/app/Policies/MemoryNotePolicy.php index a7fd40ca84..15ac5c79e0 100644 --- a/app/Policies/MemoryNotePolicy.php +++ b/app/Policies/MemoryNotePolicy.php @@ -17,7 +17,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::DEVELOPER_JUNIOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -36,7 +35,6 @@ public function create(User $user): bool { return $user->hasAnyRole([ Role::DEVELOPER_JUNIOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -49,7 +47,6 @@ public function update(User $user, MemoryNote $memoryNote): bool } return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } @@ -62,7 +59,6 @@ public function delete(User $user, MemoryNote $memoryNote): bool } return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, ]); } diff --git a/app/Policies/MessagePolicy.php b/app/Policies/MessagePolicy.php index f0cdbac169..be4898b60c 100644 --- a/app/Policies/MessagePolicy.php +++ b/app/Policies/MessagePolicy.php @@ -69,7 +69,6 @@ public function sendToRecipient(User $user, User $targetUser): bool $canUserAlwaysPierceNoContactPreference = $user->hasAnyRole([ Role::ADMINISTRATOR, Role::DEVELOPER_JUNIOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::EVENT_MANAGER, Role::FORUM_MANAGER, diff --git a/app/Policies/NewsPolicy.php b/app/Policies/NewsPolicy.php index afd783cdec..f4a9aea433 100644 --- a/app/Policies/NewsPolicy.php +++ b/app/Policies/NewsPolicy.php @@ -17,7 +17,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::ADMINISTRATOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::EVENT_MANAGER, Role::MODERATOR, @@ -40,7 +39,6 @@ public function create(User $user): bool { return $user->hasAnyRole([ Role::ADMINISTRATOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::EVENT_MANAGER, Role::MODERATOR, @@ -53,7 +51,6 @@ public function update(User $user, News $news): bool { return $user->hasAnyRole([ Role::ADMINISTRATOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::EVENT_MANAGER, Role::MODERATOR, diff --git a/app/Policies/TicketPolicy.php b/app/Policies/TicketPolicy.php index e2642e9be6..7caef317a1 100644 --- a/app/Policies/TicketPolicy.php +++ b/app/Policies/TicketPolicy.php @@ -18,7 +18,6 @@ public function manage(User $user): bool return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, Role::TICKET_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); @@ -46,7 +45,6 @@ public function create(User $user): bool public function updateState(User $user): bool { return $user->hasAnyRole([ - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::TICKET_MANAGER, ]); diff --git a/app/Policies/TriggerTicketPolicy.php b/app/Policies/TriggerTicketPolicy.php index 0547339e82..5d11c759c2 100644 --- a/app/Policies/TriggerTicketPolicy.php +++ b/app/Policies/TriggerTicketPolicy.php @@ -19,7 +19,6 @@ public function manage(User $user): bool { return $user->hasAnyRole([ Role::GAME_HASH_MANAGER, - Role::DEVELOPER_STAFF, Role::DEVELOPER, Role::DEVELOPER_JUNIOR, ]); diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 9021c3edd3..317883d63f 100755 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -33,7 +33,6 @@ public function boot(): void Role::ROOT, Role::ADMINISTRATOR, Role::MODERATOR, - // Role::COMMUNITY_MANAGER, // rather a mix of moderator and specialized management role? Role::EVENT_MANAGER, Role::FORUM_MANAGER, Role::GAME_HASH_MANAGER, @@ -44,9 +43,7 @@ public function boot(): void Role::ARTIST, Role::WRITER, Role::GAME_EDITOR, - ]) - // TODO remove as soon as permission matrix is in place - || $user->getAttribute('Permissions') >= Permissions::JuniorDeveloper); + ])); /* * can "create". meant for creator tools opt-in @@ -55,9 +52,7 @@ public function boot(): void Role::DEVELOPER, Role::ARTIST, Role::WRITER, - ]) - // TODO remove as soon as permission matrix is in place - || $user->getAttribute('Permissions') >= Permissions::JuniorDeveloper); + ])); /* * settings diff --git a/config/roles.php b/config/roles.php index df30347a01..8137508e81 100644 --- a/config/roles.php +++ b/config/roles.php @@ -16,8 +16,10 @@ $adminAssignable = [ Role::ARTIST, Role::CHEAT_INVESTIGATOR, + Role::CODE_REVIEWER, + Role::COMMUNITY_MANAGER, + Role::DEV_COMPLIANCE, Role::DEVELOPER_JUNIOR, - Role::DEVELOPER_STAFF, Role::DEVELOPER_RETIRED, Role::DEVELOPER, Role::EVENT_MANAGER, @@ -27,15 +29,11 @@ Role::MODERATOR, Role::NEWS_MANAGER, Role::PLAY_TESTER, + Role::QUALITY_ASSURANCE, Role::TICKET_MANAGER, Role::WRITER, ]; -$staffDevAssignable = [ - Role::DEVELOPER, - Role::DEVELOPER_JUNIOR, -]; - /* * Note: permissions are not assigned to roles in database for now - check AuthServiceProvider */ @@ -73,9 +71,20 @@ 'legacy_role' => Permissions::Moderator, ], [ - 'name' => Role::DEVELOPER_STAFF, // staff dev + 'name' => Role::DEV_COMPLIANCE, + 'display' => 4, + 'staff' => true, + 'legacy_role' => Permissions::Developer, + ], + [ + 'name' => Role::QUALITY_ASSURANCE, + 'display' => 4, + 'staff' => true, + 'legacy_role' => Permissions::Developer, + ], + [ + 'name' => Role::CODE_REVIEWER, 'display' => 4, - 'assign' => $staffDevAssignable, 'staff' => true, 'legacy_role' => Permissions::Developer, ], @@ -182,6 +191,11 @@ // vanity roles assigned by admin + [ + 'name' => Role::COMMUNITY_MANAGER, + 'display' => 3, + 'legacy_role' => Permissions::Registered, + ], [ 'name' => Role::DEVELOPER_RETIRED, 'display' => 5, diff --git a/lang/en/permission.php b/lang/en/permission.php index 6d5d44d128..c53da952b8 100755 --- a/lang/en/permission.php +++ b/lang/en/permission.php @@ -15,7 +15,9 @@ // creator roles - Role::DEVELOPER_STAFF => __('Staff Developer'), + Role::DEV_COMPLIANCE => __('Developer Compliance'), + Role::QUALITY_ASSURANCE => __('Quality Assurance'), + Role::CODE_REVIEWER => __('Code Reviewer'), Role::DEVELOPER => __('Developer'), Role::DEVELOPER_JUNIOR => __('Junior Developer'), Role::ARTIST => __('Artist'), @@ -41,6 +43,7 @@ // vanity roles assigned by admins + Role::COMMUNITY_MANAGER => __('Community Manager'), Role::DEVELOPER_RETIRED => __('Developer (retired)'), ], ]; diff --git a/public/request/user/update.php b/public/request/user/update.php index 8d6ec539d2..9247462619 100644 --- a/public/request/user/update.php +++ b/public/request/user/update.php @@ -41,9 +41,15 @@ } elseif ($value === Permissions::Registered) { $foundTargetUser->removeRole(Role::DEVELOPER_JUNIOR); $foundTargetUser->removeRole(Role::DEVELOPER); + $foundTargetUser->removeRole(Role::DEV_COMPLIANCE); + $foundTargetUser->removeRole(Role::QUALITY_ASSURANCE); + $foundTargetUser->removeRole(Role::CODE_REVIEWER); $foundTargetUser->removeRole(Role::MODERATOR); } elseif ($value === Permissions::JuniorDeveloper) { $foundTargetUser->removeRole(Role::DEVELOPER); + $foundTargetUser->removeRole(Role::DEV_COMPLIANCE); + $foundTargetUser->removeRole(Role::QUALITY_ASSURANCE); + $foundTargetUser->removeRole(Role::CODE_REVIEWER); $foundTargetUser->removeRole(Role::MODERATOR); $foundTargetUser->assignRole(Role::DEVELOPER_JUNIOR); diff --git a/resources/js/common/utils/generatedAppConstants.ts b/resources/js/common/utils/generatedAppConstants.ts index 349838d4c5..91b516c339 100644 --- a/resources/js/common/utils/generatedAppConstants.ts +++ b/resources/js/common/utils/generatedAppConstants.ts @@ -63,7 +63,9 @@ export const UserRole = { ADMINISTRATOR: 'administrator', RELEASE_MANAGER: 'release-manager', GAME_HASH_MANAGER: 'game-hash-manager', - DEVELOPER_STAFF: 'developer-staff', + DEV_COMPLIANCE: 'dev-compliance', + QUALITY_ASSURANCE: 'quality-assurance', + CODE_REVIEWER: 'code-reviewer', DEVELOPER: 'developer', DEVELOPER_JUNIOR: 'developer-junior', ARTIST: 'artist', @@ -81,6 +83,7 @@ export const UserRole = { ENGINEER: 'engineer', TEAM_ACCOUNT: 'team-account', BETA: 'beta', + COMMUNITY_MANAGER: 'community-manager', DEVELOPER_RETIRED: 'developer-retired', } as const; diff --git a/resources/js/types/generated.d.ts b/resources/js/types/generated.d.ts index 7872b27820..bba0994f5a 100644 --- a/resources/js/types/generated.d.ts +++ b/resources/js/types/generated.d.ts @@ -269,7 +269,9 @@ declare namespace App.Models { | 'administrator' | 'release-manager' | 'game-hash-manager' - | 'developer-staff' + | 'dev-compliance' + | 'quality-assurance' + | 'code-reviewer' | 'developer' | 'developer-junior' | 'artist' @@ -287,6 +289,7 @@ declare namespace App.Models { | 'engineer' | 'team-account' | 'beta' + | 'community-manager' | 'developer-retired'; } declare namespace App.Platform.Data {