From 4e2f9795013b2468a67ddb8ce9b346f6f0a8df4e Mon Sep 17 00:00:00 2001
From: "lee.5151" <lee.5151@osu.edu>
Date: Tue, 8 Aug 2023 15:06:56 -0400
Subject: [PATCH] Upgrading drupal/msqrole (1.0.8 => 1.0.10)

---
 composer.lock                                 |  20 +++---
 vendor/composer/autoload_files.php            |   2 +-
 vendor/composer/autoload_static.php           |   2 +-
 vendor/composer/installed.json                |  26 ++++----
 vendor/composer/installed.php                 |  10 +--
 web/modules/msqrole/.gitignore                |   1 +
 web/modules/msqrole/README.md                 | Bin 0 -> 3948 bytes
 web/modules/msqrole/README.txt                | Bin 4072 -> 0 bytes
 web/modules/msqrole/composer.json             |  11 +++
 web/modules/msqrole/css/masquerade-role.css   |  11 +--
 web/modules/msqrole/js/masquerade-role.js     |   2 +-
 web/modules/msqrole/msqrole.info.yml          |  10 +--
 web/modules/msqrole/msqrole.module            |  38 +++++++----
 web/modules/msqrole/msqrole.services.yml      |   2 +-
 .../src/Controller/MasqueradeRoleReset.php    |   9 ++-
 .../msqrole/src/DynamicRolePermissions.php    |   3 -
 .../msqrole/src/Entity/MasqueradeRoleUser.php |  48 +++++++++++++
 .../msqrole/src/Form/MasqueradeRoleForm.php   |   2 +-
 .../src/Form/MasqueradeRoleSettings.php       |  54 ++++++++++++++-
 .../msqrole/src/MasqueradeAccountProxy.php    |   6 +-
 web/modules/msqrole/src/RoleManager.php       |  63 +++++++++++++-----
 .../msqrole/src/RoleManagerInterface.php      |  20 ++++--
 .../templates/msqrole-status.html.twig        |  10 ++-
 23 files changed, 255 insertions(+), 95 deletions(-)
 create mode 100644 web/modules/msqrole/README.md
 delete mode 100644 web/modules/msqrole/README.txt
 create mode 100644 web/modules/msqrole/composer.json
 create mode 100644 web/modules/msqrole/src/Entity/MasqueradeRoleUser.php

diff --git a/composer.lock b/composer.lock
index 07ec98f8ff..5b53180ac3 100644
--- a/composer.lock
+++ b/composer.lock
@@ -5838,26 +5838,28 @@
         },
         {
             "name": "drupal/msqrole",
-            "version": "1.0.8",
+            "version": "1.0.10",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/msqrole.git",
-                "reference": "1.0.8"
+                "reference": "1.0.10"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/msqrole-1.0.8.zip",
-                "reference": "1.0.8",
-                "shasum": "7ca4924a0f0d23ad44701c5d9d69fa92d47fb3de"
+                "url": "https://ftp.drupal.org/files/projects/msqrole-1.0.10.zip",
+                "reference": "1.0.10",
+                "shasum": "90867c8709093ffa83f5b06c5a6088e9bc30a30f"
             },
             "require": {
-                "drupal/core": "^8.8.4 || ^9 || ^10"
+                "drupal/core": "^9.4 || ^10",
+                "drupal/token": "~1",
+                "php": ">=7.4"
             },
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "1.0.8",
-                    "datestamp": "1650607669",
+                    "version": "1.0.10",
+                    "datestamp": "1690031508",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -5874,7 +5876,7 @@
                     "homepage": "https://www.drupal.org/user/3612901"
                 }
             ],
-            "description": "Masquerades a user based on role, and not as another user",
+            "description": "Allows the user to masquerade as certain roles rather than specific users.",
             "homepage": "https://www.drupal.org/project/msqrole",
             "support": {
                 "source": "https://git.drupalcode.org/project/msqrole"
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index 9bd4635e64..6d39faf11f 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -18,8 +18,8 @@
     '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
     'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
     'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
-    '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
     '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
+    '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
     'c9d07b32a2e02bc0fc582d4f0c1b56cc' => $vendorDir . '/laminas/laminas-servicemanager/src/autoload.php',
     '3e41e0554275033aae3e9e7e056c2d14' => $vendorDir . '/longwave/laminas-diactoros/src/functions/create_uploaded_file.php',
     'f4ee20bfdee1006b0970e8d951bea11e' => $vendorDir . '/longwave/laminas-diactoros/src/functions/marshal_headers_from_sapi.php',
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 9995636fb0..edb4a7b95c 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -19,8 +19,8 @@ class ComposerStaticInit5c689ffcd54b9e495ed983fdce09b530
         '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
         'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
         'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
-        '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
         '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
+        '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
         'c9d07b32a2e02bc0fc582d4f0c1b56cc' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/autoload.php',
         '3e41e0554275033aae3e9e7e056c2d14' => __DIR__ . '/..' . '/longwave/laminas-diactoros/src/functions/create_uploaded_file.php',
         'f4ee20bfdee1006b0970e8d951bea11e' => __DIR__ . '/..' . '/longwave/laminas-diactoros/src/functions/marshal_headers_from_sapi.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index cd00489d5a..c42b28626c 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -6071,30 +6071,32 @@
         },
         {
             "name": "drupal/msqrole",
-            "version": "1.0.8",
-            "version_normalized": "1.0.8.0",
+            "version": "1.0.10",
+            "version_normalized": "1.0.10.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/msqrole.git",
-                "reference": "1.0.8"
+                "reference": "1.0.10"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/msqrole-1.0.8.zip",
-                "reference": "1.0.8",
-                "shasum": "7ca4924a0f0d23ad44701c5d9d69fa92d47fb3de"
+                "url": "https://ftp.drupal.org/files/projects/msqrole-1.0.10.zip",
+                "reference": "1.0.10",
+                "shasum": "90867c8709093ffa83f5b06c5a6088e9bc30a30f"
             },
             "require": {
-                "drupal/core": "^8.8.4 || ^9 || ^10"
+                "drupal/core": "^9.4 || ^10",
+                "drupal/token": "~1",
+                "php": ">=7.4"
             },
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "1.0.8",
-                    "datestamp": "1650607669",
+                    "version": "1.0.10",
+                    "datestamp": "1690031508",
                     "security-coverage": {
-                        "status": "not-covered",
-                        "message": "Project has not opted into security advisory coverage!"
+                        "status": "covered",
+                        "message": "Covered by Drupal's security advisory policy"
                     }
                 }
             },
@@ -6109,7 +6111,7 @@
                     "homepage": "https://www.drupal.org/user/3612901"
                 }
             ],
-            "description": "Masquerades a user based on role, and not as another user",
+            "description": "Allows the user to masquerade as certain roles rather than specific users.",
             "homepage": "https://www.drupal.org/project/msqrole",
             "support": {
                 "source": "https://git.drupalcode.org/project/msqrole"
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index d50b7d50cd..3de5f3943a 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => 'osu-asc-webservices/d8-upstream',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => '8e8d09103abc6af07826c501f2e89361a15286f4',
+        'reference' => 'c04844796ef3d7d8ec36f41e833624e3c88f0ab1',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -1001,9 +1001,9 @@
             'dev_requirement' => false,
         ),
         'drupal/msqrole' => array(
-            'pretty_version' => '1.0.8',
-            'version' => '1.0.8.0',
-            'reference' => '1.0.8',
+            'pretty_version' => '1.0.10',
+            'version' => '1.0.10.0',
+            'reference' => '1.0.10',
             'type' => 'drupal-module',
             'install_path' => __DIR__ . '/../../web/modules/msqrole',
             'aliases' => array(),
@@ -1564,7 +1564,7 @@
         'osu-asc-webservices/d8-upstream' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => '8e8d09103abc6af07826c501f2e89361a15286f4',
+            'reference' => 'c04844796ef3d7d8ec36f41e833624e3c88f0ab1',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
diff --git a/web/modules/msqrole/.gitignore b/web/modules/msqrole/.gitignore
index 9f11b755a1..f32e31af49 100644
--- a/web/modules/msqrole/.gitignore
+++ b/web/modules/msqrole/.gitignore
@@ -1 +1,2 @@
 .idea/
+.DS_Store
diff --git a/web/modules/msqrole/README.md b/web/modules/msqrole/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a6e34c2e22f2bd009461c9b85f237e7e498bdcf
GIT binary patch
literal 3948
zcmbuC-EJdA5QY01iFX)jFGwU3i(Bpx2q_mUK{jv`A+3Mn#H?c*j~$a|<K2Ms)p2cm
zl5w)y)yU(S{;4{B>U4F@fB(KIO?g{}r7eGzZMi9HJx}!Cl*_U#b3J`szKY*fxr_Ff
zM>pkO^Cq&z+(y>sx|U@p4^7$ZZEW?1FItwmx9T63m7dmnuZ&)nMU1fDsq8$K^N(0&
zVbS*+J+EYOTxNTZkD6&O)4<XMrnUMP<yL*H@j*YZt%UhT?HjcZ^*_=7ujL2bSHcT7
z*ay#4_nqEGdY@@L?M4Jk?=%8Sjc^S0GwzL^Z)5&YtD_eT4{Dw3X`+AZ;Byx<So6JF
zyAes;w1bir%!FsExmY#&WDhhaYCV_dbB$${V4CY0JZ<?<PRqCPb|*X7^c~LO8T&kg
zcceSB&8MU2(cM@x4!+<Oi>-X2Cm4rmtg;T!jf1OEyu-jOyfx*Uy%)6co!-pug=Tdb
zOFmlJhs9%@pQwK>B&ZCZ3o$kmo^2o-sV^f^)%jbw5If*!2jptdZe^;K1^CU~ai;M<
zYdpA#j#UTWD6N%mw6{7~snwJ_;*d$=@({kzSmMG{qw88$i1VMaJC6R9Ji_oFius*d
zHX6~E@5?~fF0ON-SPL;D=Ryt6TlID=4Wv6%mnu5#tnNy);AAU3+zTDZMtWm6p}<vG
z-DpJJMW~bL!ZtiJ`!=wm4ad9<9hy1oWh`|PEwp6qw1LE{CkAG}+2<@G@#Sl;c3UxX
zj0vLfMpsjQ)Oy)<-g~UNM$|e%X@?mUja+IxnRXV8WZv=mvfq2deW(X@AL^ryW?#T0
zQJn|V<`k4zGsZ*3C+j)lDxytHLE4J*r7lLne2yaL(}E}d$vH;B2!7_|rPVQtGsN5+
zuBVAe!{9=`QORL0x4QZ`tGlm@;M4eH4jf(go_}Air{_8RCb9}XD-ULaj6t4RD@TG0
zrE|it&xk8orOOz3gPp}0#eOAUIMX=yEFw2p4XA_tO8%|$$Vf|h$<vM8KreCF#rV7M
zdYBQ+IOtdbJNoG<G>+CfAB%kvcUwjCC@fpq<J=@)SkWM^wLw-5<VRG9^2smk5B6R%
zSI;n8bxy|aELc9QGWs-hvA5l~tMJk72Q!@I3U;xQd7whiYelZECULvPX9ap?Z*fA9
zQL`TSNiCVPyYc5t|2=pmu3)-;f(k!m=B|ym@|3k%`x!ZtnqaKe4#fN4fs<;<zRvVi
z@eZQ3=BB<eXB|zqu{);0m^HkX2UJG<nD0K=%q-Ryy_a(yT=iu}v}|u#H{z8%MEp=I
z`;j;iYtS_1y=ufs^e$qAPp`z*lz%kl7g?afbe)kc&uzYsD87cQzpiu*P4#7D-Ac*l
z2b|^p_!Qj7Sv<Bb&WLW!3Z6@?-fMp+eAFgZLM!&blRuvyub)O4zYD2>+>jMF=NH=i
zpf<F}9^wpVhq?B^FFS1=?_>j4q<nV}XT}-ZAT&*7`Lw4|g+<j}wUV_`o?*$cPqIG!
zFqcyfjHjy7k^!<Rmo<RyT?eHqkHtRoYh|FWKeb%zr}Thw$(y!*uP06r&Y|iLwfEHy
z><d?%xfW}09FaEP*v{{n<Rn-4{A4umnMq&!y6M~Xs1Gas6$+eQON;)xBlnU&d4p$m
a2wFXPHsbU%a^zO}^H&ewc6>j$j{YBCPp44;

literal 0
HcmV?d00001

diff --git a/web/modules/msqrole/README.txt b/web/modules/msqrole/README.txt
deleted file mode 100644
index 0a307820066139749e1bc6af58970a8871f34cec..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4072
zcmbuC+j1I55Qh6YRe6WKi<Gj2<D_!BQ;?NVWvmEr?g0TJ<`h;ErDw~#CHcQ@Mzf0`
zmdZu3yEC)h)BVrihyC}Trd`^5>)BhscCFC(Lf4-CW-ViUq5C_ne`#OX$+LgF&A+g(
z^>5k2Zf$K#yS6(U>UpZ?Mdgi-jqES2P4(8u=K3R1?z}OS)O@>ot#_`ad%o2=)42LR
zdzRACx0!zZJ$p9YhOzdXXy^6bcY1F1oeiV|{Wp?Xx~_$!vWFLTW>=MQTiT}XL)=Hw
z6V@eUT8?-}c%Rz`YYOp}p9SlOa89y4*)fvu>{2>z=<f>;W;?PFYwOq)S_g@xZ6s63
zhtP4S5z@>obuG2tx0RkaukgCi)1o3X*8GE=y1&>mb&YWarIj=eH5)rVNHTUA>ps&6
z7OWkgiH}BhF9~d0J)S-GF8qYAgl(af8_i%V)-P?W>qeu2##7nOd{_iZUA+N|3fa-u
zKYWD^6PNF6e^xo8d(F=DbgesjVAaMY@OiG;I>yLgH}hQaXDWNfl0_@b&FB?&q`6Z`
zoN5*yu?Q5frnHZCY_A+iPNa$?n1eI=dB)y>uE+<Taf%^Rje~d(yucMJi3Ave<sgk#
z`~V-28u%zjNnu}Y_kbDSXcXACBvZ#Lp;1aZ7#>3WNb57%0ms;LA-r<rMSLZj5;s36
zCXV$!QnN>2>Nu6M6MR!_M8>(01eS9;!MflbXbiP76`xWTN^DBIR*`%q`Fp(`9LrI&
zl8&YQ>8HVIue1}${=Cfrh30Ow!>v|I%{KJg`0rF0tz|P3Gue%u6Rp-YHgqPiF2!Ko
zyPl*#g}gMEbyzUa2v)+tm1`w`<|u-loG+0FlaQXc&2S^~aVaK(Mq~r{G88{KFSr!k
z!5gf>!_V~*T;u#oA+X<L_UfqqTq#So{Hgs|typ_buG|+PkxdGD6<AhtR-m}A9%Y^-
zyQrXT{ivYlx}FP__BN|iH@lA3AuH?i=;R+9-k;r%J{$F?84W%VXZ6U6=plowJzo$5
zu#IZEu5h3lFQEgT5fiYN=%FsbMIvz_HYL7A-o170>>YB%=hB%GQbY=?XxK;_&*bH5
ze2`mvn#YsfY&_I#pbBHN2K4M>M$EAq_B_a%J4q4^#1B?S2F<lHRZ-%Hj7UroZ{)+M
zRXLl7zQ|621sLawQLSUxO{dV6cW3Iu-s$?1P9gVSxfj9{uuOh!+`pOIN;Is6ZT2yF
z6Eney$lp|yspp+kHP1DZGF!d-;C%jYv^l?g8ZXO{SO=FHsz^WDPxga-XK(DabdTNc
zVA$Fj5<Lyp#~MB*-qoWxdSLq8UzKAz&qVmdy~xqJ+f8z!aEN<i2Qh(NL=l-UW!+Tw
z&g30y3tx|loop`bZ)y5n@^nej-=&$S8lPv^{@y71Kst@Et6uM;KZ?lsw7t8i<TE(r
z&;G2}k=NmKS9VcXL5W@tPt(7r)4S9e{^DOOU46q`>PNi1*V*z`J>Tw*lAaVb^qBM>
z(Mi&y(7k=sTtoZAda@8Pk-JG^W9?&NJMskmG$+q{VRu6(4F{gC&@a+WX7;2WfNC3&
z8#QYmmyn{KVcqezQsY%r>l59Z&dI3jiJymfkn&^pJo}wkoxZu)0sU}-tQWfHdZGf*
zhvnUNyT8ow)JG*hf`vmr`#>4psXNb}vHR1y7Fefz_o+_3o)y~iB)-w&{#M-jzgnKS
z(^Ry_`NwwvR$&L-K6m0j_fUKtceKKn4jGm#Nv;IRm*vKkV;c6YeXsoZM)~oz?%4Go
D&U}-m

diff --git a/web/modules/msqrole/composer.json b/web/modules/msqrole/composer.json
new file mode 100644
index 0000000000..b9b5351075
--- /dev/null
+++ b/web/modules/msqrole/composer.json
@@ -0,0 +1,11 @@
+{
+    "name": "drupal/msqrole",
+    "type": "drupal-module",
+    "description": "Allows the user to masquerade as certain roles rather than specific users.",
+    "require": {
+        "php": ">=7.4",
+        "drupal/core": "^9.4 || ^10",
+        "drupal/token": "~1"
+    },
+    "minimum-stability": "dev"
+}
diff --git a/web/modules/msqrole/css/masquerade-role.css b/web/modules/msqrole/css/masquerade-role.css
index 0ced89ac46..fb9e06b9dd 100644
--- a/web/modules/msqrole/css/masquerade-role.css
+++ b/web/modules/msqrole/css/masquerade-role.css
@@ -1,18 +1,12 @@
-html {
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-}
-
 .masquerade-role-status {
   opacity: 0.5;
-  transition: opacity .4s ease-in-out;
+  transition: .4s ease-in-out;
   border-top-right-radius: 10px;
   background: #1d5fc3;
   position: fixed;
   z-index: 2000001;
   padding: 10px 20px;
-  bottom: 0;
+  bottom: -60px;
   left: 0;
   -moz-box-shadow: inset -2px 2px 10px 0 #000000;
   -webkit-box-shadow: inset -2px 2px 10px 0 #000000;
@@ -23,6 +17,7 @@ html {
 .masquerade-role-status:focus,
 .masquerade-role-status:focus-within {
   opacity: 1;
+  bottom: 0;
 }
 
 .masquerade-role-status .roles {
diff --git a/web/modules/msqrole/js/masquerade-role.js b/web/modules/msqrole/js/masquerade-role.js
index 8485a9d2e9..507783bbb3 100644
--- a/web/modules/msqrole/js/masquerade-role.js
+++ b/web/modules/msqrole/js/masquerade-role.js
@@ -1,3 +1,3 @@
 (function ($, Drupal, drupalSettings) {
-  $('body').prepend(drupalSettings.msqrole.markup);
+  $('body').append(drupalSettings.msqrole.markup);
 })(jQuery, Drupal, drupalSettings);
diff --git a/web/modules/msqrole/msqrole.info.yml b/web/modules/msqrole/msqrole.info.yml
index d3b4985cb5..2fcd6cac5b 100644
--- a/web/modules/msqrole/msqrole.info.yml
+++ b/web/modules/msqrole/msqrole.info.yml
@@ -2,10 +2,12 @@ name: 'Masquerade as Role'
 description: 'Masquerades a user based on role, and not as another user'
 package: 'Administration'
 type: module
-core_version_requirement: ^8.8.4 || ^9 || ^10
+core_version_requirement: ^9.4 || ^10
 configure: msqrole.settings_form
+dependencies:
+  - token:token
 
-# Information added by Drupal.org packaging script on 2022-04-22
-version: '1.0.8'
+# Information added by Drupal.org packaging script on 2023-07-22
+version: '1.0.10'
 project: 'msqrole'
-datestamp: 1650607671
+datestamp: 1690031510
diff --git a/web/modules/msqrole/msqrole.module b/web/modules/msqrole/msqrole.module
index 70b2a15224..e117bc1e9d 100644
--- a/web/modules/msqrole/msqrole.module
+++ b/web/modules/msqrole/msqrole.module
@@ -1,8 +1,8 @@
 <?php
 
-use Drupal\Core\Render\Renderer;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
+use Drupal\user\Entity\Role;
 
 /**
  * Implements hook_help().
@@ -30,12 +30,26 @@ function msqrole_theme() {
   ];
 }
 
+/**
+ * Implements hook_entity_type_alter().
+ */
+function msqrole_entity_type_alter(array &$entity_types) {
+  /**
+   * @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
+   */
+  // Set the user class, because we need to override the getRoles method.
+  $entity_types['user']
+    ->setClass('Drupal\\msqrole\\Entity\\MasqueradeRoleUser');
+}
+
 /**
  * Implements hook_user_logout().
  */
 function msqrole_user_logout($account) {
-  /** @var RoleManager $roleManager */
-  if (!$role_manager = Drupal::service('msqrole.manager')) {
+  /**
+   * @var \Drupal\msqrole\RoleManagerInterface $roleManager
+   */
+  if (!$role_manager = \Drupal::service('msqrole.manager')) {
     return;
   }
 
@@ -50,7 +64,7 @@ function msqrole_page_attachments(array &$page) {
   /**
    * @var \Drupal\msqrole\RoleManagerInterface $roleManager
    */
-  if (!$role_manager = Drupal::service('msqrole.manager')) {
+  if (!$role_manager = \Drupal::service('msqrole.manager')) {
     return;
   }
 
@@ -60,12 +74,12 @@ function msqrole_page_attachments(array &$page) {
   }
 
   $roles = [];
-  foreach ($current_user->getRoles() as $role) {
-    if ($role === 'authenticated') {
+  foreach ($current_user->getRoles() as $role_id) {
+    if ($role_id === 'authenticated') {
       continue;
     }
-    $current = \Drupal\user\Entity\Role::load($role);
-    $roles[$role] = $current->label();
+    $role = Role::load($role_id);
+    $roles[$role_id] = $role->label();
   }
 
   $render = [
@@ -79,12 +93,12 @@ function msqrole_page_attachments(array &$page) {
     ],
   ];
 
-  /** @var Renderer $renderer */
+  /**
+   * @var \Drupal\Core\Render\RendererInterface $renderer
+   */
   $renderer = \Drupal::service('renderer');
-  $settings_js = [
+  $page['#attached']['drupalSettings']['msqrole'] = [
     'markup' => $renderer->renderPlain($render),
   ];
-
-  $page['#attached']['drupalSettings']['msqrole'] = $settings_js;
   $page['#attached']['library'][] = 'msqrole/msqrole.status';
 }
diff --git a/web/modules/msqrole/msqrole.services.yml b/web/modules/msqrole/msqrole.services.yml
index 96195be912..f2158931e9 100644
--- a/web/modules/msqrole/msqrole.services.yml
+++ b/web/modules/msqrole/msqrole.services.yml
@@ -1,7 +1,7 @@
 services:
   msqrole.manager:
     class: Drupal\msqrole\RoleManager
-    arguments: [ '@user.data', '@entity_type.manager', '@config.factory' ]
+    arguments: [ '@user.data', '@entity_type.manager', '@config.factory', '@token' ]
   current_user:
     class: Drupal\msqrole\MasqueradeAccountProxy
     arguments: [ '@event_dispatcher', '@msqrole.manager' ]
diff --git a/web/modules/msqrole/src/Controller/MasqueradeRoleReset.php b/web/modules/msqrole/src/Controller/MasqueradeRoleReset.php
index d49376eada..da85debc5a 100644
--- a/web/modules/msqrole/src/Controller/MasqueradeRoleReset.php
+++ b/web/modules/msqrole/src/Controller/MasqueradeRoleReset.php
@@ -24,14 +24,14 @@ class MasqueradeRoleReset extends ControllerBase {
    *
    * @var \Drupal\msqrole\RoleManagerInterface
    */
-  protected $roleManager;
+  protected RoleManagerInterface $roleManager;
 
   /**
    * The redirect destination object.
    *
    * @var \Drupal\Core\Routing\RedirectDestinationInterface
    */
-  protected $destination;
+  protected RedirectDestinationInterface $destination;
 
   /**
    * MasqueradeRoleReset constructor.
@@ -66,10 +66,11 @@ public static function create(ContainerInterface $container) {
   public function reset() {
     $this->roleManager->removeData($this->currentUser()->id());
 
-    // Invalidate cache tags
+    // Invalidate cache tags.
     try {
       $this->roleManager->invalidateTags($this->currentUser()->id());
     } catch (InvalidPluginDefinitionException | PluginNotFoundException $e) {
+      // Do nothing if this fails.
     }
 
     try {
@@ -78,7 +79,9 @@ public function reset() {
         return $this->redirect($destination->getRouteName(), $destination->getRouteParameters());
       }
     } catch(\Exception $e) {
+      // Do nothing, just redirect to the front page.
     }
+
     return $this->redirect('<front>');
   }
 
diff --git a/web/modules/msqrole/src/DynamicRolePermissions.php b/web/modules/msqrole/src/DynamicRolePermissions.php
index d17337a7f5..9a4595212e 100644
--- a/web/modules/msqrole/src/DynamicRolePermissions.php
+++ b/web/modules/msqrole/src/DynamicRolePermissions.php
@@ -25,9 +25,6 @@ public static function callback() {
     $roles = $role_manager->getConfigurableRoles();
     $permissions = [];
 
-    /**
-     * @var \Drupal\user\RoleInterface $role
-     */
     foreach ($roles as $role) {
       $permissions['masquerade as ' . $role->id()] = [
         'title' => t('Masquerade as :role', [
diff --git a/web/modules/msqrole/src/Entity/MasqueradeRoleUser.php b/web/modules/msqrole/src/Entity/MasqueradeRoleUser.php
new file mode 100644
index 0000000000..2386d5e015
--- /dev/null
+++ b/web/modules/msqrole/src/Entity/MasqueradeRoleUser.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\msqrole\Entity;
+
+use Drupal\msqrole\RoleManagerInterface;
+use Drupal\user\Entity\User;
+use Drupal\user\RoleInterface;
+
+class MasqueradeRoleUser extends User {
+
+  /**
+   * The role manager.
+   *
+   * @var \Drupal\msqrole\RoleManagerInterface
+   */
+  protected RoleManagerInterface $roleManager;
+
+  /**
+   * Returns the role manager.
+   *
+   * @return \Drupal\msqrole\RoleManagerInterface
+   */
+  protected function roleManager(): RoleManagerInterface {
+    if (!isset($this->roleManager)) {
+      $this->roleManager = \Drupal::service('msqrole.manager');
+    }
+
+    return $this->roleManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRoles($exclude_locked_roles = FALSE) {
+    if (!$this->roleManager()->isActive($this->id())) {
+      return parent::getRoles($exclude_locked_roles);
+    }
+
+    $roles = $this->roleManager()->getRoles($this->id());
+    if ($exclude_locked_roles) {
+      unset($roles[RoleInterface::ANONYMOUS_ID]);
+      unset($roles[RoleInterface::AUTHENTICATED_ID]);
+    }
+
+    return $roles;
+  }
+
+}
\ No newline at end of file
diff --git a/web/modules/msqrole/src/Form/MasqueradeRoleForm.php b/web/modules/msqrole/src/Form/MasqueradeRoleForm.php
index 4fd430d36e..6bbc8839bf 100644
--- a/web/modules/msqrole/src/Form/MasqueradeRoleForm.php
+++ b/web/modules/msqrole/src/Form/MasqueradeRoleForm.php
@@ -22,7 +22,7 @@ class MasqueradeRoleForm extends FormBase implements ContainerInjectionInterface
    *
    * @var \Drupal\msqrole\RoleManagerInterface
    */
-  protected $roleManager;
+  protected RoleManagerInterface $roleManager;
 
   /**
    * MasqueradeRoleForm constructor.
diff --git a/web/modules/msqrole/src/Form/MasqueradeRoleSettings.php b/web/modules/msqrole/src/Form/MasqueradeRoleSettings.php
index 09547f56b6..8ceb966e11 100644
--- a/web/modules/msqrole/src/Form/MasqueradeRoleSettings.php
+++ b/web/modules/msqrole/src/Form/MasqueradeRoleSettings.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\msqrole\Form;
 
+use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RendererInterface;
 use Drupal\msqrole\RoleManagerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Class MasqueradeRoleSettings
@@ -13,6 +16,37 @@
  */
 class MasqueradeRoleSettings extends ConfigFormBase {
 
+  /**
+   * The renderer.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected RendererInterface $renderer;
+
+  /**
+   * Constructs the settings form.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   * @param \Drupal\Core\Render\RendererInterface $renderer
+   *   The renderer.
+   */
+  public function __construct(ConfigFactoryInterface $config_factory, RendererInterface $renderer) {
+    parent::__construct($config_factory);
+
+    $this->renderer = $renderer;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('config.factory'),
+      $container->get('renderer')
+    );
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -42,11 +76,27 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#type' => 'inline_template',
       '#template' => '<strong>Default/always enabled tags:</strong><pre>{{ tags }}</pre>',
       '#context' => [
-        'tags' => print_r(implode(PHP_EOL,
-          array_merge(RoleManagerInterface::TAGS_TO_INVALIDATE, ['user:{current_user.id}'])), TRUE)
+        'tags' => print_r(implode(PHP_EOL, RoleManagerInterface::TAGS_TO_INVALIDATE), TRUE)
       ],
     ];
 
+    $token_info = [
+      '#theme' => 'token_tree_link',
+      '#token_types' => [
+          'current-date' => 'current-date',
+          'current-user' => 'current-user',
+          'current-page' => 'current-page',
+          'site' => 'site',
+          'random' => 'random',
+          'user' => 'user',
+        ],
+      '#show_restricted' => TRUE,
+      '#weight' => 90,
+    ];
+
+    $form['tags']['#description'] .= '<br />' . $this->t('This field supports tokens. @browse_tokens_link', [
+      '@browse_tokens_link' => $this->renderer->renderPlain($token_info),
+    ]);
 
     return $form;
   }
diff --git a/web/modules/msqrole/src/MasqueradeAccountProxy.php b/web/modules/msqrole/src/MasqueradeAccountProxy.php
index 90641a660c..78609c4eb0 100644
--- a/web/modules/msqrole/src/MasqueradeAccountProxy.php
+++ b/web/modules/msqrole/src/MasqueradeAccountProxy.php
@@ -21,7 +21,7 @@ class MasqueradeAccountProxy extends AccountProxy implements AccountProxyInterfa
    *
    * @var \Drupal\msqrole\RoleManagerInterface
    */
-  protected $roleManager;
+  protected RoleManagerInterface $roleManager;
 
   /**
    * AccountProxy constructor.
@@ -54,7 +54,7 @@ protected function getRoleStorage(): RoleStorageInterface {
    */
   public function getRoles($exclude_locked_roles = FALSE) {
     if (!$this->roleManager->isActive($this->getAccount()->id())) {
-      return $this->getAccount()->getRoles($exclude_locked_roles);
+      return parent::getRoles($exclude_locked_roles);
     }
     return $this->roleManager->getRoles($this->getAccount()->id());
   }
@@ -63,7 +63,7 @@ public function getRoles($exclude_locked_roles = FALSE) {
    * {@inheritdoc}
    */
   public function hasPermission($permission) {
-    $default = $this->getAccount()->hasPermission($permission);
+    $default = parent::hasPermission($permission);
     if (!$this->roleManager->isActive($this->getAccount()->id())) {
       return $default;
     }
diff --git a/web/modules/msqrole/src/RoleManager.php b/web/modules/msqrole/src/RoleManager.php
index eba6e5640e..7810aee59e 100644
--- a/web/modules/msqrole/src/RoleManager.php
+++ b/web/modules/msqrole/src/RoleManager.php
@@ -4,7 +4,10 @@
 
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\ImmutableConfig;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Utility\Token;
+use Drupal\user\Entity\User;
 use Drupal\user\UserDataInterface;
 
 /**
@@ -19,24 +22,38 @@ class RoleManager implements RoleManagerInterface {
    *
    * @var \Drupal\user\UserDataInterface
    */
-  protected $userData;
+  protected UserDataInterface $userData;
 
   /**
    * The entity type manager.
    *
    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
    */
-  protected $entityTypeManager;
+  protected EntityTypeManagerInterface $entityTypeManager;
 
   /**
-   * The config factory.
+   * The msqrole config.
    *
    * @var \Drupal\Core\Config\ImmutableConfig
    */
-  protected $config;
+  protected ImmutableConfig $config;
 
   /**
-   * RoleManager constructor.
+   * The theme config.
+   *
+   * @var \Drupal\Core\Config\ImmutableConfig
+   */
+  protected ImmutableConfig $themeConfig;
+
+  /**
+   * The token service.
+   *
+   * @var \Drupal\Core\Utility\Token
+   */
+  protected Token $token;
+
+  /**
+   * Constructs the RoleManager class.
    *
    * @param \Drupal\user\UserDataInterface $user_data
    *   The user data object.
@@ -45,10 +62,12 @@ class RoleManager implements RoleManagerInterface {
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The config factory.
    */
-  public function __construct(UserDataInterface $user_data, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory) {
+  public function __construct(UserDataInterface $user_data, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, Token $token) {
     $this->userData = $user_data;
     $this->entityTypeManager = $entity_type_manager;
     $this->config = $config_factory->get('msqrole.settings');
+    $this->themeConfig = $config_factory->get('system.theme');
+    $this->token = $token;
   }
 
   /**
@@ -60,7 +79,6 @@ public function isPermissionInRoles($permission, array $roles) {
       return FALSE;
     }
 
-    /** @var \Drupal\user\RoleInterface $role */
     foreach ($roles as $role) {
       if ($role->hasPermission($permission)) {
         return TRUE;
@@ -73,12 +91,13 @@ public function isPermissionInRoles($permission, array $roles) {
   /**
    * {@inheritDoc}
    */
-  public function getAllRoles(?array $rids = NULL) {
-    if (is_array($rids)) {
+  public function getAllRoles(?array $role_ids = NULL) {
+    if (is_array($role_ids)) {
       return $this->entityTypeManager
         ->getStorage('user_role')
-        ->loadMultiple($rids);
+        ->loadMultiple($role_ids);
     }
+
     return $this->entityTypeManager
       ->getStorage('user_role')
       ->loadMultiple();
@@ -164,13 +183,25 @@ public function removeData($uid, ?string $key = NULL) {
    * {@inheritDoc}
    */
   public function invalidateTags($uid) {
-    $custom_tags = unserialize($this->config->get('tags_to_invalidate')) ?: [];
-    // Replace possible variables.
-    // @todo use tokens?
-    foreach ($custom_tags as &$tag) {
-      $tag = str_replace('{current_user.id}', $uid, $tag);
+    $user = User::load($uid);
+    $admin_theme = $this->themeConfig->get('admin');
+    $default_theme = $this->themeConfig->get('default');
+
+    // Replace possible variables in the tags.
+    $tags = Cache::mergeTags(
+      RoleManagerInterface::TAGS_TO_INVALIDATE,
+      (unserialize($this->config->get('tags_to_invalidate')) ?: [])
+    );
+    foreach ($tags as &$tag) {
+      $tag = $this->token->replace($tag, [
+        'user' => $user,
+      ]);
+      $tag = str_replace('[theme:admin]', $admin_theme, $tag);
+      $tag = str_replace('[theme:default]', $default_theme, $tag);
     }
-    Cache::invalidateTags(array_merge(RoleManagerInterface::TAGS_TO_INVALIDATE, ['user:' . $uid], $custom_tags));
+    $tags = array_filter($tags);
+
+    Cache::invalidateTags($tags);
   }
 
 }
diff --git a/web/modules/msqrole/src/RoleManagerInterface.php b/web/modules/msqrole/src/RoleManagerInterface.php
index 91940943bf..2d695a563c 100644
--- a/web/modules/msqrole/src/RoleManagerInterface.php
+++ b/web/modules/msqrole/src/RoleManagerInterface.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\msqrole;
 
+use Drupal\user\RoleInterface;
+
 /**
  * Interface RoleManagerInterface.
  *
@@ -13,12 +15,16 @@ interface RoleManagerInterface {
    * Tags to invalidate when masquerading as different role.
    */
   const TAGS_TO_INVALIDATE = [
-    'config:block.block.bartik_local_actions',
-    'config:block.block.bartik_local_tasks',
+    'config:block.block.[theme:admin]_local_actions',
+    'config:block.block.[theme:admin]_local_tasks',
+    'config:block.block.[theme:default]_local_actions',
+    'config:block.block.[theme:default]_local_tasks',
     'config:system.menu.account',
     'config:system.menu.admin',
     'config:system.menu.tools',
     'local_task',
+    'local_action',
+    'user:[user:uid]',
   ];
 
   /**
@@ -37,18 +43,18 @@ public function isPermissionInRoles($permission, array $roles);
   /**
    * Returns all existing roles or roles based on given ids.
    *
-   * @param array|null $rids
+   * @param array|null $role_ids
    *   Array of role ids to load.
    *
-   * @return array
+   * @return \Drupal\user\RoleInterface[]
    *   Array of roles.
    */
-  public function getAllRoles(?array $rids = NULL);
+  public function getAllRoles(?array $role_ids = NULL);
 
   /**
    * Returns configurable roles.
    *
-   * @return array
+   * @return \Drupal\user\RoleInterface[]
    *   The configurable roles.
    */
   public function getConfigurableRoles();
@@ -57,7 +63,7 @@ public function getConfigurableRoles();
    * Returns the role the current user is masquerading as.
    *
    * @return array
-   *   User roles.
+   *   User roles as an array of strings.
    */
   public function getRoles($uid);
 
diff --git a/web/modules/msqrole/templates/msqrole-status.html.twig b/web/modules/msqrole/templates/msqrole-status.html.twig
index 705e81ca3a..d543d73c04 100644
--- a/web/modules/msqrole/templates/msqrole-status.html.twig
+++ b/web/modules/msqrole/templates/msqrole-status.html.twig
@@ -1,9 +1,7 @@
 <div class="masquerade-role-status">
-  <div class="content">
-    <div class="roles">
-      <label>{{ 'Current roles'|t }}:</label>
-      <br/>{{- roles|join(', ', ' and '|t) -}}
-      <div class="reset"><a href="{{ reset_url }}">{{ 'Reset roles'|t }}</a></div>
-    </div>
+  <div class="roles">
+    <label>{{ 'Masquerade Role'|t }}</label>
+    <br />{{- roles|join(', ', ' and '|t) -}}
+    <div class="reset"><a href="{{ reset_url }}">{{ 'Reset roles'|t }}</a></div>
   </div>
 </div>
-- 
GitLab