add user registration

This commit is contained in:
João Geonizeli
2022-07-08 19:08:03 -03:00
parent 874706cabb
commit 688d5e89b7
16 changed files with 478 additions and 235 deletions

View File

@@ -0,0 +1 @@
export { UserRoutes } from './users.controller'

View File

@@ -0,0 +1,30 @@
import { RequestHandler, Router } from 'express'
import { UserDto } from '../dto/user.dto';
import { UserService } from '../service/user.service';
const router = Router();
const basePath = '/users'
export const post: RequestHandler = (req, res) => {
const { email, password } = req.body;
UserService.create({
email,
password
}).then(user => {
const respose: UserDto = {
id: user.id,
email: user.email
}
res.json(respose);
}).catch(err => {
res.status(422).json({
error: err.message
});
})
}
router.post(basePath, post)
export const UserRoutes = router;

View File

@@ -0,0 +1,4 @@
export type NewUserDto = {
email: string
password: string
}

View File

@@ -0,0 +1,4 @@
export type UserDto = {
id: number
email: string
}

View File

@@ -1,3 +1,4 @@
import { IsEmail, IsNotEmpty } from "class-validator"
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
@@ -6,7 +7,9 @@ export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
@Column({ unique: true })
@IsEmail()
@IsNotEmpty()
email: string
@Column()

View File

@@ -2,18 +2,18 @@ import "reflect-metadata"
import * as dotenv from 'dotenv';
import * as express from 'express';
import { AppDataSource } from "./infra/dataSource";
import { UserRoutes } from "./controller";
dotenv.config();
const app = express();
const port = process.env.PORT;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.use(express.json());
app.use(UserRoutes)
AppDataSource.initialize().then(() => {
const port = process.env.PORT;
app.listen(port, () => {
console.log(`Server is running at ${port} 🚀`);
});

View File

@@ -0,0 +1,4 @@
import { User } from "../entity/user.entity";
import { AppDataSource } from "../infra/dataSource";
export const userRepository = AppDataSource.getRepository(User)

View File

@@ -0,0 +1,76 @@
import { User } from "../../entity/user.entity";
import { AuthService, SALT_ROUNDS } from "../auth.service";
import * as bcrypt from 'bcrypt'
describe('AuthService', () => {
describe('#updateUserPassword', () => {
it('should return a change user encryptedPassword', async () => {
const user = new User();
await new Promise<void>((resolve, reject) => {
bcrypt.hash('example', SALT_ROUNDS, function (err, hash) {
if (err) {
reject(err)
}
user.encryptedPassword = hash
resolve()
});
})
const currentUserEncryptedPassowrd = user.encryptedPassword
await AuthService.updateUserPassword(user, 'example');
expect(currentUserEncryptedPassowrd).not.toBe(user.encryptedPassword);
});
})
describe('#isUserPasswordValid', () => {
it('should return true if password is valid', async () => {
const user = new User();
await new Promise<void>((resolve, reject) => {
bcrypt.hash('example', SALT_ROUNDS, function (err, hash) {
if (err) {
reject(err)
}
user.encryptedPassword = hash
resolve()
});
})
const currentUserEncryptedPassowrd = user.encryptedPassword
const result = await AuthService.isUserPasswordValid(user, 'example');
expect(result).toBeTruthy()
});
it('should return false if password is invalid', async () => {
const user = new User();
await new Promise<void>((resolve, reject) => {
bcrypt.hash('example', SALT_ROUNDS, function (err, hash) {
if (err) {
reject(err)
}
user.encryptedPassword = hash
resolve()
});
})
const currentUserEncryptedPassowrd = user.encryptedPassword
const result = await AuthService.isUserPasswordValid(user, 'example2');
expect(result).toBeFalsy()
})
})
})

View File

@@ -0,0 +1,35 @@
import { User } from "../entity/user.entity";
import * as bcrypt from 'bcrypt'
export const SALT_ROUNDS = 10
const updateUserPassword = (user: User, password: string) => {
return new Promise<boolean>((resolve, reject) => {
bcrypt.hash(password, SALT_ROUNDS, function (err, hash) {
if (err) {
reject(err)
}
user.encryptedPassword = hash
resolve(true)
});
})
}
const isUserPasswordValid = (user: User, password: string) => {
return new Promise<boolean>((resolve, reject) => {
bcrypt.compare(password, user.encryptedPassword, function (err, result) {
if (err) {
reject(err)
}
resolve(result)
});
})
}
export const AuthService = {
updateUserPassword,
isUserPasswordValid
}

View File

@@ -0,0 +1,37 @@
import { validate } from "class-validator"
import { NewUserDto } from "../dto/newUser.dto"
import { User } from "../entity/user.entity"
import { userRepository } from "../repository/user.repository"
import { AuthService } from "./auth.service"
async function create(newUserDto: NewUserDto): Promise<User> {
const user = new User()
user.email = newUserDto.email
const errors = await validate(user);
if (errors.length > 0) {
throw new Error("Invalid user data")
}
const result = await findByEmail(user.email)
if (result) {
throw new Error("User already exists")
}
await AuthService.updateUserPassword(user, newUserDto.password)
return userRepository.save(user)
}
async function findByEmail(email: string): Promise<User | undefined> {
return userRepository.findOneBy({ email })
}
export const UserService = {
create,
findByEmail
}

View File

@@ -1,5 +0,0 @@
describe('test', () => {
it('true', () => {
expect(true).toBeTruthy()
})
})