157 lines
3.7 KiB
PHP
157 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace Kirby\Cms;
|
|
|
|
use Closure;
|
|
use Throwable;
|
|
|
|
/**
|
|
* AppUsers
|
|
*
|
|
* @package Kirby Cms
|
|
* @author Bastian Allgeier <bastian@getkirby.com>
|
|
* @link https://getkirby.com
|
|
* @copyright Bastian Allgeier
|
|
* @license https://getkirby.com/license
|
|
*/
|
|
trait AppUsers
|
|
{
|
|
protected Auth|null $auth = null;
|
|
protected User|string|null $user = null;
|
|
protected Users|null $users = null;
|
|
|
|
/**
|
|
* Returns the Authentication layer class
|
|
*/
|
|
public function auth(): Auth
|
|
{
|
|
return $this->auth ??= new Auth($this);
|
|
}
|
|
|
|
/**
|
|
* Become any existing user or disable the current user
|
|
*
|
|
* @param string|null $who User ID or email address,
|
|
* `null` to use the actual user again,
|
|
* `'kirby'` for a virtual admin user or
|
|
* `'nobody'` to disable the actual user
|
|
* @param Closure|null $callback Optional action function that will be run with
|
|
* the permissions of the impersonated user; the
|
|
* impersonation will be reset afterwards
|
|
* @return mixed If called without callback: User that was impersonated;
|
|
* if called with callback: Return value from the callback
|
|
* @throws \Throwable
|
|
*/
|
|
public function impersonate(
|
|
string|null $who = null,
|
|
Closure|null $callback = null
|
|
): mixed {
|
|
$auth = $this->auth();
|
|
|
|
$userBefore = $auth->currentUserFromImpersonation();
|
|
$userAfter = $auth->impersonate($who);
|
|
|
|
if ($callback === null) {
|
|
return $userAfter;
|
|
}
|
|
|
|
try {
|
|
return $callback($userAfter);
|
|
} catch (Throwable $e) {
|
|
throw $e;
|
|
} finally {
|
|
// ensure that the impersonation is *always* reset
|
|
// to the original value, even if an error occurred
|
|
$auth->impersonate($userBefore?->id());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns all user roles
|
|
*/
|
|
public function roles(): Roles
|
|
{
|
|
return $this->roles ??= Roles::load($this->root('roles'));
|
|
}
|
|
|
|
/**
|
|
* Returns a specific user role by id
|
|
* or the role of the current user if no id is given
|
|
*
|
|
* @param bool $allowImpersonation If set to false, only the role of the
|
|
* actually logged in user will be returned
|
|
* (when `$id` is passed as `null`)
|
|
*/
|
|
public function role(
|
|
string|null $id = null,
|
|
bool $allowImpersonation = true
|
|
): Role|null {
|
|
if ($id !== null) {
|
|
return $this->roles()->find($id);
|
|
}
|
|
|
|
return $this->user(null, $allowImpersonation)?->role();
|
|
}
|
|
|
|
/**
|
|
* Set the currently active user id
|
|
*
|
|
* @return $this
|
|
*/
|
|
protected function setUser(User|string|null $user = null): static
|
|
{
|
|
$this->user = $user;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Create your own set of app users
|
|
*
|
|
* @return $this
|
|
*/
|
|
protected function setUsers(array|null $users = null): static
|
|
{
|
|
if ($users !== null) {
|
|
$this->users = Users::factory($users);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Returns a specific user by id
|
|
* or the current user if no id is given
|
|
*
|
|
* @param bool $allowImpersonation If set to false, only the actually
|
|
* logged in user will be returned
|
|
* (when `$id` is passed as `null`)
|
|
*/
|
|
public function user(
|
|
string|null $id = null,
|
|
bool $allowImpersonation = true
|
|
): User|null {
|
|
if ($id !== null) {
|
|
return $this->users()->find($id);
|
|
}
|
|
|
|
if ($allowImpersonation === true && is_string($this->user) === true) {
|
|
return $this->auth()->impersonate($this->user);
|
|
}
|
|
|
|
try {
|
|
return $this->auth()->user(null, $allowImpersonation);
|
|
} catch (Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns all users
|
|
*/
|
|
public function users(): Users
|
|
{
|
|
return $this->users ??= Users::load(
|
|
$this->root('accounts'),
|
|
);
|
|
}
|
|
}
|