diff --git a/demo/app/Providers/DemoSharpServiceProvider.php b/demo/app/Providers/DemoSharpServiceProvider.php index 2d16d0ecc..0ae63a48d 100644 --- a/demo/app/Providers/DemoSharpServiceProvider.php +++ b/demo/app/Providers/DemoSharpServiceProvider.php @@ -28,6 +28,7 @@ protected function configureSharp(SharpConfigBuilder $config): void ->setAuthCustomGuard('web') ->setLoginAttributes('email', 'password') ->setUserDisplayAttribute('name') + ->setUserAvatarAttribute(fn () => auth()->user()->avatar?->thumbnail(200)) ->enable2faCustom(Demo2faNotificationHandler::class) ->enableLoginRateLimiting(maxAttempts: 3) ->suggestRememberMeOnLoginForm() diff --git a/docs/guide/authentication.md b/docs/guide/authentication.md index 958a8e371..8b8c202cd 100644 --- a/docs/guide/authentication.md +++ b/docs/guide/authentication.md @@ -14,12 +14,14 @@ class SharpServiceProvider extends SharpAppServiceProvider $config ->setLoginAttributes('login', 'pwd') ->setUserDisplayAttribute('last_name') + ->setUserAvatarAttribute('avatar_url') // [...] } } ``` -The `setUserDisplayAttribute()` is useful to display the user's name in the Sharp UI. Default is `name`. +- The `setUserDisplayAttribute()` is useful to display the user's name in the Sharp UI. Default is `name`. +- The `setUserAvatarAttribute()` is useful to display the user's avatar in the Sharp UI. By default, a user icon is displayed instead. ## Login form diff --git a/resources/js/Layouts/Layout.vue b/resources/js/Layouts/Layout.vue index 679c4eacb..77c66c97a 100644 --- a/resources/js/Layouts/Layout.vue +++ b/resources/js/Layouts/Layout.vue @@ -215,8 +215,13 @@ export function useMenuBoundaryElement() { size="lg" class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" > - - + + +
{{ auth().user.name }} diff --git a/resources/js/types/generated.d.ts b/resources/js/types/generated.d.ts index 3c737415b..921b0ff6e 100644 --- a/resources/js/types/generated.d.ts +++ b/resources/js/types/generated.d.ts @@ -859,6 +859,7 @@ export type ShowTextFieldData = { export type UserData = { name: string | null; email: string | null; + avatar: string | null; }; export type UserMenuData = { items: Array; diff --git a/src/Config/SharpConfigBuilder.php b/src/Config/SharpConfigBuilder.php index 388cd3f1e..b6d02e0c3 100644 --- a/src/Config/SharpConfigBuilder.php +++ b/src/Config/SharpConfigBuilder.php @@ -15,6 +15,7 @@ use Code16\Sharp\Utils\Entities\SharpEntityResolver; use Code16\Sharp\Utils\Filters\GlobalRequiredFilter; use Code16\Sharp\Utils\Menu\SharpMenu; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\PasswordBroker; use Illuminate\Contracts\View\View; use Illuminate\Foundation\Vite; @@ -61,6 +62,7 @@ class SharpConfigBuilder 'logout_page_url' => null, 'display_attribute' => 'name', 'login_attribute' => 'email', + 'avatar_attribute' => null, 'password_attribute' => 'password', 'impersonate' => [ 'enabled' => false, @@ -414,6 +416,17 @@ public function setUserDisplayAttribute(string $displayAttribute): self return $this; } + /** + * @param (string|Closure(Authenticatable $user): string) $avatarAttribute + * @return $this + */ + public function setUserAvatarAttribute(string|Closure $avatarAttribute): self + { + $this->config['auth']['avatar_attribute'] = $avatarAttribute; + + return $this; + } + public function setAuthCustomGuard(?string $guardName): self { $this->config['auth']['guard'] = $guardName; diff --git a/src/Data/UserData.php b/src/Data/UserData.php index 652064e01..91c5710ee 100644 --- a/src/Data/UserData.php +++ b/src/Data/UserData.php @@ -2,6 +2,7 @@ namespace Code16\Sharp\Data; +use Closure; use Illuminate\Contracts\Auth\Authenticatable; /** @@ -12,6 +13,7 @@ final class UserData extends Data public function __construct( public ?string $name, public ?string $email, + public ?string $avatar, ) {} public static function from(Authenticatable $user): self @@ -19,6 +21,11 @@ public static function from(Authenticatable $user): self return new self( name: $user->{sharp()->config()->get('auth.display_attribute')} ?? null, email: $user->{sharp()->config()->get('auth.login_attribute')} ?? null, + avatar: match (true) { + is_string(sharp()->config()->get('auth.avatar_attribute')) => $user->{sharp()->config()->get('auth.avatar_attribute')}, + sharp()->config()->get('auth.avatar_attribute') instanceof Closure => sharp()->config()->get('auth.avatar_attribute')($user), + default => null, + }, ); } }