Merge pull request #424 from mz8i/feature/286-validate-username
Feature 286: validate username
This commit is contained in:
commit
0a5c14762e
@ -5,6 +5,7 @@ import express from 'express';
|
||||
import * as userService from '../services/user';
|
||||
import * as passwordResetService from '../services/passwordReset';
|
||||
import { TokenVerificationError } from '../services/passwordReset';
|
||||
import { ValidationError } from '../validation';
|
||||
|
||||
function createUser(req, res) {
|
||||
const user = req.body;
|
||||
@ -86,6 +87,8 @@ async function resetPassword(req: express.Request, res: express.Response) {
|
||||
} catch (err) {
|
||||
if (err instanceof TokenVerificationError) {
|
||||
return res.send({ error: 'Could not verify token' });
|
||||
} else if (err instanceof ValidationError) {
|
||||
return res.send({ error: err.message});
|
||||
}
|
||||
|
||||
throw err;
|
||||
|
@ -5,6 +5,7 @@ import nodemailer from 'nodemailer';
|
||||
import db from '../../db';
|
||||
import * as userService from './user';
|
||||
import { transporter } from './email';
|
||||
import { validatePassword } from '../validation';
|
||||
|
||||
|
||||
/**
|
||||
@ -24,6 +25,7 @@ export async function sendPasswordResetToken(email: string, siteOrigin: string):
|
||||
}
|
||||
|
||||
export async function resetPassword(passwordResetToken: string, newPassword: string): Promise<void> {
|
||||
validatePassword(newPassword);
|
||||
const userId = await verifyPasswordResetToken(passwordResetToken);
|
||||
if (userId != undefined) {
|
||||
await updatePasswordForUser(userId, newPassword);
|
||||
|
@ -5,14 +5,18 @@
|
||||
import { errors } from 'pg-promise';
|
||||
|
||||
import db from '../../db';
|
||||
import { validateUsername, ValidationError, validatePassword } from '../validation';
|
||||
|
||||
function createUser(user) {
|
||||
if (!user.password || user.password.length < 8) {
|
||||
return Promise.reject({ error: 'Password must be at least 8 characters' })
|
||||
}
|
||||
if (user.password.length > 70) {
|
||||
return Promise.reject({ error: 'Password must be at most 70 characters' })
|
||||
try {
|
||||
validateUsername(user.username);
|
||||
validatePassword(user.password);
|
||||
} catch(err) {
|
||||
if (err instanceof ValidationError) {
|
||||
return Promise.reject({ error: err.message });
|
||||
} else throw err;
|
||||
}
|
||||
|
||||
return db.one(
|
||||
`INSERT
|
||||
INTO users (
|
||||
|
25
app/src/api/validation.ts
Normal file
25
app/src/api/validation.ts
Normal file
@ -0,0 +1,25 @@
|
||||
class ValidationError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
}
|
||||
|
||||
function validateUsername(username: string): void {
|
||||
if (username == undefined) throw new ValidationError('Username is required');
|
||||
if (!username.match(/^\w+$/)) throw new ValidationError('Username can only contain alphanumeric characters and underscore');
|
||||
if (username.length < 4) throw new ValidationError('Username must be at least 4 characters long');
|
||||
if (username.length > 30) throw new ValidationError('Username must be at most 30 characters long');
|
||||
}
|
||||
|
||||
function validatePassword(password: string): void {
|
||||
if (password == undefined) throw new ValidationError('Password is required');
|
||||
if (password.length < 8) throw new ValidationError('Password must be at least 8 characters long');
|
||||
if (password.length > 128) throw new ValidationError('Password must be at most 128 characters long');
|
||||
}
|
||||
|
||||
export {
|
||||
ValidationError,
|
||||
validateUsername,
|
||||
validatePassword
|
||||
};
|
@ -94,6 +94,10 @@ class SignUp extends Component<any, any> { // TODO: add proper types
|
||||
className="form-control" type="text"
|
||||
value={this.state.username} onChange={this.handleChange}
|
||||
placeholder="not-your-real-name" required
|
||||
minLength={4}
|
||||
maxLength={30}
|
||||
pattern="\w+"
|
||||
title="Usernames can contain only letters, numbers and the underscore"
|
||||
/>
|
||||
|
||||
<label htmlFor="email">Email (optional)</label>
|
||||
@ -115,6 +119,8 @@ class SignUp extends Component<any, any> { // TODO: add proper types
|
||||
type={(this.state.show_password)? 'text': 'password'}
|
||||
value={this.state.password} onChange={this.handleChange}
|
||||
required
|
||||
minLength={8}
|
||||
maxLength={128}
|
||||
/>
|
||||
|
||||
<div className="form-check">
|
||||
|
Loading…
Reference in New Issue
Block a user