Skip to content

Commit

Permalink
fix: partner and public matching (#4090)
Browse files Browse the repository at this point in the history
* fix: partner and public matching

* fix: improved test coverage

* fix: consistent text labeling

* fix: unit testing
  • Loading branch information
ColinBuyck authored May 23, 2024
1 parent 1f96fbb commit 0efab7a
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 3 deletions.
11 changes: 11 additions & 0 deletions api/src/services/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,17 @@ export class UserService {
UserViews.full,
);

const isPartnerPortalUser =
storedUser.userRoles?.isAdmin ||
storedUser.userRoles?.isJurisdictionalAdmin ||
storedUser.userRoles?.isPartner;
const isUserSiteMatch =
(isPartnerPortalUser && dto.appUrl === process.env.PARTNERS_PORTAL_URL) ||
(!isPartnerPortalUser &&
dto.appUrl === storedUser.jurisdictions?.[0]?.publicUrl);
// user on wrong site, return neutral message and don't send email
if (!isUserSiteMatch) return { success: true };

const payload = {
id: storedUser.id,
exp: Number.parseInt(dayjs().add(1, 'hour').format('X')),
Expand Down
108 changes: 106 additions & 2 deletions api/test/integration/user.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,13 @@ describe('User Controller Tests', () => {
expect(userPostResend.hitConfirmationUrl).toBeNull();
});

it('should set resetToken when forgot-password is called', async () => {
it('should set resetToken when forgot-password is called by public user on the public site', async () => {
const juris = await prisma.jurisdictions.create({
data: jurisdictionFactory(),
});

const userA = await prisma.userAccounts.create({
data: await userFactory(),
data: await userFactory({ jurisdictionIds: [juris.id] }),
});

const mockforgotPassword = jest.spyOn(testEmailService, 'forgotPassword');
Expand All @@ -544,6 +548,7 @@ describe('User Controller Tests', () => {
.set({ passkey: process.env.API_PASS_KEY || '' })
.send({
email: userA.email,
appUrl: juris.publicUrl,
} as EmailAndAppUrl)
.expect(200);

Expand All @@ -559,6 +564,105 @@ describe('User Controller Tests', () => {
expect(mockforgotPassword.mock.calls.length).toBe(1);
});

it('should not set resetToken when forgot-password is called by public user on the partners site', async () => {
const juris = await prisma.jurisdictions.create({
data: jurisdictionFactory(),
});

const userA = await prisma.userAccounts.create({
data: await userFactory({ jurisdictionIds: [juris.id] }),
});

const mockforgotPassword = jest.spyOn(testEmailService, 'forgotPassword');
const res = await request(app.getHttpServer())
.put(`/user/forgot-password/`)
.set({ passkey: process.env.API_PASS_KEY || '' })
.send({
email: userA.email,
appUrl: process.env.PARTNERS_PORTAL_URL,
} as EmailAndAppUrl)
.expect(200);

expect(res.body.success).toBe(true);

const userPostResend = await prisma.userAccounts.findUnique({
where: {
id: userA.id,
},
});

expect(userPostResend.resetToken).toBeNull();
expect(mockforgotPassword.mock.calls.length).toBe(0);
});

it('should set resetToken when forgot-password is called by partner user on the partners site', async () => {
const juris = await prisma.jurisdictions.create({
data: jurisdictionFactory(),
});

const userA = await prisma.userAccounts.create({
data: await userFactory({
roles: { isAdmin: true },
jurisdictionIds: [juris.id],
}),
});

const mockforgotPassword = jest.spyOn(testEmailService, 'forgotPassword');
const res = await request(app.getHttpServer())
.put(`/user/forgot-password/`)
.set({ passkey: process.env.API_PASS_KEY || '' })
.send({
email: userA.email,
appUrl: process.env.PARTNERS_PORTAL_URL,
} as EmailAndAppUrl)
.expect(200);

expect(res.body.success).toBe(true);

const userPostResend = await prisma.userAccounts.findUnique({
where: {
id: userA.id,
},
});

expect(userPostResend.resetToken).not.toBeNull();
expect(mockforgotPassword.mock.calls.length).toBe(1);
});

it('should not set resetToken when forgot-password is called by partner user on the public site', async () => {
const juris = await prisma.jurisdictions.create({
data: jurisdictionFactory(),
});

const userA = await prisma.userAccounts.create({
data: await userFactory({
roles: { isAdmin: true },
jurisdictionIds: [juris.id],
}),
});

const mockforgotPassword = jest.spyOn(testEmailService, 'forgotPassword');
const res = await request(app.getHttpServer())
.put(`/user/forgot-password/`)
.set({ passkey: process.env.API_PASS_KEY || '' })
.send({
email: userA.email,
appUrl: juris.publicUrl,
} as EmailAndAppUrl)
.expect(200);

expect(res.body.success).toBe(true);

const userPostResend = await prisma.userAccounts.findUnique({
where: {
id: userA.id,
},
});

expect(userPostResend.resetToken).toBeNull();
expect(mockforgotPassword.mock.calls.length).toBe(0);
});

it('should create public user', async () => {
const juris = await prisma.jurisdictions.create({
data: jurisdictionFactory(),
Expand Down
106 changes: 105 additions & 1 deletion api/test/unit/services/user.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -664,12 +664,13 @@ describe('Testing user service', () => {
});

describe('forgotPassword', () => {
it('should set resetToken', async () => {
it('should set resetToken when public user on public site', async () => {
const id = randomUUID();
const email = '[email protected]';

prisma.userAccounts.findUnique = jest.fn().mockResolvedValue({
id,
jurisdictions: [{ publicUrl: 'http://localhost:3000' }],
});
prisma.userAccounts.update = jest.fn().mockResolvedValue({
id,
Expand Down Expand Up @@ -699,6 +700,109 @@ describe('Testing user service', () => {
});
});

it('should not set resetToken when public user on partner site', async () => {
const id = randomUUID();
const email = '[email protected]';

prisma.userAccounts.findUnique = jest.fn().mockResolvedValue({
id,
jurisdictions: [{ publicUrl: 'http://localhost:3000' }],
});
prisma.userAccounts.update = jest.fn().mockResolvedValue({
id,
resetToken: 'example reset token',
});
emailService.forgotPassword = jest.fn();

await service.forgotPassword({
email,
appUrl: process.env.PARTNERS_PORTAL_URL,
});
expect(prisma.userAccounts.findUnique).toHaveBeenCalledWith({
include: {
jurisdictions: true,
listings: true,
userRoles: true,
},
where: {
email,
id: undefined,
},
});
expect(prisma.userAccounts.update).not.toHaveBeenCalled();
});

it('should set resetToken when partner user on partner site', async () => {
const id = randomUUID();
const email = '[email protected]';

prisma.userAccounts.findUnique = jest.fn().mockResolvedValue({
id,
userRoles: { isAdmin: true },
});
prisma.userAccounts.update = jest.fn().mockResolvedValue({
id,
resetToken: 'example reset token',
});
emailService.forgotPassword = jest.fn();

await service.forgotPassword({
email,
appUrl: process.env.PARTNERS_PORTAL_URL,
});
expect(prisma.userAccounts.findUnique).toHaveBeenCalledWith({
include: {
jurisdictions: true,
listings: true,
userRoles: true,
},
where: {
email,
id: undefined,
},
});
expect(prisma.userAccounts.update).toHaveBeenCalledWith({
data: {
resetToken: expect.anything(),
},
where: {
id,
},
});
});

it('should not set resetToken when partner user on public site', async () => {
const id = randomUUID();
const email = '[email protected]';

prisma.userAccounts.findUnique = jest.fn().mockResolvedValue({
id,
userRoles: { isAdmin: true },
});
prisma.userAccounts.update = jest.fn().mockResolvedValue({
id,
resetToken: 'example reset token',
});
emailService.forgotPassword = jest.fn();

await service.forgotPassword({
email,
appUrl: 'http://localhost:3000',
});
expect(prisma.userAccounts.findUnique).toHaveBeenCalledWith({
include: {
jurisdictions: true,
listings: true,
userRoles: true,
},
where: {
email,
id: undefined,
},
});
expect(prisma.userAccounts.update).not.toHaveBeenCalled();
});

it('should error when trying to set resetToken on nonexistent user', async () => {
const email = '[email protected]';

Expand Down

0 comments on commit 0efab7a

Please sign in to comment.