Skip to content

Commit 647978c

Browse files
authored
update user handling (#67)
1 parent 1542daa commit 647978c

File tree

5 files changed

+189
-85
lines changed

5 files changed

+189
-85
lines changed

app/config/swaggerconfig.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const swaggerDefinition = {
7878
"type": "object",
7979
"required": [
8080
"gender",
81-
"pronous",
81+
"pronouns",
8282
"age",
8383
"ethnicity",
8484
"gradYear",
@@ -107,7 +107,7 @@ const swaggerDefinition = {
107107
"description": "Applicant's gender",
108108
"example": "Male"
109109
},
110-
"pronous": {
110+
"pronouns": {
111111
"type": "string",
112112
"description": "Applicant's preferred pronouns",
113113
"example": "he/him"

app/controllers/User.controller.js

Lines changed: 118 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,83 +4,126 @@ import logger from "../utils/logger.js";
44
const prisma = prismaInstance;
55

66

7-
export const getUser = async(req, res) => {
8-
try {
9-
if (!req.query.id && !req.query.email) {
10-
return res.status(400).json({
11-
message: "id or email query is required"
12-
});
13-
}
14-
15-
// verify logged in user matches requested user
16-
if ((req.query.id && req.user.id !== req.query.id) || (req.query.email && req.user.email !== req.query.email)) {
17-
logger.warn(`Attempted unauthorized access to user with id ${req.query.id} or email ${req.query.email}`);
18-
return res.status(403).json({
19-
message: "You are not authorized to access this resource"
20-
});
21-
}
22-
23-
const user = await prisma.user.findFirst({
24-
where: {
25-
OR: [
26-
{ id: req.query.id || '' },
27-
{ email: req.query.email || '' }
28-
]
29-
},
30-
include: {
31-
projects: req.query.include ? true : false,
32-
applications: req.query.include ? true : false,
33-
},
34-
35-
});
36-
37-
if (!user) {
38-
return res.status(404).json({
39-
message: "User not found"
40-
});
41-
}
42-
43-
44-
logger.info(`User with id ${req.query.id} retrieved`)
45-
return res.status(200).json(user);
46-
47-
48-
} catch(err) {
49-
logger.error(err);
50-
res.status(500).json({
51-
message: "Something went wrong",
52-
error: err
53-
});
7+
export const getUser = async (req, res) => {
8+
try {
9+
if (!req.query.id && !req.query.email) {
10+
return res.status(400).json({
11+
message: "id or email query is required"
12+
});
5413
}
14+
15+
// verify logged in user matches requested user
16+
if ((req.query.id && req.user.id !== req.query.id) || (req.query.email && req.user.email !== req.query.email)) {
17+
logger.warn(`Attempted unauthorized access to user with id ${req.query.id} or email ${req.query.email}`);
18+
return res.status(403).json({
19+
message: "You are not authorized to access this resource"
20+
});
21+
}
22+
23+
const user = await prisma.user.findFirst({
24+
where: {
25+
OR: [
26+
{ id: req.query.id || '' },
27+
{ email: req.query.email || '' }
28+
]
29+
},
30+
include: {
31+
projects: req.query.include ? true : false,
32+
applications: req.query.include ? true : false,
33+
},
34+
35+
});
36+
37+
if (!user) {
38+
return res.status(404).json({
39+
message: "User not found"
40+
});
41+
}
42+
43+
44+
logger.info(`User with id ${req.query.id} retrieved`)
45+
return res.status(200).json(user);
46+
47+
48+
} catch (err) {
49+
logger.error(err);
50+
res.status(500).json({
51+
message: "Something went wrong",
52+
error: err
53+
});
54+
}
5555
}
5656

57-
export const getSelf = async(req, res) => {
58-
try {
59-
// finds user based on token info instead of query
60-
const user = await prisma.user.findUnique({
61-
where: {
62-
id: req.user.id
63-
},
64-
select: {
65-
id: true,
66-
email: true
67-
}
68-
});
69-
70-
if (!user) {
71-
return res.status(404).json({
72-
message: "User not found"
73-
});
74-
}
75-
76-
// logger.info(`User with id ${req.user.id} retrieved`)
77-
return res.status(200).json(user);
78-
79-
} catch(err) {
80-
logger.error(err);
81-
res.status(500).json({
82-
message: "Something went wrong",
83-
error: err
84-
});
57+
export const getSelf = async (req, res) => {
58+
try {
59+
// finds user based on token info instead of query
60+
const user = await prisma.user.findUnique({
61+
where: {
62+
id: req.user.id
63+
},
64+
select: {
65+
id: true,
66+
email: true
67+
}
68+
});
69+
70+
if (!user) {
71+
return res.status(404).json({
72+
message: "User not found"
73+
});
8574
}
75+
76+
// logger.info(`User with id ${req.user.id} retrieved`)
77+
return res.status(200).json(user);
78+
79+
} catch (err) {
80+
logger.error(err);
81+
res.status(500).json({
82+
message: "Something went wrong",
83+
error: err
84+
});
85+
}
86+
}
87+
88+
export const updateUser = async (req, res) => {
89+
try {
90+
if (!req.params.id) {
91+
return res.status(400).json({
92+
message: "id param is required"
93+
});
94+
}
95+
96+
if (req.user.id !== req.params.id) {
97+
logger.warn(`Attempted unauthorized update to user with id ${req.params.id}`);
98+
return res.status(403).json({
99+
message: "You are not authorized to update this resource"
100+
});
101+
}
102+
103+
const { firstName, lastName } = req.body;
104+
105+
const updatedUser = await prisma.user.update({
106+
where: {
107+
id: req.params.id
108+
},
109+
data: {
110+
firstName,
111+
lastName
112+
}
113+
});
114+
115+
return res.status(200).json(updatedUser);
116+
} catch (err) {
117+
if (err.name === "ZodError") {
118+
return res.status(400).json({
119+
message: "Invalid request data",
120+
error: err.errors
121+
});
122+
}
123+
124+
return res.status(500).json({
125+
message: "Something went wrong",
126+
error: err
127+
});
128+
}
86129
}

app/routes/Admin/AdminApplication.routes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ router.get("/:id", getApplicationById);
114114
* type: string
115115
* gender:
116116
* type: string
117-
* pronous:
117+
* pronouns:
118118
* type: string
119119
* age:
120120
* type: integer
@@ -196,7 +196,7 @@ router.post("/", createApplication);
196196
* type: string
197197
* gender:
198198
* type: string
199-
* pronous:
199+
* pronouns:
200200
* type: string
201201
* age:
202202
* type: integer

app/routes/Application.routes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const router = express.Router();
3434
* type: string
3535
* gender:
3636
* type: string
37-
* pronous:
37+
* pronouns:
3838
* type: string
3939
* age:
4040
* type: integer
@@ -113,7 +113,7 @@ router.post("/", verifyToken, upload.single('resume'), createApplication);
113113
* properties:
114114
* gender:
115115
* type: string
116-
* pronous:
116+
* pronouns:
117117
* type: string
118118
* age:
119119
* type: integer

app/routes/User.routes.js

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import express from "express"
2-
import { getSelf, getUser } from "../controllers/User.controller.js";
2+
import { getSelf, getUser, updateUser } from "../controllers/User.controller.js";
33
import { verifyToken } from "../middleware/verifyToken.js";
44

55
const router = express.Router();
@@ -81,7 +81,68 @@ router.get("/", verifyToken, getUser);
8181
*/
8282
router.get("/me", verifyToken, getSelf);
8383

84-
// update user should prevent updates to certain fields
85-
// router.put("/:id", verifyToken, updateUser);
84+
/**
85+
* @openapi
86+
*
87+
* /user/{id}:
88+
* put:
89+
* summary: Update user information
90+
* description: Update user's firstName and lastName. Users can only update their own information.
91+
* tags: [User]
92+
* security:
93+
* - accessToken: []
94+
* parameters:
95+
* - in: cookie
96+
* name: access_token
97+
* description: Login token
98+
* required: true
99+
* schema:
100+
* type: string
101+
* - in: path
102+
* name: id
103+
* description: User ID to update
104+
* required: true
105+
* schema:
106+
* type: string
107+
* requestBody:
108+
* required: true
109+
* content:
110+
* application/json:
111+
* schema:
112+
* type: object
113+
* properties:
114+
* firstName:
115+
* type: string
116+
* description: User's first name
117+
* lastName:
118+
* type: string
119+
* description: User's last name
120+
* responses:
121+
* 200:
122+
* description: User updated successfully
123+
* content:
124+
* application/json:
125+
* schema:
126+
* type: object
127+
* $ref: "#/components/schemas/User"
128+
* 400:
129+
* description: Bad request - missing ID parameter or invalid request data
130+
* content:
131+
* application/json:
132+
* schema:
133+
* type: object
134+
* properties:
135+
* message:
136+
* type: string
137+
* error:
138+
* type: array
139+
* 403:
140+
* $ref: "#/components/responses/403forbidden"
141+
* 401:
142+
* $ref: "#/components/responses/401unauthorized"
143+
* 500:
144+
* $ref: "#/components/responses/500internalservererror"
145+
*/
146+
router.put("/:id", verifyToken, updateUser);
86147

87-
export default router;
148+
export default router;

0 commit comments

Comments
 (0)