Skip to content

Commit

Permalink
Merge branch 'develop' into 1.1
Browse files Browse the repository at this point in the history
* develop:
  Open the backend from the demo theme in the same window
  CSS fix for position: sticky
  Log the real user for a CMS theme change
  Added global notice to backend when the user is being impersonated
  Improve typehint and clear mergedPermissions on impersonation
  Prevent user from impersonating self
  WIP on impersonation improvements
  • Loading branch information
LukeTowers committed Aug 24, 2021
2 parents 398d1ba + 6c1ab2c commit bac9382
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 4 deletions.
5 changes: 4 additions & 1 deletion modules/backend/assets/css/winter.css
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ body.loading,
body.loading * {cursor:wait !important}
body.no-select {-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default !important}
html,
body {height:100%}
body {min-height:100%}
body {font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";background:#f9f9f9;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
#layout-canvas {min-height:100%;height:100%}
.control-tabs.primary-tabs >ul.nav-tabs,
Expand All @@ -586,6 +586,9 @@ body {font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sa
.control-tabs.primary-tabs.tabs-no-inset >ul.nav-tabs,
.control-tabs.primary-tabs.tabs-no-inset >div >ul.nav-tabs,
.control-tabs.primary-tabs.tabs-no-inset >div >div >ul.nav-tabs {margin-left:0;margin-right:0}
.global-notice{position:sticky;top:0;display:flex;align-items:center;flex-wrap:wrap;gap:0.5em;justify-content:space-between;z-index:10500;background:#ab2a1c;color:#FFF;padding:0.5em 0.75em}
.global-notice .notice-icon{font-size:1.5em;vertical-align:bottom;display:inline-block;margin-right:.25em}
.global-notice .notice-text{display:inline-block;vertical-align:middle}
.layout {display:table;table-layout:fixed;height:100%;width:100%}
.layout >.layout-row {display:table-row;vertical-align:top;height:100%}
.layout >.layout-row >.layout-cell {display:table-cell;vertical-align:top;height:100%}
Expand Down
2 changes: 1 addition & 1 deletion modules/backend/lang/en/lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
'impersonate_confirm' => 'Are you sure you want to impersonate this user? You can revert to your original state by logging out.',
'impersonate_success' => 'You are now impersonating this user',
'impersonate_working' => 'Impersonating...',
'impersonating' => 'Impersonating :full_name',
'impersonating' => 'You are temporarily logged in as :impersonatee. Logs are still able to identify you as :impersonator',
'stop_impersonating' => 'Stop impersonating',
'unsuspend' => 'Unsuspend',
'unsuspend_confirm' => 'Are you sure you want to unsuspend this user?',
Expand Down
17 changes: 17 additions & 0 deletions modules/backend/layouts/default.htm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@
</head>
<body class="<?= $this->bodyClass ?>">
<div id="layout-canvas">
<?php if (\BackendAuth::isImpersonator()) : ?>
<div class="global-notice">
<div class="notice-content">
<span class="notice-text">
<span class="notice-icon wn-icon icon-exclamation-triangle"></span>
<?= e(trans('backend::lang.account.impersonating', [
'impersonator' => \BackendAuth::getImpersonator()->email,
'impersonatee' => \BackendAuth::getUser()->email,
])); ?>
</span>
</div>
<a href="<?= Backend::url('backend/auth/signout') ?>" class="notice-action btn btn-secondary">
<?= e(trans('backend::lang.account.stop_impersonating')) ?>
</a>
</div>
<?php endif; ?>

<div class="layout">

<!-- Main Menu -->
Expand Down
62 changes: 62 additions & 0 deletions modules/backend/models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,66 @@ public function unsuspend()
{
BackendAuth::findThrottleByUserId($this->id)->unsuspend();
}

//
// Impersonation
//

/**
* Returns an array of merged permissions based on the user's individual permissions
* and their group permissions filtering out any permissions the impersonator doesn't
* have access to (if the current user is being impersonated)
*
* @return array
*/
public function getMergedPermissions()
{
if (!$this->mergedPermissions) {
$permissions = parent::getMergedPermissions();

// If the user is being impersonated filter out any permissions the impersonator doesn't have access to already
if (BackendAuth::isImpersonator()) {
$impersonator = BackendAuth::getImpersonator();
if ($impersonator && $impersonator !== $this) {
foreach ($permissions as $i => $permission) {
if (!$impersonator->hasAccess($permission)) {
unset($permissions[$i]);
}
}
$this->mergedPermissions = $permissions;
}
}
}

return $this->mergedPermissions;
}

/**
* Check if this user can be impersonated by the provided impersonator
* Super users cannot be impersonated and all users cannot be impersonated unless there is an impersonator
* present and the impersonator has access to `backend.impersonate_users`, and the impersonator is not the
* user being impersonated
*
* @param \Winter\Storm\Auth\Models\User|false $impersonator The user attempting to impersonate this user, false when not available
* @return boolean
*/
public function canBeImpersonated($impersonator = false)
{
if (
$this->isSuperUser() ||
!$impersonator ||
!($impersonator instanceof static) ||
!$impersonator->hasAccess('backend.impersonate_users') ||
$impersonator === $this
) {
return false;
}

// Clear the merged permissions before the impersonation starts
// so that they are correct even if they had been loaded prior
// to the impersonation starting
$this->mergedPermissions = null;

return true;
}
}
2 changes: 1 addition & 1 deletion modules/cms/models/ThemeLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public static function add(HalcyonModel $template, $type = null)
$record->content = $isDelete ? '' : $newContent;
$record->old_content = $oldContent;

if ($user = BackendAuth::getUser()) {
if ($user = BackendAuth::getRealUser()) {
$record->user_id = $user->id;
}

Expand Down
1 change: 1 addition & 0 deletions themes/demo/meta/static-pages.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static-pages: { }
2 changes: 1 addition & 1 deletion themes/demo/partials/site/header.htm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<li class="{% if this.page.id == 'home' %}active{% endif %}"><a href="{{ 'home'|page }}">Basic concepts</a></li>
<li class="{% if this.page.id == 'ajax' %}active{% endif %}"><a href="{{ 'ajax'|page }}">AJAX framework</a></li>
<li class="{% if this.page.id == 'plugins' %}active{% endif %}"><a href="{{ 'plugins'|page }}">Plugin components</a></li>
<li><a href="{{ backendUrl }}" target="backend">Sign in to the Backend</a></li>
<li><a href="{{ backendUrl }}">Sign in to the Backend</a></li>
</ul>
</div>
</div>
Expand Down

0 comments on commit bac9382

Please sign in to comment.