feat(auth): Implement user signup functionality
This commit introduces a new feature for user signup. It creates `auth.controller.ts`, `auth.dto.ts`, and `auth.schema.ts` for handling user registration requests with validation. Moreover, it enhances `auth.service.ts` to handle the database interaction part and also modifies `auth.module.ts` by adding `AuthController`. Now, the application can handle user registration successfully with proper error handling.
This commit is contained in:
parent
1990bedcfd
commit
de3d1cca05
24
src/auth/auth.controller.ts
Normal file
24
src/auth/auth.controller.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Body, Controller, HttpCode, HttpStatus, Post } from "@nestjs/common";
|
||||
import { SignUpDto } from "src/auth/auth.dto";
|
||||
import { AuthService } from "src/auth/auth.service";
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {
|
||||
}
|
||||
|
||||
//POST signup
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@Post("signup")
|
||||
async signUp(@Body() dto: SignUpDto) {
|
||||
console.log(dto)
|
||||
return this.authService.doRegister(dto)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//POST signin
|
||||
//GET me -- Get current user data via jwt
|
||||
//DELETE me
|
||||
//PATCH me
|
||||
}
|
50
src/auth/auth.dto.ts
Normal file
50
src/auth/auth.dto.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import {
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
IsString,
|
||||
IsStrongPassword,
|
||||
MaxLength,
|
||||
MinLength,
|
||||
} from "class-validator";
|
||||
|
||||
export class SignUpDto {
|
||||
@MinLength(1)
|
||||
@MaxLength(24)
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
firstName: string;
|
||||
|
||||
@MinLength(1)
|
||||
@MaxLength(24)
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
lastName: string;
|
||||
|
||||
@MaxLength(32)
|
||||
@IsEmail()
|
||||
@IsNotEmpty()
|
||||
email: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@IsStrongPassword({
|
||||
minLength: 6,
|
||||
minSymbols: 1,
|
||||
})
|
||||
password: string;
|
||||
}
|
||||
|
||||
export class SignInDto {
|
||||
@MaxLength(32)
|
||||
@IsEmail()
|
||||
@IsNotEmpty()
|
||||
email: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@IsStrongPassword({
|
||||
minLength: 6,
|
||||
minSymbols: 1,
|
||||
})
|
||||
password: string;
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { DrizzleModule } from "src/drizzle/drizzle.module";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { CredentialsModule } from "src/credentials/credentials.module";
|
||||
import { DrizzleModule } from "src/drizzle/drizzle.module";
|
||||
import { AuthController } from "./auth.controller";
|
||||
import { AuthService } from "./auth.service";
|
||||
|
||||
@Module({
|
||||
imports: [DrizzleModule, CredentialsModule],
|
||||
providers: [AuthService],
|
||||
controllers: [AuthController],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
31
src/auth/auth.schema.ts
Normal file
31
src/auth/auth.schema.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { UsersTableInsertSchema } from "src/schema";
|
||||
import { z } from "zod";
|
||||
|
||||
export const SignUpBodySchema = z.object({
|
||||
firstName: z.string({ message: "'firstName' should be a string." }).max(24),
|
||||
lastName: z.string({ message: "'lastName' should be a string." }).max(24),
|
||||
email: z
|
||||
.string({ message: "'email' should be a string." })
|
||||
.max(32, "'email' should be less than 32 characters")
|
||||
.email("Of course 'email' should be an email."),
|
||||
password: z
|
||||
.string({ message: "'password' should be a string." })
|
||||
.min(6)
|
||||
//regex for strong password
|
||||
.regex(
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,32}$/,
|
||||
)
|
||||
.max(32),
|
||||
});
|
||||
|
||||
export const SignInBodySchema = z.object({
|
||||
email: z
|
||||
.string({ message: "'email' should be a string." })
|
||||
.max(32, "'email' should be less than 32 characters")
|
||||
.email("Of course 'email' should be an email."),
|
||||
|
||||
password: z
|
||||
.string({ message: "'password' should be a string." })
|
||||
.min(6)
|
||||
.max(32),
|
||||
});
|
@ -1,27 +1,80 @@
|
||||
// biome-ignore lint/style/useImportType: used by Next.js
|
||||
import { Injectable, OnModuleInit } from "@nestjs/common";
|
||||
// biome-ignore lint/style/useImportType: used by Next.js
|
||||
import * as console from "node:console";
|
||||
import {
|
||||
Injectable,
|
||||
OnModuleInit,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { SignUpBodySchema } from "src/auth/auth.schema";
|
||||
import { CredentialsService } from "src/credentials/credentials.service";
|
||||
import { DrizzleService } from "src/drizzle/drizzle.service";
|
||||
import { UsersTable } from "src/schema";
|
||||
// biome-ignore lint/style/useImportType: used by Next.js
|
||||
import { CredentialsService } from "src/credentials/credentials.service";
|
||||
import { SignInDto, SignUpDto } from "src/auth/auth.dto";
|
||||
|
||||
@Injectable()
|
||||
export class AuthService implements OnModuleInit {
|
||||
constructor(
|
||||
private db: DrizzleService,
|
||||
private credentials: CredentialsService
|
||||
private credentials: CredentialsService,
|
||||
) {}
|
||||
doRegister() {}
|
||||
doLogin() {}
|
||||
async doRegister(data: SignUpDto) {
|
||||
console.log(data);
|
||||
const existingUser = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.email, data.email))
|
||||
.prepare("userByEmail")
|
||||
.execute();
|
||||
if (existingUser.length !== 0)
|
||||
throw new UnauthorizedException("Already exist");
|
||||
const query = await this.db
|
||||
.use()
|
||||
.insert(UsersTable)
|
||||
.values({
|
||||
firstName: data.firstName,
|
||||
lastName: data.lastName,
|
||||
email: data.email,
|
||||
hash: await this.credentials.hash(data.password),
|
||||
})
|
||||
.returning()
|
||||
.prepare("insertUser")
|
||||
.execute()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw new UnauthorizedException(
|
||||
"Error occurred while inserting user",
|
||||
err,
|
||||
);
|
||||
});
|
||||
return {
|
||||
message: "User created, check your email for validation.",
|
||||
token: await this.credentials.signAuthToken({sub: query[0].uuid})
|
||||
}
|
||||
}
|
||||
|
||||
doLogin(data: SignInDto) {}
|
||||
|
||||
async fetchUser(userId: string) {
|
||||
const userInDb = await this.db.use().select().from(UsersTable);
|
||||
console.log("Users : \n", userInDb);
|
||||
//TODO Pagination
|
||||
const usersInDb = await this.db.use().select().from(UsersTable);
|
||||
const result = {
|
||||
total: usersInDb.length,
|
||||
users: usersInDb.map((user)=>{
|
||||
delete user.hash
|
||||
return {
|
||||
...user
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log(result)
|
||||
}
|
||||
updateUser() {}
|
||||
deleteUser() {}
|
||||
|
||||
async onModuleInit() {
|
||||
await this.fetchUser("ee");
|
||||
setTimeout(()=>{
|
||||
this.fetchUser("ee");
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user