mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: Optionally skip the create account popup for external auth
This commit is contained in:
parent
041d28295f
commit
5284d41a8e
@ -20,6 +20,7 @@ import { userPath } from "discourse/lib/url";
|
|||||||
import { findAll } from "discourse/models/login-method";
|
import { findAll } from "discourse/models/login-method";
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
import User from "discourse/models/user";
|
import User from "discourse/models/user";
|
||||||
|
import { Promise } from "rsvp";
|
||||||
|
|
||||||
export default Controller.extend(
|
export default Controller.extend(
|
||||||
ModalFunctionality,
|
ModalFunctionality,
|
||||||
@ -41,9 +42,13 @@ export default Controller.extend(
|
|||||||
|
|
||||||
hasAuthOptions: notEmpty("authOptions"),
|
hasAuthOptions: notEmpty("authOptions"),
|
||||||
canCreateLocal: setting("enable_local_logins"),
|
canCreateLocal: setting("enable_local_logins"),
|
||||||
showCreateForm: or("hasAuthOptions", "canCreateLocal"),
|
|
||||||
requireInviteCode: setting("require_invite_code"),
|
requireInviteCode: setting("require_invite_code"),
|
||||||
|
|
||||||
|
@discourseComputed("hasAuthOptions", "canCreateLocal", "skipConfirmation")
|
||||||
|
showCreateForm(hasAuthOptions, canCreateLocal, skipConfirmation) {
|
||||||
|
return (hasAuthOptions || canCreateLocal) && !skipConfirmation;
|
||||||
|
},
|
||||||
|
|
||||||
resetForm() {
|
resetForm() {
|
||||||
// We wrap the fields in a structure so we can assign a value
|
// We wrap the fields in a structure so we can assign a value
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
@ -197,26 +202,44 @@ export default Controller.extend(
|
|||||||
|
|
||||||
@on("init")
|
@on("init")
|
||||||
fetchConfirmationValue() {
|
fetchConfirmationValue() {
|
||||||
return ajax(userPath("hp.json")).then(json => {
|
if (this._challengeDate === undefined && this._hpPromise) {
|
||||||
this._challengeDate = new Date();
|
// Request already in progress
|
||||||
// remove 30 seconds for jitter, make sure this works for at least
|
return this._hpPromise;
|
||||||
// 30 seconds so we don't have hard loops
|
}
|
||||||
this._challengeExpiry = parseInt(json.expires_in, 10) - 30;
|
|
||||||
if (this._challengeExpiry < 30) {
|
|
||||||
this._challengeExpiry = 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setProperties({
|
this._hpPromise = ajax(userPath("hp.json"))
|
||||||
accountHoneypot: json.value,
|
.then(json => {
|
||||||
accountChallenge: json.challenge
|
this._challengeDate = new Date();
|
||||||
.split("")
|
// remove 30 seconds for jitter, make sure this works for at least
|
||||||
.reverse()
|
// 30 seconds so we don't have hard loops
|
||||||
.join("")
|
this._challengeExpiry = parseInt(json.expires_in, 10) - 30;
|
||||||
});
|
if (this._challengeExpiry < 30) {
|
||||||
});
|
this._challengeExpiry = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setProperties({
|
||||||
|
accountHoneypot: json.value,
|
||||||
|
accountChallenge: json.challenge
|
||||||
|
.split("")
|
||||||
|
.reverse()
|
||||||
|
.join("")
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => (this._hpPromise = undefined));
|
||||||
|
|
||||||
|
return this._hpPromise;
|
||||||
},
|
},
|
||||||
|
|
||||||
performAccountCreation() {
|
performAccountCreation() {
|
||||||
|
if (
|
||||||
|
!this._challengeDate ||
|
||||||
|
new Date() - this._challengeDate > 1000 * this._challengeExpiry
|
||||||
|
) {
|
||||||
|
return this.fetchConfirmationValue().then(() =>
|
||||||
|
this.performAccountCreation()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const attrs = this.getProperties(
|
const attrs = this.getProperties(
|
||||||
"accountName",
|
"accountName",
|
||||||
"accountEmail",
|
"accountEmail",
|
||||||
@ -263,6 +286,7 @@ export default Controller.extend(
|
|||||||
.find("input[name=redirect]")
|
.find("input[name=redirect]")
|
||||||
.val(userPath("account-created"));
|
.val(userPath("account-created"));
|
||||||
$hidden_login_form.submit();
|
$hidden_login_form.submit();
|
||||||
|
return new Promise(() => {}); // This will never resolve, the page will reload instead
|
||||||
} else {
|
} else {
|
||||||
this.flash(
|
this.flash(
|
||||||
result.message || I18n.t("create_account.failed"),
|
result.message || I18n.t("create_account.failed"),
|
||||||
@ -298,6 +322,14 @@ export default Controller.extend(
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
if (this.skipConfirmation) {
|
||||||
|
this.performAccountCreation().finally(() =>
|
||||||
|
this.set("skipConfirmation", false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
externalLogin(provider) {
|
externalLogin(provider) {
|
||||||
this.login.send("externalLogin", provider);
|
this.login.send("externalLogin", provider);
|
||||||
@ -332,13 +364,7 @@ export default Controller.extend(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new Date() - this._challengeDate > 1000 * this._challengeExpiry) {
|
this.performAccountCreation();
|
||||||
this.fetchConfirmationValue().then(() =>
|
|
||||||
this.performAccountCreation()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.performAccountCreation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,12 +381,16 @@ export default Controller.extend(ModalFunctionality, {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const skipConfirmation =
|
||||||
|
options && this.siteSettings.external_auth_skip_create_confirm;
|
||||||
|
|
||||||
const createAccountController = this.createAccount;
|
const createAccountController = this.createAccount;
|
||||||
createAccountController.setProperties({
|
createAccountController.setProperties({
|
||||||
accountEmail: options.email,
|
accountEmail: options.email,
|
||||||
accountUsername: options.username,
|
accountUsername: options.username,
|
||||||
accountName: options.name,
|
accountName: options.name,
|
||||||
authOptions: EmberObject.create(options)
|
authOptions: EmberObject.create(options),
|
||||||
|
skipConfirmation
|
||||||
});
|
});
|
||||||
|
|
||||||
showModal("createAccount", { modalClass: "create-account" });
|
showModal("createAccount", { modalClass: "create-account" });
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
{{login-buttons externalLogin=(action "externalLogin")}}
|
{{login-buttons externalLogin=(action "externalLogin")}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
|
{{#if skipConfirmation}}
|
||||||
|
{{loading-spinner size="large"}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if showCreateForm}}
|
{{#if showCreateForm}}
|
||||||
<div class="login-form">
|
<div class="login-form">
|
||||||
<form>
|
<form>
|
||||||
|
@ -1624,6 +1624,8 @@ en:
|
|||||||
password_unique_characters: "Minimum number of unique characters that a password must have."
|
password_unique_characters: "Minimum number of unique characters that a password must have."
|
||||||
block_common_passwords: "Don't allow passwords that are in the 10,000 most common passwords."
|
block_common_passwords: "Don't allow passwords that are in the 10,000 most common passwords."
|
||||||
|
|
||||||
|
external_auth_skip_create_confirm: When signing up via external auth, skip the create account popup. Best used alongside sso_overrides_email, sso_overrides_username and sso_overrides_name.
|
||||||
|
|
||||||
enable_sso: "Enable single sign on via an external site (WARNING: USERS' EMAIL ADDRESSES *MUST* BE VALIDATED BY THE EXTERNAL SITE!)"
|
enable_sso: "Enable single sign on via an external site (WARNING: USERS' EMAIL ADDRESSES *MUST* BE VALIDATED BY THE EXTERNAL SITE!)"
|
||||||
verbose_sso_logging: "Log verbose SSO related diagnostics to <a href='%{base_path}/logs' target='_blank'>/logs</a>"
|
verbose_sso_logging: "Log verbose SSO related diagnostics to <a href='%{base_path}/logs' target='_blank'>/logs</a>"
|
||||||
enable_sso_provider: "Implement Discourse SSO provider protocol at the /session/sso_provider endpoint, requires sso_provider_secrets to be set"
|
enable_sso_provider: "Implement Discourse SSO provider protocol at the /session/sso_provider endpoint, requires sso_provider_secrets to be set"
|
||||||
|
@ -379,6 +379,9 @@ login:
|
|||||||
discord_trusted_guilds:
|
discord_trusted_guilds:
|
||||||
default: ""
|
default: ""
|
||||||
type: list
|
type: list
|
||||||
|
external_auth_skip_create_confirm:
|
||||||
|
default: false
|
||||||
|
client: true
|
||||||
enable_sso:
|
enable_sso:
|
||||||
client: true
|
client: true
|
||||||
default: false
|
default: false
|
||||||
|
43
test/javascripts/acceptance/create-account-external-test.js
Normal file
43
test/javascripts/acceptance/create-account-external-test.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { acceptance } from "helpers/qunit-helpers";
|
||||||
|
|
||||||
|
acceptance("Create Account - external auth", {
|
||||||
|
beforeEach() {
|
||||||
|
const node = document.createElement("meta");
|
||||||
|
node.dataset.authenticationData = JSON.stringify({
|
||||||
|
auth_provider: "test",
|
||||||
|
email: "blah@example.com",
|
||||||
|
can_edit_username: true,
|
||||||
|
can_edit_name: true
|
||||||
|
});
|
||||||
|
node.id = "data-authentication";
|
||||||
|
document.querySelector("head").appendChild(node);
|
||||||
|
},
|
||||||
|
afterEach() {
|
||||||
|
document
|
||||||
|
.querySelector("head")
|
||||||
|
.removeChild(document.getElementById("data-authentication"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("when skip is disabled (default)", async assert => {
|
||||||
|
await visit("/");
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
exists("#discourse-modal div.create-account"),
|
||||||
|
"it shows the registration modal"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(exists("#new-account-username"), "it shows the fields");
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("when skip is enabled", async assert => {
|
||||||
|
Discourse.SiteSettings.external_auth_skip_create_confirm = true;
|
||||||
|
await visit("/");
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
exists("#discourse-modal div.create-account"),
|
||||||
|
"it shows the registration modal"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.not(exists("#new-account-username"), "it does not show the fields");
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user