hotfix: magiclink dynamic email redirection url (#67)
* chore: modified magiclink /signin function to work with origin * chore: modified testcases for signInMagicLink to reflect new changes * chore: removed prisma migration file * chore: removed admin module dulicate from guards folder * chore: implemented ENUMs for origins in signin method * chore: added VITE_ADMIN_URL to .env.example file
This commit is contained in:
@@ -47,6 +47,7 @@ RATE_LIMIT_MAX=100 # Max requests per IP
|
|||||||
# Base URLs
|
# Base URLs
|
||||||
VITE_BASE_URL=http://localhost:3000
|
VITE_BASE_URL=http://localhost:3000
|
||||||
VITE_SHORTCODE_BASE_URL=http://localhost:3000
|
VITE_SHORTCODE_BASE_URL=http://localhost:3000
|
||||||
|
VITE_ADMIN_URL=http://localhost:3100
|
||||||
|
|
||||||
# Backend URLs
|
# Backend URLs
|
||||||
VITE_BACKEND_GQL_URL=http://localhost:3170/graphql
|
VITE_BACKEND_GQL_URL=http://localhost:3170/graphql
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
Controller,
|
Controller,
|
||||||
Get,
|
Get,
|
||||||
Post,
|
Post,
|
||||||
|
Query,
|
||||||
Req,
|
Req,
|
||||||
Request,
|
Request,
|
||||||
Res,
|
Res,
|
||||||
@@ -34,9 +35,13 @@ export class AuthController {
|
|||||||
** Route to initiate magic-link auth for a users email
|
** Route to initiate magic-link auth for a users email
|
||||||
*/
|
*/
|
||||||
@Post('signin')
|
@Post('signin')
|
||||||
async signInMagicLink(@Body() authData: SignInMagicDto) {
|
async signInMagicLink(
|
||||||
|
@Body() authData: SignInMagicDto,
|
||||||
|
@Query('origin') origin: string,
|
||||||
|
) {
|
||||||
const deviceIdToken = await this.authService.signInMagicLink(
|
const deviceIdToken = await this.authService.signInMagicLink(
|
||||||
authData.email,
|
authData.email,
|
||||||
|
origin,
|
||||||
);
|
);
|
||||||
if (E.isLeft(deviceIdToken)) throwHTTPErr(deviceIdToken.left);
|
if (E.isLeft(deviceIdToken)) throwHTTPErr(deviceIdToken.left);
|
||||||
return deviceIdToken.right;
|
return deviceIdToken.right;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ const encodedRefreshToken =
|
|||||||
|
|
||||||
describe('signInMagicLink', () => {
|
describe('signInMagicLink', () => {
|
||||||
test('Should throw error if email is not in valid format', async () => {
|
test('Should throw error if email is not in valid format', async () => {
|
||||||
const result = await authService.signInMagicLink('bbbgmail.com');
|
const result = await authService.signInMagicLink('bbbgmail.com', 'admin');
|
||||||
expect(result).toEqualLeft({
|
expect(result).toEqualLeft({
|
||||||
message: INVALID_EMAIL,
|
message: INVALID_EMAIL,
|
||||||
statusCode: HttpStatus.BAD_REQUEST,
|
statusCode: HttpStatus.BAD_REQUEST,
|
||||||
@@ -94,6 +94,7 @@ describe('signInMagicLink', () => {
|
|||||||
|
|
||||||
const result = await authService.signInMagicLink(
|
const result = await authService.signInMagicLink(
|
||||||
'dwight@dundermifflin.com',
|
'dwight@dundermifflin.com',
|
||||||
|
'admin',
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight({
|
expect(result).toEqualRight({
|
||||||
deviceIdentifier: passwordlessData.deviceIdentifier,
|
deviceIdentifier: passwordlessData.deviceIdentifier,
|
||||||
@@ -108,6 +109,7 @@ describe('signInMagicLink', () => {
|
|||||||
|
|
||||||
const result = await authService.signInMagicLink(
|
const result = await authService.signInMagicLink(
|
||||||
'dwight@dundermifflin.com',
|
'dwight@dundermifflin.com',
|
||||||
|
'admin',
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight({
|
expect(result).toEqualRight({
|
||||||
deviceIdentifier: passwordlessData.deviceIdentifier,
|
deviceIdentifier: passwordlessData.deviceIdentifier,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { JwtService } from '@nestjs/jwt';
|
|||||||
import { AuthError } from 'src/types/AuthError';
|
import { AuthError } from 'src/types/AuthError';
|
||||||
import { AuthUser, IsAdmin } from 'src/types/AuthUser';
|
import { AuthUser, IsAdmin } from 'src/types/AuthUser';
|
||||||
import { VerificationToken } from '@prisma/client';
|
import { VerificationToken } from '@prisma/client';
|
||||||
|
import { Origin } from './helper';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
@@ -195,7 +196,7 @@ export class AuthService {
|
|||||||
* @param email User's email
|
* @param email User's email
|
||||||
* @returns Either containing DeviceIdentifierToken
|
* @returns Either containing DeviceIdentifierToken
|
||||||
*/
|
*/
|
||||||
async signInMagicLink(email: string) {
|
async signInMagicLink(email: string, origin: string) {
|
||||||
if (!validateEmail(email))
|
if (!validateEmail(email))
|
||||||
return E.left({
|
return E.left({
|
||||||
message: INVALID_EMAIL,
|
message: INVALID_EMAIL,
|
||||||
@@ -213,11 +214,25 @@ export class AuthService {
|
|||||||
|
|
||||||
const generatedTokens = await this.generateMagicLinkTokens(user);
|
const generatedTokens = await this.generateMagicLinkTokens(user);
|
||||||
|
|
||||||
|
// check to see if origin is valid
|
||||||
|
let url: string;
|
||||||
|
switch (origin) {
|
||||||
|
case Origin.ADMIN:
|
||||||
|
url = process.env.VITE_ADMIN_URL;
|
||||||
|
break;
|
||||||
|
case Origin.APP:
|
||||||
|
url = process.env.VITE_BASE_URL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// if origin is invalid by default set URL to Hoppscotch-App
|
||||||
|
url = process.env.VITE_BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
await this.mailerService.sendAuthEmail(email, {
|
await this.mailerService.sendAuthEmail(email, {
|
||||||
template: 'code-your-own',
|
template: 'code-your-own',
|
||||||
variables: {
|
variables: {
|
||||||
inviteeEmail: email,
|
inviteeEmail: email,
|
||||||
magicLink: `${process.env.VITE_BASE_URL}/magic-link?token=${generatedTokens.token}`,
|
magicLink: `${url}/magic-link?token=${generatedTokens.token}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ enum AuthTokenType {
|
|||||||
REFRESH_TOKEN = 'refresh_token',
|
REFRESH_TOKEN = 'refresh_token',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Origin {
|
||||||
|
ADMIN = 'admin',
|
||||||
|
APP = 'app',
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function allows throw to be used as an expression
|
* This function allows throw to be used as an expression
|
||||||
* @param errMessage Message present in the error message
|
* @param errMessage Message present in the error message
|
||||||
|
|||||||
Reference in New Issue
Block a user