mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-16 21:24:59 +08:00
Use separate email add and bind flow for supporting HSes
This changes the paths used for binding emails for discovery to use the new separate bind / unbind APIs on supporting servers. Part of https://github.com/vector-im/riot-web/issues/10839
This commit is contained in:
parent
9a1305bf4a
commit
ff69ad02b9
@ -27,6 +27,10 @@ import IdentityAuthClient from './IdentityAuthClient';
|
|||||||
* This involves getting an email token from the identity server to "prove" that
|
* This involves getting an email token from the identity server to "prove" that
|
||||||
* the client owns the given email address, which is then passed to the
|
* the client owns the given email address, which is then passed to the
|
||||||
* add threepid API on the homeserver.
|
* add threepid API on the homeserver.
|
||||||
|
*
|
||||||
|
* Diagrams of the intended API flows here are available at:
|
||||||
|
*
|
||||||
|
* https://gist.github.com/jryans/839a09bf0c5a70e2f36ed990d50ed928
|
||||||
*/
|
*/
|
||||||
export default class AddThreepid {
|
export default class AddThreepid {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -59,10 +63,30 @@ export default class AddThreepid {
|
|||||||
* @param {string} emailAddress The email address to add
|
* @param {string} emailAddress The email address to add
|
||||||
* @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked().
|
* @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked().
|
||||||
*/
|
*/
|
||||||
bindEmailAddress(emailAddress) {
|
async bindEmailAddress(emailAddress) {
|
||||||
this.bind = true;
|
this.bind = true;
|
||||||
// TODO: Actually use a different API here
|
if (await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
|
||||||
return this.addEmailAddress(emailAddress);
|
// For separate bind, request a token directly from the IS.
|
||||||
|
const authClient = new IdentityAuthClient();
|
||||||
|
const identityAccessToken = await authClient.getAccessToken();
|
||||||
|
return MatrixClientPeg.get().requestEmailToken(
|
||||||
|
emailAddress, this.clientSecret, 1,
|
||||||
|
undefined, undefined, identityAccessToken,
|
||||||
|
).then((res) => {
|
||||||
|
this.sessionId = res.sid;
|
||||||
|
return res;
|
||||||
|
}, function(err) {
|
||||||
|
if (err.errcode === 'M_THREEPID_IN_USE') {
|
||||||
|
err.message = _t('This email address is already in use');
|
||||||
|
} else if (err.httpStatus) {
|
||||||
|
err.message = err.message + ` (Status ${err.httpStatus})`;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// For tangled bind, request a token via the HS.
|
||||||
|
return this.addEmailAddress(emailAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,20 +131,40 @@ export default class AddThreepid {
|
|||||||
* with a "message" property which contains a human-readable message detailing why
|
* with a "message" property which contains a human-readable message detailing why
|
||||||
* the request failed.
|
* the request failed.
|
||||||
*/
|
*/
|
||||||
checkEmailLinkClicked() {
|
async checkEmailLinkClicked() {
|
||||||
const identityServerDomain = MatrixClientPeg.get().idBaseUrl.split("://")[1];
|
const identityServerDomain = MatrixClientPeg.get().idBaseUrl.split("://")[1];
|
||||||
return MatrixClientPeg.get().addThreePid({
|
try {
|
||||||
sid: this.sessionId,
|
if (await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
|
||||||
client_secret: this.clientSecret,
|
if (this.bind) {
|
||||||
id_server: identityServerDomain,
|
const authClient = new IdentityAuthClient();
|
||||||
}, this.bind).catch(function(err) {
|
const identityAccessToken = await authClient.getAccessToken();
|
||||||
|
await MatrixClientPeg.get().bindThreePid({
|
||||||
|
sid: this.sessionId,
|
||||||
|
client_secret: this.clientSecret,
|
||||||
|
id_server: identityServerDomain,
|
||||||
|
id_access_token: identityAccessToken,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await MatrixClientPeg.get().addThreePidOnly({
|
||||||
|
sid: this.sessionId,
|
||||||
|
client_secret: this.clientSecret,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await MatrixClientPeg.get().addThreePid({
|
||||||
|
sid: this.sessionId,
|
||||||
|
client_secret: this.clientSecret,
|
||||||
|
id_server: identityServerDomain,
|
||||||
|
}, this.bind);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
if (err.httpStatus === 401) {
|
if (err.httpStatus === 401) {
|
||||||
err.message = _t('Failed to verify email address: make sure you clicked the link in the email');
|
err.message = _t('Failed to verify email address: make sure you clicked the link in the email');
|
||||||
} else if (err.httpStatus) {
|
} else if (err.httpStatus) {
|
||||||
err.message += ` (Status ${err.httpStatus})`;
|
err.message += ` (Status ${err.httpStatus})`;
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,6 +64,44 @@ export class EmailAddress extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async changeBinding({ bind, label, errorTitle }) {
|
async changeBinding({ bind, label, errorTitle }) {
|
||||||
|
if (!await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
|
||||||
|
return this.changeBindingTangledAddBind({ bind, label, errorTitle });
|
||||||
|
}
|
||||||
|
|
||||||
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
const { medium, address } = this.props.email;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (bind) {
|
||||||
|
const task = new AddThreepid();
|
||||||
|
this.setState({
|
||||||
|
verifying: true,
|
||||||
|
continueDisabled: true,
|
||||||
|
addTask: task,
|
||||||
|
});
|
||||||
|
await task.bindEmailAddress(address);
|
||||||
|
this.setState({
|
||||||
|
continueDisabled: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await MatrixClientPeg.get().unbindThreePid(medium, address);
|
||||||
|
}
|
||||||
|
this.setState({ bound: bind });
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Unable to ${label} email address ${address} ${err}`);
|
||||||
|
this.setState({
|
||||||
|
verifying: false,
|
||||||
|
continueDisabled: false,
|
||||||
|
addTask: null,
|
||||||
|
});
|
||||||
|
Modal.createTrackedDialog(`Unable to ${label} email address`, '', ErrorDialog, {
|
||||||
|
title: errorTitle,
|
||||||
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async changeBindingTangledAddBind({ bind, label, errorTitle }) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
const { medium, address } = this.props.email;
|
const { medium, address } = this.props.email;
|
||||||
|
|
||||||
@ -75,12 +113,6 @@ export class EmailAddress extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// XXX: Unfortunately, at the moment we can't just bind via the HS
|
|
||||||
// in a single operation, at it will error saying the 3PID is in use
|
|
||||||
// even though it's in use by the current user. For the moment, we
|
|
||||||
// work around this by removing the 3PID from the HS and re-adding
|
|
||||||
// it with IS binding enabled.
|
|
||||||
// See https://github.com/matrix-org/matrix-doc/pull/2140/files#r311462052
|
|
||||||
await MatrixClientPeg.get().deleteThreePid(medium, address);
|
await MatrixClientPeg.get().deleteThreePid(medium, address);
|
||||||
if (bind) {
|
if (bind) {
|
||||||
await task.bindEmailAddress(address);
|
await task.bindEmailAddress(address);
|
||||||
|
Loading…
Reference in New Issue
Block a user