mirror of https://github.com/vector-im/riot-web
Remove support for team servers
parent
2061ce2dbf
commit
20b7debcaf
|
@ -27,7 +27,6 @@ import UserActivity from './UserActivity';
|
||||||
import Presence from './Presence';
|
import Presence from './Presence';
|
||||||
import dis from './dispatcher';
|
import dis from './dispatcher';
|
||||||
import DMRoomMap from './utils/DMRoomMap';
|
import DMRoomMap from './utils/DMRoomMap';
|
||||||
import RtsClient from './RtsClient';
|
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import sdk from './index';
|
import sdk from './index';
|
||||||
import ActiveWidgetStore from './stores/ActiveWidgetStore';
|
import ActiveWidgetStore from './stores/ActiveWidgetStore';
|
||||||
|
@ -224,7 +223,7 @@ function _registerAsGuest(hsUrl, isUrl, defaultDeviceDisplayName) {
|
||||||
//
|
//
|
||||||
// The plan is to gradually move the localStorage access done here into
|
// The plan is to gradually move the localStorage access done here into
|
||||||
// SessionStore to avoid bugs where the view becomes out-of-sync with
|
// SessionStore to avoid bugs where the view becomes out-of-sync with
|
||||||
// localStorage (e.g. teamToken, isGuest etc.)
|
// localStorage (e.g. isGuest etc.)
|
||||||
async function _restoreFromLocalStorage() {
|
async function _restoreFromLocalStorage() {
|
||||||
if (!localStorage) {
|
if (!localStorage) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -286,15 +285,6 @@ function _handleLoadSessionFailure(e) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let rtsClient = null;
|
|
||||||
export function initRtsClient(url) {
|
|
||||||
if (url) {
|
|
||||||
rtsClient = new RtsClient(url);
|
|
||||||
} else {
|
|
||||||
rtsClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transitions to a logged-in state using the given credentials.
|
* Transitions to a logged-in state using the given credentials.
|
||||||
*
|
*
|
||||||
|
@ -333,7 +323,7 @@ async function _doSetLoggedIn(credentials, clearStorage) {
|
||||||
);
|
);
|
||||||
|
|
||||||
// This is dispatched to indicate that the user is still in the process of logging in
|
// This is dispatched to indicate that the user is still in the process of logging in
|
||||||
// because `teamPromise` may take some time to resolve, breaking the assumption that
|
// because async code may take some time to resolve, breaking the assumption that
|
||||||
// `setLoggedIn` takes an "instant" to complete, and dispatch `on_logged_in` a few ms
|
// `setLoggedIn` takes an "instant" to complete, and dispatch `on_logged_in` a few ms
|
||||||
// later than MatrixChat might assume.
|
// later than MatrixChat might assume.
|
||||||
//
|
//
|
||||||
|
@ -347,10 +337,6 @@ async function _doSetLoggedIn(credentials, clearStorage) {
|
||||||
|
|
||||||
Analytics.setLoggedIn(credentials.guest, credentials.homeserverUrl, credentials.identityServerUrl);
|
Analytics.setLoggedIn(credentials.guest, credentials.homeserverUrl, credentials.identityServerUrl);
|
||||||
|
|
||||||
// Resolves by default
|
|
||||||
let teamPromise = Promise.resolve(null);
|
|
||||||
|
|
||||||
|
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
try {
|
try {
|
||||||
_persistCredentialsToLocalStorage(credentials);
|
_persistCredentialsToLocalStorage(credentials);
|
||||||
|
@ -367,27 +353,13 @@ async function _doSetLoggedIn(credentials, clearStorage) {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Error using local storage: can't persist session!", e);
|
console.warn("Error using local storage: can't persist session!", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtsClient && !credentials.guest) {
|
|
||||||
teamPromise = rtsClient.login(credentials.userId).then((body) => {
|
|
||||||
if (body.team_token) {
|
|
||||||
localStorage.setItem("mx_team_token", body.team_token);
|
|
||||||
}
|
|
||||||
return body.team_token;
|
|
||||||
}, (err) => {
|
|
||||||
console.warn(`Failed to get team token on login: ${err}` );
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
console.warn("No local storage available: can't persist session!");
|
console.warn("No local storage available: can't persist session!");
|
||||||
}
|
}
|
||||||
|
|
||||||
MatrixClientPeg.replaceUsingCreds(credentials);
|
MatrixClientPeg.replaceUsingCreds(credentials);
|
||||||
|
|
||||||
teamPromise.then((teamToken) => {
|
dis.dispatch({ action: 'on_logged_in' });
|
||||||
dis.dispatch({action: 'on_logged_in', teamToken: teamToken});
|
|
||||||
});
|
|
||||||
|
|
||||||
await startMatrixClient();
|
await startMatrixClient();
|
||||||
return MatrixClientPeg.get();
|
return MatrixClientPeg.get();
|
||||||
|
|
104
src/RtsClient.js
104
src/RtsClient.js
|
@ -1,104 +0,0 @@
|
||||||
import 'whatwg-fetch';
|
|
||||||
|
|
||||||
let fetchFunction = fetch;
|
|
||||||
|
|
||||||
function checkStatus(response) {
|
|
||||||
if (!response.ok) {
|
|
||||||
return response.text().then((text) => {
|
|
||||||
throw new Error(text);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseJson(response) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeQueryParams(params) {
|
|
||||||
return '?' + Object.keys(params).map((k) => {
|
|
||||||
return k + '=' + encodeURIComponent(params[k]);
|
|
||||||
}).join('&');
|
|
||||||
}
|
|
||||||
|
|
||||||
const request = (url, opts) => {
|
|
||||||
if (opts && opts.qs) {
|
|
||||||
url += encodeQueryParams(opts.qs);
|
|
||||||
delete opts.qs;
|
|
||||||
}
|
|
||||||
if (opts && opts.body) {
|
|
||||||
if (!opts.headers) {
|
|
||||||
opts.headers = {};
|
|
||||||
}
|
|
||||||
opts.body = JSON.stringify(opts.body);
|
|
||||||
opts.headers['Content-Type'] = 'application/json';
|
|
||||||
}
|
|
||||||
return fetchFunction(url, opts)
|
|
||||||
.then(checkStatus)
|
|
||||||
.then(parseJson);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default class RtsClient {
|
|
||||||
constructor(url) {
|
|
||||||
this._url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTeamsConfig() {
|
|
||||||
return request(this._url + '/teams');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Track a referral with the Riot Team Server. This should be called once a referred
|
|
||||||
* user has been successfully registered.
|
|
||||||
* @param {string} referrer the user ID of one who referred the user to Riot.
|
|
||||||
* @param {string} sid the sign-up identity server session ID .
|
|
||||||
* @param {string} clientSecret the sign-up client secret.
|
|
||||||
* @returns {Promise} a promise that resolves to { team_token: 'sometoken' } upon
|
|
||||||
* success.
|
|
||||||
*/
|
|
||||||
trackReferral(referrer, sid, clientSecret) {
|
|
||||||
return request(this._url + '/register',
|
|
||||||
{
|
|
||||||
body: {
|
|
||||||
referrer: referrer,
|
|
||||||
session_id: sid,
|
|
||||||
client_secret: clientSecret,
|
|
||||||
},
|
|
||||||
method: 'POST',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTeam(teamToken) {
|
|
||||||
return request(this._url + '/teamConfiguration',
|
|
||||||
{
|
|
||||||
qs: {
|
|
||||||
team_token: teamToken,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal to the RTS that a login has occurred and that a user requires their team's
|
|
||||||
* token.
|
|
||||||
* @param {string} userId the user ID of the user who is a member of a team.
|
|
||||||
* @returns {Promise} a promise that resolves to { team_token: 'sometoken' } upon
|
|
||||||
* success.
|
|
||||||
*/
|
|
||||||
login(userId) {
|
|
||||||
return request(this._url + '/login',
|
|
||||||
{
|
|
||||||
qs: {
|
|
||||||
user_id: userId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// allow fetch to be replaced, for testing.
|
|
||||||
static setFetch(fn) {
|
|
||||||
fetchFunction = fn;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,11 +30,6 @@ class HomePage extends React.Component {
|
||||||
static displayName = 'HomePage';
|
static displayName = 'HomePage';
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
// URL base of the team server. Optional.
|
|
||||||
teamServerUrl: PropTypes.string,
|
|
||||||
// Team token. Optional. If set, used to get the static homepage of the team
|
|
||||||
// associated. If unset, homePageUrl will be used.
|
|
||||||
teamToken: PropTypes.string,
|
|
||||||
// URL to use as the iFrame src. Defaults to /home.html.
|
// URL to use as the iFrame src. Defaults to /home.html.
|
||||||
homePageUrl: PropTypes.string,
|
homePageUrl: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
@ -56,35 +51,29 @@ class HomePage extends React.Component {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
|
|
||||||
if (this.props.teamToken && this.props.teamServerUrl) {
|
// we use request() to inline the homepage into the react component
|
||||||
this.setState({
|
// so that it can inherit CSS and theming easily rather than mess around
|
||||||
iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`,
|
// with iframes and trying to synchronise document.stylesheets.
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// we use request() to inline the homepage into the react component
|
|
||||||
// so that it can inherit CSS and theming easily rather than mess around
|
|
||||||
// with iframes and trying to synchronise document.stylesheets.
|
|
||||||
|
|
||||||
const src = this.props.homePageUrl || 'home.html';
|
const src = this.props.homePageUrl || 'home.html';
|
||||||
|
|
||||||
request(
|
request(
|
||||||
{ method: "GET", url: src },
|
{ method: "GET", url: src },
|
||||||
(err, response, body) => {
|
(err, response, body) => {
|
||||||
if (this._unmounted) {
|
if (this._unmounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err || response.status < 200 || response.status >= 300) {
|
if (err || response.status < 200 || response.status >= 300) {
|
||||||
console.warn(`Error loading home page: ${err}`);
|
console.warn(`Error loading home page: ${err}`);
|
||||||
this.setState({ page: _t("Couldn't load home page") });
|
this.setState({ page: _t("Couldn't load home page") });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
|
body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
|
||||||
this.setState({ page: body });
|
this.setState({ page: body });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|
|
@ -63,7 +63,6 @@ const LoggedInView = React.createClass({
|
||||||
// transitioned to PWLU)
|
// transitioned to PWLU)
|
||||||
onRegistered: PropTypes.func,
|
onRegistered: PropTypes.func,
|
||||||
collapsedRhs: PropTypes.bool,
|
collapsedRhs: PropTypes.bool,
|
||||||
teamToken: PropTypes.string,
|
|
||||||
|
|
||||||
// Used by the RoomView to handle joining rooms
|
// Used by the RoomView to handle joining rooms
|
||||||
viaServers: PropTypes.arrayOf(PropTypes.string),
|
viaServers: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
@ -457,8 +456,6 @@ const LoggedInView = React.createClass({
|
||||||
pageElement = <UserSettings
|
pageElement = <UserSettings
|
||||||
onClose={this.props.onCloseAllSettings}
|
onClose={this.props.onCloseAllSettings}
|
||||||
brand={this.props.config.brand}
|
brand={this.props.config.brand}
|
||||||
referralBaseUrl={this.props.config.referralBaseUrl}
|
|
||||||
teamToken={this.props.teamToken}
|
|
||||||
/>;
|
/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -475,15 +472,7 @@ const LoggedInView = React.createClass({
|
||||||
|
|
||||||
case PageTypes.HomePage:
|
case PageTypes.HomePage:
|
||||||
{
|
{
|
||||||
// If team server config is present, pass the teamServerURL. props.teamToken
|
|
||||||
// must also be set for the team page to be displayed, otherwise the
|
|
||||||
// welcomePageUrl is used (which might be undefined).
|
|
||||||
const teamServerUrl = this.props.config.teamServerConfig ?
|
|
||||||
this.props.config.teamServerConfig.teamServerURL : null;
|
|
||||||
|
|
||||||
pageElement = <HomePage
|
pageElement = <HomePage
|
||||||
teamServerUrl={teamServerUrl}
|
|
||||||
teamToken={this.props.teamToken}
|
|
||||||
homePageUrl={this.props.config.welcomePageUrl}
|
homePageUrl={this.props.config.welcomePageUrl}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,8 @@ const VIEWS = {
|
||||||
// we have valid matrix credentials (either via an explicit login, via the
|
// we have valid matrix credentials (either via an explicit login, via the
|
||||||
// initial re-animation/guest registration, or via a registration), and are
|
// initial re-animation/guest registration, or via a registration), and are
|
||||||
// now setting up a matrixclient to talk to it. This isn't an instant
|
// now setting up a matrixclient to talk to it. This isn't an instant
|
||||||
// process because (a) we need to clear out indexeddb, and (b) we need to
|
// process because we need to clear out indexeddb. While it is going on we
|
||||||
// talk to the team server; while it is going on we show a big spinner.
|
// show a big spinner.
|
||||||
LOGGING_IN: 5,
|
LOGGING_IN: 5,
|
||||||
|
|
||||||
// we are logged in with an active matrix client.
|
// we are logged in with an active matrix client.
|
||||||
|
@ -256,42 +256,6 @@ export default React.createClass({
|
||||||
MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit;
|
MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To enable things like riot.im/geektime in a nicer way than rewriting the URL
|
|
||||||
// and appending a team token query parameter, use the first path segment to
|
|
||||||
// indicate a team, with "public" team tokens stored in the config teamTokenMap.
|
|
||||||
let routedTeamToken = null;
|
|
||||||
if (this.props.config.teamTokenMap) {
|
|
||||||
const teamName = window.location.pathname.split('/')[1];
|
|
||||||
if (teamName && this.props.config.teamTokenMap.hasOwnProperty(teamName)) {
|
|
||||||
routedTeamToken = this.props.config.teamTokenMap[teamName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Persist the team token across refreshes using sessionStorage. A new window or
|
|
||||||
// tab will not persist sessionStorage, but refreshes will.
|
|
||||||
if (this.props.startingFragmentQueryParams.team_token) {
|
|
||||||
window.sessionStorage.setItem(
|
|
||||||
'mx_team_token',
|
|
||||||
this.props.startingFragmentQueryParams.team_token,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the locally-stored team token first, then as a fall-back, check to see if
|
|
||||||
// a referral link was used, which will contain a query parameter `team_token`.
|
|
||||||
this._teamToken = routedTeamToken ||
|
|
||||||
window.localStorage.getItem('mx_team_token') ||
|
|
||||||
window.sessionStorage.getItem('mx_team_token');
|
|
||||||
|
|
||||||
// Some users have ended up with "undefined" as their local storage team token,
|
|
||||||
// treat that as undefined.
|
|
||||||
if (this._teamToken === "undefined") {
|
|
||||||
this._teamToken = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._teamToken) {
|
|
||||||
console.info(`Team token set to ${this._teamToken}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the default URLs (async)
|
// Set up the default URLs (async)
|
||||||
if (this.getDefaultServerName() && !this.getDefaultHsUrl(false)) {
|
if (this.getDefaultServerName() && !this.getDefaultHsUrl(false)) {
|
||||||
this.setState({loadingDefaultHomeserver: true});
|
this.setState({loadingDefaultHomeserver: true});
|
||||||
|
@ -360,9 +324,6 @@ export default React.createClass({
|
||||||
linkifyMatrix.onGroupClick = this.onGroupClick;
|
linkifyMatrix.onGroupClick = this.onGroupClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
const teamServerConfig = this.props.config.teamServerConfig || {};
|
|
||||||
Lifecycle.initRtsClient(teamServerConfig.teamServerURL);
|
|
||||||
|
|
||||||
// the first thing to do is to try the token params in the query-string
|
// the first thing to do is to try the token params in the query-string
|
||||||
Lifecycle.attemptTokenLogin(this.props.realQueryParams).then((loggedIn) => {
|
Lifecycle.attemptTokenLogin(this.props.realQueryParams).then((loggedIn) => {
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
|
@ -726,7 +687,7 @@ export default React.createClass({
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'on_logged_in':
|
case 'on_logged_in':
|
||||||
this._onLoggedIn(payload.teamToken);
|
this._onLoggedIn();
|
||||||
break;
|
break;
|
||||||
case 'on_logged_out':
|
case 'on_logged_out':
|
||||||
this._onLoggedOut();
|
this._onLoggedOut();
|
||||||
|
@ -1196,16 +1157,10 @@ export default React.createClass({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a new logged in session has started
|
* Called when a new logged in session has started
|
||||||
*
|
|
||||||
* @param {string} teamToken
|
|
||||||
*/
|
*/
|
||||||
_onLoggedIn: async function(teamToken) {
|
_onLoggedIn: async function() {
|
||||||
this.setStateForNewView({view: VIEWS.LOGGED_IN});
|
this.setStateForNewView({view: VIEWS.LOGGED_IN});
|
||||||
if (teamToken) {
|
if (this._is_registered) {
|
||||||
// A team member has logged in, not a guest
|
|
||||||
this._teamToken = teamToken;
|
|
||||||
dis.dispatch({action: 'view_home_page'});
|
|
||||||
} else if (this._is_registered) {
|
|
||||||
this._is_registered = false;
|
this._is_registered = false;
|
||||||
|
|
||||||
if (this.props.config.welcomeUserId && getCurrentLanguage().startsWith("en")) {
|
if (this.props.config.welcomeUserId && getCurrentLanguage().startsWith("en")) {
|
||||||
|
@ -1261,7 +1216,6 @@ export default React.createClass({
|
||||||
currentRoomId: null,
|
currentRoomId: null,
|
||||||
page_type: PageTypes.RoomDirectory,
|
page_type: PageTypes.RoomDirectory,
|
||||||
});
|
});
|
||||||
this._teamToken = null;
|
|
||||||
this._setPageSubtitle();
|
this._setPageSubtitle();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1707,15 +1661,13 @@ export default React.createClass({
|
||||||
|
|
||||||
onReturnToAppClick: function() {
|
onReturnToAppClick: function() {
|
||||||
// treat it the same as if the user had completed the login
|
// treat it the same as if the user had completed the login
|
||||||
this._onLoggedIn(null);
|
this._onLoggedIn();
|
||||||
},
|
},
|
||||||
|
|
||||||
// returns a promise which resolves to the new MatrixClient
|
// returns a promise which resolves to the new MatrixClient
|
||||||
onRegistered: function(credentials, teamToken) {
|
onRegistered: function(credentials) {
|
||||||
// XXX: These both should be in state or ideally store(s) because we risk not
|
// XXX: This should be in state or ideally store(s) because we risk not
|
||||||
// rendering the most up-to-date view of state otherwise.
|
// rendering the most up-to-date view of state otherwise.
|
||||||
// teamToken may not be truthy
|
|
||||||
this._teamToken = teamToken;
|
|
||||||
this._is_registered = true;
|
this._is_registered = true;
|
||||||
return Lifecycle.setLoggedIn(credentials);
|
return Lifecycle.setLoggedIn(credentials);
|
||||||
},
|
},
|
||||||
|
@ -1888,7 +1840,6 @@ export default React.createClass({
|
||||||
onCloseAllSettings={this.onCloseAllSettings}
|
onCloseAllSettings={this.onCloseAllSettings}
|
||||||
onRegistered={this.onRegistered}
|
onRegistered={this.onRegistered}
|
||||||
currentRoomId={this.state.currentRoomId}
|
currentRoomId={this.state.currentRoomId}
|
||||||
teamToken={this._teamToken}
|
|
||||||
showCookieBar={this.state.showCookieBar}
|
showCookieBar={this.state.showCookieBar}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
{...this.state}
|
{...this.state}
|
||||||
|
@ -1929,7 +1880,6 @@ export default React.createClass({
|
||||||
defaultHsUrl={this.getDefaultHsUrl()}
|
defaultHsUrl={this.getDefaultHsUrl()}
|
||||||
defaultIsUrl={this.getDefaultIsUrl()}
|
defaultIsUrl={this.getDefaultIsUrl()}
|
||||||
brand={this.props.config.brand}
|
brand={this.props.config.brand}
|
||||||
teamServerConfig={this.props.config.teamServerConfig}
|
|
||||||
customHsUrl={this.getCurrentHsUrl()}
|
customHsUrl={this.getCurrentHsUrl()}
|
||||||
customIsUrl={this.getCurrentIsUrl()}
|
customIsUrl={this.getCurrentIsUrl()}
|
||||||
makeRegistrationUrl={this._makeRegistrationUrl}
|
makeRegistrationUrl={this._makeRegistrationUrl}
|
||||||
|
|
|
@ -167,13 +167,6 @@ module.exports = React.createClass({
|
||||||
onClose: PropTypes.func,
|
onClose: PropTypes.func,
|
||||||
// The brand string given when creating email pushers
|
// The brand string given when creating email pushers
|
||||||
brand: PropTypes.string,
|
brand: PropTypes.string,
|
||||||
|
|
||||||
// The base URL to use in the referral link. Defaults to window.location.origin.
|
|
||||||
referralBaseUrl: PropTypes.string,
|
|
||||||
|
|
||||||
// Team token for the referral link. If falsy, the referral section will
|
|
||||||
// not appear
|
|
||||||
teamToken: PropTypes.string,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
|
@ -590,27 +583,6 @@ module.exports = React.createClass({
|
||||||
return <GroupUserSettings />;
|
return <GroupUserSettings />;
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderReferral: function() {
|
|
||||||
const teamToken = this.props.teamToken;
|
|
||||||
if (!teamToken) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (typeof teamToken !== 'string') {
|
|
||||||
console.warn('Team token not a string');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const href = (this.props.referralBaseUrl || window.location.origin) +
|
|
||||||
`/#/register?referrer=${this._me}&team_token=${teamToken}`;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h3>Referral</h3>
|
|
||||||
<div className="mx_UserSettings_section">
|
|
||||||
{ _t("Refer a friend to Riot:") } <a href={href} target="_blank" rel="noopener">{ href }</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
onLanguageChange: function(newLang) {
|
onLanguageChange: function(newLang) {
|
||||||
if (this.state.language !== newLang) {
|
if (this.state.language !== newLang) {
|
||||||
SettingsStore.setValue("language", null, SettingLevel.DEVICE, newLang);
|
SettingsStore.setValue("language", null, SettingLevel.DEVICE, newLang);
|
||||||
|
@ -1355,8 +1327,6 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
{ this._renderGroupSettings() }
|
{ this._renderGroupSettings() }
|
||||||
|
|
||||||
{ this._renderReferral() }
|
|
||||||
|
|
||||||
{ notificationArea }
|
{ notificationArea }
|
||||||
|
|
||||||
{ this._renderUserInterfaceSettings() }
|
{ this._renderUserInterfaceSettings() }
|
||||||
|
|
|
@ -23,9 +23,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
|
||||||
import RegistrationForm from '../../views/auth/RegistrationForm';
|
import RegistrationForm from '../../views/auth/RegistrationForm';
|
||||||
import RtsClient from '../../../RtsClient';
|
|
||||||
import { _t, _td } from '../../../languageHandler';
|
import { _t, _td } from '../../../languageHandler';
|
||||||
import SdkConfig from '../../../SdkConfig';
|
import SdkConfig from '../../../SdkConfig';
|
||||||
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
|
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
|
||||||
|
@ -48,13 +46,6 @@ module.exports = React.createClass({
|
||||||
brand: PropTypes.string,
|
brand: PropTypes.string,
|
||||||
email: PropTypes.string,
|
email: PropTypes.string,
|
||||||
referrer: PropTypes.string,
|
referrer: PropTypes.string,
|
||||||
teamServerConfig: PropTypes.shape({
|
|
||||||
// Email address to request new teams
|
|
||||||
supportEmail: PropTypes.string.isRequired,
|
|
||||||
// URL of the riot-team-server to get team configurations and track referrals
|
|
||||||
teamServerURL: PropTypes.string.isRequired,
|
|
||||||
}),
|
|
||||||
teamSelected: PropTypes.object,
|
|
||||||
|
|
||||||
// The default server name to use when the user hasn't specified
|
// The default server name to use when the user hasn't specified
|
||||||
// one. This is used when displaying the defaultHsUrl in the UI.
|
// one. This is used when displaying the defaultHsUrl in the UI.
|
||||||
|
@ -70,18 +61,11 @@ module.exports = React.createClass({
|
||||||
onLoginClick: PropTypes.func.isRequired,
|
onLoginClick: PropTypes.func.isRequired,
|
||||||
onCancelClick: PropTypes.func,
|
onCancelClick: PropTypes.func,
|
||||||
onServerConfigChange: PropTypes.func.isRequired,
|
onServerConfigChange: PropTypes.func.isRequired,
|
||||||
|
|
||||||
rtsClient: PropTypes.shape({
|
|
||||||
getTeamsConfig: PropTypes.func.isRequired,
|
|
||||||
trackReferral: PropTypes.func.isRequired,
|
|
||||||
getTeam: PropTypes.func.isRequired,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
busy: false,
|
busy: false,
|
||||||
teamServerBusy: false,
|
|
||||||
errorText: null,
|
errorText: null,
|
||||||
// We remember the values entered by the user because
|
// We remember the values entered by the user because
|
||||||
// the registration form will be unmounted during the
|
// the registration form will be unmounted during the
|
||||||
|
@ -106,37 +90,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
|
|
||||||
this._replaceClient();
|
this._replaceClient();
|
||||||
|
|
||||||
if (
|
|
||||||
this.props.teamServerConfig &&
|
|
||||||
this.props.teamServerConfig.teamServerURL &&
|
|
||||||
!this._rtsClient
|
|
||||||
) {
|
|
||||||
this._rtsClient = this.props.rtsClient || new RtsClient(this.props.teamServerConfig.teamServerURL);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
teamServerBusy: true,
|
|
||||||
});
|
|
||||||
// GET team configurations including domains, names and icons
|
|
||||||
this._rtsClient.getTeamsConfig().then((data) => {
|
|
||||||
const teamsConfig = {
|
|
||||||
teams: data,
|
|
||||||
supportEmail: this.props.teamServerConfig.supportEmail,
|
|
||||||
};
|
|
||||||
console.log('Setting teams config to ', teamsConfig);
|
|
||||||
this.setState({
|
|
||||||
teamsConfig: teamsConfig,
|
|
||||||
teamServerBusy: false,
|
|
||||||
});
|
|
||||||
}, (err) => {
|
|
||||||
console.error('Error retrieving config for teams', err);
|
|
||||||
this.setState({
|
|
||||||
teamServerBusy: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onServerConfigChange: function(config) {
|
onServerConfigChange: function(config) {
|
||||||
|
@ -191,7 +145,7 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_onUIAuthFinished: function(success, response, extra) {
|
_onUIAuthFinished: async function(success, response, extra) {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
let msg = response.message || response.toString();
|
let msg = response.message || response.toString();
|
||||||
// can we give a better error message?
|
// can we give a better error message?
|
||||||
|
@ -240,58 +194,15 @@ module.exports = React.createClass({
|
||||||
doingUIAuth: false,
|
doingUIAuth: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Done regardless of `teamSelected`. People registering with non-team emails
|
const cli = await this.props.onLoggedIn({
|
||||||
// will just nop. The point of this being we might not have the email address
|
userId: response.user_id,
|
||||||
// that the user registered with at this stage (depending on whether this
|
deviceId: response.device_id,
|
||||||
// is the client they initiated registration).
|
homeserverUrl: this._matrixClient.getHomeserverUrl(),
|
||||||
let trackPromise = Promise.resolve(null);
|
identityServerUrl: this._matrixClient.getIdentityServerUrl(),
|
||||||
if (this._rtsClient && extra.emailSid) {
|
accessToken: response.access_token,
|
||||||
// Track referral if this.props.referrer set, get team_token in order to
|
|
||||||
// retrieve team config and see welcome page etc.
|
|
||||||
trackPromise = this._rtsClient.trackReferral(
|
|
||||||
this.props.referrer || '', // Default to empty string = not referred
|
|
||||||
extra.emailSid,
|
|
||||||
extra.clientSecret,
|
|
||||||
).then((data) => {
|
|
||||||
const teamToken = data.team_token;
|
|
||||||
// Store for use /w welcome pages
|
|
||||||
window.localStorage.setItem('mx_team_token', teamToken);
|
|
||||||
|
|
||||||
this._rtsClient.getTeam(teamToken).then((team) => {
|
|
||||||
console.log(
|
|
||||||
`User successfully registered with team ${team.name}`,
|
|
||||||
);
|
|
||||||
if (!team.rooms) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Auto-join rooms
|
|
||||||
team.rooms.forEach((room) => {
|
|
||||||
if (room.auto_join && room.room_id) {
|
|
||||||
console.log(`Auto-joining ${room.room_id}`);
|
|
||||||
MatrixClientPeg.get().joinRoom(room.room_id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, (err) => {
|
|
||||||
console.error('Error getting team config', err);
|
|
||||||
});
|
|
||||||
|
|
||||||
return teamToken;
|
|
||||||
}, (err) => {
|
|
||||||
console.error('Error tracking referral', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
trackPromise.then((teamToken) => {
|
|
||||||
return this.props.onLoggedIn({
|
|
||||||
userId: response.user_id,
|
|
||||||
deviceId: response.device_id,
|
|
||||||
homeserverUrl: this._matrixClient.getHomeserverUrl(),
|
|
||||||
identityServerUrl: this._matrixClient.getIdentityServerUrl(),
|
|
||||||
accessToken: response.access_token,
|
|
||||||
}, teamToken);
|
|
||||||
}).then((cli) => {
|
|
||||||
return this._setupPushers(cli);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._setupPushers(cli);
|
||||||
},
|
},
|
||||||
|
|
||||||
_setupPushers: function(matrixClient) {
|
_setupPushers: function(matrixClient) {
|
||||||
|
@ -356,12 +267,6 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onTeamSelected: function(teamSelected) {
|
|
||||||
if (!this._unmounted) {
|
|
||||||
this.setState({ teamSelected });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onLoginClick: function(ev) {
|
onLoginClick: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
@ -418,7 +323,7 @@ module.exports = React.createClass({
|
||||||
poll={true}
|
poll={true}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (this.state.busy || this.state.teamServerBusy || !this.state.flows) {
|
} else if (this.state.busy || !this.state.flows) {
|
||||||
registerBody = <Spinner />;
|
registerBody = <Spinner />;
|
||||||
} else {
|
} else {
|
||||||
let serverConfigSection;
|
let serverConfigSection;
|
||||||
|
@ -443,11 +348,9 @@ module.exports = React.createClass({
|
||||||
defaultPhoneCountry={this.state.formVals.phoneCountry}
|
defaultPhoneCountry={this.state.formVals.phoneCountry}
|
||||||
defaultPhoneNumber={this.state.formVals.phoneNumber}
|
defaultPhoneNumber={this.state.formVals.phoneNumber}
|
||||||
defaultPassword={this.state.formVals.password}
|
defaultPassword={this.state.formVals.password}
|
||||||
teamsConfig={this.state.teamsConfig}
|
|
||||||
minPasswordLength={MIN_PASSWORD_LENGTH}
|
minPasswordLength={MIN_PASSWORD_LENGTH}
|
||||||
onError={this.onFormValidationFailed}
|
onError={this.onFormValidationFailed}
|
||||||
onRegisterClick={this.onFormSubmit}
|
onRegisterClick={this.onFormSubmit}
|
||||||
onTeamSelected={this.onTeamSelected}
|
|
||||||
flows={this.state.flows}
|
flows={this.state.flows}
|
||||||
/>
|
/>
|
||||||
{ serverConfigSection }
|
{ serverConfigSection }
|
||||||
|
@ -472,12 +375,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthPage>
|
<AuthPage>
|
||||||
<AuthHeader
|
<AuthHeader />
|
||||||
icon={this.state.teamSelected ?
|
|
||||||
this.props.teamServerConfig.teamServerURL + "/static/common/" +
|
|
||||||
this.state.teamSelected.domain + "/icon.png" :
|
|
||||||
null}
|
|
||||||
/>
|
|
||||||
<AuthBody>
|
<AuthBody>
|
||||||
<h2>{ _t('Create your account') }</h2>
|
<h2>{ _t('Create your account') }</h2>
|
||||||
{ registerBody }
|
{ registerBody }
|
||||||
|
|
|
@ -46,17 +46,6 @@ module.exports = React.createClass({
|
||||||
defaultPhoneNumber: PropTypes.string,
|
defaultPhoneNumber: PropTypes.string,
|
||||||
defaultUsername: PropTypes.string,
|
defaultUsername: PropTypes.string,
|
||||||
defaultPassword: PropTypes.string,
|
defaultPassword: PropTypes.string,
|
||||||
teamsConfig: PropTypes.shape({
|
|
||||||
// Email address to request new teams
|
|
||||||
supportEmail: PropTypes.string,
|
|
||||||
teams: PropTypes.arrayOf(PropTypes.shape({
|
|
||||||
// The displayed name of the team
|
|
||||||
"name": PropTypes.string,
|
|
||||||
// The domain of team email addresses
|
|
||||||
"domain": PropTypes.string,
|
|
||||||
})).required,
|
|
||||||
}),
|
|
||||||
|
|
||||||
minPasswordLength: PropTypes.number,
|
minPasswordLength: PropTypes.number,
|
||||||
onError: PropTypes.func,
|
onError: PropTypes.func,
|
||||||
onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
|
onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
|
||||||
|
@ -75,7 +64,6 @@ module.exports = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
fieldValid: {},
|
fieldValid: {},
|
||||||
selectedTeam: null,
|
|
||||||
// The ISO2 country code selected in the phone number entry
|
// The ISO2 country code selected in the phone number entry
|
||||||
phoneCountry: this.props.defaultPhoneCountry,
|
phoneCountry: this.props.defaultPhoneCountry,
|
||||||
};
|
};
|
||||||
|
@ -150,10 +138,6 @@ module.exports = React.createClass({
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_isUniEmail: function(email) {
|
|
||||||
return email.endsWith('.ac.uk') || email.endsWith('.edu') || email.endsWith('matrix.org');
|
|
||||||
},
|
|
||||||
|
|
||||||
validateField: function(fieldID) {
|
validateField: function(fieldID) {
|
||||||
const pwd1 = this.refs.password.value.trim();
|
const pwd1 = this.refs.password.value.trim();
|
||||||
const pwd2 = this.refs.passwordConfirm.value.trim();
|
const pwd2 = this.refs.passwordConfirm.value.trim();
|
||||||
|
@ -161,24 +145,6 @@ module.exports = React.createClass({
|
||||||
switch (fieldID) {
|
switch (fieldID) {
|
||||||
case FIELD_EMAIL: {
|
case FIELD_EMAIL: {
|
||||||
const email = this.refs.email.value;
|
const email = this.refs.email.value;
|
||||||
if (this.props.teamsConfig && this._isUniEmail(email)) {
|
|
||||||
const matchingTeam = this.props.teamsConfig.teams.find(
|
|
||||||
(team) => {
|
|
||||||
return email.split('@').pop() === team.domain;
|
|
||||||
},
|
|
||||||
) || null;
|
|
||||||
this.setState({
|
|
||||||
selectedTeam: matchingTeam,
|
|
||||||
showSupportEmail: !matchingTeam,
|
|
||||||
});
|
|
||||||
this.props.onTeamSelected(matchingTeam);
|
|
||||||
} else {
|
|
||||||
this.props.onTeamSelected(null);
|
|
||||||
this.setState({
|
|
||||||
selectedTeam: null,
|
|
||||||
showSupportEmail: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const emailValid = email === '' || Email.looksValid(email);
|
const emailValid = email === '' || Email.looksValid(email);
|
||||||
if (this._authStepIsRequired('m.login.email.identity') && (!emailValid || email === '')) {
|
if (this._authStepIsRequired('m.login.email.identity') && (!emailValid || email === '')) {
|
||||||
this.markFieldValid(fieldID, false, "RegistrationForm.ERR_MISSING_EMAIL");
|
this.markFieldValid(fieldID, false, "RegistrationForm.ERR_MISSING_EMAIL");
|
||||||
|
@ -304,30 +270,6 @@ module.exports = React.createClass({
|
||||||
value={self.state.email} />
|
value={self.state.email} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
let belowEmailSection;
|
|
||||||
if (this.props.teamsConfig) {
|
|
||||||
if (this.props.teamsConfig.supportEmail && this.state.showSupportEmail) {
|
|
||||||
belowEmailSection = (
|
|
||||||
<p className="mx_Login_support">
|
|
||||||
Sorry, but your university is not registered with us just yet.
|
|
||||||
Email us on
|
|
||||||
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
|
|
||||||
{ this.props.teamsConfig.supportEmail }
|
|
||||||
</a>
|
|
||||||
to get your university signed up.
|
|
||||||
Or continue to register with Riot to enjoy our open source platform.
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
} else if (this.state.selectedTeam) {
|
|
||||||
belowEmailSection = (
|
|
||||||
<p className="mx_Login_support">
|
|
||||||
{_t("You are registering with %(SelectedTeamName)s", {
|
|
||||||
SelectedTeamName: this.state.selectedTeam.name,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown');
|
const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown');
|
||||||
let phoneSection;
|
let phoneSection;
|
||||||
|
@ -369,7 +311,6 @@ module.exports = React.createClass({
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
{ emailSection }
|
{ emailSection }
|
||||||
{ belowEmailSection }
|
|
||||||
{ phoneSection }
|
{ phoneSection }
|
||||||
<input type="text" ref="username"
|
<input type="text" ref="username"
|
||||||
placeholder={placeholderUserName} defaultValue={this.props.defaultUsername}
|
placeholder={placeholderUserName} defaultValue={this.props.defaultUsername}
|
||||||
|
|
|
@ -193,9 +193,6 @@ export default React.createClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Implement RTS /register here
|
|
||||||
const teamToken = null;
|
|
||||||
|
|
||||||
this.props.onFinished(true, {
|
this.props.onFinished(true, {
|
||||||
userId: response.user_id,
|
userId: response.user_id,
|
||||||
deviceId: response.device_id,
|
deviceId: response.device_id,
|
||||||
|
@ -203,7 +200,6 @@ export default React.createClass({
|
||||||
identityServerUrl: this._matrixClient.getIdentityServerUrl(),
|
identityServerUrl: this._matrixClient.getIdentityServerUrl(),
|
||||||
accessToken: response.access_token,
|
accessToken: response.access_token,
|
||||||
password: this._generatedPassword,
|
password: this._generatedPassword,
|
||||||
teamToken: teamToken,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Skinner from './Skinner';
|
import Skinner from './Skinner';
|
||||||
import RtsClient from './RtsClient';
|
|
||||||
|
|
||||||
module.exports.loadSkin = function(skinObject) {
|
module.exports.loadSkin = function(skinObject) {
|
||||||
Skinner.load(skinObject);
|
Skinner.load(skinObject);
|
||||||
|
@ -28,7 +27,3 @@ module.exports.resetSkin = function() {
|
||||||
module.exports.getComponent = function(componentName) {
|
module.exports.getComponent = function(componentName) {
|
||||||
return Skinner.getComponent(componentName);
|
return Skinner.getComponent(componentName);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.setFetch = function(fetchFunction) {
|
|
||||||
RtsClient.setFetch(fetchFunction);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const jest = require('jest-mock');
|
|
||||||
const React = require('react');
|
|
||||||
const ReactTestUtils = require('react-addons-test-utils');
|
|
||||||
const expect = require('expect');
|
|
||||||
|
|
||||||
const testUtils = require('test-utils');
|
|
||||||
|
|
||||||
const sdk = require('matrix-react-sdk');
|
|
||||||
const Registration = sdk.getComponent('structures.auth.Registration');
|
|
||||||
|
|
||||||
let rtsClient;
|
|
||||||
let client;
|
|
||||||
|
|
||||||
const TEAM_CONFIG = {
|
|
||||||
supportEmail: 'support@some.domain',
|
|
||||||
teamServerURL: 'http://someteamserver.bla',
|
|
||||||
};
|
|
||||||
|
|
||||||
const CREDENTIALS = {userId: '@me:here'};
|
|
||||||
const MOCK_REG_RESPONSE = {
|
|
||||||
user_id: CREDENTIALS.userId,
|
|
||||||
device_id: 'mydevice',
|
|
||||||
access_token: '2234569864534231',
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Registration', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
testUtils.beforeEach(this);
|
|
||||||
client = testUtils.createTestClient();
|
|
||||||
client.credentials = CREDENTIALS;
|
|
||||||
|
|
||||||
// Mock an RTS client that supports one team and naively returns team tokens when
|
|
||||||
// tracking by mapping email SIDs to team tokens. This is fine because we only
|
|
||||||
// want to assert the client behaviour such that a user recognised by the
|
|
||||||
// rtsClient (which would normally talk to the RTS server) as a team member is
|
|
||||||
// correctly logged in as one (and other such assertions).
|
|
||||||
rtsClient = testUtils.createTestRtsClient(
|
|
||||||
{
|
|
||||||
'myawesometeam123': {
|
|
||||||
name: 'Team Awesome',
|
|
||||||
domain: 'team.awesome.net',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{'someEmailSid1234': 'myawesometeam123'},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should track a referral following successful registration of a team member', function(done) {
|
|
||||||
const expectedCreds = {
|
|
||||||
userId: MOCK_REG_RESPONSE.user_id,
|
|
||||||
deviceId: MOCK_REG_RESPONSE.device_id,
|
|
||||||
homeserverUrl: client.getHomeserverUrl(),
|
|
||||||
identityServerUrl: client.getIdentityServerUrl(),
|
|
||||||
accessToken: MOCK_REG_RESPONSE.access_token,
|
|
||||||
};
|
|
||||||
const onLoggedIn = function(creds, teamToken) {
|
|
||||||
expect(creds).toEqual(expectedCreds);
|
|
||||||
expect(teamToken).toBe('myawesometeam123');
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
|
|
||||||
const res = ReactTestUtils.renderIntoDocument(
|
|
||||||
<Registration
|
|
||||||
teamServerConfig={TEAM_CONFIG}
|
|
||||||
onLoggedIn={onLoggedIn}
|
|
||||||
rtsClient={rtsClient}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
|
|
||||||
res._onUIAuthFinished(true, MOCK_REG_RESPONSE, {emailSid: 'someEmailSid1234'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should NOT track a referral following successful registration of a non-team member', function(done) {
|
|
||||||
const onLoggedIn = jest.fn(function(creds, teamToken) {
|
|
||||||
expect(teamToken).toBeFalsy();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
const res = ReactTestUtils.renderIntoDocument(
|
|
||||||
<Registration
|
|
||||||
teamServerConfig={TEAM_CONFIG}
|
|
||||||
onLoggedIn={onLoggedIn}
|
|
||||||
rtsClient={rtsClient}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
|
|
||||||
res._onUIAuthFinished(true, MOCK_REG_RESPONSE, {emailSid: 'someOtherEmailSid11'});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,91 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const jest = require('jest-mock');
|
|
||||||
const React = require('react');
|
|
||||||
const ReactTestUtils = require('react-addons-test-utils');
|
|
||||||
const expect = require('expect');
|
|
||||||
|
|
||||||
const testUtils = require('test-utils');
|
|
||||||
|
|
||||||
const sdk = require('matrix-react-sdk');
|
|
||||||
const RegistrationForm = sdk.getComponent('views.auth.RegistrationForm');
|
|
||||||
|
|
||||||
const TEAM_CONFIG = {
|
|
||||||
supportEmail: "support@some.domain",
|
|
||||||
teams: [
|
|
||||||
{ name: "The Team Org.", domain: "team.ac.uk" },
|
|
||||||
{ name: "The Super Team", domain: "superteam.ac.uk" },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
function doInputEmail(inputEmail, onTeamSelected) {
|
|
||||||
const res = ReactTestUtils.renderIntoDocument(
|
|
||||||
<RegistrationForm
|
|
||||||
teamsConfig={TEAM_CONFIG}
|
|
||||||
onTeamSelected={onTeamSelected}
|
|
||||||
flows={[
|
|
||||||
{
|
|
||||||
stages: ['m.login.dummy'],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
|
|
||||||
const teamInput = res.refs.email;
|
|
||||||
teamInput.value = inputEmail;
|
|
||||||
|
|
||||||
ReactTestUtils.Simulate.change(teamInput);
|
|
||||||
ReactTestUtils.Simulate.blur(teamInput);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
function expectTeamSelectedFromEmailInput(inputEmail, expectedTeam) {
|
|
||||||
const onTeamSelected = jest.fn();
|
|
||||||
doInputEmail(inputEmail, onTeamSelected);
|
|
||||||
|
|
||||||
expect(onTeamSelected).toHaveBeenCalledWith(expectedTeam);
|
|
||||||
}
|
|
||||||
|
|
||||||
function expectSupportFromEmailInput(inputEmail, isSupportShown) {
|
|
||||||
const onTeamSelected = jest.fn();
|
|
||||||
const res = doInputEmail(inputEmail, onTeamSelected);
|
|
||||||
|
|
||||||
expect(res.state.showSupportEmail).toBe(isSupportShown);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('RegistrationForm', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
testUtils.beforeEach(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should select a team when a team email is entered', function() {
|
|
||||||
expectTeamSelectedFromEmailInput("member@team.ac.uk", TEAM_CONFIG.teams[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not select a team when an unrecognised team email is entered', function() {
|
|
||||||
expectTeamSelectedFromEmailInput("member@someunknownteam.ac.uk", null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show support when an unrecognised team email is entered', function() {
|
|
||||||
expectSupportFromEmailInput("member@someunknownteam.ac.uk", true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should NOT show support when an unrecognised non-team email is entered', function() {
|
|
||||||
expectSupportFromEmailInput("someone@yahoo.com", false);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -104,20 +104,6 @@ export function createTestClient() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTestRtsClient(teamMap, sidMap) {
|
|
||||||
return {
|
|
||||||
getTeamsConfig() {
|
|
||||||
return Promise.resolve(Object.keys(teamMap).map((token) => teamMap[token]));
|
|
||||||
},
|
|
||||||
trackReferral(referrer, emailSid, clientSecret) {
|
|
||||||
return Promise.resolve({team_token: sidMap[emailSid]});
|
|
||||||
},
|
|
||||||
getTeam(teamToken) {
|
|
||||||
return Promise.resolve(teamMap[teamToken]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an Event.
|
* Create an Event.
|
||||||
* @param {Object} opts Values for the event.
|
* @param {Object} opts Values for the event.
|
||||||
|
|
Loading…
Reference in New Issue