FEATURE: Add safe-mode toggle to `/u/admin-login` (#17930)

Previously, this would require manually adding `?safe_mode=...` multiple times during the email-based login flow. `/u/admin-login` is often used when debugging a site, so it makes sense for this to be easier.

This commit introduces a new checkbox on the `/u/admin-login` screen. When checked, it'll set the safe_mode parameter on the `/email-login` link, and then pass it all the way through to the homepage redirect.
This commit is contained in:
David Taylor 2022-08-15 15:30:07 +01:00 committed by GitHub
parent 64a66cf82b
commit 3ffc213fa9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 2 deletions

View File

@ -6,8 +6,11 @@ import discourseComputed from "discourse-common/utils/decorators";
import getURL from "discourse-common/lib/get-url";
import { getWebauthnCredential } from "discourse/lib/webauthn";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { inject as service } from "@ember/service";
export default Controller.extend({
router: service(),
lockImageUrl: getURL("/images/lock.svg"),
@discourseComputed("model")
@ -41,7 +44,20 @@ export default Controller.extend({
})
.then((result) => {
if (result.success) {
DiscourseURL.redirectTo("/");
let destination = "/";
const safeMode = new URL(
this.router.currentURL,
window.location.origin
).searchParams.get("safe_mode");
if (safeMode) {
const params = new URLSearchParams();
params.set("safe_mode", safeMode);
destination += `?${params.toString()}`;
}
DiscourseURL.redirectTo(destination);
} else {
this.set("model.error", result.error);
}

View File

@ -6,6 +6,10 @@ import {
import { click, fillIn, visit } from "@ember/test-helpers";
import I18n from "I18n";
import { test } from "qunit";
import DiscourseURL from "discourse/lib/url";
import sinon from "sinon";
const TOKEN = "sometoken";
acceptance("Login with email", function (needs) {
needs.settings({
@ -18,6 +22,20 @@ acceptance("Login with email", function (needs) {
server.post("/u/email-login", () =>
helper.response({ success: "OK", user_found: userFound })
);
server.get(`/session/email-login/${TOKEN}.json`, () =>
helper.response({
token: TOKEN,
can_login: true,
token_email: "blah@example.com",
})
);
server.post(`/session/email-login/${TOKEN}`, () =>
helper.response({
success: true,
})
);
});
test("with email button", async function (assert) {
@ -83,4 +101,21 @@ acceptance("Login with email", function (needs) {
userFound = false;
});
test("finish login UI", async function (assert) {
await visit(`/session/email-login/${TOKEN}`);
sinon.stub(DiscourseURL, "redirectTo");
await click(".email-login .btn-primary");
assert.true(DiscourseURL.redirectTo.calledWith("/"), "redirects to home");
});
test("finish login UI - safe mode", async function (assert) {
await visit(`/session/email-login/${TOKEN}?safe_mode=no_themes,no_plugins`);
sinon.stub(DiscourseURL, "redirectTo");
await click(".email-login .btn-primary");
assert.true(
DiscourseURL.redirectTo.calledWith("/?safe_mode=no_themes%2Cno_plugins"),
"redirects to home with safe mode"
);
});
});

View File

@ -961,7 +961,11 @@ class UsersController < ApplicationController
if user = User.with_email(params[:email]).admins.human_users.first
email_token = user.email_tokens.create!(email: user.email, scope: EmailToken.scopes[:email_login])
Jobs.enqueue(:critical_user_email, type: "admin_login", user_id: user.id, email_token: email_token.token)
token_string = email_token.token
if params["use_safe_mode"]
token_string += "?safe_mode=no_plugins,no_themes"
end
Jobs.enqueue(:critical_user_email, type: "admin_login", user_id: user.id, email_token: token_string)
@message = I18n.t("admin_login.success")
else
@message = I18n.t("admin_login.errors.unknown_email_address")

View File

@ -5,6 +5,11 @@
<%=form_tag(u_admin_login_path, method: :put) do %>
<%= label_tag(:email, t('admin_login.email_input')) %>
<%= text_field_tag(:email, nil, autofocus: true) %><br><br>
<label for="use_safe_mode">
<%= check_box_tag 'use_safe_mode' %>
<%= t 'admin_login.safe_mode' %>
</label>
<br/>
<%= submit_tag t('admin_login.submit_button'), class: "btn btn-primary" %>
<% end %>
<% end %>

View File

@ -4833,6 +4833,7 @@ en:
invalid_token: "Invalid token."
email_input: "Admin Email"
submit_button: "Send Email"
safe_mode: "Safe Mode: disable all themes/plugins when logging in"
performance_report:
initial_post_raw: This topic includes daily performance reports for your site.

View File

@ -535,6 +535,14 @@ RSpec.describe UsersController do
expect(args["user_id"]).to eq(admin.id)
end
it 'passes through safe mode' do
put "/u/admin-login", params: { email: admin.email, use_safe_mode: true }
expect(response.status).to eq(200)
expect(Jobs::CriticalUserEmail.jobs.size).to eq(1)
args = Jobs::CriticalUserEmail.jobs.first["args"].first
expect(args["email_token"]).to end_with("?safe_mode=no_plugins,no_themes")
end
context 'when email is incorrect' do
it 'should return the right response' do
put "/u/admin-login", params: { email: 'random' }