chore: manually committing auth module to remoter
This commit is contained in:
14
packages/hoppscotch-backend/src/auth/auth.controller.ts
Normal file
14
packages/hoppscotch-backend/src/auth/auth.controller.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Body, Controller, Get, Post } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { signInMagicDto } from './dto/signin-magic.dto';
|
||||
import { verifyMagicDto } from './dto/verify-magic.dto';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private authService: AuthService) {}
|
||||
|
||||
@Post('signin')
|
||||
async signIn(@Body() authData: signInMagicDto) {
|
||||
return this.authService.signIn(authData.email);
|
||||
}
|
||||
}
|
||||
13
packages/hoppscotch-backend/src/auth/auth.module.ts
Normal file
13
packages/hoppscotch-backend/src/auth/auth.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { MailerModule } from 'src/mailer/mailer.module';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UserModule, MailerModule],
|
||||
providers: [AuthService],
|
||||
controllers: [AuthController],
|
||||
})
|
||||
export class AuthModule {}
|
||||
18
packages/hoppscotch-backend/src/auth/auth.service.spec.ts
Normal file
18
packages/hoppscotch-backend/src/auth/auth.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
describe('AuthService', () => {
|
||||
let service: AuthService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [AuthService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<AuthService>(AuthService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
68
packages/hoppscotch-backend/src/auth/auth.service.ts
Normal file
68
packages/hoppscotch-backend/src/auth/auth.service.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { MailerService } from 'src/mailer/mailer.service';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
import { User } from 'src/user/user.model';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { verifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { DateTime } from 'luxon';
|
||||
import * as argon2 from 'argon2';
|
||||
import bcrypt from 'bcrypt';
|
||||
import * as O from 'fp-ts/Option';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import * as TE from 'fp-ts/TaskEither';
|
||||
import { PasswordlessToken } from 'src/types/Passwordless';
|
||||
import { EmailCodec } from 'src/types/Email';
|
||||
import { INVALID_EMAIL } from 'src/errors';
|
||||
import { pipe } from 'fp-ts/lib/function';
|
||||
import { validateEmail } from 'src/utils';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private usersService: UserService,
|
||||
private prismaService: PrismaService,
|
||||
private readonly mailerService: MailerService,
|
||||
) {}
|
||||
|
||||
// generate Id and token for email magiclink
|
||||
private async generatePasswordlessTokens(user: User) {
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
const expiresOn = DateTime.now().plus({ hours: 3 }).toISO().toString();
|
||||
|
||||
const idToken: PasswordlessToken =
|
||||
await this.prismaService.passwordlessVerification.create({
|
||||
data: {
|
||||
expiresOn: expiresOn,
|
||||
deviceIdentifier: salt,
|
||||
userUid: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
return idToken;
|
||||
}
|
||||
|
||||
async signIn(email: string) {
|
||||
if (!validateEmail(email)) return E.left(INVALID_EMAIL);
|
||||
|
||||
let user: User;
|
||||
const queriedUser = await this.usersService.findUserByEmail(email);
|
||||
|
||||
if (O.isNone(queriedUser)) {
|
||||
user = await this.usersService.createUser(email);
|
||||
} else {
|
||||
user = queriedUser.value;
|
||||
}
|
||||
|
||||
const generatedTokens = await this.generatePasswordlessTokens(user);
|
||||
|
||||
this.mailerService.sendMail(email, {
|
||||
template: 'code-your-own',
|
||||
variables: {
|
||||
inviteeEmail: email,
|
||||
magicLink: `${process.env.APP_DOMAIN}/magic-link?token=${generatedTokens.token}`,
|
||||
},
|
||||
});
|
||||
|
||||
return { deviceIdentifier: generatedTokens.deviceIdentifier };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export class refreshTokensDto {
|
||||
refresh_token: string;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export class signInMagicDto {
|
||||
email: string;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export class verifyMagicDto {
|
||||
identifier: string;
|
||||
token: string;
|
||||
}
|
||||
Reference in New Issue
Block a user