Separate user uploadable avatars into own setting (#1286)

This commit is contained in:
Boy132 2025-04-23 16:02:52 +02:00 committed by GitHub
parent 90fd73f6a4
commit 914e215bc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 42 additions and 52 deletions

View File

@ -2,11 +2,11 @@
namespace App\Extensions\Avatar;
use Filament\AvatarProviders\Contracts\AvatarProvider as AvatarProviderContract;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
abstract class AvatarProvider implements AvatarProviderContract
abstract class AvatarProvider
{
/**
* @var array<string, static>
@ -33,6 +33,8 @@ abstract class AvatarProvider implements AvatarProviderContract
abstract public function getId(): string;
abstract public function get(User $user): ?string;
public function getName(): string
{
return Str::title($this->getId());

View File

@ -4,8 +4,6 @@ namespace App\Extensions\Avatar\Providers;
use App\Extensions\Avatar\AvatarProvider;
use App\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
class GravatarProvider extends AvatarProvider
{
@ -14,10 +12,9 @@ class GravatarProvider extends AvatarProvider
return 'gravatar';
}
public function get(Model|Authenticatable $record): string
public function get(User $user): string
{
/** @var User $record */
return 'https://gravatar.com/avatar/' . md5($record->email);
return 'https://gravatar.com/avatar/' . md5($user->email);
}
public static function register(): self

View File

@ -1,29 +0,0 @@
<?php
namespace App\Extensions\Avatar\Providers;
use App\Extensions\Avatar\AvatarProvider;
use Filament\AvatarProviders\UiAvatarsProvider as FilamentUiAvatarsProvider;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class LocalAvatarProvider extends AvatarProvider
{
public function getId(): string
{
return 'local';
}
public function get(Model|Authenticatable $record): string
{
$path = 'avatars/' . $record->getKey() . '.png';
return Storage::disk('public')->exists($path) ? Storage::url($path) : (new FilamentUiAvatarsProvider())->get($record);
}
public static function register(): self
{
return new self();
}
}

View File

@ -3,9 +3,7 @@
namespace App\Extensions\Avatar\Providers;
use App\Extensions\Avatar\AvatarProvider;
use Filament\AvatarProviders\UiAvatarsProvider as FilamentUiAvatarsProvider;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use App\Models\User;
class UiAvatarsProvider extends AvatarProvider
{
@ -19,9 +17,10 @@ class UiAvatarsProvider extends AvatarProvider
return 'UI Avatars';
}
public function get(Model|Authenticatable $record): string
public function get(User $user): ?string
{
return (new FilamentUiAvatarsProvider())->get($record);
// UI Avatars is the default of filament so just return null here
return null;
}
public static function register(): self

View File

@ -161,11 +161,20 @@ class Settings extends Page implements HasForms
->default(env('FILAMENT_TOP_NAVIGATION', config('panel.filament.top-navigation'))),
Select::make('FILAMENT_AVATAR_PROVIDER')
->label(trans('admin/setting.general.avatar_provider'))
->columnSpan(2)
->native(false)
->options(collect(AvatarProvider::getAll())->mapWithKeys(fn ($provider) => [$provider->getId() => $provider->getName()]))
->selectablePlaceholder(false)
->default(env('FILAMENT_AVATAR_PROVIDER', config('panel.filament.avatar-provider'))),
Toggle::make('FILAMENT_UPLOADABLE_AVATARS')
->label(trans('admin/setting.general.uploadable_avatars'))
->inline(false)
->onIcon('tabler-check')
->offIcon('tabler-x')
->onColor('success')
->offColor('danger')
->formatStateUsing(fn ($state) => (bool) $state)
->afterStateUpdated(fn ($state, Set $set) => $set('FILAMENT_UPLOADABLE_AVATARS', (bool) $state))
->default(env('FILAMENT_UPLOADABLE_AVATARS', config('panel.filament.uploadable-avatars'))),
]),
ToggleButtons::make('PANEL_USE_BINARY_PREFIX')
->label(trans('admin/setting.general.unit_prefix'))

View File

@ -128,7 +128,7 @@ class EditProfile extends BaseEditProfile
->options(fn (LanguageService $languageService) => $languageService->getAvailableLanguages())
->native(false),
FileUpload::make('avatar')
->visible(fn () => config('panel.filament.avatar-provider') === 'local')
->visible(fn () => config('panel.filament.uploadable-avatars'))
->avatar()
->acceptedFileTypes(['image/png'])
->directory('avatars')

View File

@ -4,6 +4,7 @@ namespace App\Models;
use App\Contracts\Validatable;
use App\Exceptions\DisplayException;
use App\Extensions\Avatar\AvatarProvider;
use App\Rules\Username;
use App\Facades\Activity;
use App\Traits\HasValidation;
@ -23,6 +24,7 @@ use Illuminate\Auth\Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Traits\HasAccessTokens;
use Filament\Models\Contracts\HasAvatar;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\Access\Authorizable;
@ -30,6 +32,7 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Support\Facades\Storage;
use ResourceBundle;
use Spatie\Permission\Traits\HasRoles;
@ -87,7 +90,7 @@ use Spatie\Permission\Traits\HasRoles;
* @method static Builder|User whereUsername($value)
* @method static Builder|User whereUuid($value)
*/
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, FilamentUser, HasName, HasTenants, Validatable
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, FilamentUser, HasAvatar, HasName, HasTenants, Validatable
{
use Authenticatable;
use Authorizable { can as protected canned; }
@ -372,6 +375,21 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
return $this->username;
}
public function getFilamentAvatarUrl(): ?string
{
if (config('panel.filament.uploadable-avatars')) {
$path = "avatars/$this->id.png";
if (Storage::disk('public')->exists($path)) {
return Storage::url($path);
}
}
$provider = AvatarProvider::getProvider(config('panel.filament.avatar-provider'));
return $provider?->get($this);
}
public function canTarget(Model $user): bool
{
if ($this->isRootAdmin()) {

View File

@ -11,7 +11,6 @@ use App\Checks\PanelVersionCheck;
use App\Checks\ScheduleCheck;
use App\Checks\UsedDiskSpaceCheck;
use App\Extensions\Avatar\Providers\GravatarProvider;
use App\Extensions\Avatar\Providers\LocalAvatarProvider;
use App\Extensions\Avatar\Providers\UiAvatarsProvider;
use App\Extensions\OAuth\Providers\GitlabProvider;
use App\Models;
@ -121,7 +120,6 @@ class AppServiceProvider extends ServiceProvider
// Default Avatar providers
GravatarProvider::register();
UiAvatarsProvider::register();
LocalAvatarProvider::register();
FilamentColor::register([
'danger' => Color::Red,

View File

@ -2,7 +2,6 @@
namespace App\Providers\Filament;
use App\Extensions\Avatar\AvatarProvider;
use App\Filament\Pages\Auth\Login;
use App\Filament\Pages\Auth\EditProfile;
use App\Http\Middleware\LanguageMiddleware;
@ -39,7 +38,6 @@ class AdminPanelProvider extends PanelProvider
->favicon(config('app.favicon', '/pelican.ico'))
->topNavigation(config('panel.filament.top-navigation', false))
->maxContentWidth(config('panel.filament.display-width', 'screen-2xl'))
->defaultAvatarProvider(fn () => get_class(AvatarProvider::getProvider(config('panel.filament.avatar-provider'))))
->login(Login::class)
->passwordReset()
->userMenuItems([

View File

@ -2,7 +2,6 @@
namespace App\Providers\Filament;
use App\Extensions\Avatar\AvatarProvider;
use App\Filament\Pages\Auth\Login;
use App\Filament\Pages\Auth\EditProfile;
use Filament\Facades\Filament;
@ -35,7 +34,6 @@ class AppPanelProvider extends PanelProvider
->favicon(config('app.favicon', '/pelican.ico'))
->topNavigation(config('panel.filament.top-navigation', false))
->maxContentWidth(config('panel.filament.display-width', 'screen-2xl'))
->defaultAvatarProvider(fn () => get_class(AvatarProvider::getProvider(config('panel.filament.avatar-provider'))))
->navigation(false)
->profile(EditProfile::class, false)
->login(Login::class)

View File

@ -2,7 +2,6 @@
namespace App\Providers\Filament;
use App\Extensions\Avatar\AvatarProvider;
use App\Filament\App\Resources\ServerResource\Pages\ListServers;
use App\Filament\Pages\Auth\Login;
use App\Filament\Admin\Resources\ServerResource\Pages\EditServer;
@ -42,7 +41,6 @@ class ServerPanelProvider extends PanelProvider
->favicon(config('app.favicon', '/pelican.ico'))
->topNavigation(config('panel.filament.top-navigation', false))
->maxContentWidth(config('panel.filament.display-width', 'screen-2xl'))
->defaultAvatarProvider(fn () => get_class(AvatarProvider::getProvider(config('panel.filament.avatar-provider'))))
->login(Login::class)
->passwordReset()
->userMenuItems([

View File

@ -53,6 +53,7 @@ return [
'top-navigation' => env('FILAMENT_TOP_NAVIGATION', false),
'display-width' => env('FILAMENT_WIDTH', 'screen-2xl'),
'avatar-provider' => env('FILAMENT_AVATAR_PROVIDER', 'gravatar'),
'uploadable-avatars' => env('FILAMENT_UPLOADABLE_AVATARS', false),
],
'use_binary_prefix' => env('PANEL_USE_BINARY_PREFIX', true),

View File

@ -35,6 +35,7 @@ return [
'set_to_cf' => 'Set to Cloudflare IPs',
'display_width' => 'Display Width',
'avatar_provider' => 'Avatar Provider',
'uploadable_avatars' => 'Allow users to upload own avatar?',
],
'captcha' => [
'enable' => 'Enable',