Skip to content

Commit e80ccc5

Browse files
Impersonate from user menu dropdown #6524
1 parent e7141eb commit e80ccc5

20 files changed

+106
-11
lines changed

assets/js/app.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class App {
3232
this.#createModalWindowsForDeleteActions();
3333
this.#createPopovers();
3434
this.#createTooltips();
35+
this.#createImpersonateModal();
3536

3637
document.addEventListener('ea.collection.item-added', () => this.#createAutoCompleteFields());
3738
}
@@ -449,4 +450,12 @@ class App {
449450
});
450451
});
451452
}
453+
454+
#createImpersonateModal(){
455+
const impersonateButton = document.querySelector('#modal-impersonate-link');
456+
const impersonateModal = document.querySelector(impersonateButton.getAttribute('data-bs-target'));
457+
document.querySelector('#impersonate-modal-apply-button').addEventListener('click', () => {
458+
impersonateModal.querySelector('form').submit();
459+
});
460+
}
452461
}

public/app.d52c6a33.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/app.3048ce28.js renamed to public/app.fb2fb73c.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/entrypoints.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"/app.d52c6a33.css"
66
],
77
"js": [
8-
"/app.3048ce28.js"
8+
"/app.fb2fb73c.js"
99
]
1010
},
1111
"form": {

public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"app.css": "app.d52c6a33.css",
3-
"app.js": "app.3048ce28.js",
3+
"app.js": "app.fb2fb73c.js",
44
"form.js": "form.ec4ce275.js",
55
"page-layout.js": "page-layout.3347892e.js",
66
"page-color-scheme.js": "page-color-scheme.30cb23c2.js",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace EasyCorp\Bundle\EasyAdminBundle\Config\Menu;
4+
5+
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Menu\MenuItemInterface;
6+
use EasyCorp\Bundle\EasyAdminBundle\Dto\MenuItemDto;
7+
use Symfony\Contracts\Translation\TranslatableInterface;
8+
9+
/**
10+
* @see EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem::linkToAccessImpersonation()
11+
*
12+
* @author Elías Fernández <[email protected]>
13+
*/
14+
final class AccessImpersonationMenuItem implements MenuItemInterface
15+
{
16+
use MenuItemTrait;
17+
18+
public function __construct(TranslatableInterface|string $label, ?string $icon)
19+
{
20+
$this->dto = new MenuItemDto();
21+
22+
$this->dto->setType(MenuItemDto::TYPE_ACCESS_IMPERSONATION);
23+
$this->dto->setLabel($label);
24+
$this->dto->setIcon($icon);
25+
$this->dto->setLinkUrl('test');
26+
}
27+
}

src/Config/MenuItem.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace EasyCorp\Bundle\EasyAdminBundle\Config;
44

5+
use EasyCorp\Bundle\EasyAdminBundle\Config\Menu\AccessImpersonationMenuItem;
56
use EasyCorp\Bundle\EasyAdminBundle\Config\Menu\CrudMenuItem;
67
use EasyCorp\Bundle\EasyAdminBundle\Config\Menu\DashboardMenuItem;
78
use EasyCorp\Bundle\EasyAdminBundle\Config\Menu\ExitImpersonationMenuItem;
@@ -45,6 +46,14 @@ public static function linkToExitImpersonation(TranslatableInterface|string $lab
4546
return new ExitImpersonationMenuItem($label, $icon);
4647
}
4748

49+
/**
50+
* @param string|null $icon The full CSS classes of the FontAwesome icon to render (see https://fontawesome.com/v6/search?m=free)
51+
*/
52+
public static function linkToAccessImpersonation(TranslatableInterface|string $label, ?string $icon = null): AccessImpersonationMenuItem
53+
{
54+
return new AccessImpersonationMenuItem($label, $icon);
55+
}
56+
4857
/**
4958
* @param string|null $icon The full CSS classes of the FontAwesome icon to render (see https://fontawesome.com/v6/search?m=free)
5059
*/

src/Controller/AbstractDashboardController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public function configureUserMenu(UserInterface $user): UserMenu
6969
if ($this->isGranted(Permission::EA_EXIT_IMPERSONATION)) {
7070
$userMenuItems[] = MenuItem::linkToExitImpersonation(t('user.exit_impersonation', domain: 'EasyAdminBundle'), 'fa-user-lock');
7171
}
72+
if (!$this->isGranted(Permission::EA_EXIT_IMPERSONATION) && $this->isGranted(Permission::EA_CAN_SWITCH_USER)) {
73+
$userMenuItems[] = MenuItem::linkToAccessImpersonation(t('user.impersonate_user', domain: 'EasyAdminBundle'), 'fa-user-lock');
74+
}
7275

7376
$userName = method_exists($user, '__toString') ? (string) $user : $user->getUserIdentifier();
7477

src/Dto/MenuItemDto.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ final class MenuItemDto
1414
public const TYPE_URL = 'url';
1515
public const TYPE_SECTION = 'section';
1616
public const TYPE_EXIT_IMPERSONATION = 'exit_impersonation';
17+
public const TYPE_ACCESS_IMPERSONATION = 'access_impersonation';
1718
public const TYPE_DASHBOARD = 'dashboard';
1819
public const TYPE_LOGOUT = 'logout';
1920
public const TYPE_SUBMENU = 'submenu';

src/Resources/public/app.d52c6a33.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Resources/public/app.3048ce28.js renamed to src/Resources/public/app.fb2fb73c.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Resources/public/entrypoints.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"/app.d52c6a33.css"
66
],
77
"js": [
8-
"/app.3048ce28.js"
8+
"/app.fb2fb73c.js"
99
]
1010
},
1111
"form": {

src/Resources/public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"app.css": "app.d52c6a33.css",
3-
"app.js": "app.3048ce28.js",
3+
"app.js": "app.fb2fb73c.js",
44
"form.js": "form.ec4ce275.js",
55
"page-layout.js": "page-layout.3347892e.js",
66
"page-color-scheme.js": "page-color-scheme.30cb23c2.js",

src/Security/Permission.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ final class Permission
1212
public const EA_VIEW_MENU_ITEM = 'EA_VIEW_MENU_ITEM';
1313
public const EA_VIEW_FIELD = 'EA_VIEW_FIELD';
1414
public const EA_EXIT_IMPERSONATION = 'EA_EXIT_IMPERSONATION';
15+
public const EA_CAN_SWITCH_USER = 'EA_CAN_SWITCH_USER';
1516

1617
public static function exists(?string $permissionName): bool
1718
{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<div id="modal-impersonate" class="modal fade" tabindex="-1">
2+
<div class="modal-dialog">
3+
<div class="modal-content">
4+
<div class="modal-body p-4">
5+
<form method="get">
6+
<div class="row">
7+
<div class="col-12">
8+
<div class="field-text form-group">
9+
<label for="_switch_user" class="form-control-label required">{{ 'impersonate.username'|trans(domain = 'EasyAdminBundle') }}</label>
10+
<div class="form-widget">
11+
<input type="text" name="_switch_user" id="impersonate_user_name" required="required" class="form-control" value="">
12+
</div>
13+
</div>
14+
</div>
15+
</div>
16+
</form>
17+
</div>
18+
<div class="modal-footer">
19+
<button type="button" data-bs-dismiss="modal" class="btn btn-sm btn-secondary" id="impersonate-modal-clear-button" formtarget="_self">
20+
<i class="fa fa-close"></i> {{ 'action.close'|trans(domain = 'EasyAdminBundle') }}
21+
</button>
22+
23+
<button type="button" data-bs-dismiss="modal" class="btn btn-sm btn-primary" id="impersonate-modal-apply-button" formtarget="_self">
24+
<i class="fa fa-check"></i> {{ 'user.impersonate_user'|trans(domain = 'EasyAdminBundle') }}
25+
</button>
26+
</div>
27+
</div>
28+
</div>
29+
</div>

templates/layout.html.twig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@
104104
{% elseif not item.isMenuSection %}
105105
<a href="{{ item.linkUrl }}" class="dropdown-item user-action {{ item.cssClass }}"
106106
target="{{ item.linkTarget }}" rel="{{ item.linkRel }}"
107+
{% if item.type == "access_impersonation" %}
108+
data-bs-toggle="modal" data-bs-target="#modal-impersonate" id="modal-impersonate-link"
109+
{% endif %}
107110
referrerpolicy="origin-when-cross-origin">
108111
{% if item.icon is not empty %}<i class="fa fa-fw {{ item.icon }}"></i>{% endif %}
109112
{{ item.label|trans }}
@@ -361,6 +364,9 @@
361364

362365
<section id="main" class="content-body">
363366
{% block main %}{% endblock %}
367+
{% if impersonator_permission == 'IS_IMPERSONATOR' %}
368+
{{ include('@EasyAdmin/includes/_impersonate_modal.html.twig') }}
369+
{% endif %}
364370
</section>
365371

366372
{% block content_footer_wrapper %}

translations/EasyAdminBundle.en.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
'anonymous' => 'Anonymous User',
110110
'sign_out' => 'Sign out',
111111
'exit_impersonation' => 'Exit impersonation',
112+
'impersonate_user' => 'Impersonate user',
112113
],
113114

114115
'settings' => [
@@ -141,4 +142,8 @@
141142
'no-more-results' => 'No more results',
142143
'loading-more-results' => 'Loading more results…',
143144
],
145+
146+
'impersonate' => [
147+
'username' => 'Username to impersonate',
148+
],
144149
];

translations/EasyAdminBundle.es.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@
108108
'unnamed' => 'Usuario sin nombre',
109109
'anonymous' => 'Usuario anónimo',
110110
'sign_out' => 'Cerrar sesión',
111-
'exit_impersonation' => 'Terminar impersonación',
111+
'exit_impersonation' => 'Terminar suplantación',
112+
'impersonate_user' => 'Suplantar usuario',
112113
],
113114

114115
'settings' => [
@@ -141,4 +142,8 @@
141142
'no-more-results' => 'No hay más resultados',
142143
'loading-more-results' => 'Cargando más resultados…',
143144
],
145+
146+
'impersonate' => [
147+
'username' => 'Nombre de usuario a suplantar',
148+
],
144149
];

0 commit comments

Comments
 (0)