diff --git a/config/forms/user.php b/config/forms/user.php
deleted file mode 100644
index 44499eb19..000000000
--- a/config/forms/user.php
+++ /dev/null
@@ -1,59 +0,0 @@
- [
-
- 'name' => [
- 'text',
- [
- 'label' => __('Display Name'),
- 'class' => 'half-width',
- 'label_class' => 'mb-2',
- ],
- ],
-
- 'email' => [
- 'email',
- [
- 'label' => __('E-mail Address'),
- 'required' => true,
- 'autocomplete' => 'new-password',
- 'label_class' => 'mb-2',
- 'form_group_class' => 'mt-3',
- ],
- ],
-
- 'new_password' => [
- 'password',
- [
- 'label' => __('Reset Password'),
- 'description' => __('Leave blank to use the current password.'),
- 'autocomplete' => 'off',
- 'required' => false,
- 'label_class' => 'mb-2',
- 'form_group_class' => 'mt-3',
- ],
- ],
-
- 'roles' => [
- 'multiCheckbox',
- [
- 'label' => __('Roles'),
- 'options' => $roles,
- 'form_group_class' => 'mt-3',
- ],
- ],
-
- 'submit' => [
- 'submit',
- [
- 'type' => 'submit',
- 'label' => __('Save Changes'),
-
- 'class' => 'btn btn-lg btn-primary',
- 'form_group_class' => 'mt-3',
- ],
- ],
- ],
-];
diff --git a/config/routes/admin.php b/config/routes/admin.php
index 7c306b855..a1dfc779b 100644
--- a/config/routes/admin.php
+++ b/config/routes/admin.php
@@ -146,25 +146,9 @@ return static function (RouteCollectorProxy $app) {
->setName('admin:storage_locations:index')
->add(new Middleware\Permissions(Acl::GLOBAL_STORAGE_LOCATIONS));
- $group->group(
- '/users',
- function (RouteCollectorProxy $group) {
- $group->get('', Controller\Admin\UsersController::class . ':indexAction')
- ->setName('admin:users:index');
-
- $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\UsersController::class . ':editAction')
- ->setName('admin:users:edit');
-
- $group->map(['GET', 'POST'], '/add', Controller\Admin\UsersController::class . ':editAction')
- ->setName('admin:users:add');
-
- $group->get('/delete/{id}/{csrf}', Controller\Admin\UsersController::class . ':deleteAction')
- ->setName('admin:users:delete');
-
- $group->get('/login-as/{id}/{csrf}', Controller\Admin\UsersController::class . ':impersonateAction')
- ->setName('admin:users:impersonate');
- }
- )->add(new Middleware\Permissions(Acl::GLOBAL_ALL));
+ $group->get('/users', Controller\Admin\UsersAction::class)
+ ->setName('admin:users:index')
+ ->add(new Middleware\Permissions(Acl::GLOBAL_ALL));
}
)
->add(Middleware\Module\Admin::class)
diff --git a/config/routes/base.php b/config/routes/base.php
index 70f701cad..3ff0faf89 100644
--- a/config/routes/base.php
+++ b/config/routes/base.php
@@ -17,6 +17,10 @@ return static function (RouteCollectorProxy $app) {
$group->get('/logout', Controller\Frontend\Account\LogoutAction::class)
->setName('account:logout');
+ $group->get('/login-as/{id}/{csrf}', Controller\Frontend\Account\MasqueradeAction::class)
+ ->setName('account:masquerade')
+ ->add(new Middleware\Permissions(App\Acl::GLOBAL_ALL));
+
$group->get('/endsession', Controller\Frontend\Account\EndMasqueradeAction::class)
->setName('account:endmasquerade');
diff --git a/frontend/vue/components/Admin/Users.vue b/frontend/vue/components/Admin/Users.vue
new file mode 100644
index 000000000..f914bac29
--- /dev/null
+++ b/frontend/vue/components/Admin/Users.vue
@@ -0,0 +1,101 @@
+
+ Users
+ {{ row.item.name }}
+ {{ row.item.email }}
+
+
' . $user->getEmail(),
- Flash::SUCCESS
- );
-
- return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
- }
-}
diff --git a/src/Controller/Api/AbstractApiCrudController.php b/src/Controller/Api/AbstractApiCrudController.php
index 1d962e8bc..de30ac105 100644
--- a/src/Controller/Api/AbstractApiCrudController.php
+++ b/src/Controller/Api/AbstractApiCrudController.php
@@ -81,10 +81,9 @@ abstract class AbstractApiCrudController
if ($record instanceof IdentifiableEntityInterface) {
$return['links'] = [
'self' => (string)$router->fromHere(
- $this->resourceRouteName,
- ['id' => $record->getIdRequired()],
- [],
- !$isInternal
+ route_name: $this->resourceRouteName,
+ route_params: ['id' => $record->getIdRequired()],
+ absolute: !$isInternal
),
];
}
diff --git a/src/Controller/Api/Admin/UsersController.php b/src/Controller/Api/Admin/UsersController.php
index 42470dd94..121790b6b 100644
--- a/src/Controller/Api/Admin/UsersController.php
+++ b/src/Controller/Api/Admin/UsersController.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Controller\Api\Admin;
+use App\Controller\Frontend\Account\MasqueradeAction;
use App\Entity;
use App\Http\Response;
use App\Http\ServerRequest;
@@ -80,6 +81,37 @@ class UsersController extends AbstractAdminApiCrudController
* )
*/
+ protected function viewRecord(object $record, ServerRequest $request): mixed
+ {
+ if (!($record instanceof $this->entityClass)) {
+ throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
+ }
+
+ $return = $this->toArray($record);
+
+ $isInternal = ('true' === $request->getParam('internal', 'false'));
+ $router = $request->getRouter();
+ $csrf = $request->getCsrf();
+
+ $return['links'] = [
+ 'self' => (string)$router->fromHere(
+ route_name: $this->resourceRouteName,
+ route_params: ['id' => $record->getIdRequired()],
+ absolute: !$isInternal
+ ),
+ 'masquerade' => (string)$router->fromHere(
+ route_name: 'account:masquerade',
+ route_params: [
+ 'id' => $record->getIdRequired(),
+ 'csrf' => $csrf->generate(MasqueradeAction::CSRF_NAMESPACE),
+ ],
+ absolute: !$isInternal
+ ),
+ ];
+
+ return $return;
+ }
+
/**
* @OA\Delete(path="/admin/user/{id}",
* tags={"Administration: Users"},
diff --git a/src/Controller/Frontend/Account/MasqueradeAction.php b/src/Controller/Frontend/Account/MasqueradeAction.php
new file mode 100644
index 000000000..cb1028fef
--- /dev/null
+++ b/src/Controller/Frontend/Account/MasqueradeAction.php
@@ -0,0 +1,43 @@
+getCsrf()->verify($csrf, self::CSRF_NAMESPACE);
+
+ $user = $userRepo->find($id);
+
+ if (!($user instanceof Entity\User)) {
+ throw new NotFoundException(__('User not found.'));
+ }
+
+ $auth = $request->getAuth();
+ $auth->masqueradeAsUser($user);
+
+ $request->getFlash()->addMessage(
+ '' . __('Logged in successfully.') . '
' . $user->getEmail(),
+ Flash::SUCCESS
+ );
+
+ return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
+ }
+}
diff --git a/templates/admin/users/index.phtml b/templates/admin/users/index.phtml
deleted file mode 100644
index f2ac1fb0d..000000000
--- a/templates/admin/users/index.phtml
+++ /dev/null
@@ -1,59 +0,0 @@
-layout('main', ['title' => __('User Accounts'), 'manual' => true]); ?>
-
-
=__('Actions') ?> | -=__('E-mail Address') ?> | -=__('Roles') ?> | -
---|---|---|
-
- getId() !== $user->getId()): ?>
- =__('Log In') ?>
-
- =__('Edit') ?>
- getId() !== $user->getId()): ?>
- getEmail())) ?>" href="=$router->named('admin:users:delete', ['id' => $user_row->getId(), 'csrf' => $csrf]) ?>">=__('Delete') ?>
-
- =__('Delete') ?>
-
-
- |
-
- =$this->e($user_row->getName()) ?>
-
- =$this->mailto($user_row->getEmail()) ?>
- getId() === $user->getId()): ?>=__('(You)') ?>
-
- |
-
- getRoles() as $role): ?>
- =$this->e($role->getName()) ?>
-
- |
-