Ghost/ghost/admin/app/components/members/modals/logout-member.hbs
Simon Backx 75bb53f065
🔒 Added support for logging out members on all devices (#18935)
fixes https://github.com/TryGhost/Product/issues/3738
https://www.notion.so/ghost/Member-Session-Invalidation-13254316f2244c34bcbc65c101eb5cc4

- Adds the transient_id column to the members table. This defaults to
email, to keep it backwards compatible (not logging out all existing
sessions)
- Instead of using the email in the cookies, we now use the transient_id
- Updating the transient_id means invalidating all sessions of a member
- Adds an endpoint to the admin api to log out a member from all devices
- Added the `all` body property to the DELETE session endpoint in the
members API. Setting it to true will sign a member out from all devices.
- Adds a UI button in Admin to sign a member out from all devices
- Portal 'sign out of all devices' will not be added for now

Related changes (added because these areas were affected by the code
changes):
- Adds a serializer to member events / activity feed endpoints - all
member fields were returned here, so the transient_id would also be
returned - which is not needed and bloats the API response size
(`transient_id` is not a secret because the cookies are signed)
- Removed `loadMemberSession` from public settings browse (not used
anymore + bad pattern)

Performance tests on site with 50.000 members (on Macbook M1 Pro):
- Migrate: 6s (adding column 4s, setting to email is 1s, dropping
nullable: 1s)
- Rollback: 2s
2023-11-15 17:10:28 +01:00

31 lines
1.0 KiB
Handlebars

<div class="modal-content" data-test-modal="logout-member">
<header class="modal-header">
<h1>Sign out member from all devices?</h1>
</header>
<button type="button" class="close" title="Close" {{on "click" (fn @close false)}}>{{svg-jar "close"}}<span class="hidden">Close</span></button>
<div class="modal-body">
<p class="mb6">
<strong>{{or @data.member.name @data.member.email}}</strong> will be signed out of all active sessions, and will need to sign in again upon return.
</p>
</div>
<div class="modal-footer">
<button
type="button"
class="gh-btn"
{{on "click" (fn @close false)}}
data-test-button="cancel"
>
<span>Cancel</span>
</button>
<GhTaskButton
@buttonText="Sign out"
@successText="Signed out"
@task={{this.logoutMemberTask}}
@class="gh-btn gh-btn-red gh-btn-icon"
data-test-button="confirm"
/>
</div>
</div>