signup_controller.jsx 13.4 KB
Newer Older
1
2
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
3

4
import PropTypes from 'prop-types';
5
6
import React from 'react';
import {FormattedMessage} from 'react-intl';
7
import {Link} from 'react-router-dom';
8
import {Client4} from 'mattermost-redux/client';
9

10
import {browserHistory} from 'utils/browser_history';
11
import * as GlobalActions from 'actions/global_actions.jsx';
12
import {addUserToTeamFromInvite, getInviteInfo} from 'actions/team_actions.jsx';
13
import {loadMe} from 'actions/user_actions.jsx';
14
15
import BrowserStore from 'stores/browser_store.jsx';
import UserStore from 'stores/user_store.jsx';
16
import logoImage from 'images/logo.png';
17
18
19
20
import AnnouncementBar from 'components/announcement_bar';
import BackButton from 'components/common/back_button.jsx';
import FormError from 'components/form_error.jsx';
import LoadingScreen from 'components/loading_screen.jsx';
21
import {Constants} from 'utils/constants.jsx';
22
23
24
25
26
27
28
29
30
31
32
33

export default class SignupController extends React.Component {
    constructor(props) {
        super(props);

        this.renderSignupControls = this.renderSignupControls.bind(this);

        let loading = false;
        let serverError = '';
        let noOpenServerError = false;
        let usedBefore = false;

34
35
        if (this.props.location.search) {
            const params = new URLSearchParams(this.props.location.search);
36
37
38
            let token = params.get('t');
            if (token == null) {
                token = '';
39
40
41
42
43
            }
            let inviteId = params.get('id');
            if (inviteId == null) {
                inviteId = '';
            }
44

Joram Wilander's avatar
Joram Wilander committed
45
46
            if (inviteId) {
                loading = true;
47
48
            } else if (token && !UserStore.getCurrentUser()) {
                usedBefore = BrowserStore.getGlobalItem(token);
49
            } else if (!inviteId && !this.props.enableOpenServer && !this.props.noAccounts) {
50
51
52
53
54
55
56
57
58
59
60
61
62
63
                noOpenServerError = true;
                serverError = (
                    <FormattedMessage
                        id='signup_user_completed.no_open_server'
                        defaultMessage='This server does not allow open signups.  Please speak with your Administrator to receive an invitation.'
                    />
                );
            }
        }

        this.state = {
            loading,
            serverError,
            noOpenServerError,
64
            usedBefore,
65
66
67
68
        };
    }

    componentDidMount() {
enahum's avatar
enahum committed
69
        BrowserStore.removeGlobalItem('team');
70
71
        if (this.props.location.search) {
            const params = new URLSearchParams(this.props.location.search);
72
            const token = params.get('t') || '';
73
            const inviteId = params.get('id') || '';
74

Joram Wilander's avatar
Joram Wilander committed
75
76
            const userLoggedIn = UserStore.getCurrentUser() != null;

77
            if ((inviteId || token) && userLoggedIn) {
78
                addUserToTeamFromInvite(
79
                    token,
Joram Wilander's avatar
Joram Wilander committed
80
81
                    inviteId,
                    (team) => {
82
                        loadMe().then(
Joram Wilander's avatar
Joram Wilander committed
83
                            () => {
84
                                browserHistory.push('/' + team.name + `/channels/${Constants.DEFAULT_CHANNEL}`);
85
                            }
Joram Wilander's avatar
Joram Wilander committed
86
87
                        );
                    },
88
                    this.handleInvalidInvite
Joram Wilander's avatar
Joram Wilander committed
89
                );
90

Joram Wilander's avatar
Joram Wilander committed
91
92
93
94
                return;
            }

            if (inviteId) {
95
                getInviteInfo(
Joram Wilander's avatar
Joram Wilander committed
96
97
98
99
                    inviteId,
                    (inviteData) => {
                        if (!inviteData) {
                            return;
100
                        }
Joram Wilander's avatar
Joram Wilander committed
101
102
103

                        this.setState({ // eslint-disable-line react/no-did-mount-set-state
                            serverError: '',
104
                            loading: false,
Joram Wilander's avatar
Joram Wilander committed
105
106
                        });
                    },
107
                    this.handleInvalidInvite
Joram Wilander's avatar
Joram Wilander committed
108
109
110
111
112
113
                );

                return;
            }

            if (userLoggedIn) {
enahum's avatar
enahum committed
114
                GlobalActions.redirectUserToDefaultTeam();
115
116
117
118
            }
        }
    }

119
120
    handleInvalidInvite = (err) => {
        let serverError;
121
        if (err.server_error_id === 'store.sql_user.save.max_accounts.app_error') {
122
123
124
125
126
127
128
129
130
131
132
133
134
            serverError = err.message;
        } else {
            serverError = (
                <FormattedMessage
                    id='signup_user_completed.invalid_invite'
                    defaultMessage='The invite link was invalid.  Please speak with your Administrator to receive an invitation.'
                />
            );
        }

        this.setState({
            noOpenServerError: true,
            loading: false,
135
            serverError,
136
137
138
        });
    }

139
140
141
    renderSignupControls() {
        let signupControls = [];

142
        if (this.props.enableSignUpWithEmail) {
143
144
145
146
147
148
149
            signupControls.push(
                <Link
                    className='btn btn-custom-login btn--full email'
                    key='email'
                    to={'/signup_email' + window.location.search}
                >
                    <span>
Asaad Mahmood's avatar
Asaad Mahmood committed
150
                        <span className='icon fa fa-envelope'/>
151
152
153
154
155
156
157
158
159
                        <FormattedMessage
                            id='signup.email'
                            defaultMessage='Email and Password'
                        />
                    </span>
                </Link>
            );
        }

160
        if (this.props.enableSignUpWithGitLab) {
161
162
163
164
            signupControls.push(
                <a
                    className='btn btn-custom-login btn--full gitlab'
                    key='gitlab'
165
                    href={Client4.getOAuthRoute() + '/gitlab/signup' + window.location.search}
166
167
                >
                    <span>
Asaad Mahmood's avatar
Asaad Mahmood committed
168
169
170
171
                        <span className='icon'/>
                        <span>
                            <FormattedMessage
                                id='signup.gitlab'
172
                                defaultMessage='GitLab Single Sign-On'
Asaad Mahmood's avatar
Asaad Mahmood committed
173
174
                            />
                        </span>
175
176
177
178
179
                    </span>
                </a>
            );
        }

180
        if (this.props.isLicensed && this.props.enableSignUpWithGoogle) {
181
182
183
184
            signupControls.push(
                <a
                    className='btn btn-custom-login btn--full google'
                    key='google'
185
                    href={Client4.getOAuthRoute() + '/google/signup' + window.location.search}
186
187
                >
                    <span>
Asaad Mahmood's avatar
Asaad Mahmood committed
188
189
190
191
192
193
194
                        <span className='icon'/>
                        <span>
                            <FormattedMessage
                                id='signup.google'
                                defaultMessage='Google Account'
                            />
                        </span>
195
196
197
198
199
                    </span>
                </a>
            );
        }

200
        if (this.props.isLicensed && this.props.enableSignUpWithOffice365) {
201
202
203
204
            signupControls.push(
                <a
                    className='btn btn-custom-login btn--full office365'
                    key='office365'
205
                    href={Client4.getOAuthRoute() + '/office365/signup' + window.location.search}
206
207
                >
                    <span>
Asaad Mahmood's avatar
Asaad Mahmood committed
208
209
210
211
212
213
214
                        <span className='icon'/>
                        <span>
                            <FormattedMessage
                                id='signup.office365'
                                defaultMessage='Office 365'
                            />
                        </span>
215
216
                    </span>
                </a>
217
            );
218
219
        }

220
        if (this.props.isLicensed && this.props.enableLDAP) {
221
222
223
224
            signupControls.push(
                <Link
                    className='btn btn-custom-login btn--full ldap'
                    key='ldap'
225
                    to={'/login' + this.props.location.search}
226
227
                >
                    <span>
Asaad Mahmood's avatar
Asaad Mahmood committed
228
229
230
231
232
233
234
                        <span className='icon fa fa-folder-open fa--margin-top'/>
                        <span>
                            <FormattedMessage
                                id='signup.ldap'
                                defaultMessage='AD/LDAP Credentials'
                            />
                        </span>
235
236
237
238
239
                    </span>
                </Link>
            );
        }

240
        if (this.props.isLicensed && this.props.enableSAML) {
241
242
243
244
245
246
247
248
249
250
251
252
253
254
            let query = '';
            if (window.location.search) {
                query = '&action=signup';
            } else {
                query = '?action=signup';
            }

            signupControls.push(
                <a
                    className='btn btn-custom-login btn--full saml'
                    key='saml'
                    href={'/login/sso/saml' + window.location.search + query}
                >
                    <span>
Asaad Mahmood's avatar
Asaad Mahmood committed
255
256
                        <span className='icon fa fa-lock fa--margin-top'/>
                        <span>
257
                            {this.props.samlLoginButtonText}
Asaad Mahmood's avatar
Asaad Mahmood committed
258
                        </span>
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
                    </span>
                </a>
            );
        }

        if (signupControls.length === 0) {
            const signupDisabledError = (
                <FormattedMessage
                    id='signup_user_completed.none'
                    defaultMessage='No user creation method has been enabled. Please contact an administrator for access.'
                />
            );
            signupControls = (
                <FormError
                    error={signupDisabledError}
                    margin={true}
                />
            );
277
        } else if (signupControls.length === 1) {
278
            if (this.props.enableSignUpWithEmail) {
279
                return browserHistory.push('/signup_email' + window.location.search);
280
            } else if (this.props.isLicensed && this.props.enableLDAP) {
281
                return browserHistory.push('/login' + window.location.search);
282
            }
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
        }

        return signupControls;
    }

    render() {
        if (this.state.loading) {
            return (<LoadingScreen/>);
        }

        if (this.state.usedBefore) {
            return (
                <div>
                    <FormattedMessage
                        id='signup_user_completed.expired'
                        defaultMessage="You've already completed the signup process for this invitation or this invitation has expired."
                    />
                </div>
            );
        }

        let serverError = null;
        if (this.state.serverError) {
            serverError = (
                <div className={'form-group has-error'}>
                    <label className='control-label'>{this.state.serverError}</label>
                </div>
            );
        }

313
        let signupControls;
314
315
        if (this.state.noOpenServerError || this.state.usedBefore) {
            signupControls = null;
316
317
        } else {
            signupControls = this.renderSignupControls();
318
319
320
321
        }

        return (
            <div>
322
                <AnnouncementBar/>
323
                <BackButton/>
324
325
326
327
328
329
330
                <div className='col-sm-12'>
                    <div className='signup-team__container'>
                        <img
                            className='signup-team-logo'
                            src={logoImage}
                        />
                        <div className='signup__content'>
331
                            <h1>{this.props.siteName}</h1>
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
                            <h4 className='color--light'>
                                <FormattedMessage
                                    id='web.root.signup_info'
                                />
                            </h4>
                            <div className='margin--extra'>
                                <h5><strong>
                                    <FormattedMessage
                                        id='signup.title'
                                        defaultMessage='Create an account with:'
                                    />
                                </strong></h5>
                            </div>
                            {signupControls}
                            {serverError}
                        </div>
348
349
350
351
352
353
354
                        <span className='color--light'>
                            <FormattedMessage
                                id='signup_user_completed.haveAccount'
                                defaultMessage='Already have an account?'
                            />
                            {' '}
                            <Link
Joram Wilander's avatar
Joram Wilander committed
355
                                to={'/login' + this.props.location.search}
356
357
358
359
360
361
362
                            >
                                <FormattedMessage
                                    id='signup_user_completed.signIn'
                                    defaultMessage='Click here to sign in.'
                                />
                            </Link>
                        </span>
363
364
365
366
367
368
369
370
                    </div>
                </div>
            </div>
        );
    }
}

SignupController.propTypes = {
371
372
373
374
375
376
377
378
379
380
381
    location: PropTypes.object,
    isLicensed: PropTypes.bool.isRequired,
    enableOpenServer: PropTypes.bool.isRequired,
    noAccounts: PropTypes.bool.isRequired,
    enableSignUpWithEmail: PropTypes.bool.isRequired,
    enableSignUpWithGitLab: PropTypes.bool.isRequired,
    enableSignUpWithGoogle: PropTypes.bool.isRequired,
    enableSignUpWithOffice365: PropTypes.bool.isRequired,
    enableLDAP: PropTypes.bool.isRequired,
    enableSAML: PropTypes.bool.isRequired,
    samlLoginButtonText: PropTypes.string,
382
    siteName: PropTypes.string,
Joram Wilander's avatar
Joram Wilander committed
383
};