Skip to content
This repository was archived by the owner on Oct 14, 2025. It is now read-only.

Commit 0b6b965

Browse files
authored
Merge pull request #296 from TreeHacks/connorff/update-form-api
feat: restrict scope access to forms, add/modify form schemas
2 parents 47be7e2 + bc1ecf8 commit 0b6b965

File tree

13 files changed

+113
-38
lines changed

13 files changed

+113
-38
lines changed

backend/index.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ import {
2828
} from "./routes/application_info";
2929
import { createEventPushSubscription, deleteEventPushSubscription, getEventSubscriptions } from "./routes/event_subscriptions"
3030
import { getMeetInfo, setMeetInfo } from "./routes/meet_info";
31-
import { getUsedMeals, setUsedMeals } from "./routes/used_meals";
31+
import { getMealInfo, setMealInfo } from "./routes/meal_info";
3232
import { getWorkshopList, setWorkshopList } from "./routes/workshop_info";
33-
import { getCheckIn, setCheckIn } from "./routes/check_in";
33+
import { getCheckInInfo, setCheckInInfo } from "./routes/check_in_info";
34+
import { getHardwareInfo, setHardwareInfo } from "./routes/hardware_info";
3435
import { addTeammate, getTeamInfo, removeTeammate, setTeamInfo } from "./routes/team_info";
3536
import { getSubmitInfo, setSubmitInfo } from "./routes/submit_info";
37+
import { getAllForms } from "./routes/forms";
3638
import { getUserDetail } from "./routes/user_detail";
3739
import { getUserList, getUserStats, getMeetList } from "./routes/user_list";
3840
import {
@@ -189,10 +191,12 @@ authenticatedRoute.post(
189191
);
190192
authenticatedRoute.get("/users/:userId/forms/meet_info", getMeetInfo);
191193
authenticatedRoute.put("/users/:userId/forms/meet_info", setMeetInfo);
192-
authenticatedRoute.get("/users/:userId/forms/used_meals", getUsedMeals);
193-
authenticatedRoute.put("/users/:userId/forms/used_meals", setUsedMeals);
194-
authenticatedRoute.get("/users/:userId/forms/check_in", getCheckIn);
195-
authenticatedRoute.put("/users/:userId/forms/check_in", setCheckIn);
194+
authenticatedRoute.get("/users/:userId/forms/meal_info", getMealInfo);
195+
authenticatedRoute.put("/users/:userId/forms/meal_info", setMealInfo);
196+
authenticatedRoute.get("/users/:userId/forms/check_in_info", getCheckInInfo);
197+
authenticatedRoute.put("/users/:userId/forms/check_in_info", setCheckInInfo);
198+
authenticatedRoute.get("/users/:userId/forms/hardware_info", getHardwareInfo);
199+
authenticatedRoute.put("/users/:userId/forms/hardware_info", setHardwareInfo);
196200
authenticatedRoute.get("/users/:userId/forms/submit_info", getSubmitInfo);
197201
authenticatedRoute.put("/users/:userId/forms/submit_info", setSubmitInfo);
198202
authenticatedRoute.get("/users/:userId/forms/team_info", getTeamInfo);
@@ -205,6 +209,7 @@ authenticatedRoute.put("/users/:userId/forms/remove_teammate", removeTeammate);
205209
// What permission should this one be?
206210
authenticatedRoute.get("/users/:userId/status", getApplicationStatus);
207211
authenticatedRoute.get("/users/:userId", getUserDetail);
212+
authenticatedRoute.get("/users/:userId/forms", getAllForms);
208213

209214
// Room reservations
210215
authenticatedRoute.get("/rooms", getRooms);

backend/models/Application.d.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,22 @@ export interface ITransportationInfo {
5353
[e: string]: any;
5454
}
5555

56-
export interface IUsedMeals {
57-
mealList?: String;
56+
export interface IMealInfo {
57+
usedMeals?: [String];
5858
}
5959

6060
export interface ITeamInfo {
6161
teamList?: String;
6262
}
6363

6464
export interface IWorkshopInfo {
65-
workshopList?: String;
65+
attendedWorkshops?: [String];
6666
}
6767

68-
export interface ICheckIn {
69-
checkInStatus?: Boolean;
68+
export interface ICheckInInfo {
69+
checkedIn?: Boolean;
70+
checkedInBy?: String;
71+
checkedInAt?: Date;
7072
}
7173

7274
export interface IMeetInfo {
@@ -98,17 +100,27 @@ export interface ISubmitInfo {
98100
url?: String;
99101
}
100102

103+
export interface IHardwareInfo {
104+
checkedOutBy?: String;
105+
checkedOutAt?: Date;
106+
pendingReturn?: Boolean;
107+
returnedAt?: Date;
108+
returnedBy?: String;
109+
hardwareList?: String;
110+
}
111+
101112
export interface IApplication extends Document {
102113
forms: {
103114
// can only be modified by user/editors
104115
application_info: IApplicationInfo;
105116
transportation: ITransportationInfo;
106117
meet_info: IMeetInfo;
107118
submit_info: ISubmitInfo;
108-
used_meals: IUsedMeals;
109-
check_in: ICheckIn;
119+
meal_info: IMealInfo;
120+
check_in_info: ICheckInInfo;
110121
team_info: ITeamInfo;
111122
workshop_info: IWorkshopInfo;
123+
hardware_info: IHardwareInfo;
112124
// we can conceivably add additional forms here.
113125
};
114126
admin_info: {

backend/models/ApplicationAnyYear.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import { IApplication } from "./Application.d"
44
import applicationInfoSchema from "./applicationInfoSchema";
55
import adminInfoSchema from "./adminInfoSchema";
66
import meetInfoSchema from "./meetInfoSchema";
7-
import usedMealsSchema from "./usedMealsSchema";
7+
import mealInfoSchema from "./mealInfoSchema";
88
import checkInSchema from "./checkInSchema";
99
import teamInfoSchema from "./teamInfoSchema";
1010
import workshopInfoSchema from "./workshopInfoSchema";
1111
import submitInfoSchema from "./submitInfoSchema";
12+
import hardwareInfoSchema from "./hardwareInfoSchema";
1213
import reviewSchema from "./reviewSchema";
1314
import { STATUS, TRANSPORTATION_STATUS } from "../constants";
1415
import {values} from "lodash";
@@ -20,10 +21,11 @@ export const applicationSchema: Schema = new mongoose.Schema({
2021
"application_info": applicationInfoSchema,
2122
"transportation": transportationInfoSchema,
2223
"meet_info": meetInfoSchema,
23-
"used_meals": usedMealsSchema,
24-
"check_in": checkInSchema,
24+
"meal_info": mealInfoSchema,
25+
"check_in_info": checkInSchema,
2526
"team_info": teamInfoSchema,
2627
"workshop_info": workshopInfoSchema,
28+
"hardware_info": hardwareInfoSchema,
2729
"submit_info": submitInfoSchema
2830
},
2931
"admin_info": adminInfoSchema, // Only editable by admin.

backend/models/checkInSchema.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import mongoose from "mongoose";
22
import { Schema } from "mongoose";
33

44
const checkInSchema: Schema = new mongoose.Schema({
5-
checkInStatus: Boolean,
5+
checkedIn: Boolean,
6+
checkedInBy: String,
7+
checkedInAt: Date
68
}, { _id: false });
79

810
export default checkInSchema;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import mongoose from "mongoose";
2+
import { Schema } from "mongoose";
3+
4+
const hardwareInfoSchema: Schema = new mongoose.Schema({
5+
checkedOutBy: String,
6+
checkedOutAt: Date,
7+
pendingReturn: Boolean,
8+
returnedAt: Date,
9+
returnedBy: String,
10+
hardwareList: String
11+
}, { _id: false });
12+
13+
export default hardwareInfoSchema;

backend/models/mealInfoSchema.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import mongoose from "mongoose";
2+
import { Schema } from "mongoose";
3+
4+
const mealInfoSchema: Schema = new mongoose.Schema({
5+
usedMeals: [String],
6+
}, { _id: false });
7+
8+
export default mealInfoSchema;

backend/models/usedMealsSchema.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

backend/models/workshopInfoSchema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import mongoose from "mongoose";
22
import { Schema } from "mongoose";
33

44
const workshopInfoSchema: Schema = new mongoose.Schema({
5-
workshopList: String,
5+
attendedWorkshops: [String],
66
}, { _id: false });
77

88
export default workshopInfoSchema;
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import { Request, Response } from 'express';
22
import { getApplicationAttribute, setApplicationAttribute } from "./common";
33
import { IApplication } from '../models/Application.d';
44

5-
export function getUsedMeals(req: Request, res: Response) {
5+
export function getCheckInInfo(req: Request, res: Response) {
66
return getApplicationAttribute(req, res, (e: IApplication) => {
7-
return e.forms.used_meals || {};
7+
return e.forms.check_in_info || {};
88
}, true);
99
}
1010

11-
export function setUsedMeals(req: Request, res: Response) {
11+
export function setCheckInInfo(req: Request, res: Response) {
1212
return setApplicationAttribute(req, res,
1313
(e: IApplication) => {
14-
e.forms.used_meals = req.body;
14+
e.forms.check_in_info = req.body;
1515
},
16-
e => e.forms.used_meals
16+
e => e.forms.check_in_info
1717
);
18-
}
18+
}

backend/routes/common.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ export async function getApplicationAttribute(
3333
getter: (e: IApplication) => any,
3434
createIfNotFound = false
3535
) {
36+
// prevent non-admins from viewing applications
37+
const groups = res.locals.user["cognito:groups"] || [];
38+
const canView = groups.includes("admin") || groups.includes("organizers_current");
39+
if (!canView && res.locals.user.sub !== req.params.userId) {
40+
return res.status(403).send("You do not have access to view this application");
41+
}
42+
3643
let application: IApplication | null = await Application.findOne(
3744
{ "user.id": req.params.userId },
3845
{ __v: 0, reviews: 0 },
@@ -69,6 +76,13 @@ export async function setApplicationAttribute(
6976
getter: (e: IApplication) => any = (e) => e,
7077
considerDeadline = false
7178
) {
79+
// prevent non-admins from viewing other applications
80+
const groups = res.locals.user["cognito:groups"] || [];
81+
const canEdit = groups.includes("admin") || groups.includes("organizers_current");
82+
if (!canEdit && res.locals.user.sub !== req.params.userId) {
83+
return res.status(403).send("You do not have access to edit this application");
84+
}
85+
7286
const application: IApplication | null = await Application.findOne(
7387
{ "user.id": req.params.userId },
7488
{ __v: 0, reviews: 0 }

0 commit comments

Comments
 (0)