Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/backend/src/controllers/recruitment.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,17 @@ export default class RecruitmentController {
next(error);
}
}

static async createFaq(req: Request, res: Response, next: NextFunction) {
try {
const { question, answer } = req.body;
const submitter = await getCurrentUser(res);
const organizationId = getOrganizationId(req.headers);

const faq = await RecruitmentServices.createFaq(submitter, question, answer, organizationId);
res.status(200).json(faq);
} catch (error: unknown) {
next(error);
}
}
}
15 changes: 15 additions & 0 deletions src/backend/src/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { transformDate } from '../utils/datetime.utils';
import { writeFileSync } from 'fs';
import WorkPackageTemplatesService from '../services/work-package-template.services';
import OrganizationsService from '../services/organizations.service';
import RecruitmentServices from '../services/recruitment.services';

const prisma = new PrismaClient();

Expand Down Expand Up @@ -1957,6 +1958,20 @@ const performSeed: () => Promise<void> = async () => {
url: 'https://docs.google.com'
}
]);

await RecruitmentServices.createFaq(batman, 'Who is the Chief Software Engineer?', 'Peyton McKee', organizationId);
await RecruitmentServices.createFaq(
batman,
'When was FinishLine created?',
'FinishLine was created in 2019',
organizationId
);
await RecruitmentServices.createFaq(
batman,
'How many developers are working on FinishLine?',
'178 as of 2024',
organizationId
);
};

performSeed()
Expand Down
8 changes: 8 additions & 0 deletions src/backend/src/routes/recruitment.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ recruitmentRouter.post(
RecruitmentController.createMilestone
);

recruitmentRouter.post(
'/faq/create',
nonEmptyString(body('question')),
nonEmptyString(body('answer')),
validateInputs,
RecruitmentController.createFaq
);

recruitmentRouter.get('/milestones', RecruitmentController.getAllMilestones);

export default recruitmentRouter;
34 changes: 33 additions & 1 deletion src/backend/src/services/recruitment.services.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { User } from '@prisma/client';
import { isAdmin } from 'shared';
import prisma from '../prisma/prisma';
import { AccessDeniedAdminOnlyException, HttpException } from '../utils/errors.utils';
import { AccessDeniedAdminOnlyException, HttpException, NotFoundException } from '../utils/errors.utils';
import { userHasPermission } from '../utils/users.utils';

export default class RecruitmentServices {
Expand Down Expand Up @@ -61,4 +61,36 @@ export default class RecruitmentServices {

return allMilestones;
}

/**
* Creates a new FAQ in the given organization Id
* @param submitter a user who is making this request
* @param question question to be displayed by the FAQ
* @param answer answer to the question of the FAQ
* @param organizationId the organization Id of the FAQ
* @returns A newly created FAQ
*/
static async createFaq(submitter: User, question: string, answer: string, organizationId: string) {
const organization = await prisma.organization.findUnique({
where: { organizationId }
});

if (!organization) {
throw new NotFoundException('Organization', organizationId);
}

if (!(await userHasPermission(submitter.userId, organizationId, isAdmin)))
throw new AccessDeniedAdminOnlyException('create an faq');

const faq = await prisma.frequentlyAskedQuestion.create({
data: {
question,
answer,
organizationId,
userCreatedId: submitter.userId
}
});

return faq;
}
}
1 change: 1 addition & 0 deletions src/backend/src/utils/errors.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,5 @@ export type ExceptionObjectNames =
| 'Work Package Template'
| 'Description Bullet Type'
| 'Organization'
| 'Faq'
| 'Car';
1 change: 1 addition & 0 deletions src/backend/tests/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const resetUsers = async () => {
await prisma.team_Type.deleteMany();
await prisma.wBS_Element.deleteMany();
await prisma.milestone.deleteMany();
await prisma.frequentlyAskedQuestion.deleteMany();
await prisma.organization.deleteMany();
await prisma.user.deleteMany();
};
Expand Down
31 changes: 29 additions & 2 deletions src/backend/tests/unmocked/recruitment.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import RecruitmentServices from '../../src/services/recruitment.services';
import { AccessDeniedAdminOnlyException, HttpException } from '../../src/utils/errors.utils';
import { batmanAppAdmin, wonderwomanGuest, supermanAdmin } from '../test-data/users.test-data';
import { AccessDeniedAdminOnlyException, HttpException, NotFoundException } from '../../src/utils/errors.utils';
import { batmanAppAdmin, wonderwomanGuest, supermanAdmin, member } from '../test-data/users.test-data';
import { createTestOrganization, createTestUser, resetUsers } from '../test-utils';

describe('Recruitment Tests', () => {
Expand Down Expand Up @@ -88,4 +88,31 @@ describe('Recruitment Tests', () => {
expect(result).toStrictEqual([milestone1, milestone2]);
});
});

describe('Create FAQ', () => {
it('Fails if user is not an admin', async () => {
await expect(
async () => await RecruitmentServices.createFaq(await createTestUser(member, orgId), 'question', 'answer', orgId)
).rejects.toThrow(new AccessDeniedAdminOnlyException('create an faq'));
});

it('Fails if organization doesn`t exist', async () => {
await expect(
async () =>
await RecruitmentServices.createFaq(await createTestUser(batmanAppAdmin, orgId), 'question', 'answer', '5')
).rejects.toThrow(new NotFoundException('Organization', `5`));
});

it('Succeeds and creates an FAQ', async () => {
const result = await RecruitmentServices.createFaq(
await createTestUser(batmanAppAdmin, orgId),
'question',
'answer',
orgId
);

expect(result.question).toEqual('question');
expect(result.answer).toEqual('answer');
});
});
});