From 11a3f3f06704c2bd4dd9d3723e1dad666507ab7f Mon Sep 17 00:00:00 2001 From: elijah Date: Fri, 7 Oct 2016 17:43:07 -0700 Subject: [feat] ui - add support for sign up with invite code --- ui/app/components/login.js | 71 +++++++++++++++++++++++++++++++++++++++------- ui/app/lib/bitmask.js | 4 +-- ui/app/models/account.js | 4 +-- 3 files changed, 65 insertions(+), 14 deletions(-) (limited to 'ui') diff --git a/ui/app/components/login.js b/ui/app/components/login.js index 00f52d5..af3dfe8 100644 --- a/ui/app/components/login.js +++ b/ui/app/components/login.js @@ -8,6 +8,7 @@ import Spinner from './spinner' import Validate from 'lib/validate' import App from 'app' import Account from 'models/account' +import Provider from 'models/provider' class Login extends React.Component { @@ -41,8 +42,13 @@ class Login extends React.Component { password2State: null, // password confirm validation state password2Error: false, // password confirm help message + requireInvite: false, + invite: null, // invite code value + inviteState: null, // invite code validation state + inviteError: false, // invite code error + disabled: false, - remember: false // remember is checked? + remember: false // remember is checked? } // prebind: @@ -50,12 +56,20 @@ class Login extends React.Component { this.onUsernameBlur = this.onUsernameBlur.bind(this) this.onPassword = this.onPassword.bind(this) this.onPassword2 = this.onPassword2.bind(this) + this.onInvite = this.onInvite.bind(this) this.onSubmit = this.onSubmit.bind(this) this.onRemember = this.onRemember.bind(this) } componentDidMount() { Validate.loadPasswdLib() + if (this.props.domain && this.props.mode == 'signup') { + Provider.get(this.props.domain).then(provider => { + if (provider.enrollment_policy == 'invite') { + this.setState({requireInvite: true}) + } + }) + } } render () { @@ -65,6 +79,7 @@ class Login extends React.Component { let passwordHelp = null let password2Help = null let password2Elem = null + let inviteElem = null let message = null let buttonText = "Log In" @@ -125,7 +140,7 @@ class Login extends React.Component { if (this.props.mode == 'signup') { buttonText = 'Sign Up' if (this.state.password2Error) { - + password2Help = {this.state.password2Error} } password2Elem = ( @@ -139,6 +154,18 @@ class Login extends React.Component { {password2Help} ) + if (this.state.requireInvite) { + let inviteHelp = null + inviteElem = ( + + Invite Code + + {inviteHelp} + + ) + } } let buttonProps = { @@ -200,6 +227,7 @@ class Login extends React.Component { {password2Elem} + {inviteElem} {submitButton} {rememberCheck} @@ -272,6 +300,10 @@ class Login extends React.Component { this.validatePassword2(password2, this.state.password) } + onInvite(e) { + this.setState({invite: e.target.value}) + } + onRemember(e) { let currentValue = e.target.value == 'on' ? true : false let value = !currentValue @@ -339,7 +371,9 @@ class Login extends React.Component { if (this.props.mode == 'login') { return ok } else if (this.props.mode == 'signup') { - return ok && this.state.password2 == this.state.password + return ok && + this.state.password2 == this.state.password && + (!this.state.requireInvite || this.state.invite) } } @@ -379,7 +413,11 @@ class Login extends React.Component { } doSignup() { - Account.create(this.state.username, this.state.password).then( + Account.create( + this.state.username, + this.state.password, + this.state.invite + ).then( account => { this.doLogin() }, @@ -387,12 +425,25 @@ class Login extends React.Component { if (error == "") { error = "Something failed, but we did not get a message" } - this.setState({ - loading: false, - usernameState: 'error', - passwordState: 'error', - authError: error - }) + // error messages for invite codes are in english, and + // hardcoded in leap_web in the file invite_code_validator.rb + // all the code error messages have the word 'code' in them. + // the api backend is returning {user: {code: "error message"}} + // but that structure is lost by the time it reaches us. + if (/code/.test(error)) { + this.setState({ + loading: false, + inviteState: 'error', + authError: error + }) + } else { + this.setState({ + loading: false, + usernameState: 'error', + passwordState: 'error', + authError: error + }) + } } ) } diff --git a/ui/app/lib/bitmask.js b/ui/app/lib/bitmask.js index 823504d..f388e95 100644 --- a/ui/app/lib/bitmask.js +++ b/ui/app/lib/bitmask.js @@ -143,11 +143,11 @@ var bitmask = function(){ * @param {boolean} autoconf If the provider should be autoconfigured if it's not allready known * If it's not provided it will default to false */ - create: function(uid, password, autoconf) { + create: function(uid, password, invite, autoconf) { if (typeof autoconf !== 'boolean') { autoconf = false; } - return call(['bonafide', 'user', 'create', uid, password, autoconf]); + return call(['bonafide', 'user', 'create', uid, password, invite, autoconf]); }, /** diff --git a/ui/app/models/account.js b/ui/app/models/account.js index 0ffdb07..412ee56 100644 --- a/ui/app/models/account.js +++ b/ui/app/models/account.js @@ -135,8 +135,8 @@ export default class Account { }) } - static create(address, password) { - return bitmask.bonafide.user.create(address, password).then( + static create(address, password, invite=null) { + return bitmask.bonafide.user.create(address, password, invite).then( response => { return new Account(address) } -- cgit v1.2.3