Give trusted apps the user's role

Anikeen ID now sends trusted apps the user's role (admin or user) in
GET v1/user, a user read by ID and user.updated, so an app like the
Console can take its admins from Anikeen ID. Enums\Role, the Socialite
user's role and Resources\User::role()/isAdmin() expose it.
This commit is contained in:
envoyr committed 2026-11-07 15:24:48 +00:00
1 parent 31de31aa47
commit 642e518259
8 files changed
+154 -1

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
<?php
namespace Anikeen\Id\Enums;
/**
* A user's role on Anikeen ID. Only trusted apps see it: `role` of GET v1/user (the Socialite
* user), of a user read by ID and of user.updated; other apps get none.
*/
class Role
{
/** Runs Anikeen (the Anikeen ID admin panel). */
const ADMIN = 'admin';
const USER = 'user';
/**
* @return list<string>
*/
public static function all(): array
{
return [self::ADMIN, self::USER];
}
}
+18
View File
@@ -2,6 +2,7 @@
namespace Anikeen\Id\Resources;
use Anikeen\Id\Enums\Role;
use DateTimeImmutable;
use JsonSerializable;
@@ -27,6 +28,7 @@ use JsonSerializable;
* @property ?string $created_at REST shapes
* @property ?string $pending_email profile updates only: a new address waiting for confirmation
* @property ?string $pending_email_expires_at profile updates only
* @property ?string $role trusted apps only: Role::ADMIN or Role::USER
*/
class User implements JsonSerializable
{
@@ -97,6 +99,22 @@ class User implements JsonSerializable
return (int) ($this->data->profile_version ?? $this->data->version ?? 0);
}
/**
* Role::ADMIN or Role::USER; null for apps that aren't trusted (they never see it).
*/
public function role(): ?string
{
return $this->data->role ?? null;
}
/**
* An Anikeen ID admin (trusted apps only; false when the role isn't known).
*/
public function isAdmin(): bool
{
return $this->role() === Role::ADMIN;
}
/**
* A new email address waiting for the user's confirmation (profile updates only); `email`
* stays the current address until then.
+2
View File
@@ -83,6 +83,8 @@ class Provider extends AbstractProvider implements ProviderInterface
'name' => $user['name'],
'email' => Arr::get($user, 'email'),
'avatar' => $user['avatar'],
// trusted apps only (Enums\Role), null for others: $socialiteUser->role
'role' => Arr::get($user, 'role'),
]);
}
+2 -1
View File
@@ -92,7 +92,8 @@ final class EventType
* the changed fields (never their old values). An email address appears only once verified
* (`email` is null while it isn't); `avatar` in `changed` means the picture behind the stable URL
* changed. Keep the highest `version` and ignore older events. Opt-in (not through `*`); also
* sent to the app that made the change.
* sent to the app that made the change. Trusted apps also get `role` (Enums\Role) and `role` in
* `changed`; a change of the role alone reaches only them.
*/
public const USER_UPDATED = 'user.updated';