diff --git a/src/resolvers/MembershipRequest/user.ts b/src/resolvers/MembershipRequest/user.ts index f8de5dedab..09206dd638 100644 --- a/src/resolvers/MembershipRequest/user.ts +++ b/src/resolvers/MembershipRequest/user.ts @@ -22,18 +22,14 @@ export const user: MembershipRequestResolvers["user"] = async (parent) => { }).lean(); if (!result) { - throw new errors.NotFoundError("User not found"); - } - const { decrypted } = decryptEmail(result.email); - result.email = decrypted; - - if (result) { - return result; - } else { throw new errors.NotFoundError( requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), USER_NOT_FOUND_ERROR.CODE, USER_NOT_FOUND_ERROR.PARAM, ); } + const { decrypted } = decryptEmail(result.email); + result.email = decrypted; + + return result; }; diff --git a/src/resolvers/Mutation/updateUserProfile.ts b/src/resolvers/Mutation/updateUserProfile.ts index 5f15712a36..43915c8b01 100644 --- a/src/resolvers/Mutation/updateUserProfile.ts +++ b/src/resolvers/Mutation/updateUserProfile.ts @@ -10,6 +10,7 @@ import { deleteUserFromCache } from "../../services/UserCache/deleteUserFromCach import { findUserInCache } from "../../services/UserCache/findUserInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; import { uploadEncodedImage } from "../../utilities/encodedImageStorage/uploadEncodedImage"; +import { decryptEmail } from "../../utilities/encryption"; import { hashEmail } from "../../utilities/hashEmail"; /** * This function enables to update user profile. @@ -45,7 +46,9 @@ export const updateUserProfile: MutationResolvers["updateUserProfile"] = async ( ); } - const hashedEmail = hashEmail(args.data?.email); + const decryptedEmail = decryptEmail(currentUser.email).decrypted; + + const hashedEmail = hashEmail(decryptedEmail); if (args.data?.email && args.data?.email !== currentUser?.email) { const userWithEmailExists = await User.findOne({ diff --git a/src/resolvers/Query/checkAuth.ts b/src/resolvers/Query/checkAuth.ts index 51fa722bf2..1456df814b 100644 --- a/src/resolvers/Query/checkAuth.ts +++ b/src/resolvers/Query/checkAuth.ts @@ -38,7 +38,7 @@ export const checkAuth: QueryResolvers["checkAuth"] = async ( ); } - const { decrypted } = decryptEmail(currentUser.email); + const decrypted = decryptEmail(currentUser.email).decrypted.toLowerCase(); return { ...currentUser, diff --git a/tests/resolvers/Mutation/forgotPassword.spec.ts b/tests/resolvers/Mutation/forgotPassword.spec.ts index 415c47f9ee..efc95066e4 100644 --- a/tests/resolvers/Mutation/forgotPassword.spec.ts +++ b/tests/resolvers/Mutation/forgotPassword.spec.ts @@ -15,6 +15,7 @@ import type { MutationForgotPasswordArgs } from "../../../src/types/generatedGra import { connect, disconnect } from "../../helpers/db"; import { createTestUserFunc } from "../../helpers/user"; import type { TestUserType } from "../../helpers/userAndOrg"; +import { decryptEmail } from "../../../src/utilities/encryption"; let testUser: TestUserType; let MONGOOSE_INSTANCE: typeof mongoose; @@ -164,9 +165,15 @@ describe("resolvers -> Mutation -> forgotPassword", () => { const hashedOtp = await bcrypt.hash(otp, 1); + let email = ""; + + if (testUser?.email) { + email = decryptEmail(testUser.email).decrypted; + } + const otpToken = jwt.sign( { - email: testUser?.email ?? "", + email, otp: hashedOtp, }, ACCESS_TOKEN_SECRET as string, diff --git a/tests/resolvers/Mutation/login.spec.ts b/tests/resolvers/Mutation/login.spec.ts index 0f376197c0..3c00b6fdb3 100644 --- a/tests/resolvers/Mutation/login.spec.ts +++ b/tests/resolvers/Mutation/login.spec.ts @@ -111,7 +111,7 @@ describe("resolvers -> Mutation -> login", () => { // Prepare the arguments for the login resolver const args: MutationLoginArgs = { data: { - email: newUser.email, + email: email, password: "password", }, }; @@ -161,7 +161,7 @@ describe("resolvers -> Mutation -> login", () => { const args: MutationLoginArgs = { data: { - email: newUser?.email, + email: email, password: "password", }, }; @@ -239,7 +239,7 @@ describe("resolvers -> Mutation -> login", () => { ); const args: MutationLoginArgs = { data: { - email: newUser?.email, + email: email, password: "password", }, }; diff --git a/tests/resolvers/Mutation/otp.spec.ts b/tests/resolvers/Mutation/otp.spec.ts index e39fdb8c48..5392902b49 100644 --- a/tests/resolvers/Mutation/otp.spec.ts +++ b/tests/resolvers/Mutation/otp.spec.ts @@ -9,6 +9,7 @@ import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; import { mailer } from "../../../src/utilities"; import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; import { nanoid } from "nanoid"; +import { decryptEmail } from "../../../src/utilities/encryption"; let testUser: TestUserType; let MONGOOSE_INSTANCE: typeof mongoose; @@ -37,9 +38,13 @@ describe("resolvers -> Mutation -> otp", () => { } }); it("should generate and send OTP to the user", async () => { + let email = ""; + if (testUser?.email) { + email = decryptEmail(testUser.email).decrypted; + } const args: MutationOtpArgs = { data: { - email: testUser?.email, + email: email, }, }; vi.mock("../../../src/utilities", () => ({ diff --git a/tests/resolvers/Mutation/signUp.spec.ts b/tests/resolvers/Mutation/signUp.spec.ts index c3302b1006..f6dc03ede4 100644 --- a/tests/resolvers/Mutation/signUp.spec.ts +++ b/tests/resolvers/Mutation/signUp.spec.ts @@ -27,6 +27,7 @@ import type { import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; import _ from "lodash"; import { hashEmail } from "../../../src/utilities/hashEmail"; +import { decryptEmail } from "../../../src/utilities/encryption"; const testImagePath = `${nanoid().toLowerCase()}test.png`; let MONGOOSE_INSTANCE: typeof mongoose; let testUser: TestUserType; @@ -99,7 +100,7 @@ describe("resolvers -> Mutation -> signUp", () => { .populate("adminFor") .lean(); - expect(_.isEqual(signUpPayload?.user, createdUser)).toBe(true); + expect(_.isEqual(signUpPayload?.user, createdUser?.toObject())).toBe(true); expect( _.isEqual(signUpPayload?.appUserProfile, createdUserAppProfile), ).toBe(true); @@ -206,6 +207,10 @@ describe("resolvers -> Mutation -> signUp", () => { }); it(`throws ConflictError message if a user already with email === args.data.email already exists`, async () => { + let email = ""; + if (testUser?.email) { + email = decryptEmail(testUser.email).decrypted; + } const EMAIL_MESSAGE = "email.alreadyExists"; const { requestContext } = await import("../../../src/libraries"); const spy = vi @@ -214,7 +219,7 @@ describe("resolvers -> Mutation -> signUp", () => { try { const args: MutationSignUpArgs = { data: { - email: testUser?.email, + email: email, firstName: "firstName", lastName: "lastName", password: "password", diff --git a/tests/resolvers/Mutation/updateCommunity.spec.ts b/tests/resolvers/Mutation/updateCommunity.spec.ts index 1af5df7d54..3c885c66ba 100644 --- a/tests/resolvers/Mutation/updateCommunity.spec.ts +++ b/tests/resolvers/Mutation/updateCommunity.spec.ts @@ -23,6 +23,8 @@ import { import { createTestUserFunc, type TestUserType } from "../../helpers/user"; import { AppUserProfile, User } from "../../../src/models"; import { nanoid } from "nanoid"; +import { hashEmail } from "../../../src/utilities/hashEmail"; +import { encryptEmail } from "../../../src/utilities/encryption"; let MONGOOSE_INSTANCE: typeof mongoose; let testUser1: TestUserType; @@ -102,9 +104,13 @@ describe("resolvers -> Mutation -> updateCommunity", () => { .spyOn(requestContext, "translate") .mockImplementation((message) => `Translated ${message}`); + const email = `email${nanoid().toLowerCase()}@gmail.com`; + const hashedEmail = hashEmail(email); + try { const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, + email: encryptEmail(email), + hashedEmail: hashedEmail, password: `pass${nanoid().toLowerCase()}`, firstName: `firstName${nanoid().toLowerCase()}`, lastName: `lastName${nanoid().toLowerCase()}`, diff --git a/tests/resolvers/Mutation/updateUserProfile.spec.ts b/tests/resolvers/Mutation/updateUserProfile.spec.ts index a254998cee..96b05c2d01 100644 --- a/tests/resolvers/Mutation/updateUserProfile.spec.ts +++ b/tests/resolvers/Mutation/updateUserProfile.spec.ts @@ -25,7 +25,7 @@ import { } from "../../../src/constants"; import { updateUserProfile as updateUserProfileResolver } from "../../../src/resolvers/Mutation/updateUserProfile"; import * as uploadEncodedImage from "../../../src/utilities/encodedImageStorage/uploadEncodedImage"; -import { encryptEmail } from "../../../src/utilities/encryption"; +import { decryptEmail, encryptEmail } from "../../../src/utilities/encryption"; import { hashEmail } from "../../../src/utilities/hashEmail"; let MONGOOSE_INSTANCE: typeof mongoose; @@ -44,7 +44,6 @@ beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); const firstEmail = `email${nanoid().toLowerCase()}@gmail.com`; - const hashedFirstEmail = hashEmail(firstEmail); testUser = (await User.create({ @@ -170,10 +169,12 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => `Translated ${message}`); + const email = decryptEmail(testUser2.email).decrypted; + try { const args: MutationUpdateUserProfileArgs = { data: { - email: testUser2.email, + email: email, }, }; @@ -201,7 +202,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { it(`updates if email not changed by user`, async () => { const args: MutationUpdateUserProfileArgs = { data: { - email: testUser.email, + email: decryptEmail(testUser.email).decrypted, }, }; @@ -252,6 +253,8 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { }); it(`updates current user's user object when any single argument(firstName) is given w/0 changing other fields `, async () => { + const testUserobj = await User.findById({ _id: testUser.id }); + const args: MutationUpdateUserProfileArgs = { data: { firstName: "newFirstName", @@ -268,8 +271,6 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { context, ); - const testUserobj = await User.findById({ _id: testUser.id }); - expect(updateUserProfilePayload).toEqual({ ...testUser.toObject(), email: testUserobj?.email, diff --git a/tests/resolvers/Query/me.spec.ts b/tests/resolvers/Query/me.spec.ts index 9739eb18e5..edc474a38b 100644 --- a/tests/resolvers/Query/me.spec.ts +++ b/tests/resolvers/Query/me.spec.ts @@ -66,7 +66,7 @@ describe("resolvers -> Query -> me", () => { const currentUser = mePayload.user as InterfaceUser; currentUser.email = decryptEmail(user.email).decrypted; - expect(mePayload?.user).toEqual(user); + expect(mePayload?.user).toEqual(currentUser); }); it("throws an error if user does not have appUserProfile", async () => { diff --git a/tests/resolvers/Query/organizationsMemberConnection.spec.ts b/tests/resolvers/Query/organizationsMemberConnection.spec.ts index cfa8398fab..1176cbc910 100644 --- a/tests/resolvers/Query/organizationsMemberConnection.spec.ts +++ b/tests/resolvers/Query/organizationsMemberConnection.spec.ts @@ -12,6 +12,7 @@ import { nanoid } from "nanoid"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { BASE_URL } from "../../../src/constants"; import { decryptEmail, encryptEmail } from "../../../src/utilities/encryption"; +import { hashEmail } from "../../../src/utilities/hashEmail"; let MONGOOSE_INSTANCE: typeof mongoose; let testUsers: (InterfaceUser & Document)[]; @@ -20,10 +21,14 @@ let testOrganization: InterfaceOrganization & beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); + const email1 = `email${nanoid().toLowerCase()}@gmail.com`; + const email2 = `email${nanoid().toLowerCase()}@gmail.com`; + const email3 = `email${nanoid().toLowerCase()}@gmail.com`; testUsers = await User.insertMany([ { - email: encryptEmail(`email${nanoid().toLowerCase()}@gmail.com`), + email: encryptEmail(email1), + hashedEmail: hashEmail(email1), password: "password", firstName: `1firstName${nanoid()}`, lastName: `lastName${nanoid()}`, @@ -39,7 +44,8 @@ beforeAll(async () => { }, }, { - email: encryptEmail(`email${nanoid().toLowerCase()}@gmail.com`), + email: encryptEmail(email2), + hashedEmail: hashEmail(email2), password: "password", firstName: `2firstName${nanoid()}`, lastName: `lastName${nanoid()}`, @@ -55,7 +61,8 @@ beforeAll(async () => { }, }, { - email: encryptEmail(`email${nanoid().toLowerCase()}@gmail.com`), + email: encryptEmail(email3), + hashedEmail: hashEmail(email3), password: "password", firstName: `3firstName${nanoid()}`, lastName: `lastName${nanoid()}`, @@ -234,6 +241,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -327,6 +336,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -419,6 +430,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -514,6 +527,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -609,6 +624,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -692,6 +709,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -874,6 +893,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -946,6 +967,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -1047,6 +1070,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, @@ -1129,6 +1154,8 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { createdAt: user.createdAt, educationGrade: user.educationGrade, email: decryptEmail(user.email).decrypted, + hashedEmail: user.hashedEmail, + identifier: user.identifier, employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, diff --git a/tests/resolvers/Query/users.spec.ts b/tests/resolvers/Query/users.spec.ts index f99d285339..3725243f37 100644 --- a/tests/resolvers/Query/users.spec.ts +++ b/tests/resolvers/Query/users.spec.ts @@ -19,6 +19,7 @@ let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); + import("../../../src/models/FundraisingCampaignPledge"); }); afterAll(async () => {