mirror of https://github.com/vector-im/riot-web
Fix race in Registration between server change and flows fetch (#8359)
parent
6e86a14cc9
commit
b4bcbb2f30
|
@ -110,7 +110,9 @@ interface IState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Registration extends React.Component<IProps, IState> {
|
export default class Registration extends React.Component<IProps, IState> {
|
||||||
loginLogic: Login;
|
private readonly loginLogic: Login;
|
||||||
|
// `replaceClient` tracks latest serverConfig to spot when it changes under the async method which fetches flows
|
||||||
|
private latestServerConfig: ValidatedServerConfig;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -149,26 +151,28 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async replaceClient(serverConfig: ValidatedServerConfig) {
|
private async replaceClient(serverConfig: ValidatedServerConfig) {
|
||||||
|
this.latestServerConfig = serverConfig;
|
||||||
|
const { hsUrl, isUrl } = serverConfig;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
errorText: null,
|
errorText: null,
|
||||||
serverDeadError: null,
|
serverDeadError: null,
|
||||||
serverErrorIsFatal: false,
|
serverErrorIsFatal: false,
|
||||||
// busy while we do liveness check (we need to avoid trying to render
|
// busy while we do live-ness check (we need to avoid trying to render
|
||||||
// the UI auth component while we don't have a matrix client)
|
// the UI auth component while we don't have a matrix client)
|
||||||
busy: true,
|
busy: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Do a liveliness check on the URLs
|
// Do a liveliness check on the URLs
|
||||||
try {
|
try {
|
||||||
await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
|
await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(hsUrl, isUrl);
|
||||||
serverConfig.hsUrl,
|
if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us
|
||||||
serverConfig.isUrl,
|
|
||||||
);
|
|
||||||
this.setState({
|
this.setState({
|
||||||
serverIsAlive: true,
|
serverIsAlive: true,
|
||||||
serverErrorIsFatal: false,
|
serverErrorIsFatal: false,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us
|
||||||
this.setState({
|
this.setState({
|
||||||
busy: false,
|
busy: false,
|
||||||
...AutoDiscoveryUtils.authComponentStateForError(e, "register"),
|
...AutoDiscoveryUtils.authComponentStateForError(e, "register"),
|
||||||
|
@ -178,7 +182,6 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { hsUrl, isUrl } = serverConfig;
|
|
||||||
const cli = createClient({
|
const cli = createClient({
|
||||||
baseUrl: hsUrl,
|
baseUrl: hsUrl,
|
||||||
idBaseUrl: isUrl,
|
idBaseUrl: isUrl,
|
||||||
|
@ -190,8 +193,10 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
let ssoFlow: ISSOFlow;
|
let ssoFlow: ISSOFlow;
|
||||||
try {
|
try {
|
||||||
const loginFlows = await this.loginLogic.getFlows();
|
const loginFlows = await this.loginLogic.getFlows();
|
||||||
|
if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us
|
||||||
ssoFlow = loginFlows.find(f => f.type === "m.login.sso" || f.type === "m.login.cas") as ISSOFlow;
|
ssoFlow = loginFlows.find(f => f.type === "m.login.sso" || f.type === "m.login.cas") as ISSOFlow;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us
|
||||||
logger.error("Failed to get login flows to check for SSO support", e);
|
logger.error("Failed to get login flows to check for SSO support", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,23 +205,19 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
ssoFlow,
|
ssoFlow,
|
||||||
busy: false,
|
busy: false,
|
||||||
});
|
});
|
||||||
const showGenericError = (e) => {
|
|
||||||
this.setState({
|
|
||||||
errorText: _t("Unable to query for supported registration methods."),
|
|
||||||
// add empty flows array to get rid of spinner
|
|
||||||
flows: [],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
// We do the first registration request ourselves to discover whether we need to
|
// We do the first registration request ourselves to discover whether we need to
|
||||||
// do SSO instead. If we've already started the UI Auth process though, we don't
|
// do SSO instead. If we've already started the UI Auth process though, we don't
|
||||||
// need to.
|
// need to.
|
||||||
if (!this.state.doingUIAuth) {
|
if (!this.state.doingUIAuth) {
|
||||||
await this.makeRegisterRequest(null);
|
await this.makeRegisterRequest(null);
|
||||||
|
if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us
|
||||||
// This should never succeed since we specified no auth object.
|
// This should never succeed since we specified no auth object.
|
||||||
logger.log("Expecting 401 from register request but got success!");
|
logger.log("Expecting 401 from register request but got success!");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us
|
||||||
if (e.httpStatus === 401) {
|
if (e.httpStatus === 401) {
|
||||||
this.setState({
|
this.setState({
|
||||||
flows: e.data.flows,
|
flows: e.data.flows,
|
||||||
|
@ -239,16 +240,20 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log("Unable to query for supported registration methods.", e);
|
logger.log("Unable to query for supported registration methods.", e);
|
||||||
showGenericError(e);
|
this.setState({
|
||||||
|
errorText: _t("Unable to query for supported registration methods."),
|
||||||
|
// add empty flows array to get rid of spinner
|
||||||
|
flows: [],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFormSubmit = async (formVals): Promise<void> => {
|
private onFormSubmit = async (formVals: Record<string, string>): Promise<void> => {
|
||||||
this.setState({
|
this.setState({
|
||||||
errorText: "",
|
errorText: "",
|
||||||
busy: true,
|
busy: true,
|
||||||
formVals: formVals,
|
formVals,
|
||||||
doingUIAuth: true,
|
doingUIAuth: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -3209,8 +3209,8 @@
|
||||||
"Signing In...": "Signing In...",
|
"Signing In...": "Signing In...",
|
||||||
"If you've joined lots of rooms, this might take a while": "If you've joined lots of rooms, this might take a while",
|
"If you've joined lots of rooms, this might take a while": "If you've joined lots of rooms, this might take a while",
|
||||||
"New? <a>Create account</a>": "New? <a>Create account</a>",
|
"New? <a>Create account</a>": "New? <a>Create account</a>",
|
||||||
"Unable to query for supported registration methods.": "Unable to query for supported registration methods.",
|
|
||||||
"Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.",
|
"Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.",
|
||||||
|
"Unable to query for supported registration methods.": "Unable to query for supported registration methods.",
|
||||||
"This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.",
|
"This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.",
|
||||||
"Someone already has that username, please try another.": "Someone already has that username, please try another.",
|
"Someone already has that username, please try another.": "Someone already has that username, please try another.",
|
||||||
"That e-mail address is already in use.": "That e-mail address is already in use.",
|
"That e-mail address is already in use.": "That e-mail address is already in use.",
|
||||||
|
|
Loading…
Reference in New Issue