Implement simple team-based registration (#620)
* Implement simple team-based registration Config required goes in the `teams` top-level property in config.json. This consists of an array of team objects: ```json { "name": "University of Bath", "emailSuffix": "bath.ac.uk" } ``` These can be selected on registration and require a user to have a certain email address in order to register as part of a team. This is for vector-im/riot-web#2940. The next step would be sending users with emails matching the emailSuffix of a team to the correct welcome page as in vector-im/riot-web#2430.
This commit is contained in:
parent
fcb1d7a664
commit
5ef5204c8c
3 changed files with 108 additions and 12 deletions
|
@ -1003,6 +1003,7 @@ module.exports = React.createClass({
|
||||||
defaultHsUrl={this.getDefaultHsUrl()}
|
defaultHsUrl={this.getDefaultHsUrl()}
|
||||||
defaultIsUrl={this.getDefaultIsUrl()}
|
defaultIsUrl={this.getDefaultIsUrl()}
|
||||||
brand={this.props.config.brand}
|
brand={this.props.config.brand}
|
||||||
|
teamsConfig={this.props.config.teamsConfig}
|
||||||
customHsUrl={this.getCurrentHsUrl()}
|
customHsUrl={this.getCurrentHsUrl()}
|
||||||
customIsUrl={this.getCurrentIsUrl()}
|
customIsUrl={this.getCurrentIsUrl()}
|
||||||
registrationUrl={this.props.registrationUrl}
|
registrationUrl={this.props.registrationUrl}
|
||||||
|
|
|
@ -49,6 +49,16 @@ module.exports = React.createClass({
|
||||||
email: React.PropTypes.string,
|
email: React.PropTypes.string,
|
||||||
username: React.PropTypes.string,
|
username: React.PropTypes.string,
|
||||||
guestAccessToken: React.PropTypes.string,
|
guestAccessToken: React.PropTypes.string,
|
||||||
|
teamsConfig: React.PropTypes.shape({
|
||||||
|
// Email address to request new teams
|
||||||
|
supportEmail: React.PropTypes.string,
|
||||||
|
teams: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||||
|
// The displayed name of the team
|
||||||
|
"name": React.PropTypes.string,
|
||||||
|
// The suffix with which every team email address ends
|
||||||
|
"emailSuffix": React.PropTypes.string,
|
||||||
|
})).required,
|
||||||
|
}),
|
||||||
|
|
||||||
defaultDeviceDisplayName: React.PropTypes.string,
|
defaultDeviceDisplayName: React.PropTypes.string,
|
||||||
|
|
||||||
|
@ -254,6 +264,7 @@ module.exports = React.createClass({
|
||||||
defaultUsername={this.state.formVals.username}
|
defaultUsername={this.state.formVals.username}
|
||||||
defaultEmail={this.state.formVals.email}
|
defaultEmail={this.state.formVals.email}
|
||||||
defaultPassword={this.state.formVals.password}
|
defaultPassword={this.state.formVals.password}
|
||||||
|
teamsConfig={this.props.teamsConfig}
|
||||||
guestUsername={this.props.username}
|
guestUsername={this.props.username}
|
||||||
minPasswordLength={MIN_PASSWORD_LENGTH}
|
minPasswordLength={MIN_PASSWORD_LENGTH}
|
||||||
onError={this.onFormValidationFailed}
|
onError={this.onFormValidationFailed}
|
||||||
|
|
|
@ -38,6 +38,16 @@ module.exports = React.createClass({
|
||||||
defaultEmail: React.PropTypes.string,
|
defaultEmail: React.PropTypes.string,
|
||||||
defaultUsername: React.PropTypes.string,
|
defaultUsername: React.PropTypes.string,
|
||||||
defaultPassword: React.PropTypes.string,
|
defaultPassword: React.PropTypes.string,
|
||||||
|
teamsConfig: React.PropTypes.shape({
|
||||||
|
// Email address to request new teams
|
||||||
|
supportEmail: React.PropTypes.string,
|
||||||
|
teams: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||||
|
// The displayed name of the team
|
||||||
|
"name": React.PropTypes.string,
|
||||||
|
// The suffix with which every team email address ends
|
||||||
|
"emailSuffix": React.PropTypes.string,
|
||||||
|
})).required,
|
||||||
|
}),
|
||||||
|
|
||||||
// A username that will be used if no username is entered.
|
// A username that will be used if no username is entered.
|
||||||
// Specifying this param will also warn the user that entering
|
// Specifying this param will also warn the user that entering
|
||||||
|
@ -62,7 +72,8 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
fieldValid: {}
|
fieldValid: {},
|
||||||
|
selectedTeam: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -119,6 +130,25 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSelectTeam: function(teamIndex) {
|
||||||
|
let team = this._getSelectedTeam(teamIndex);
|
||||||
|
if (team) {
|
||||||
|
this.refs.email.value = this.refs.email.value.split("@")[0];
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
selectedTeam: team,
|
||||||
|
showSupportEmail: teamIndex === "other",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_getSelectedTeam: function(teamIndex) {
|
||||||
|
if (this.props.teamsConfig &&
|
||||||
|
this.props.teamsConfig.teams[teamIndex]) {
|
||||||
|
return this.props.teamsConfig.teams[teamIndex];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if all fields were valid last time
|
* Returns true if all fields were valid last time
|
||||||
* they were validated.
|
* they were validated.
|
||||||
|
@ -139,11 +169,15 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
switch (field_id) {
|
switch (field_id) {
|
||||||
case FIELD_EMAIL:
|
case FIELD_EMAIL:
|
||||||
this.markFieldValid(
|
let email = this.refs.email.value;
|
||||||
field_id,
|
if (this.props.teamsConfig) {
|
||||||
this.refs.email.value == '' || Email.looksValid(this.refs.email.value),
|
let team = this.state.selectedTeam;
|
||||||
"RegistrationForm.ERR_EMAIL_INVALID"
|
if (team) {
|
||||||
);
|
email = email + "@" + team.emailSuffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let valid = email === '' || Email.looksValid(email);
|
||||||
|
this.markFieldValid(field_id, valid, "RegistrationForm.ERR_EMAIL_INVALID");
|
||||||
break;
|
break;
|
||||||
case FIELD_USERNAME:
|
case FIELD_USERNAME:
|
||||||
// XXX: SPEC-1
|
// XXX: SPEC-1
|
||||||
|
@ -222,17 +256,64 @@ module.exports = React.createClass({
|
||||||
return cls;
|
return cls;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_renderEmailInputSuffix: function() {
|
||||||
|
let suffix = null;
|
||||||
|
if (!this.state.selectedTeam) {
|
||||||
|
return suffix;
|
||||||
|
}
|
||||||
|
let team = this.state.selectedTeam;
|
||||||
|
if (team) {
|
||||||
|
suffix = "@" + team.emailSuffix;
|
||||||
|
}
|
||||||
|
return suffix;
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var emailSection, registerButton;
|
var emailSection, teamSection, teamAdditionSupport, registerButton;
|
||||||
if (this.props.showEmail) {
|
if (this.props.showEmail) {
|
||||||
|
let emailSuffix = this._renderEmailInputSuffix();
|
||||||
emailSection = (
|
emailSection = (
|
||||||
|
<div>
|
||||||
<input type="text" ref="email"
|
<input type="text" ref="email"
|
||||||
autoFocus={true} placeholder="Email address (optional)"
|
autoFocus={true} placeholder="Email address (optional)"
|
||||||
defaultValue={this.props.defaultEmail}
|
defaultValue={this.props.defaultEmail}
|
||||||
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
||||||
onBlur={function() {self.validateField(FIELD_EMAIL)}} />
|
onBlur={function() {self.validateField(FIELD_EMAIL)}}
|
||||||
|
value={self.state.email}/>
|
||||||
|
{emailSuffix ? <input className="mx_Login_field" value={emailSuffix} disabled/> : null }
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
if (this.props.teamsConfig) {
|
||||||
|
teamSection = (
|
||||||
|
<select
|
||||||
|
defaultValue="-1"
|
||||||
|
className="mx_Login_field"
|
||||||
|
onBlur={function() {self.validateField(FIELD_EMAIL)}}
|
||||||
|
onChange={function(ev) {self.onSelectTeam(ev.target.value)}}
|
||||||
|
>
|
||||||
|
<option key="-1" value="-1">No team</option>
|
||||||
|
{this.props.teamsConfig.teams.map((t, index) => {
|
||||||
|
return (
|
||||||
|
<option key={index} value={index}>
|
||||||
|
{t.name}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<option key="-2" value="other">Other</option>
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
if (this.props.teamsConfig.supportEmail && this.state.showSupportEmail) {
|
||||||
|
teamAdditionSupport = (
|
||||||
|
<span>
|
||||||
|
If your team is not listed, email
|
||||||
|
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
|
||||||
|
{this.props.teamsConfig.supportEmail}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.props.onRegisterClick) {
|
if (this.props.onRegisterClick) {
|
||||||
registerButton = (
|
registerButton = (
|
||||||
|
@ -248,6 +329,9 @@ module.exports = React.createClass({
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
|
{teamSection}
|
||||||
|
{teamAdditionSupport}
|
||||||
|
<br />
|
||||||
{emailSection}
|
{emailSection}
|
||||||
<br />
|
<br />
|
||||||
<input type="text" ref="username"
|
<input type="text" ref="username"
|
||||||
|
|
Loading…
Reference in a new issue