test: refactored all test cases with new user type change
This commit is contained in:
@@ -10,8 +10,8 @@ import {
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { signInMagicDto } from './dto/signin-magic.dto';
|
||||
import { verifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { SignInMagicDto } from './dto/signin-magic.dto';
|
||||
import { VerifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { Response } from 'express';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { authCookieHandler, throwHTTPErr } from 'src/utils';
|
||||
@@ -29,7 +29,7 @@ export class AuthController {
|
||||
** Route to initiate magic-link auth for a users email
|
||||
*/
|
||||
@Post('signin')
|
||||
async signInMagicLink(@Body() authData: signInMagicDto) {
|
||||
async signInMagicLink(@Body() authData: SignInMagicDto) {
|
||||
const deviceIdToken = await this.authService.signInMagicLink(
|
||||
authData.email,
|
||||
);
|
||||
@@ -41,7 +41,7 @@ export class AuthController {
|
||||
** Route to verify and sign in a valid user via magic-link
|
||||
*/
|
||||
@Post('verify')
|
||||
async verify(@Body() data: verifyMagicDto, @Res() res: Response) {
|
||||
async verify(@Body() data: VerifyMagicDto, @Res() res: Response) {
|
||||
const authTokens = await this.authService.verifyMagicLinkTokens(data);
|
||||
if (E.isLeft(authTokens)) throwHTTPErr(authTokens.left);
|
||||
authCookieHandler(res, authTokens.right, false);
|
||||
|
||||
@@ -16,9 +16,10 @@ import { AuthUser } from 'src/types/AuthUser';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { AuthService } from './auth.service';
|
||||
import * as O from 'fp-ts/Option';
|
||||
import { verifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { VerifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { DateTime } from 'luxon';
|
||||
import * as argon2 from 'argon2';
|
||||
import * as E from 'fp-ts/Either';
|
||||
|
||||
const mockPrisma = mockDeep<PrismaService>();
|
||||
const mockUser = mockDeep<UserService>();
|
||||
@@ -50,7 +51,7 @@ const passwordlessData: VerificationToken = {
|
||||
expiresOn: new Date(),
|
||||
};
|
||||
|
||||
const magicLinkVerify: verifyMagicDto = {
|
||||
const magicLinkVerify: VerifyMagicDto = {
|
||||
deviceIdentifier: 'Dscdc',
|
||||
token: 'SDcsdc',
|
||||
};
|
||||
@@ -154,7 +155,8 @@ describe('verifyMagicLinkTokens', () => {
|
||||
// mockPrisma.account.findUnique.mockResolvedValueOnce(null);
|
||||
// generateAuthTokens
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockResolvedValueOnce(user);
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(E.right(user));
|
||||
// deletePasswordlessVerificationToken
|
||||
mockPrisma.verificationToken.delete.mockResolvedValueOnce(passwordlessData);
|
||||
|
||||
@@ -178,7 +180,8 @@ describe('verifyMagicLinkTokens', () => {
|
||||
mockUser.createUserSSO.mockResolvedValueOnce(user);
|
||||
// generateAuthTokens
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockResolvedValueOnce(user);
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(E.right(user));
|
||||
// deletePasswordlessVerificationToken
|
||||
mockPrisma.verificationToken.delete.mockResolvedValueOnce(passwordlessData);
|
||||
|
||||
@@ -219,7 +222,10 @@ describe('verifyMagicLinkTokens', () => {
|
||||
// mockPrisma.account.findUnique.mockResolvedValueOnce(null);
|
||||
// generateAuthTokens
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockRejectedValueOnce('RecordNotFound');
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(
|
||||
E.left(USER_NOT_FOUND),
|
||||
);
|
||||
|
||||
const result = await authService.verifyMagicLinkTokens(magicLinkVerify);
|
||||
expect(result).toEqualLeft({
|
||||
@@ -241,7 +247,8 @@ describe('verifyMagicLinkTokens', () => {
|
||||
// mockPrisma.account.findUnique.mockResolvedValueOnce(null);
|
||||
// generateAuthTokens
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockResolvedValueOnce(user);
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(E.right(user));
|
||||
// deletePasswordlessVerificationToken
|
||||
mockPrisma.verificationToken.delete.mockRejectedValueOnce('RecordNotFound');
|
||||
|
||||
@@ -256,7 +263,8 @@ describe('verifyMagicLinkTokens', () => {
|
||||
describe('generateAuthTokens', () => {
|
||||
test('should successfully generate tokens with valid inputs', async () => {
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockResolvedValueOnce(user);
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(E.right(user));
|
||||
|
||||
const result = await authService.generateAuthTokens(user.uid);
|
||||
expect(result).toEqualRight({
|
||||
@@ -267,7 +275,10 @@ describe('generateAuthTokens', () => {
|
||||
|
||||
test('should throw USER_NOT_FOUND when updating refresh tokens fails', async () => {
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockRejectedValueOnce('RecordNotFound');
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(
|
||||
E.left(USER_NOT_FOUND),
|
||||
);
|
||||
|
||||
const result = await authService.generateAuthTokens(user.uid);
|
||||
expect(result).toEqualLeft({
|
||||
@@ -291,7 +302,10 @@ describe('refreshAuthTokens', () => {
|
||||
test('should throw USER_NOT_FOUND when updating refresh tokens fails', async () => {
|
||||
// generateAuthTokens
|
||||
mockJWT.sign.mockReturnValue(user.refreshToken);
|
||||
mockPrisma.user.update.mockRejectedValueOnce('RecordNotFound');
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(
|
||||
E.left(USER_NOT_FOUND),
|
||||
);
|
||||
|
||||
const result = await authService.refreshAuthTokens(
|
||||
'$argon2id$v=19$m=65536,t=3,p=4$MvVOam2clCOLtJFGEE26ZA$czvA5ez9hz+A/LML8QRgqgaFuWa5JcbwkH6r+imTQbs',
|
||||
@@ -317,10 +331,13 @@ describe('refreshAuthTokens', () => {
|
||||
test('should successfully refresh the tokens and generate a new auth token pair', async () => {
|
||||
// generateAuthTokens
|
||||
mockJWT.sign.mockReturnValue('sdhjcbjsdhcbshjdcb');
|
||||
mockPrisma.user.update.mockResolvedValueOnce({
|
||||
...user,
|
||||
refreshToken: 'sdhjcbjsdhcbshjdcb',
|
||||
});
|
||||
// UpdateUserRefreshToken
|
||||
mockUser.UpdateUserRefreshToken.mockResolvedValueOnce(
|
||||
E.right({
|
||||
...user,
|
||||
refreshToken: 'sdhjcbjsdhcbshjdcb',
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await authService.refreshAuthTokens(
|
||||
'$argon2id$v=19$m=65536,t=3,p=4$MvVOam2clCOLtJFGEE26ZA$czvA5ez9hz+A/LML8QRgqgaFuWa5JcbwkH6r+imTQbs',
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 { VerifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { DateTime } from 'luxon';
|
||||
import * as argon2 from 'argon2';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
@@ -70,7 +70,7 @@ export class AuthService {
|
||||
* @param magicLinkTokens Object containing deviceIdentifier and token
|
||||
* @returns Option of VerificationToken token
|
||||
*/
|
||||
private async validatePasswordlessTokens(magicLinkTokens: verifyMagicDto) {
|
||||
private async validatePasswordlessTokens(magicLinkTokens: VerifyMagicDto) {
|
||||
try {
|
||||
const tokens =
|
||||
await this.prismaService.verificationToken.findUniqueOrThrow({
|
||||
@@ -234,7 +234,7 @@ export class AuthService {
|
||||
* @returns Either of generated AuthTokens
|
||||
*/
|
||||
async verifyMagicLinkTokens(
|
||||
magicLinkIDTokens: verifyMagicDto,
|
||||
magicLinkIDTokens: VerifyMagicDto,
|
||||
): Promise<E.Right<AuthTokens> | E.Left<AuthError>> {
|
||||
const passwordlessTokens = await this.validatePasswordlessTokens(
|
||||
magicLinkIDTokens,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { UserSettingsService } from './user-settings.service';
|
||||
import { JSON_INVALID, USER_SETTINGS_NULL_SETTINGS } from 'src/errors';
|
||||
import { UserSettings } from './user-settings.model';
|
||||
import { User } from 'src/user/user.model';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
|
||||
const mockPrisma = mockDeep<PrismaService>();
|
||||
const mockPubSub = mockDeep<PubSubService>();
|
||||
@@ -16,12 +17,20 @@ const userSettingsService = new UserSettingsService(
|
||||
mockPubSub as any,
|
||||
);
|
||||
|
||||
const user: User = {
|
||||
const currentTime = new Date();
|
||||
|
||||
const user: AuthUser = {
|
||||
uid: 'aabb22ccdd',
|
||||
displayName: 'user-display-name',
|
||||
email: 'user-email',
|
||||
photoURL: 'user-photo-url',
|
||||
isAdmin: false,
|
||||
refreshToken: 'hbfvdkhjbvkdvdfjvbnkhjb',
|
||||
currentGQLSession: {},
|
||||
currentRESTSession: {},
|
||||
createdOn: currentTime,
|
||||
};
|
||||
|
||||
const settings: UserSettings = {
|
||||
id: '1',
|
||||
userUid: user.uid,
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
USER_SETTINGS_NULL_SETTINGS,
|
||||
USER_SETTINGS_NOT_FOUND,
|
||||
} from 'src/errors';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
|
||||
@Injectable()
|
||||
export class UserSettingsService {
|
||||
@@ -46,7 +47,7 @@ export class UserSettingsService {
|
||||
* @param properties stringified user settings properties
|
||||
* @returns an Either of `UserSettings` or error
|
||||
*/
|
||||
async createUserSettings(user: User, properties: string) {
|
||||
async createUserSettings(user: AuthUser, properties: string) {
|
||||
if (!properties) return E.left(USER_SETTINGS_NULL_SETTINGS);
|
||||
|
||||
const jsonProperties = stringToJson(properties);
|
||||
@@ -80,7 +81,7 @@ export class UserSettingsService {
|
||||
* @param properties stringified user settings
|
||||
* @returns Promise of an Either of `UserSettings` or error
|
||||
*/
|
||||
async updateUserSettings(user: User, properties: string) {
|
||||
async updateUserSettings(user: AuthUser, properties: string) {
|
||||
if (!properties) return E.left(USER_SETTINGS_NULL_SETTINGS);
|
||||
|
||||
const jsonProperties = stringToJson(properties);
|
||||
|
||||
@@ -7,6 +7,7 @@ import { UserService } from './user.service';
|
||||
import { throwErr } from 'src/utils';
|
||||
import * as E from 'fp-ts/lib/Either';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
|
||||
@Resolver(() => User)
|
||||
export class UserResolver {
|
||||
@@ -31,7 +32,7 @@ export class UserResolver {
|
||||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async updateUserSessions(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args({
|
||||
name: 'currentSession',
|
||||
description: 'JSON string of the saved REST/GQL session',
|
||||
|
||||
@@ -21,8 +21,8 @@ const user: AuthUser = {
|
||||
displayName: 'Dwight Schrute',
|
||||
photoURL: 'https://en.wikipedia.org/wiki/Dwight_Schrute',
|
||||
isAdmin: false,
|
||||
currentRESTSession: JSON.stringify({}),
|
||||
currentGQLSession: JSON.stringify({}),
|
||||
currentRESTSession: {},
|
||||
currentGQLSession: {},
|
||||
refreshToken: 'hbfvdkhjbvkdvdfjvbnkhjb',
|
||||
createdOn: currentTime,
|
||||
};
|
||||
@@ -227,21 +227,22 @@ describe('createProviderAccount', () => {
|
||||
describe('updateUserSessions', () => {
|
||||
test('Should resolve right and update users GQL session', async () => {
|
||||
const sessionData = user.currentGQLSession;
|
||||
|
||||
mockPrisma.user.update.mockResolvedValue({
|
||||
...user,
|
||||
currentGQLSession: JSON.parse(sessionData),
|
||||
currentGQLSession: sessionData,
|
||||
currentRESTSession: null,
|
||||
});
|
||||
|
||||
const result = await userService.updateUserSessions(
|
||||
user,
|
||||
sessionData,
|
||||
JSON.stringify(sessionData),
|
||||
'GQL',
|
||||
);
|
||||
|
||||
expect(result).toEqualRight({
|
||||
...user,
|
||||
currentGQLSession: sessionData,
|
||||
currentGQLSession: JSON.stringify(sessionData),
|
||||
currentRESTSession: null,
|
||||
});
|
||||
});
|
||||
@@ -250,19 +251,19 @@ describe('updateUserSessions', () => {
|
||||
mockPrisma.user.update.mockResolvedValue({
|
||||
...user,
|
||||
currentGQLSession: null,
|
||||
currentRESTSession: JSON.parse(sessionData),
|
||||
currentRESTSession: sessionData,
|
||||
});
|
||||
|
||||
const result = await userService.updateUserSessions(
|
||||
user,
|
||||
sessionData,
|
||||
JSON.stringify(sessionData),
|
||||
'REST',
|
||||
);
|
||||
|
||||
expect(result).toEqualRight({
|
||||
...user,
|
||||
currentGQLSession: null,
|
||||
currentRESTSession: sessionData,
|
||||
currentRESTSession: JSON.stringify(sessionData),
|
||||
});
|
||||
});
|
||||
test('Should reject left and update user for invalid GQL session', async () => {
|
||||
@@ -291,16 +292,22 @@ describe('updateUserSessions', () => {
|
||||
test('Should publish pubsub message on user update sessions', async () => {
|
||||
mockPrisma.user.update.mockResolvedValue({
|
||||
...user,
|
||||
currentGQLSession: JSON.parse(user.currentGQLSession),
|
||||
currentRESTSession: JSON.parse(user.currentRESTSession),
|
||||
});
|
||||
|
||||
await userService.updateUserSessions(user, user.currentGQLSession, 'GQL');
|
||||
await userService.updateUserSessions(
|
||||
user,
|
||||
JSON.stringify(user.currentGQLSession),
|
||||
'GQL',
|
||||
);
|
||||
|
||||
expect(mockPubSub.publish).toHaveBeenCalledTimes(1);
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`user/${user.uid}/updated`,
|
||||
user,
|
||||
{
|
||||
...user,
|
||||
currentGQLSession: JSON.stringify(user.currentGQLSession),
|
||||
currentRESTSession: JSON.stringify(user.currentRESTSession),
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -199,7 +199,7 @@ export class UserService {
|
||||
* @returns a Either of User or error
|
||||
*/
|
||||
async updateUserSessions(
|
||||
user: User,
|
||||
user: AuthUser,
|
||||
currentSession: string,
|
||||
sessionType: string,
|
||||
): Promise<E.Right<User> | E.Left<string>> {
|
||||
|
||||
Reference in New Issue
Block a user