Skip to content

Commit

Permalink
Merge pull request #2107 from Northeastern-Electric-Racing/#2009-desi…
Browse files Browse the repository at this point in the history
…gn-review-calendar-get-user-schedule-settings-endpoint

#2009 added get user schedule settings endpoint
  • Loading branch information
walker-sean authored Feb 25, 2024
2 parents 7f1ef95 + de5fc0e commit 069af8b
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 5 deletions.
11 changes: 11 additions & 0 deletions src/backend/src/controllers/users.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,15 @@ export default class UsersController {
next(error);
}
}

static async getUserScheduleSettings(req: Request, res: Response, next: NextFunction) {
try {
const userId: number = parseInt(req.params.userId);
const submitter = await getCurrentUser(res);
const userScheduleSettings = await UsersService.getUserScheduleSettings(userId, submitter);
res.status(200).json(userScheduleSettings);
} catch (error: unknown) {
next(error);
}
}
}
2 changes: 1 addition & 1 deletion src/backend/src/routes/users.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ userRouter.post(
UsersController.setUserSecureSettings
);
userRouter.get('/:userId/secure-settings', UsersController.getUserSecureSettings);

userRouter.get('/:userId/schedule-settings', UsersController.getUserScheduleSettings);
export default userRouter;
21 changes: 20 additions & 1 deletion src/backend/src/services/users.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
Project,
RoleEnum,
isHead,
UserSecureSettings
UserSecureSettings,
UserScheduleSettings
} from 'shared';
import authUserQueryArgs from '../prisma-query-args/auth-user.query-args';
import prisma from '../prisma/prisma';
Expand All @@ -21,6 +22,7 @@ import projectTransformer from '../transformers/projects.transformer';
import projectQueryArgs from '../prisma-query-args/projects.query-args';
import userSecureSettingsTransformer from '../transformers/user-secure-settings.transformer';
import { validateUserIsPartOfFinanceTeam } from '../utils/reimbursement-requests.utils';
import userScheduleSettingsTransformer from '../transformers/user-schedule-settings.transformer';

export default class UsersService {
/**
Expand Down Expand Up @@ -320,4 +322,21 @@ export default class UsersService {

return newUserSecureSettings.userSecureSettingsId;
}

/**
* Gets a user's schedule settings
* @param userId the id of the user who's schedule settings are being returned
* @param submitter the user who's requesting the schedule settings
* @returns the user's schedule settings
* @throws if the user doesn't have schedule settings
*/
static async getUserScheduleSettings(userId: number, submitter: PrismaUser): Promise<UserScheduleSettings> {
if (submitter.userId !== userId) throw new AccessDeniedException('You can only access your own schedule settings');
const scheduleSettings = await prisma.schedule_Settings.findUnique({
where: { userId }
});
if (!scheduleSettings) throw new HttpException(404, 'User Schedule Settings Not Found');

return userScheduleSettingsTransformer(scheduleSettings);
}
}
13 changes: 13 additions & 0 deletions src/backend/src/transformers/user-schedule-settings.transformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Prisma } from '@prisma/client';
import { UserScheduleSettings } from 'shared';

const userScheduleSettingsTransformer = (settings: Prisma.Schedule_SettingsGetPayload<null>): UserScheduleSettings => {
return {
drScheduleSettingsId: settings.drScheduleSettingsId,
personalGmail: settings.personalGmail,
personalZoomLink: settings.personalZoomLink,
availability: settings.availability
};
};

export default userScheduleSettingsTransformer;
34 changes: 32 additions & 2 deletions src/backend/tests/test-data/users.test-data.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Role as PrismaRole, Theme, User as PrismaUser, User_Settings, User_Secure_Settings, Team } from '@prisma/client';
import { User as SharedUser } from 'shared';
import {
Role as PrismaRole,
Theme,
User as PrismaUser,
User_Settings,
User_Secure_Settings,
Team,
Schedule_Settings
} from '@prisma/client';
import { User as SharedUser, UserScheduleSettings } from 'shared';

export const batman: PrismaUser = {
userId: 1,
Expand Down Expand Up @@ -132,3 +140,25 @@ export const supermanWithUserSettings: PrismaUser & { userSettings: User_Setting
...supermanSettings
}
};

export const batmanScheduleSettings: Schedule_Settings = {
drScheduleSettingsId: 'bmschedule',
personalGmail: '[email protected]',
personalZoomLink: 'https://zoom.us/j/gotham',
availability: [],
userId: 69
};

export const batmanWithScheduleSettings: PrismaUser & { scheduleSettings: Schedule_Settings } = {
...batman,
scheduleSettings: {
...batmanScheduleSettings
}
};

export const batmanUserScheduleSettings: UserScheduleSettings = {
drScheduleSettingsId: 'bmschedule',
personalGmail: '[email protected]',
personalZoomLink: 'https://zoom.us/j/gotham',
availability: []
};
32 changes: 31 additions & 1 deletion src/backend/tests/users.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
superman,
batmanSecureSettings,
sharedBatman,
theVisitor
theVisitor,
batmanWithScheduleSettings,
batmanScheduleSettings,
batmanUserScheduleSettings
} from './test-data/users.test-data';
import { Role } from '@prisma/client';
import UsersService from '../src/services/users.services';
Expand Down Expand Up @@ -138,4 +141,31 @@ describe('Users', () => {
).rejects.toThrow(new HttpException(400, 'Phone number already in use'));
});
});

describe('getUserScheduleSettings', () => {
test('getUserScheduleSettings for user with no settings', async () => {
vi.spyOn(prisma.user, 'findUnique').mockResolvedValue(batman);
vi.spyOn(prisma.schedule_Settings, 'findUnique').mockResolvedValue(null);
await expect(() => UsersService.getUserScheduleSettings(batman.userId, batman)).rejects.toThrow(
new HttpException(404, 'User Schedule Settings Not Found')
);
});

test('non-valid user tries to get someone elses settings', async () => {
vi.spyOn(prisma.user, 'findUnique').mockResolvedValue(batmanWithScheduleSettings);
vi.spyOn(prisma.schedule_Settings, 'findUnique').mockResolvedValue(batmanScheduleSettings);
await expect(() => UsersService.getUserScheduleSettings(superman.userId, batmanWithScheduleSettings)).rejects.toThrow(
new AccessDeniedException('You can only access your own schedule settings')
);
});

test('getUserScheduleSettings works successfully', async () => {
vi.spyOn(prisma.user, 'findUnique').mockResolvedValue(batmanWithScheduleSettings);
vi.spyOn(prisma.schedule_Settings, 'findUnique').mockResolvedValue(batmanScheduleSettings);
const res = await UsersService.getUserScheduleSettings(batmanWithScheduleSettings.userId, batmanWithScheduleSettings);

expect(prisma.schedule_Settings.findUnique).toHaveBeenCalledTimes(1);
expect(res).toStrictEqual(batmanUserScheduleSettings);
});
});
});
7 changes: 7 additions & 0 deletions src/shared/src/types/user-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,10 @@ export interface UpdateUserRolePayload {
userId: number;
role: string;
}

export interface UserScheduleSettings {
drScheduleSettingsId: string;
personalGmail: string;
personalZoomLink: string;
availability: number[];
}

0 comments on commit 069af8b

Please sign in to comment.