Skip to content

Commit

Permalink
feat: auth flow changes (#73)
Browse files Browse the repository at this point in the history
* Add joined at date for searched user

* Update user search query to respect respect http standards

* Enable cors

* minor fixes

* Correct relations

* Check if users are connected when doing an user search

* fix db structure

* fix namings

* Use passwordless signup

* Return props needed for signin redirection
  • Loading branch information
adelinaenache authored May 19, 2024
1 parent 2b4edfb commit f128c7f
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 76 deletions.
23 changes: 2 additions & 21 deletions src/auth/auth.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,39 +39,23 @@ describe('Auth Controller Tests', () => {
expect(prisma).toBeDefined();
});

it('should fail sign up if password does not meet requirements', async () => {
const response = await app.inject({
method: 'POST',
url: '/auth/sign-up',
payload: {
email: '[email protected]',
password: 'password',
},
});

expect(response.statusCode).toEqual(400);
});

it('should be able to sign up using email and password', async () => {
it('should be able to sign up using email', async () => {
const response = await app.inject({
method: 'POST',
url: '/auth/sign-up',
payload: {
email: '[email protected]',
password: 'Password123',
},
});

expect(response.statusCode).toEqual(201);
expect(response.json().email).toEqual('[email protected]');
expect(response.json().password).toBeUndefined();
});

it('should be able to sign in using email and password', async () => {
it('should be able to sign in using email', async () => {
await prisma.user.create({
data: {
email: '[email protected]',
password: SHA256('password').toString(),
isEmailVerified: true,
authType: AuthType.EMAIL,
},
Expand All @@ -82,14 +66,11 @@ describe('Auth Controller Tests', () => {
url: '/auth/sign-in',
payload: {
email: '[email protected]',
password: 'password',
},
});

expect(response.statusCode).toEqual(201);
expect(response.json().email).toEqual('[email protected]');
expect(response.json().password).toBeUndefined();
expect(response.json().token).toBeDefined();
});

it('should send verification code to email on sign up', async () => {
Expand Down
15 changes: 6 additions & 9 deletions src/auth/controller/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
HttpStatus,
Param,
Post,
Put,
Req,
Res,
UseGuards,
Expand All @@ -29,7 +30,6 @@ import {
ApiNotFoundResponse,
ApiOperation,
ApiTags,
ApiUnauthorizedResponse,
} from '@nestjs/swagger';
import { userProperties } from '../../schemas/user.properties';

Expand Down Expand Up @@ -144,7 +144,7 @@ export class AuthController {
@Post('sign-up')
@ApiOperation({
summary: 'Sign up',
description: 'Sign up with email and password',
description: 'Sign up with email',
})
@ApiCreatedResponse({
description: 'User signed up successfully',
Expand All @@ -160,21 +160,18 @@ export class AuthController {
@Post('sign-in')
@ApiOperation({
summary: 'Sign in',
description: 'Sign in with email and password',
description: 'Sign in with email',
})
@ApiNotFoundResponse({
description: 'User not found',
})
@ApiUnauthorizedResponse({
description: 'Invalid password',
})
@ApiCreatedResponse({
description: 'User signed in successfully',
schema: {
type: 'object',
properties: {
...userProperties,
token: { type: 'string' },
isEmailVerified: userProperties.isEmailVerified,
email: userProperties.email,
},
},
})
Expand All @@ -183,7 +180,7 @@ export class AuthController {
}

@Public()
@Get('regenerate-code/:email')
@Put('regenerate-code/:email')
@ApiOperation({
summary: 'Resend email verification code',
description: 'Resend email verification code to the user',
Expand Down
11 changes: 1 addition & 10 deletions src/auth/dto/signin.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsString } from 'class-validator';
import { IsEmail } from 'class-validator';

export class SigninDto {
@IsEmail()
Expand All @@ -11,13 +11,4 @@ export class SigninDto {
example: '[email protected]',
})
email: string;
@IsString()
@ApiProperty({
name: 'password',
description: 'User password. Must be a string.',
required: true,
type: String,
example: 'password123',
})
password: string;
}
15 changes: 1 addition & 14 deletions src/auth/dto/signup.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, Matches } from 'class-validator';
import { IsEmail } from 'class-validator';

export class SignupDto {
@IsEmail()
Expand All @@ -11,17 +11,4 @@ export class SignupDto {
example: '[email protected]',
})
email: string;
@Matches(/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{9,}$/, {
message:
'Password must contain at least 1 letter, 1 number and be at least 9 characters long',
})
@ApiProperty({
name: 'password',
description:
'User password. Must contain at least 1 letter, 1 number and be at least 9 characters long.',
required: true,
type: String,
example: 'password123',
})
password: string;
}
27 changes: 6 additions & 21 deletions src/auth/service/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@ import {
ConflictException,
Injectable,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { JwtService } from '@nestjs/jwt';
import { AuthType, User } from '@prisma/client';
import { SignupDto } from '../dto/signup.dto';
import { SHA256 } from 'crypto-js';
import { MailService } from '../../mail/mail.service';
import { SigninDto } from '../dto/signin.dto';

function hashPassword(password: string) {
return SHA256(password).toString();
}

@Injectable()
export class AuthService {
constructor(
Expand All @@ -31,7 +25,6 @@ export class AuthService {
AuthType.EMAIL,
null,
null,
hashPassword(dto.password),
true,
);

Expand All @@ -43,24 +36,18 @@ export class AuthService {
where: {
email: dto.email,
},
select: {
isEmailVerified: true,
email: true,
},
});

if (!user) {
throw new NotFoundException('User not found');
}

if (user.password !== hashPassword(dto.password)) {
throw new UnauthorizedException('Invalid password');
}

user.password = undefined;

const token = await this.generateToken(user);

return {
...user,
token,
};
await this.sendEmailVerificationCode(dto.email);
return user;
}

async handleGoogleOAuthLogin(req: any) {
Expand Down Expand Up @@ -212,7 +199,6 @@ export class AuthService {
authType: AuthType,
name?: string,
profilePictureUrl?: string,
password?: string,
throwErrorIfUserExists?: boolean,
) {
let user = await this.findUserByEmail(email);
Expand All @@ -227,7 +213,6 @@ export class AuthService {
name: name,
profilePictureUrl: profilePictureUrl,
authType,
password,
},
select: {
id: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:
- You are about to drop the column `password` on the `User` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "User" DROP COLUMN "password";
1 change: 0 additions & 1 deletion src/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ enum AuthType {
model User {
id String @id @default(cuid())
email String @unique
password String?
name String?
profilePictureUrl String?
socialAccounts UserSocialAccount[]
Expand Down

0 comments on commit f128c7f

Please sign in to comment.