Create DTOs for user registration and complete user model

master
nicekid1 2 months ago
parent 894ab52709
commit 435083a682
  1. 62
      migrations/20250104074851-create-user.js
  2. 30
      models/user.js
  3. 4
      src/cart/entities/cart.entity.ts
  4. 6
      src/invoice/entities/invoice.entity.ts
  5. 2
      src/main.ts
  6. 29
      src/users/dto/create-user.dto.ts
  7. 22
      src/users/entities/user.entity.ts
  8. 8
      src/users/users.controller.ts
  9. 37
      src/users/users.service.ts
  10. 10
      src/wallet/entities/wallet.entity.ts

@ -0,0 +1,62 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
email: {
type: Sequelize.STRING,
unique: true,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
},
role: {
type: Sequelize.STRING,
defaultValue: 'user'
},
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
},
username: {
type: Sequelize.STRING,
unique: true,
allowNull: false
},
phoneNumber: {
type: Sequelize.STRING,
unique: true,
allowNull: false
},
gender: {
type: Sequelize.ENUM("male", "female"),
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Users');
}
};

@ -0,0 +1,30 @@
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
User.init({
email: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
username: DataTypes.STRING,
phoneNumber: DataTypes.STRING,
gender: DataTypes.ENUM
}, {
sequelize,
modelName: 'User',
});
return User;
};

@ -8,14 +8,14 @@ export class Cart extends Model<Cart> {
@Column
userId: number;
@BelongsTo(() => User)
@BelongsTo(() => User, { onDelete: 'CASCADE' })
user: User;
@ForeignKey(() => Product)
@Column
productId: number;
@BelongsTo(() => Product)
@BelongsTo(() => Product, { onDelete: 'CASCADE' })
product: Product;
@Column({

@ -1,14 +1,16 @@
import { Table, Model, Column, BelongsTo, ForeignKey } from "sequelize-typescript";
import { User } from "../../users/entities/user.entity";
import { Product } from "../../products/entities/product.entity";
import { Product } from "../../products/entities/product.entity";
@Table
export class Invoice extends Model<Invoice> {
@ForeignKey(() => User)
@Column
userId: number;
@BelongsTo(() => User)
@BelongsTo(() => User, { onDelete: 'CASCADE' })
user: User;
@Column
totalAmount: number;
}

@ -1,8 +1,10 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

@ -0,0 +1,29 @@
import { IsString, IsEmail, IsEnum, IsNotEmpty, IsOptional, Matches } from "class-validator";
export class CreateUserDto {
@IsEmail({}, { message: "Invalid email format" })
email: string;
@IsString()
@IsNotEmpty({ message: "Password is required" })
password: string;
@IsString()
@IsNotEmpty({ message: "First name is required" })
firstName: string;
@IsString()
@IsNotEmpty({ message: "Last name is required" })
lastName: string;
@IsString()
@IsNotEmpty({ message: "Username is required" })
username: string;
@IsString()
@Matches(/^[0-9]{11}$/, { message: "Phone number must be 10 digits" })
phoneNumber: string;
@IsEnum(["male", "female"], { message: "Gender must be 'male' or 'female'" })
gender: string;
}

@ -1,11 +1,31 @@
import { Column, Table, Model } from "sequelize-typescript";
import { Column, Table, Model, DataType } from "sequelize-typescript";
@Table
export class User extends Model<User> {
@Column({ unique: true })
email: string;
@Column
password: string;
@Column({ defaultValue: "user" })
role: string;
@Column
firstName: string;
@Column
lastName: string;
@Column({ unique: true })
username: string;
@Column({ unique: true })
phoneNumber: string;
@Column({
type: DataType.ENUM("male", "female"),
allowNull: false,
})
gender: string;
}

@ -1,15 +1,15 @@
import { Controller, Post, Body, Res, UseGuards, Get } from "@nestjs/common";
import { Controller, Post, Body} from "@nestjs/common";
import { UsersService } from "./users.service";
import { User } from "./entities/user.entity";
import { CreateUserDto } from "./dto/create-user.dto";
@Controller("user")
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post("register")
async register(@Body() body: { email: string; password: string }):Promise<User> {
const { email, password } = body;
return this.usersService.register(email, password);
async register(@Body() createUserDto: CreateUserDto):Promise<User> {
return this.usersService.register(createUserDto);
}
@Post("login")

@ -2,41 +2,44 @@ import { HttpException, HttpStatus, Injectable, UnauthorizedException, BadReques
import { InjectModel } from "@nestjs/sequelize";
import { User } from "./entities/user.entity";
import * as bcrypt from "bcrypt";
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { JwtService } from "@nestjs/jwt";
import { ConfigService } from "@nestjs/config";
import { CreateUserDto } from "./dto/create-user.dto";
@Injectable()
export class UsersService {
constructor(
@InjectModel(User) private readonly userModel: typeof User,
private readonly jwtService: JwtService,
private readonly configService: ConfigService
private readonly jwtService: JwtService,
private readonly configService: ConfigService,
) {}
// Register method
async register(email: string, password: string): Promise<User> {
if (!email) throw new BadRequestException("Email should be entered");
if (!password) throw new BadRequestException("Password should be entered");
async register(createUserDto: CreateUserDto): Promise<User> {
try {
const hashedPassword = await bcrypt.hash(password, 10);
createUserDto.password = await bcrypt.hash(
createUserDto.password,
parseInt(process.env.BCRYPT_SALT_ROUNDS || "10", 10)
);
const userExists = await this.userModel.findOne({ where: { email } });
const userExists = await this.userModel.findOne({
where: { email: createUserDto.email },
});
if (userExists) {
throw new BadRequestException('Email already exists');
throw new BadRequestException("Email already exists");
}
const user = await this.userModel.create({
email,
password: hashedPassword,
});
const user = await this.userModel.create(createUserDto);
return user;
} catch (error) {
throw new HttpException(`An error occurred: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR);
throw new HttpException(
`An error occurred: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
// Login method
async login(email: string, password: string): Promise<{ token: string }> {
if (!email) throw new BadRequestException("Email should be entered");

@ -1,4 +1,4 @@
import { Model, Table, Column, ForeignKey, BelongsTo } from 'sequelize-typescript';
import { Model, Table, Column, ForeignKey, BelongsTo, DataType } from 'sequelize-typescript';
import { User } from '../../users/entities/user.entity';
@Table
@ -7,9 +7,13 @@ export class Wallet extends Model<Wallet> {
@Column
userId: number;
@BelongsTo(() => User)
@BelongsTo(() => User, { onDelete: 'CASCADE' })
user: User;
@Column
@Column({
type: DataType.DECIMAL(10, 2),
allowNull: false,
defaultValue: 0,
})
balance: number;
}

Loading…
Cancel
Save