mirror of
				https://github.com/Alamantus/Lexiconga.git
				synced 2025-11-03 17:57:00 +01:00 
			
		
		
		
	Validate sign up form and check for email and username uniqueness.
This commit is contained in:
		
							parent
							
								
									ae5ffe0cd1
								
							
						
					
					
						commit
						bc7dc27443
					
				
					 3 changed files with 124 additions and 42 deletions
				
			
		| 
						 | 
				
			
			@ -35,6 +35,12 @@ class User {
 | 
			
		|||
    return $user->rowCount() > 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public function usernameExists ($username) {
 | 
			
		||||
    $query = 'SELECT * FROM users WHERE username=?';
 | 
			
		||||
    $user = $this->db->query($query, array($username));
 | 
			
		||||
    return $user->rowCount() > 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public function create ($email, $password) {
 | 
			
		||||
    $insert_user_query = 'INSERT INTO users (email, password) VALUES (?, ?)';
 | 
			
		||||
    $password_hash = password_hash($password, PASSWORD_DEFAULT);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,34 @@ switch ($action) {
 | 
			
		|||
      'error' => true,
 | 
			
		||||
    ), 400);
 | 
			
		||||
  }
 | 
			
		||||
  case 'check-email': {
 | 
			
		||||
    if (isset($request['email'])) {
 | 
			
		||||
      $user = new User();
 | 
			
		||||
      $email_exists = $user->emailExists($request['email']);
 | 
			
		||||
      return Response::json(array(
 | 
			
		||||
        'data' => $email_exists,
 | 
			
		||||
        'error' => false,
 | 
			
		||||
      ), 200);
 | 
			
		||||
    }
 | 
			
		||||
    return Response::json(array(
 | 
			
		||||
      'data' => 'Could not check: required information missing',
 | 
			
		||||
      'error' => true,
 | 
			
		||||
    ), 400);
 | 
			
		||||
  }
 | 
			
		||||
  case 'check-username': {
 | 
			
		||||
    if (isset($request['username'])) {
 | 
			
		||||
      $user = new User();
 | 
			
		||||
      $username_exists = $user->usernameExists($request['username']);
 | 
			
		||||
      return Response::json(array(
 | 
			
		||||
        'data' => $username_exists,
 | 
			
		||||
        'error' => false,
 | 
			
		||||
      ), 200);
 | 
			
		||||
    }
 | 
			
		||||
    return Response::json(array(
 | 
			
		||||
      'data' => 'Could not check: required information missing',
 | 
			
		||||
      'error' => true,
 | 
			
		||||
    ), 400);
 | 
			
		||||
  }
 | 
			
		||||
  case 'get-all-dictionary-names': {
 | 
			
		||||
    if ($token !== false) {
 | 
			
		||||
      $user = new User();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,8 @@ export class LoginForm extends Component {
 | 
			
		|||
      signupConfirmError: '',
 | 
			
		||||
      signupEmailChecking: false,
 | 
			
		||||
      signupUsernameChecking: false,
 | 
			
		||||
      takenUsernames: [],
 | 
			
		||||
      signupEmailIsUnique: true,
 | 
			
		||||
      signupUsernameIsUnique: true,
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,9 +49,9 @@ export class LoginForm extends Component {
 | 
			
		|||
    const requiredFields = ['loginEmail', 'loginPassword', 'signupEmail', 'signupPassword', 'signupConfirm'];
 | 
			
		||||
    const {value, checked} = event.target;
 | 
			
		||||
    const fieldUpdate = {};
 | 
			
		||||
    const errorFieldName = `${field}Error`;
 | 
			
		||||
    let isValid = true;
 | 
			
		||||
    if (requiredFields.includes(field)) {
 | 
			
		||||
      const errorFieldName = `${field}Error`;
 | 
			
		||||
      if (value === '') {
 | 
			
		||||
        isValid = false;
 | 
			
		||||
        fieldUpdate[errorFieldName] = 'This field must not be blank';
 | 
			
		||||
| 
						 | 
				
			
			@ -67,47 +68,53 @@ export class LoginForm extends Component {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (field === 'signupUsername') {
 | 
			
		||||
      if (value !== '' && /[^a-zA-Z0-9]+/g.test(value)) {
 | 
			
		||||
        isValid = false;
 | 
			
		||||
        fieldUpdate[errorFieldName] = 'Please use only letters and numbers';
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isValid) {
 | 
			
		||||
      fieldUpdate[field] = (field === 'signupAllowEmail') ? checked : value;
 | 
			
		||||
      fieldUpdate[errorFieldName] = '';
 | 
			
		||||
    }
 | 
			
		||||
    fieldUpdate[field] = (field === 'signupAllowEmail') ? checked : value;
 | 
			
		||||
    this.setState(fieldUpdate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  checkFieldUnique (field, event) {
 | 
			
		||||
    const uniqueFields = ['signupEmail', 'signupUsername'];
 | 
			
		||||
    const {value} = event.target;
 | 
			
		||||
    const fieldUpdate = {};
 | 
			
		||||
    let isUnique = true;
 | 
			
		||||
    if (uniqueFields.includes(field)) {
 | 
			
		||||
      const errorFieldName = `${field}Error`;
 | 
			
		||||
 | 
			
		||||
      request('check-email', value, (response) => {
 | 
			
		||||
 | 
			
		||||
    const errorFieldName = `${field}Error`;
 | 
			
		||||
    if (field === 'signupEmail') {
 | 
			
		||||
      this.setState({ signupEmailChecking: true }, () => {
 | 
			
		||||
        request('check-email', { email: value }, (response) => {
 | 
			
		||||
          const { data, error } = response;
 | 
			
		||||
          fieldUpdate['signupEmailChecking'] = false;
 | 
			
		||||
          if (error) {
 | 
			
		||||
            console.error(data);
 | 
			
		||||
          } else {
 | 
			
		||||
            fieldUpdate['signupEmailIsUnique'] = !data;
 | 
			
		||||
          }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.setState(fieldUpdate);
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    } else if (field === 'signupUsername') {
 | 
			
		||||
      this.setState({ signupUsernameChecking: true }, () => {
 | 
			
		||||
        request('check-username', { username: value }, (response) => {
 | 
			
		||||
          const { data, error } = response;
 | 
			
		||||
          fieldUpdate['signupUsernameChecking'] = false;
 | 
			
		||||
          if (error) {
 | 
			
		||||
            console.error(data);
 | 
			
		||||
          } else {
 | 
			
		||||
            fieldUpdate['signupUsernameIsUnique'] = !data;
 | 
			
		||||
          }
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.setState(fieldUpdate);
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
      if (value === '') {
 | 
			
		||||
        isUnique = false;
 | 
			
		||||
        fieldUpdate[errorFieldName] = 'This field must not be blank';
 | 
			
		||||
      } else if (field.includes('Email') && !/.+@.+/g.test(value)) {
 | 
			
		||||
        isUnique = false;
 | 
			
		||||
        fieldUpdate[errorFieldName] = 'The email address you entered looks wrong';
 | 
			
		||||
      } else if (field === 'signupPassword' && value.length < 6) {
 | 
			
		||||
        isUnique = false;
 | 
			
		||||
        fieldUpdate[errorFieldName] = 'Please make your password at least 6 characters long';
 | 
			
		||||
      } else if ((field === 'signupPassword' && value !== this.state.signupConfirm)
 | 
			
		||||
        || (field === 'signupConfirm' && value !== this.state.signupPassword)) {
 | 
			
		||||
        isUnique = false;
 | 
			
		||||
        fieldUpdate[errorFieldName] = 'Your passwords must match';
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (field === 'signupUsername' && value !== '') {
 | 
			
		||||
      if (this.state.takenUsernames.length < 1) {
 | 
			
		||||
        fetch()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.setState(fieldUpdate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
| 
						 | 
				
			
			@ -181,9 +188,20 @@ export class LoginForm extends Component {
 | 
			
		|||
                      <label className='label'>
 | 
			
		||||
                        Email Address<sup>*</sup>
 | 
			
		||||
                      </label>
 | 
			
		||||
                      <div className='control'>
 | 
			
		||||
                        <input className='input' type='email' value={this.state.signupEmail}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupEmail', event)} />
 | 
			
		||||
                      <div className={`control ${this.state.signupEmailChecking && 'is-loading'}`}>
 | 
			
		||||
                        <input className={`input ${(this.state.signupEmailError !== '' || !this.state.signupEmailIsUnique) && 'is-danger'}`}
 | 
			
		||||
                          type='email' value={this.state.signupEmail}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupEmail', event)}
 | 
			
		||||
                          onBlur={(event) => this.checkFieldUnique('signupEmail', event)} />
 | 
			
		||||
                        {
 | 
			
		||||
                          (this.state.signupEmailError !== '' || !this.state.signupEmailIsUnique)
 | 
			
		||||
                          ? (
 | 
			
		||||
                            <div className='help is-danger'>
 | 
			
		||||
                              {!this.state.signupEmailIsUnique && <p>This email address is already in use</p>}
 | 
			
		||||
                              {this.state.signupEmailError}
 | 
			
		||||
                            </div>
 | 
			
		||||
                          ) : null
 | 
			
		||||
                        }
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className='field'>
 | 
			
		||||
| 
						 | 
				
			
			@ -193,9 +211,20 @@ export class LoginForm extends Component {
 | 
			
		|||
                      <div className='help'>
 | 
			
		||||
                        This is your unique identifier that appears in the URL if you ever decide to share your dictionaries publicly.
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className='control'>
 | 
			
		||||
                        <input className='input' type='text' value={this.state.signupUsername}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupUsername', event)} />
 | 
			
		||||
                      <div className={`control ${this.state.signupUsernameChecking && 'is-loading'}`}>
 | 
			
		||||
                        <input className={`input ${!this.state.signupUsernameIsUnique && 'is-danger'}`}
 | 
			
		||||
                          type='text' value={this.state.signupUsername}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupUsername', event)}
 | 
			
		||||
                          onBlur={(event) => this.checkFieldUnique('signupUsername', event)} />
 | 
			
		||||
                        {
 | 
			
		||||
                          (this.state.signupUsernameError !== '' || !this.state.signupUsernameIsUnique)
 | 
			
		||||
                            ? (
 | 
			
		||||
                              <div className='help is-danger'>
 | 
			
		||||
                                {!this.state.signupUsernameIsUnique && <p>This username address is already in use</p>}
 | 
			
		||||
                                {this.state.signupUsernameError}
 | 
			
		||||
                              </div>
 | 
			
		||||
                            ) : null
 | 
			
		||||
                        }
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className='field'>
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +235,8 @@ export class LoginForm extends Component {
 | 
			
		|||
                        This is the name we greet you with and what we display if you ever decide to share your dictionaries publicly.
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className='control'>
 | 
			
		||||
                        <input className='input' type='text' value={this.state.signupPublicName}
 | 
			
		||||
                        <input className='input'
 | 
			
		||||
                          type='text' value={this.state.signupPublicName}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupPublicName', event)} />
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -215,8 +245,17 @@ export class LoginForm extends Component {
 | 
			
		|||
                        Password<sup>*</sup>
 | 
			
		||||
                      </label>
 | 
			
		||||
                      <div className='control'>
 | 
			
		||||
                        <input className='input' type='password' value={this.state.signupPassword}
 | 
			
		||||
                        <input className={`input ${this.state.signupPasswordError !== '' && 'is-danger'}`}
 | 
			
		||||
                          type='password' value={this.state.signupPassword}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupPassword', event)} />
 | 
			
		||||
                        {
 | 
			
		||||
                          this.state.signupPasswordError !== ''
 | 
			
		||||
                            ? (
 | 
			
		||||
                              <div className='help is-danger'>
 | 
			
		||||
                                {this.state.signupPasswordError}
 | 
			
		||||
                              </div>
 | 
			
		||||
                            ) : null
 | 
			
		||||
                        }
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className='field'>
 | 
			
		||||
| 
						 | 
				
			
			@ -224,8 +263,17 @@ export class LoginForm extends Component {
 | 
			
		|||
                        Confirm Password<sup>*</sup>
 | 
			
		||||
                      </label>
 | 
			
		||||
                      <div className='control'>
 | 
			
		||||
                        <input className='input' type='password' value={this.state.signupConfirm}
 | 
			
		||||
                        <input className={`input ${this.state.signupConfirmError !== '' && 'is-danger'}`}
 | 
			
		||||
                          type='password' value={this.state.signupConfirm}
 | 
			
		||||
                          onInput={(event) => this.updateField('signupConfirm', event)} />
 | 
			
		||||
                        {
 | 
			
		||||
                          this.state.signupConfirmError !== ''
 | 
			
		||||
                            ? (
 | 
			
		||||
                              <div className='help is-danger'>
 | 
			
		||||
                                {this.state.signupConfirmError}
 | 
			
		||||
                              </div>
 | 
			
		||||
                            ) : null
 | 
			
		||||
                        }
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className='field'>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue