Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: authorization in admission-status #63

Merged
merged 3 commits into from
Mar 31, 2022
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
59 changes: 59 additions & 0 deletions backend/controllers/admissionPeriodController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Request, Response } from 'express'
import { UnauthorizedUserError } from 'ntnui-tools/customError'
import { AdmissionPeriodModel } from '../models/AdmissionPeriod'
import { getUserCommitteeIdsByUserId } from '../utils/userCommittee'
import { RequestWithNtnuiNo } from '../utils/request'
import MAIN_BOARD_ID from '../utils/constants'
import isAdmissionPeriodActive from '../utils/isApplicationPeriodActive'

const getAdmissionPeriod = async (req: Request, res: Response) => {
// Only one admission period in the db at any time, so findOne() returns only the one object
const admissionPeriod = await AdmissionPeriodModel.findOne()
if (admissionPeriod) {
return res.status(200).json({ admissionPeriod })
}

return res
.status(404)
.json({ message: 'There is no admission period in the db' })
}

const putAdmissionPeriod = async (req: RequestWithNtnuiNo, res: Response) => {
const { ntnuiNo } = req
if (!ntnuiNo) throw UnauthorizedUserError
const committeeIds: number[] = await getUserCommitteeIdsByUserId(ntnuiNo)

if (committeeIds.includes(MAIN_BOARD_ID)) {
const update = {
start_date: req.body.start_date,
end_date: req.body.end_date,
}

// Update the existing admission period or create a new one if it doesn't exist
if (
await AdmissionPeriodModel.findOneAndUpdate({}, update, {
new: true,
upsert: true,
})
) {
return res.status(200).json({ message: 'Admission period updated' })
}
return res
.status(500)
.json({ message: 'Something went wrong updating the admission period' })
}
return res.status(403).json({ message: 'Not authorized' })
}

const getAdmissionPeriodStatus = async (req: Request, res: Response) => {
try {
if (await isAdmissionPeriodActive()) {
return res.status(200).json({ response: true })
}
return res.status(200).json({ response: false })
} catch (error) {
return res.status(500).json({ message: error })
}
}

export { getAdmissionPeriod, putAdmissionPeriod, getAdmissionPeriodStatus }
10 changes: 5 additions & 5 deletions backend/controllers/applicationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { RequestWithNtnuiNo } from '../utils/request'
import { ApplicationModel, IApplication } from '../models/Application'
import { UserModel } from '../models/User'
import { CommitteeModel, ICommittee } from '../models/Committee'
import isApplicationPeriodActive from '../utils/isApplicationPeriodActive'
import isAdmissionPeriodActive from '../utils/isApplicationPeriodActive'

async function getUserCommitteeIdsByUserId(userId: number | string) {
let committeeIds: number[] = []
Expand Down Expand Up @@ -104,16 +104,16 @@ const postApplication = async (
next: NextFunction
) => {
try {
if (!(await isApplicationPeriodActive())) {
throw new CustomError('Application period is not active', 403)
if (!(await isAdmissionPeriodActive())) {
throw new CustomError('Admission period is not active', 403)
}

const application = new ApplicationModel(req.body)

// Check that all applied committees accepts applicants
// Check that all applied committees accepts admissions
const closedCommittees = await CommitteeModel.findOne({
_id: { $in: application.committees },
accepts_applicants: false,
accepts_admissions: false,
})
if (closedCommittees) {
return res
Expand Down
64 changes: 0 additions & 64 deletions backend/controllers/applicationPeriodController.ts

This file was deleted.

46 changes: 33 additions & 13 deletions backend/controllers/committeeController.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,57 @@
import { NextFunction, Request, Response } from 'express'
import { CustomError, UnauthorizedUserError } from 'ntnui-tools/customError'
import { CommitteeModel } from '../models/Committee'
import MAIN_BOARD_ID from '../utils/constants'
import { RequestWithNtnuiNo } from '../utils/request'
import { getUserRoleInCommitteeByUserId } from '../utils/userCommittee'

const getCommittees = (_req: Request, res: Response) => {
CommitteeModel.find()
.then((committees) => res.json(committees))
.catch((err) => res.status(404).json({ message: err.message }))
}

async function acceptApplicants(
req: Request,
async function acceptAdmissions(
req: RequestWithNtnuiNo,
res: Response,
next: NextFunction
) {
try {
// Toggle accepts_applicants for a committee
const { ntnuiNo } = req
if (!ntnuiNo) throw UnauthorizedUserError
// Retrieve committee that is accepting admissions
const { slug } = req.params
const committee = await CommitteeModel.findOne({ slug })
if (!committee) {
return res.status(404).json({ message: 'Committee not found' })
}
committee.accepts_applicants = !committee.accepts_applicants
// Check if user is organizer or board member of the committee
const rolesInCommittees = await getUserRoleInCommitteeByUserId(ntnuiNo)
const isOrganizerOrBoardMember = rolesInCommittees.some(
(roleInCommittee) =>
roleInCommittee.committee === MAIN_BOARD_ID ||
roleInCommittee.committee === committee._id
)
if (isOrganizerOrBoardMember) {
// Toggle accepts_admissions for a committee
committee.accepts_admissions = !committee.accepts_admissions

return committee
.save()
.then(() =>
res.status(200).json({
accept_applicants: committee.accepts_applicants,
})
)
.catch((err) => res.status(500).json({ message: err.message }))
return committee
.save()
.then(() =>
res.status(200).json({
accepts_admissions: committee.accepts_admissions,
})
)
.catch((err) => res.status(500).json({ message: err.message }))
}
throw new CustomError(
'You are not authorized to change the admission status of this committee',
403
)
} catch (error) {
return next(error)
}
}

export { getCommittees, acceptApplicants }
export { getCommittees, acceptAdmissions }
2 changes: 1 addition & 1 deletion backend/controllers/userController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const getUserCommittees = async (
try {
const { ntnuiNo } = req
if (!ntnuiNo) throw UnauthorizedUserError
const user = await UserModel.findOne({ ntnuiNo }).populate(
const user = await UserModel.findOne({ _id: ntnuiNo }).populate(
'committees.committee'
)
if (!user) throw UnauthorizedUserError
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"start_date": "2022-02-25",
"end_date": "2022-03-29"
"end_date": "2022-03-31"
}
18 changes: 9 additions & 9 deletions backend/fixtures/devCommittees.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,49 @@
"name": "Triatlon",
"slug": "triatlon",
"access_roles": ["deputy_leader"],
"accepts_applicants": true
"accepts_admissions": true
},
{
"_id": 3,
"name": "Turn",
"slug": "turn",
"access_roles": [],
"accepts_applicants": true
"accepts_admissions": true
},
{
"_id": 4,
"name": "Ski og Fjellsport",
"slug": "ski-og-fjellsport",
"access_roles": ["deputy_leader"],
"accepts_applicants": false
"accepts_admissions": false
},
{
"_id": 5,
"name": "Hidden-test-group",
"slug": "hidden-test-group",
"access_roles": [],
"accepts_applicants": false
"accepts_admissions": false
},
{
"_id": 6,
"name": "Tindegruppa",
"slug": "tindegruppa",
"access_roles": ["deputy_leader"],
"accepts_applicants": false
"accepts_admissions": false
},
{
"_id": 7,
"name": "Koiene",
"slug": "koiene",
"access_roles": ["deputy_leader"],
"accepts_applicants": false
"accepts_admissions": false
},
{
"_id": 8,
"name": "Aikido",
"slug": "aikido",
"access_roles": [],
"accepts_applicants": false
"accepts_admissions": false
},
{
"_id": 9,
Expand All @@ -58,13 +58,13 @@
"board_member",
"deputy_board_member"
],
"accepts_applicants": true
"accepts_admissions": true
},
{
"_id": 10,
"name": "Sprint",
"slug": "sprint",
"access_roles": ["deputy_leader", "cashier"],
"accepts_applicants": true
"accepts_admissions": true
}
]
20 changes: 20 additions & 0 deletions backend/models/AdmissionPeriod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import mongoose from 'mongoose'

interface IAdmissionPeriod {
start_date: Date
end_date: Date
}

const AdmissionPeriodModel = mongoose.model<IAdmissionPeriod>(
'AdmissionPeriod',
new mongoose.Schema<IAdmissionPeriod>(
{
start_date: { type: Date, required: true },
end_date: { type: Date, required: true },
},
{ collection: 'admissionperiod' }
)
)

export { AdmissionPeriodModel }
export type { IAdmissionPeriod }
20 changes: 0 additions & 20 deletions backend/models/ApplicationPeriod.ts

This file was deleted.

4 changes: 2 additions & 2 deletions backend/models/Committee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ interface ICommittee {
_id: number
name: string
slug: string
accepts_applicants: boolean
accepts_admissions: boolean
access_roles: string[]
}

Expand All @@ -15,7 +15,7 @@ const CommitteeModel = mongoose.model<ICommittee>(
_id: { type: Number, required: true },
name: { type: String, required: true },
slug: { type: String, required: true },
accepts_applicants: { type: Boolean, required: true },
accepts_admissions: { type: Boolean, required: true },
access_roles: [{ type: String, enum: MembershipType, required: true }],
})
)
Expand Down
Loading