summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorJoramWilander <jwawilander@gmail.com>2015-08-28 08:37:55 -0400
committerJoramWilander <jwawilander@gmail.com>2015-08-28 08:37:55 -0400
commitf5fec3a157e6c9146a0c4e28dd5f70e6c066affd (patch)
tree176afd630a3afbe0ac3389695be6b4ce1c45d069 /web
parentdb7e8c12889485234fb2d1ba6556106e5fc7548b (diff)
downloadchat-f5fec3a157e6c9146a0c4e28dd5f70e6c066affd.tar.gz
chat-f5fec3a157e6c9146a0c4e28dd5f70e6c066affd.tar.bz2
chat-f5fec3a157e6c9146a0c4e28dd5f70e6c066affd.zip
Added the ability to create a team with SSO services and added the ability to turn off email sign up.
Diffstat (limited to 'web')
-rw-r--r--web/react/components/login.jsx80
-rw-r--r--web/react/components/signup_team.jsx106
-rw-r--r--web/react/components/signup_user_complete.jsx51
-rw-r--r--web/react/components/signup_user_oauth.jsx87
-rw-r--r--web/react/components/team_signup_choose_auth.jsx88
-rw-r--r--web/react/components/team_signup_with_email.jsx82
-rw-r--r--web/react/components/team_signup_with_sso.jsx137
-rw-r--r--web/react/pages/signup_team.jsx6
-rw-r--r--web/react/pages/signup_user_oauth.jsx11
-rw-r--r--web/react/utils/client.jsx15
-rw-r--r--web/react/utils/constants.jsx1
-rw-r--r--web/sass-files/sass/partials/_responsive.scss8
-rw-r--r--web/sass-files/sass/partials/_signup.scss42
-rw-r--r--web/templates/signup_team.html2
-rw-r--r--web/templates/signup_user_oauth.html26
-rw-r--r--web/web.go45
16 files changed, 534 insertions, 253 deletions
diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx
index 678a2ff87..489ff6960 100644
--- a/web/react/components/login.jsx
+++ b/web/react/components/login.jsx
@@ -10,7 +10,9 @@ var Constants = require('../utils/constants.jsx');
export default class Login extends React.Component {
constructor(props) {
super(props);
+
this.handleSubmit = this.handleSubmit.bind(this);
+
this.state = {};
}
handleSubmit(e) {
@@ -96,19 +98,28 @@ export default class Login extends React.Component {
var authServices = JSON.parse(this.props.authServices);
var loginMessage = [];
- if (authServices.indexOf(Constants.GITLAB_SERVICE) >= 0) {
+ if (authServices.indexOf(Constants.GITLAB_SERVICE) !== -1) {
loginMessage.push(
- <div className='form-group form-group--small'>
- <span><a href={'/' + teamName + '/login/gitlab'}>{'Log in with GitLab'}</a></span>
- </div>
- );
+ <a
+ className='btn btn-custom-login gitlab'
+ href={'/' + teamName + '/login/gitlab'}
+ >
+ <span className='icon' />
+ <span>with GitLab</span>
+ </a>
+ );
}
- if (authServices.indexOf(Constants.GOOGLE_SERVICE) >= 0) {
+
+ if (authServices.indexOf(Constants.GOOGLE_SERVICE) !== -1) {
loginMessage.push(
- <div className='form-group form-group--small'>
- <span><a href={'/' + teamName + '/login/google'}>{'Log in with Google'}</a></span>
- </div>
- );
+ <a
+ className='btn btn-custom-login google'
+ href={'/' + teamName + '/login/google'}
+ >
+ <span className='icon' />
+ <span>with Google Apps</span>
+ </a>
+ );
}
var errorClass = '';
@@ -116,15 +127,10 @@ export default class Login extends React.Component {
errorClass = ' has-error';
}
- return (
- <div className='signup-team__container'>
- <h5 className='margin--less'>Sign in to:</h5>
- <h2 className='signup-team__name'>{teamDisplayName}</h2>
- <h2 className='signup-team__subdomain'>on {config.SiteName}</h2>
- <form onSubmit={this.handleSubmit}>
- <div className={'form-group' + errorClass}>
- {serverError}
- </div>
+ var emailSignup;
+ if (authServices.indexOf(Constants.EMAIL_SERVICE) !== -1) {
+ emailSignup = (
+ <div>
<div className={'form-group' + errorClass}>
<input
autoFocus={focusEmail}
@@ -154,13 +160,43 @@ export default class Login extends React.Component {
Sign in
</button>
</div>
+ </div>
+ );
+ }
+
+ var forgotPassword;
+ if (loginMessage.length > 0 && emailSignup) {
+ loginMessage = (
+ <div>
+ {loginMessage}
+ <div className='or__container'>
+ <span>or</span>
+ </div>
+ </div>
+ );
+
+ forgotPassword = (
+ <div className='form-group'>
+ <a href={'/' + teamName + '/reset_password'}>I forgot my password</a>
+ </div>
+ );
+ }
+
+ return (
+ <div className='signup-team__container'>
+ <h5 className='margin--less'>Sign in to:</h5>
+ <h2 className='signup-team__name'>{teamDisplayName}</h2>
+ <h2 className='signup-team__subdomain'>on {config.SiteName}</h2>
+ <form onSubmit={this.handleSubmit}>
+ <div className={'form-group' + errorClass}>
+ {serverError}
+ </div>
{loginMessage}
+ {emailSignup}
<div className='form-group margin--extra form-group--small'>
<span><a href='/find_team'>{'Find other ' + strings.TeamPlural}</a></span>
</div>
- <div className='form-group'>
- <a href={'/' + teamName + '/reset_password'}>I forgot my password</a>
- </div>
+ {forgotPassword}
<div className='margin--extra'>
<span>{'Want to create your own ' + strings.Team + '? '}
<a
diff --git a/web/react/components/signup_team.jsx b/web/react/components/signup_team.jsx
index edd48e0b9..13640b1e5 100644
--- a/web/react/components/signup_team.jsx
+++ b/web/react/components/signup_team.jsx
@@ -1,69 +1,49 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-
-var utils = require('../utils/utils.jsx');
-var client = require('../utils/client.jsx');
-
-module.exports = React.createClass({
- handleSubmit: function(e) {
- e.preventDefault();
- var team = {};
- var state = { server_error: "" };
-
- team.email = this.refs.email.getDOMNode().value.trim().toLowerCase();
- if (!team.email || !utils.isEmail(team.email)) {
- state.email_error = "Please enter a valid email address";
- state.inValid = true;
+var ChoosePage = require('./team_signup_choose_auth.jsx');
+var EmailSignUpPage = require('./team_signup_with_email.jsx');
+var SSOSignupPage = require('./team_signup_with_sso.jsx');
+var Constants = require('../utils/constants.jsx');
+
+export default class TeamSignUp extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.updatePage = this.updatePage.bind(this);
+
+ if (props.services.length === 1) {
+ if (props.services[0] === Constants.EMAIL_SERVICE) {
+ this.state = {page: 'email', service: ''};
+ } else {
+ this.state = {page: 'service', service: props.services[0]};
+ }
+ } else {
+ this.state = {page: 'choose', service: ''};
}
- else {
- state.email_error = "";
- }
-
- if (state.inValid) {
- this.setState(state);
- return;
+ }
+ updatePage(page, service) {
+ this.setState({page: page, service: service});
+ }
+ render() {
+ if (this.state.page === 'email') {
+ return <EmailSignUpPage />;
+ } else if (this.state.page === 'service' && this.state.service !== '') {
+ return <SSOSignupPage service={this.state.service} />;
+ } else {
+ return (
+ <ChoosePage
+ services={this.props.services}
+ updatePage={this.updatePage}
+ />
+ );
}
-
- client.signupTeam(team.email,
- function(data) {
- if (data["follow_link"]) {
- window.location.href = data["follow_link"];
- }
- else {
- window.location.href = "/signup_team_confirm/?email=" + encodeURIComponent(team.email);
- }
- }.bind(this),
- function(err) {
- state.server_error = err.message;
- this.setState(state);
- }.bind(this)
- );
- },
- getInitialState: function() {
- return { };
- },
- render: function() {
-
- var email_error = this.state.email_error ? <label className='control-label'>{ this.state.email_error }</label> : null;
- var server_error = this.state.server_error ? <div className={ "form-group has-error" }><label className='control-label'>{ this.state.server_error }</label></div> : null;
-
- return (
- <form role="form" onSubmit={this.handleSubmit}>
- <div className={ email_error ? "form-group has-error" : "form-group" }>
- <input autoFocus={true} type="email" ref="email" className="form-control" placeholder="Email Address" maxLength="128" />
- { email_error }
- </div>
- { server_error }
- <div className="form-group">
- <button className="btn btn-md btn-primary" type="submit">Sign up</button>
- </div>
- <div className="form-group margin--extra-2x">
- <span><a href="/find_team">{"Find my " + strings.Team}</a></span>
- </div>
- </form>
- );
}
-});
-
-
+}
+
+TeamSignUp.defaultProps = {
+ services: []
+};
+TeamSignUp.propTypes = {
+ services: React.PropTypes.array
+};
diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx
index 0393e0413..e5c602c16 100644
--- a/web/react/components/signup_user_complete.jsx
+++ b/web/react/components/signup_user_complete.jsx
@@ -171,7 +171,35 @@ module.exports = React.createClass({
);
}
- if (signupMessage.length > 0) {
+ var emailSignup;
+ if (authServices.indexOf(Constants.EMAIL_SERVICE) !== -1) {
+ emailSignup = (
+ <div>
+ <div className='inner__content'>
+ {email}
+ {yourEmailIs}
+ <div className='margin--extra'>
+ <h5><strong>Choose your username</strong></h5>
+ <div className={nameDivStyle}>
+ <input type='text' ref='name' className='form-control' placeholder='' maxLength='128' />
+ {nameError}
+ <p className='form__hint'>Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'</p>
+ </div>
+ </div>
+ <div className='margin--extra'>
+ <h5><strong>Choose your password</strong></h5>
+ <div className={passwordDivStyle}>
+ <input type='password' ref='password' className='form-control' placeholder='' maxLength='128' />
+ {passwordError}
+ </div>
+ </div>
+ </div>
+ <p className='margin--extra'><button type='submit' onClick={this.handleSubmit} className='btn-primary btn'>Create Account</button></p>
+ </div>
+ );
+ }
+
+ if (signupMessage.length > 0 && emailSignup) {
signupMessage = (
<div>
{signupMessage}
@@ -196,26 +224,7 @@ module.exports = React.createClass({
<h2 className='signup-team__subdomain'>on {config.SiteName}</h2>
<h4 className='color--light'>Let's create your account</h4>
{signupMessage}
- <div className='inner__content'>
- {email}
- {yourEmailIs}
- <div className='margin--extra'>
- <h5><strong>Choose your username</strong></h5>
- <div className={nameDivStyle}>
- <input type='text' ref='name' className='form-control' placeholder='' maxLength='128' />
- {nameError}
- <p className='form__hint'>Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'</p>
- </div>
- </div>
- <div className='margin--extra'>
- <h5><strong>Choose your password</strong></h5>
- <div className={passwordDivStyle}>
- <input type='password' ref='password' className='form-control' placeholder='' maxLength='128' />
- {passwordError}
- </div>
- </div>
- </div>
- <p className='margin--extra'><button type='submit' onClick={this.handleSubmit} className='btn-primary btn'>Create Account</button></p>
+ {emailSignup}
{serverError}
{termsDisclaimer}
</form>
diff --git a/web/react/components/signup_user_oauth.jsx b/web/react/components/signup_user_oauth.jsx
deleted file mode 100644
index 8b2800bde..000000000
--- a/web/react/components/signup_user_oauth.jsx
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-
-var utils = require('../utils/utils.jsx');
-var client = require('../utils/client.jsx');
-var UserStore = require('../stores/user_store.jsx');
-var BrowserStore = require('../stores/browser_store.jsx');
-
-module.exports = React.createClass({
- handleSubmit: function(e) {
- e.preventDefault();
-
- if (!this.state.user.username) {
- this.setState({name_error: "This field is required", email_error: "", password_error: "", server_error: ""});
- return;
- }
-
- var username_error = utils.isValidUsername(this.state.user.username);
- if (username_error === "Cannot use a reserved word as a username.") {
- this.setState({name_error: "This username is reserved, please choose a new one.", email_error: "", password_error: "", server_error: ""});
- return;
- } else if (username_error) {
- this.setState({name_error: "Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'.", email_error: "", password_error: "", server_error: ""});
- return;
- }
-
- this.setState({name_error: "", server_error: ""});
-
- this.state.user.allow_marketing = this.refs.email_service.getDOMNode().checked;
-
- var user = this.state.user;
- client.createUser(user, "", "",
- function(data) {
- client.track('signup', 'signup_user_oauth_02');
- UserStore.setCurrentUser(data);
- UserStore.setLastEmail(data.email);
-
- window.location.href = '/' + this.props.teamName + '/login/' + user.auth_service + '?login_hint=' + user.email;
- }.bind(this),
- function(err) {
- this.state.server_error = err.message;
- this.setState(this.state);
- }.bind(this)
- );
- },
- handleChange: function() {
- var user = this.state.user;
- user.username = this.refs.name.getDOMNode().value;
- this.setState({ user: user });
- },
- getInitialState: function() {
- var user = JSON.parse(this.props.user);
- return { user: user };
- },
- render: function() {
-
- client.track('signup', 'signup_user_oauth_01');
-
- var name_error = this.state.name_error ? <label className='control-label'>{ this.state.name_error }</label> : null;
- var server_error = this.state.server_error ? <div className={ "form-group has-error" }><label className='control-label'>{ this.state.server_error }</label></div> : null;
-
- var yourEmailIs = this.state.user.email == "" ? "" : <span>Your email address is <b>{ this.state.user.email }.</b></span>;
-
- return (
- <div>
- <img className="signup-team-logo" src="/static/images/logo.png" />
- <h4>Welcome to { config.SiteName }</h4>
- <p>{"To continue signing up with " + this.state.user.auth_service + ", please register a username."}</p>
- <p>Your username can be made of lowercase letters and numbers.</p>
- <label className="control-label">Username</label>
- <div className={ name_error ? "form-group has-error" : "form-group" }>
- <input type="text" ref="name" className="form-control" placeholder="" maxLength="128" value={this.state.user.username} onChange={this.handleChange} />
- { name_error }
- </div>
- <p>{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others."}</p>
- <p>{ yourEmailIs } You’ll use this address to sign in to {config.SiteName}.</p>
- <div className="checkbox"><label><input type="checkbox" ref="email_service" /> It's ok to send me occassional email with updates about the {config.SiteName} service. </label></div>
- <p><button onClick={this.handleSubmit} className="btn-primary btn">Create Account</button></p>
- { server_error }
- <p>By proceeding to create your account and use { config.SiteName }, you agree to our <a href={ config.TermsLink }>Terms of Service</a> and <a href={ config.PrivacyLink }>Privacy Policy</a>. If you do not agree, you cannot use {config.SiteName}.</p>
- </div>
- );
- }
-});
-
-
diff --git a/web/react/components/team_signup_choose_auth.jsx b/web/react/components/team_signup_choose_auth.jsx
new file mode 100644
index 000000000..2d35785c2
--- /dev/null
+++ b/web/react/components/team_signup_choose_auth.jsx
@@ -0,0 +1,88 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var Constants = require('../utils/constants.jsx');
+
+export default class ChooseAuthPage extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {};
+ }
+ render() {
+ var buttons = [];
+ if (this.props.services.indexOf(Constants.GITLAB_SERVICE) !== -1) {
+ buttons.push(
+ <a
+ className='btn btn-custom-login gitlab btn-full'
+ href='#'
+ onClick={
+ function clickGit(e) {
+ e.preventDefault();
+ this.props.updatePage('service', Constants.GITLAB_SERVICE);
+ }.bind(this)
+ }
+ >
+ <span className='icon' />
+ <span>Create new {strings.Team} with GitLab Account</span>
+ </a>
+ );
+ }
+
+ if (this.props.services.indexOf(Constants.GOOGLE_SERVICE) !== -1) {
+ buttons.push(
+ <a
+ className='btn btn-custom-login google btn-full'
+ href='#'
+ onClick={
+ function clickGoogle(e) {
+ e.preventDefault();
+ this.props.updatePage('service', Constants.GOOGLE_SERVICE);
+ }.bind(this)
+ }
+ >
+ <span className='icon' />
+ <span>Create new {strings.Team} with Google Apps Account</span>
+ </a>
+ );
+ }
+
+ if (this.props.services.indexOf(Constants.EMAIL_SERVICE) !== -1) {
+ buttons.push(
+ <a
+ className='btn btn-custom-login email btn-full'
+ href='#'
+ onClick={
+ function clickEmail(e) {
+ e.preventDefault();
+ this.props.updatePage('email', '');
+ }.bind(this)
+ }
+ >
+ <span className='fa fa-envelope' />
+ <span>Create new {strings.Team} with email address</span>
+ </a>
+ );
+ }
+
+ if (buttons.length === 0) {
+ buttons = <span>No sign-up methods configured, please contact your system administrator.</span>;
+ }
+
+ return (
+ <div>
+ {buttons}
+ <div className='form-group margin--extra-2x'>
+ <span><a href='/find_team'>{'Find my ' + strings.Team}</a></span>
+ </div>
+ </div>
+ );
+ }
+}
+
+ChooseAuthPage.defaultProps = {
+ services: []
+};
+ChooseAuthPage.propTypes = {
+ services: React.PropTypes.array,
+ updatePage: React.PropTypes.func
+};
diff --git a/web/react/components/team_signup_with_email.jsx b/web/react/components/team_signup_with_email.jsx
new file mode 100644
index 000000000..c7204880f
--- /dev/null
+++ b/web/react/components/team_signup_with_email.jsx
@@ -0,0 +1,82 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var utils = require('../utils/utils.jsx');
+var client = require('../utils/client.jsx');
+
+export default class EmailSignUpPage extends React.Component {
+ constructor() {
+ super();
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+
+ this.state = {};
+ }
+ handleSubmit(e) {
+ e.preventDefault();
+ var team = {};
+ var state = {serverError: ''};
+
+ team.email = this.refs.email.getDOMNode().value.trim().toLowerCase();
+ if (!team.email || !utils.isEmail(team.email)) {
+ state.emailError = 'Please enter a valid email address';
+ state.inValid = true;
+ } else {
+ state.emailError = '';
+ }
+
+ if (state.inValid) {
+ this.setState(state);
+ return;
+ }
+
+ client.signupTeam(team.email,
+ function success(data) {
+ if (data.follow_link) {
+ window.location.href = data.follow_link;
+ } else {
+ window.location.href = '/signup_team_confirm/?email=' + encodeURIComponent(team.email);
+ }
+ },
+ function fail(err) {
+ state.serverError = err.message;
+ this.setState(state);
+ }.bind(this)
+ );
+ }
+ render() {
+ return (
+ <form
+ role='form'
+ onSubmit={this.handleSubmit}
+ >
+ <div className='form-group'>
+ <input
+ autoFocus={true}
+ type='email'
+ ref='email'
+ className='form-control'
+ placeholder='Email Address'
+ maxLength='128'
+ />
+ </div>
+ <div className='form-group'>
+ <button
+ className='btn btn-md btn-primary'
+ type='submit'
+ >
+ Sign up
+ </button>
+ </div>
+ <div className='form-group margin--extra-2x'>
+ <span><a href='/find_team'>{'Find my ' + strings.Team}</a></span>
+ </div>
+ </form>
+ );
+ }
+}
+
+EmailSignUpPage.defaultProps = {
+};
+EmailSignUpPage.propTypes = {
+};
diff --git a/web/react/components/team_signup_with_sso.jsx b/web/react/components/team_signup_with_sso.jsx
new file mode 100644
index 000000000..57996d7cc
--- /dev/null
+++ b/web/react/components/team_signup_with_sso.jsx
@@ -0,0 +1,137 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var utils = require('../utils/utils.jsx');
+var client = require('../utils/client.jsx');
+var Constants = require('../utils/constants.jsx');
+
+export default class SSOSignUpPage extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ this.nameChange = this.nameChange.bind(this);
+
+ this.state = {name: ''};
+ }
+ handleSubmit(e) {
+ e.preventDefault();
+ var team = {};
+ var state = this.state;
+ state.nameError = null;
+ state.serverError = null;
+
+ team.display_name = this.state.name;
+
+ if (team.display_name.length <= 3) {
+ return;
+ }
+
+ if (!team.display_name) {
+ state.nameError = 'Please enter a team name';
+ this.setState(state);
+ return;
+ }
+
+ team.name = utils.cleanUpUrlable(team.display_name);
+ team.type = 'O';
+
+ client.createTeamWithSSO(team,
+ this.props.service,
+ function success(data) {
+ if (data.follow_link) {
+ window.location.href = data.follow_link;
+ } else {
+ window.location.href = '/';
+ }
+ },
+ function fail(err) {
+ state.serverError = err.message;
+ this.setState(state);
+ }.bind(this)
+ );
+ }
+ nameChange() {
+ this.setState({name: this.refs.teamname.getDOMNode().value.trim()});
+ }
+ render() {
+ var nameError = null;
+ var nameDivClass = 'form-group';
+ if (this.state.nameError) {
+ nameError = <label className='control-label'>{this.state.nameError}</label>;
+ nameDivClass += ' has-error';
+ }
+
+ var serverError = null;
+ if (this.state.serverError) {
+ serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
+ }
+
+ var disabled = false;
+ if (this.state.name.length <= 3) {
+ disabled = true;
+ }
+
+ var button = null;
+
+ if (this.props.service === Constants.GITLAB_SERVICE) {
+ button = (
+ <a
+ className='btn btn-custom-login gitlab btn-full'
+ href='#'
+ onClick={this.handleSubmit}
+ disabled={disabled}
+ >
+ <span className='icon'/>
+ <span>Create {strings.Team} with GitLab Account</span>
+ </a>
+ );
+ } else if (this.props.service === Constants.GOOGLE_SERVICE) {
+ button = (
+ <a
+ className='btn btn-custom-login google btn-full'
+ href='#'
+ onClick={this.handleSubmit}
+ disabled={disabled}
+ >
+ <span className='icon'/>
+ <span>Create {strings.Team} with Google Apps Account</span>
+ </a>
+ );
+ }
+
+ return (
+ <form
+ role='form'
+ onSubmit={this.handleSubmit}
+ >
+ <div className={nameDivClass}>
+ <input
+ autoFocus={true}
+ type='text'
+ ref='teamname'
+ className='form-control'
+ placeholder='Enter name of new team'
+ maxLength='128'
+ onChange={this.nameChange}
+ />
+ {nameError}
+ </div>
+ <div className='form-group'>
+ {button}
+ {serverError}
+ </div>
+ <div className='form-group margin--extra-2x'>
+ <span><a href='/find_team'>{'Find my ' + strings.Team}</a></span>
+ </div>
+ </form>
+ );
+ }
+}
+
+SSOSignUpPage.defaultProps = {
+ service: ''
+};
+SSOSignUpPage.propTypes = {
+ service: React.PropTypes.string
+};
diff --git a/web/react/pages/signup_team.jsx b/web/react/pages/signup_team.jsx
index 37c441d4f..4b58025ac 100644
--- a/web/react/pages/signup_team.jsx
+++ b/web/react/pages/signup_team.jsx
@@ -5,11 +5,13 @@ var SignupTeam = require('../components/signup_team.jsx');
var AsyncClient = require('../utils/async_client.jsx');
-global.window.setup_signup_team_page = function() {
+global.window.setup_signup_team_page = function(authServices) {
AsyncClient.getConfig();
+ var services = JSON.parse(authServices);
+
React.render(
- <SignupTeam />,
+ <SignupTeam services={services} />,
document.getElementById('signup-team')
);
};
diff --git a/web/react/pages/signup_user_oauth.jsx b/web/react/pages/signup_user_oauth.jsx
deleted file mode 100644
index 6a0707702..000000000
--- a/web/react/pages/signup_user_oauth.jsx
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-var SignupUserOAuth = require('../components/signup_user_oauth.jsx');
-
-global.window.setup_signup_user_oauth_page = function(user, team_name, team_display_name) {
- React.render(
- <SignupUserOAuth user={user} teamName={team_name} teamDisplayName={team_display_name} />,
- document.getElementById('signup-user-complete')
- );
-};
diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx
index 70220c71e..082f82a08 100644
--- a/web/react/utils/client.jsx
+++ b/web/react/utils/client.jsx
@@ -70,6 +70,21 @@ module.exports.createTeamFromSignup = function(teamSignup, success, error) {
});
};
+module.exports.createTeamWithSSO = function(team, service, success, error) {
+ $.ajax({
+ url: '/api/v1/teams/create_with_sso/' + service,
+ dataType: 'json',
+ contentType: 'application/json',
+ type: 'POST',
+ data: JSON.stringify(team),
+ success: success,
+ error: function onError(xhr, status, err) {
+ var e = handleError('createTeamWithSSO', xhr, status, err);
+ error(e);
+ }
+ });
+};
+
module.exports.createUser = function(user, data, emailHash, success, error) {
$.ajax({
url: '/api/v1/users/create?d=' + encodeURIComponent(data) + '&h=' + encodeURIComponent(emailHash),
diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx
index 82fc3da22..6678790e2 100644
--- a/web/react/utils/constants.jsx
+++ b/web/react/utils/constants.jsx
@@ -61,6 +61,7 @@ module.exports = {
OFFTOPIC_CHANNEL: 'off-topic',
GITLAB_SERVICE: 'gitlab',
GOOGLE_SERVICE: 'google',
+ EMAIL_SERVICE: 'email',
POST_CHUNK_SIZE: 60,
MAX_POST_CHUNKS: 3,
POST_LOADING: 'loading',
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index 733d81c2b..682809f02 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -290,6 +290,14 @@
.signup-team__name {
font-size: 2em;
}
+ .btn.btn-full {
+ padding-left: 10px;
+ }
+ .btn {
+ .icon, .fa {
+ margin-right: 6px;
+ }
+ }
}
.modal {
.info__label {
diff --git a/web/sass-files/sass/partials/_signup.scss b/web/sass-files/sass/partials/_signup.scss
index ddf2aab88..2fb56e537 100644
--- a/web/sass-files/sass/partials/_signup.scss
+++ b/web/sass-files/sass/partials/_signup.scss
@@ -156,9 +156,21 @@
}
.btn {
+ font-size: 1em;
padding: em(7px) em(15px);
font-weight: 600;
margin-right: 5px;
+ .fa {
+ font-size: 17px;
+ margin-right: 8px;
+ }
+ .icon {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+ @include background-size(100% 100%);
+ display: inline-block;
+ }
&.btn-custom-login {
display: block;
min-width: 200px;
@@ -166,7 +178,7 @@
padding: 0 1em;
margin: 1em auto;
height: 40px;
- line-height: 35px;
+ line-height: 34px;
color: #fff;
@include border-radius(2px);
&.gitlab {
@@ -178,12 +190,7 @@
vertical-align: middle;
}
.icon {
- background: url("../images/gitlabLogo.png");
- width: 18px;
- height: 18px;
- margin-right: 8px;
- @include background-size(100% 100%);
- display: inline-block;
+ background-image: url("../images/gitlabLogo.png");
}
}
&.google {
@@ -195,13 +202,22 @@
vertical-align: middle;
}
.icon {
- background: url("../images/googleLogo.png");
- width: 18px;
- height: 18px;
- margin-right: 8px;
- @include background-size(100% 100%);
- display: inline-block;
+ background-image: url("../images/googleLogo.png");
+ }
+ }
+ &.email {
+ background: #2389D7;
+ &:hover {
+ background: darken(#2389D7, 10%);
}
+ span {
+ vertical-align: middle;
+ }
+ }
+ &.btn-full {
+ width: 100%;
+ text-align: left;
+ padding-left: 35px;
}
}
&.btn-default {
diff --git a/web/templates/signup_team.html b/web/templates/signup_team.html
index b896dedf5..8d9d6e0b8 100644
--- a/web/templates/signup_team.html
+++ b/web/templates/signup_team.html
@@ -22,7 +22,7 @@
</div>
</div>
<script>
-window.setup_signup_team_page();
+window.setup_signup_team_page('{{.Props.AuthServices}}');
</script>
</body>
</html>
diff --git a/web/templates/signup_user_oauth.html b/web/templates/signup_user_oauth.html
deleted file mode 100644
index 2eddb50d2..000000000
--- a/web/templates/signup_user_oauth.html
+++ /dev/null
@@ -1,26 +0,0 @@
-{{define "signup_user_oauth"}}
-<!DOCTYPE html>
-<html>
-{{template "head" . }}
-<body class="white">
- <div class="container-fluid">
- <div class="inner__wrap">
- <div class="row content">
- <div class="col-sm-12">
- <div class="signup-team__container">
- <div id="signup-user-complete"></div>
- </div>
- </div>
- <div class="footer-push"></div>
- </div>
- <div class="row footer">
- {{template "footer" . }}
- </div>
- </div>
- </div>
- <script>
- window.setup_signup_user_oauth_page('{{.Props.User}}', '{{.Props.TeamName}}', '{{.Props.TeamDisplayName}}');
- </script>
-</body>
-</html>
-{{end}}
diff --git a/web/web.go b/web/web.go
index dc2b5dced..03dbdde6a 100644
--- a/web/web.go
+++ b/web/web.go
@@ -145,6 +145,7 @@ func root(c *api.Context, w http.ResponseWriter, r *http.Request) {
if len(c.Session.UserId) == 0 {
page := NewHtmlTemplatePage("signup_team", "Signup")
+ page.Props["AuthServices"] = model.ArrayToJson(utils.GetAllowedAuthServices())
page.Render(c, w)
} else {
page := NewHtmlTemplatePage("home", "Home")
@@ -160,6 +161,7 @@ func signup(c *api.Context, w http.ResponseWriter, r *http.Request) {
}
page := NewHtmlTemplatePage("signup_team", "Signup")
+ page.Props["AuthServices"] = model.ArrayToJson(utils.GetAllowedAuthServices())
page.Render(c, w)
}
@@ -529,23 +531,52 @@ func signupCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request)
return
}
- if result := <-api.Srv.Store.User().GetByAuth(team.Id, user.AuthData, service); result.Err == nil {
+ suchan := api.Srv.Store.User().GetByAuth(team.Id, user.AuthData, service)
+ euchan := api.Srv.Store.User().GetByEmail(team.Id, user.Email)
+
+ if team.Email == "" {
+ team.Email = user.Email
+ if result := <-api.Srv.Store.Team().Update(team); result.Err != nil {
+ c.Err = result.Err
+ return
+ }
+ } else {
+ found := true
+ count := 0
+ for found {
+ if found = api.IsUsernameTaken(user.Username, team.Id); c.Err != nil {
+ return
+ } else if found {
+ user.Username = user.Username + strconv.Itoa(count)
+ count += 1
+ }
+ }
+ }
+
+ if result := <-suchan; result.Err == nil {
c.Err = model.NewAppError("signupCompleteOAuth", "This "+service+" account has already been used to sign up for team "+team.DisplayName, "email="+user.Email)
return
}
- if result := <-api.Srv.Store.User().GetByEmail(team.Id, user.Email); result.Err == nil {
+ if result := <-euchan; result.Err == nil {
c.Err = model.NewAppError("signupCompleteOAuth", "Team "+team.DisplayName+" already has a user with the email address attached to your "+service+" account", "email="+user.Email)
return
}
user.TeamId = team.Id
- page := NewHtmlTemplatePage("signup_user_oauth", "Complete User Sign Up")
- page.Props["User"] = user.ToJson()
- page.Props["TeamName"] = team.Name
- page.Props["TeamDisplayName"] = team.DisplayName
- page.Render(c, w)
+ ruser := api.CreateUser(c, team, user)
+ if c.Err != nil {
+ return
+ }
+
+ api.Login(c, w, r, ruser, "")
+
+ if c.Err != nil {
+ return
+ }
+
+ root(c, w, r)
}
}