Merge pull request #2669 from matrix-org/jryans/default-server-name

Restores support for `default_server_name` which discovers URLs via `.well-known`
This commit is contained in:
J. Ryan Stinnett 2019-02-21 10:38:15 +00:00 committed by GitHub
commit 16b9688303
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 136 additions and 82 deletions

View file

@ -1887,6 +1887,7 @@ export default React.createClass({
sessionId={this.state.register_session_id}
idSid={this.state.register_id_sid}
email={this.props.startingFragmentQueryParams.email}
defaultServerName={this.getDefaultServerName()}
defaultServerDiscoveryError={this.state.defaultServerDiscoveryError}
defaultHsUrl={this.getDefaultHsUrl()}
defaultIsUrl={this.getDefaultIsUrl()}
@ -1923,6 +1924,7 @@ export default React.createClass({
<Login
onLoggedIn={Lifecycle.setLoggedIn}
onRegisterClick={this.onRegisterClick}
defaultServerName={this.getDefaultServerName()}
defaultServerDiscoveryError={this.state.defaultServerDiscoveryError}
defaultHsUrl={this.getDefaultHsUrl()}
defaultIsUrl={this.getDefaultIsUrl()}

View file

@ -41,20 +41,22 @@ module.exports = React.createClass({
displayName: 'ForgotPassword',
propTypes: {
// The default server name to use when the user hasn't specified
// one. If set, `defaultHsUrl` and `defaultHsUrl` were derived for this
// via `.well-known` discovery. The server name is used instead of the
// HS URL when talking about "your account".
defaultServerName: PropTypes.string,
// An error passed along from higher up explaining that something
// went wrong when finding the defaultHsUrl.
defaultServerDiscoveryError: PropTypes.string,
defaultHsUrl: PropTypes.string,
defaultIsUrl: PropTypes.string,
customHsUrl: PropTypes.string,
customIsUrl: PropTypes.string,
onLoginClick: PropTypes.func,
onComplete: PropTypes.func.isRequired,
// The default server name to use when the user hasn't specified
// one. This is used when displaying the defaultHsUrl in the UI.
defaultServerName: PropTypes.string,
// An error passed along from higher up explaining that something
// went wrong when finding the defaultHsUrl.
defaultServerDiscoveryError: PropTypes.string,
},
getInitialState: function() {
@ -234,19 +236,25 @@ module.exports = React.createClass({
errorText = <div className="mx_Login_error">{ err }</div>;
}
let yourMatrixAccountText = _t('Your account');
try {
const parsedHsUrl = new URL(this.state.enteredHsUrl);
yourMatrixAccountText = _t('Your account on %(serverName)s', {
serverName: parsedHsUrl.hostname,
let yourMatrixAccountText = _t('Your Matrix account');
if (this.state.enteredHsUrl === this.props.defaultHsUrl) {
yourMatrixAccountText = _t('Your Matrix account on %(serverName)s', {
serverName: this.props.defaultServerName,
});
} catch (e) {
errorText = <div className="mx_Login_error">{_t(
"The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please " +
"enter a valid URL including the protocol prefix.",
{
hsUrl: this.state.enteredHsUrl,
})}</div>;
} else {
try {
const parsedHsUrl = new URL(this.state.enteredHsUrl);
yourMatrixAccountText = _t('Your Matrix account on %(serverName)s', {
serverName: parsedHsUrl.hostname,
});
} catch (e) {
errorText = <div className="mx_Login_error">{_t(
"The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please " +
"enter a valid URL including the protocol prefix.",
{
hsUrl: this.state.enteredHsUrl,
})}</div>;
}
}
// If custom URLs are allowed, wire up the server details edit link.

View file

@ -56,6 +56,15 @@ module.exports = React.createClass({
enableGuest: PropTypes.bool,
// The default server name to use when the user hasn't specified
// one. If set, `defaultHsUrl` and `defaultHsUrl` were derived for this
// via `.well-known` discovery. The server name is used instead of the
// HS URL when talking about where to "sign in to".
defaultServerName: PropTypes.string,
// An error passed along from higher up explaining that something
// went wrong when finding the defaultHsUrl.
defaultServerDiscoveryError: PropTypes.string,
customHsUrl: PropTypes.string,
customIsUrl: PropTypes.string,
defaultHsUrl: PropTypes.string,
@ -65,10 +74,6 @@ module.exports = React.createClass({
// different homeserver without confusing users.
fallbackHsUrl: PropTypes.string,
// An error passed along from higher up explaining that something
// went wrong when finding the defaultHsUrl.
defaultServerDiscoveryError: PropTypes.string,
defaultDeviceDisplayName: PropTypes.string,
// login shouldn't know or care how registration is done.
@ -563,11 +568,20 @@ module.exports = React.createClass({
_renderPasswordStep: function() {
const PasswordLogin = sdk.getComponent('auth.PasswordLogin');
let onEditServerDetailsClick = null;
// If custom URLs are allowed, wire up the server details edit link.
if (PHASES_ENABLED && !SdkConfig.get()['disable_custom_urls']) {
onEditServerDetailsClick = this.onEditServerDetailsClick;
}
// If the current HS URL is the default HS URL, then we can label it
// with the default HS name (if it exists).
let hsName;
if (this.state.enteredHsUrl === this.props.defaultHsUrl) {
hsName = this.props.defaultServerName;
}
return (
<PasswordLogin
onSubmit={this.onPasswordLogin}
@ -583,6 +597,7 @@ module.exports = React.createClass({
onPhoneNumberBlur={this.onPhoneNumberBlur}
onForgotPasswordClick={this.props.onForgotPasswordClick}
loginIncorrect={this.state.loginIncorrect}
hsName={hsName}
hsUrl={this.state.enteredHsUrl}
disableSubmit={this.state.findingHomeserver}
/>

View file

@ -48,15 +48,20 @@ module.exports = React.createClass({
sessionId: PropTypes.string,
makeRegistrationUrl: PropTypes.func.isRequired,
idSid: PropTypes.string,
// The default server name to use when the user hasn't specified
// one. If set, `defaultHsUrl` and `defaultHsUrl` were derived for this
// via `.well-known` discovery. The server name is used instead of the
// HS URL when talking about "your account".
defaultServerName: PropTypes.string,
// An error passed along from higher up explaining that something
// went wrong when finding the defaultHsUrl.
defaultServerDiscoveryError: PropTypes.string,
customHsUrl: PropTypes.string,
customIsUrl: PropTypes.string,
defaultHsUrl: PropTypes.string,
defaultIsUrl: PropTypes.string,
brand: PropTypes.string,
email: PropTypes.string,
// An error passed along from higher up explaining that something
// went wrong when finding the defaultHsUrl.
defaultServerDiscoveryError: PropTypes.string,
// registration shouldn't know or care how login is done.
onLoginClick: PropTypes.func.isRequired,
onServerConfigChange: PropTypes.func.isRequired,
@ -94,7 +99,7 @@ module.exports = React.createClass({
// If we've been given a session ID, we're resuming
// straight back into UI auth
doingUIAuth: Boolean(this.props.sessionId),
serverType: null,
serverType: ServerType.getTypeFromHsUrl(this.props.customHsUrl),
hsUrl: this.props.customHsUrl,
isUrl: this.props.customIsUrl,
// Phase of the overall registration dialog.
@ -122,7 +127,7 @@ module.exports = React.createClass({
});
},
onServerTypeChange(type, initial) {
onServerTypeChange(type) {
this.setState({
serverType: type,
});
@ -148,15 +153,10 @@ module.exports = React.createClass({
hsUrl: this.props.defaultHsUrl,
isUrl: this.props.defaultIsUrl,
});
// if this is the initial value from the control and we're
// already in the registration phase, don't go back to the
// server details phase (but do if it's actually a change resulting
// from user interaction).
if (!initial || !this.state.phase === PHASE_REGISTRATION) {
this.setState({
phase: PHASE_SERVER_DETAILS,
});
}
// Reset back to server details on type change.
this.setState({
phase: PHASE_SERVER_DETAILS,
});
break;
}
},
@ -389,12 +389,9 @@ module.exports = React.createClass({
// If we're on a different phase, we only show the server type selector,
// which is always shown if we allow custom URLs at all.
if (PHASES_ENABLED && this.state.phase !== PHASE_SERVER_DETAILS) {
// if we've been given a custom HS URL we should actually pass that, so
// that the appropriate section is selected at the start to match the
// homeserver URL we're using
return <div>
<ServerTypeSelector
defaultHsUrl={this.props.customHsUrl || this.props.defaultHsUrl}
selected={this.state.serverType}
onChange={this.onServerTypeChange}
/>
</div>;
@ -436,7 +433,7 @@ module.exports = React.createClass({
return <div>
<ServerTypeSelector
defaultHsUrl={this.props.defaultHsUrl}
selected={this.state.serverType}
onChange={this.onServerTypeChange}
/>
{serverDetails}
@ -478,6 +475,14 @@ module.exports = React.createClass({
) {
onEditServerDetailsClick = this.onEditServerDetailsClick;
}
// If the current HS URL is the default HS URL, then we can label it
// with the default HS name (if it exists).
let hsName;
if (this.state.hsUrl === this.props.defaultHsUrl) {
hsName = this.props.defaultServerName;
}
return <RegistrationForm
defaultUsername={this.state.formVals.username}
defaultEmail={this.state.formVals.email}
@ -489,6 +494,7 @@ module.exports = React.createClass({
onRegisterClick={this.onFormSubmit}
onEditServerDetailsClick={onEditServerDetailsClick}
flows={this.state.flows}
hsName={hsName}
hsUrl={this.state.hsUrl}
/>;
}

View file

@ -40,6 +40,10 @@ class PasswordLogin extends React.Component {
initialPhoneNumber: "",
initialPassword: "",
loginIncorrect: false,
// This is optional and only set if we used a server name to determine
// the HS URL via `.well-known` discovery. The server name is used
// instead of the HS URL when talking about where to "sign in to".
hsName: null,
hsUrl: "",
disableSubmit: false,
}
@ -54,6 +58,7 @@ class PasswordLogin extends React.Component {
loginType: PasswordLogin.LOGIN_FIELD_MXID,
};
this.onForgotPasswordClick = this.onForgotPasswordClick.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
this.onUsernameChanged = this.onUsernameChanged.bind(this);
this.onUsernameBlur = this.onUsernameBlur.bind(this);
@ -70,6 +75,12 @@ class PasswordLogin extends React.Component {
this._loginField = null;
}
onForgotPasswordClick(ev) {
ev.preventDefault();
ev.stopPropagation();
this.props.onForgotPasswordClick();
}
onSubmitForm(ev) {
ev.preventDefault();
@ -240,7 +251,7 @@ class PasswordLogin extends React.Component {
forgotPasswordJsx = <span>
{_t('Not sure of your password? <a>Set a new one</a>', {}, {
a: sub => <a className="mx_Login_forgot"
onClick={this.props.onForgotPasswordClick}
onClick={this.onForgotPasswordClick}
href="#"
>
{sub}
@ -249,14 +260,20 @@ class PasswordLogin extends React.Component {
</span>;
}
let signInToText = _t('Sign in');
try {
const parsedHsUrl = new URL(this.props.hsUrl);
signInToText = _t('Sign in to %(serverName)s', {
serverName: parsedHsUrl.hostname,
let signInToText = _t('Sign in to your Matrix account');
if (this.props.hsName) {
signInToText = _t('Sign in to your Matrix account on %(serverName)s', {
serverName: this.props.hsName,
});
} catch (e) {
// ignore
} else {
try {
const parsedHsUrl = new URL(this.props.hsUrl);
signInToText = _t('Sign in to your Matrix account on %(serverName)s', {
serverName: parsedHsUrl.hostname,
});
} catch (e) {
// ignore
}
}
let editLink = null;
@ -338,6 +355,8 @@ PasswordLogin.propTypes = {
onPhoneNumberChanged: PropTypes.func,
onPasswordChanged: PropTypes.func,
loginIncorrect: PropTypes.bool,
hsName: PropTypes.string,
hsUrl: PropTypes.string,
disableSubmit: PropTypes.bool,
};

View file

@ -50,6 +50,10 @@ module.exports = React.createClass({
onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
onEditServerDetailsClick: PropTypes.func,
flows: PropTypes.arrayOf(PropTypes.object).isRequired,
// This is optional and only set if we used a server name to determine
// the HS URL via `.well-known` discovery. The server name is used
// instead of the HS URL when talking about "your account".
hsName: PropTypes.string,
hsUrl: PropTypes.string,
},
@ -295,14 +299,20 @@ module.exports = React.createClass({
},
render: function() {
let yourMatrixAccountText = _t('Create your account');
try {
const parsedHsUrl = new URL(this.props.hsUrl);
yourMatrixAccountText = _t('Create your %(serverName)s account', {
serverName: parsedHsUrl.hostname,
let yourMatrixAccountText = _t('Create your Matrix account');
if (this.props.hsName) {
yourMatrixAccountText = _t('Create your Matrix account on %(serverName)s', {
serverName: this.props.hsName,
});
} catch (e) {
// ignore
} else {
try {
const parsedHsUrl = new URL(this.props.hsUrl);
yourMatrixAccountText = _t('Create your Matrix account on %(serverName)s', {
serverName: parsedHsUrl.hostname,
});
} catch (e) {
// ignore
}
}
let editLink = null;

View file

@ -56,14 +56,14 @@ export const TYPES = {
},
};
function getDefaultType(defaultHsUrl) {
if (!defaultHsUrl) {
export function getTypeFromHsUrl(hsUrl) {
if (!hsUrl) {
return null;
} else if (defaultHsUrl === TYPES.FREE.hsUrl) {
} else if (hsUrl === TYPES.FREE.hsUrl) {
return FREE;
} else if (new URL(defaultHsUrl).hostname.endsWith('.modular.im')) {
// TODO: Use a Riot config parameter to detect Modular-ness.
// https://github.com/vector-im/riot-web/issues/8253
} else if (new URL(hsUrl).hostname.endsWith('.modular.im')) {
// This is an unlikely case to reach, as Modular defaults to hiding the
// server type selector.
return PREMIUM;
} else {
return ADVANCED;
@ -72,8 +72,8 @@ function getDefaultType(defaultHsUrl) {
export default class ServerTypeSelector extends React.PureComponent {
static propTypes = {
// The default HS URL as another way to set the initially selected type.
defaultHsUrl: PropTypes.string,
// The default selected type.
selected: PropTypes.string,
// Handler called when the selected type changes.
onChange: PropTypes.func.isRequired,
}
@ -82,20 +82,12 @@ export default class ServerTypeSelector extends React.PureComponent {
super(props);
const {
defaultHsUrl,
onChange,
selected,
} = props;
const type = getDefaultType(defaultHsUrl);
this.state = {
selected: type,
selected,
};
if (onChange) {
// FIXME: Supply a second 'initial' param here to flag that this is
// initialising the value rather than from user interaction
// (which sometimes we'll want to ignore). Must be a better way
// to do this.
onChange(type, true);
}
}
updateSelectedType(type) {

View file

@ -1251,13 +1251,14 @@
"Username": "Username",
"Mobile phone number": "Mobile phone number",
"Not sure of your password? <a>Set a new one</a>": "Not sure of your password? <a>Set a new one</a>",
"Sign in to %(serverName)s": "Sign in to %(serverName)s",
"Sign in to your Matrix account": "Sign in to your Matrix account",
"Sign in to your Matrix account on %(serverName)s": "Sign in to your Matrix account on %(serverName)s",
"Change": "Change",
"Sign in with": "Sign in with",
"Phone": "Phone",
"If you don't specify an email address, you won't be able to reset your password. Are you sure?": "If you don't specify an email address, you won't be able to reset your password. Are you sure?",
"Create your account": "Create your account",
"Create your %(serverName)s account": "Create your %(serverName)s account",
"Create your Matrix account": "Create your Matrix account",
"Create your Matrix account on %(serverName)s": "Create your Matrix account on %(serverName)s",
"Email": "Email",
"Email (optional)": "Email (optional)",
"Phone (optional)": "Phone (optional)",
@ -1407,8 +1408,8 @@
"A new password must be entered.": "A new password must be entered.",
"New passwords must match each other.": "New passwords must match each other.",
"Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.",
"Your account": "Your account",
"Your account on %(serverName)s": "Your account on %(serverName)s",
"Your Matrix account": "Your Matrix account",
"Your Matrix account on %(serverName)s": "Your Matrix account on %(serverName)s",
"The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please enter a valid URL including the protocol prefix.": "The homeserver URL %(hsUrl)s doesn't seem to be valid URL. Please enter a valid URL including the protocol prefix.",
"A verification email will be sent to your inbox to confirm setting your new password.": "A verification email will be sent to your inbox to confirm setting your new password.",
"Send Reset Email": "Send Reset Email",
@ -1452,6 +1453,7 @@
"A phone number is required to register on this homeserver.": "A phone number is required to register on this homeserver.",
"You need to enter a username.": "You need to enter a username.",
"An unknown error occurred.": "An unknown error occurred.",
"Create your account": "Create your account",
"Commands": "Commands",
"Results from DuckDuckGo": "Results from DuckDuckGo",
"Emoji": "Emoji",