diff --git a/src/services/profile/profile-lib.ts b/src/services/profile/profile-lib.ts index b7f6ab08..ee0d9831 100644 --- a/src/services/profile/profile-lib.ts +++ b/src/services/profile/profile-lib.ts @@ -1,6 +1,7 @@ -import { AttendeeProfile } from "../../database/attendee-db.js"; +import { AttendeeProfile, AttendeeProfileModel } from "../../database/attendee-db.js"; import Constants from "../../constants.js"; import { LeaderboardEntry } from "./profile-models.js"; +import { UpdateQuery } from "mongoose"; /** * Remove non-necessary fields from a leaderboardentry item @@ -23,3 +24,19 @@ export function castLeaderboardEntries(initial: AttendeeProfile): LeaderboardEnt export function isValidLimit(limit: number): boolean { return limit > Constants.ZERO; } + +/** + * Change a user's points by a specific amount. + * @param userId ID of the user to modify + * @param amount Amount of points to change (note that this can be a negative number too!) + * @returns Promise containing the new user, or the actual attendee profile + */ +export async function updatePoints(userId: string, amount: number): Promise { + const updateQuery: UpdateQuery = { + $inc: { + points: amount, + }, + }; + + return AttendeeProfileModel.findOneAndUpdate({ userId: userId }, updateQuery); +} diff --git a/src/services/profile/profile-router.ts b/src/services/profile/profile-router.ts index dff43fde..35b7fd26 100644 --- a/src/services/profile/profile-router.ts +++ b/src/services/profile/profile-router.ts @@ -5,12 +5,11 @@ import { Response } from "express-serve-static-core"; import Constants from "../../constants.js"; import { isValidLimit } from "./profile-lib.js"; import { AttendeeMetadata, AttendeeMetadataModel, AttendeeProfile, AttendeeProfileModel } from "../../database/attendee-db.js"; -import { Query, UpdateQuery } from "mongoose"; +import { Query } from "mongoose"; import { LeaderboardEntry } from "./profile-models.js"; import { JwtPayload } from "../auth/auth-models.js"; import { strongJwtVerification, weakJwtVerification } from "../../middleware/verify-jwt.js"; -import { hasElevatedPerms } from "../auth/auth-lib.js"; import { isValidProfileModel } from "./profile-formats.js"; const profileRouter: Router = Router(); @@ -31,14 +30,12 @@ profileRouter.use(cors({ origin: "*" })); * { "profiles": [ { - "id": "profileid123456", + "displayName": "profileid123456", "points": 2021, - "discord": "patrick#1234" }, { - "id": "profileid123456", - "points": 2021, - "discord": "patrick#1234" + "displayName": "test2" + "points": 2020, }, ] } @@ -87,12 +84,11 @@ profileRouter.get("/leaderboard/", async (req: Request, res: Response) => { * HTTP/1.1 200 OK * { * "_id": "12345", - * "firstName": "Hackk", - * "lastName": "Illinois", - * "discord": "hackillinois", + * "displayName": "Illinois", + * "discordName": "hackillinois", * "avatarUrl": "na", * "points": 0, - * "id": "abcde", + * "userId": "abcde", * "foodWave": 0 * } * @@ -110,8 +106,8 @@ profileRouter.get("/leaderboard/", async (req: Request, res: Response) => { profileRouter.get("/", strongJwtVerification, async (_: Request, res: Response) => { const decodedData: JwtPayload = res.locals.payload as JwtPayload; - const id: string = decodedData.id; - const user: AttendeeProfile | null = await AttendeeProfileModel.findOne({ userId: id }); + const userId: string = decodedData.id; + const user: AttendeeProfile | null = await AttendeeProfileModel.findOne({ userId: userId }); if (!user) { return res.status(Constants.NOT_FOUND).send({ error: "UserNotFound" }); @@ -132,13 +128,11 @@ profileRouter.get("/", strongJwtVerification, async (_: Request, res: Response) * HTTP/1.1 200 OK * { * "_id": "12345", - * "firstName": "Hackk", - * "lastName": "Illinois", - * "discord": "hackillinois", + * "displayName": "Hackk", + * "discordName": "hackillinois", * "avatarUrl": "na", * "points": 0, - * "id": "abcde", - * "foodWave": 0 + * "userId": "abcde", * } * * @apiError (404: Not Found) {String} UserNotFound The user's profile was not found. @@ -153,10 +147,13 @@ profileRouter.get("/", strongJwtVerification, async (_: Request, res: Response) */ profileRouter.get("/id/:USERID", weakJwtVerification, async (req: Request, res: Response) => { - const id: string | undefined = req.params.USERID; - console.log(id); + const userId: string | undefined = req.params.USERID; - const user: AttendeeProfile | null = await AttendeeProfileModel.findOne({ userId: id }); + if (!userId) { + return res.status(Constants.BAD_REQUEST).send({ error: "InvalidParams" }); + } + + const user: AttendeeProfile | null = await AttendeeProfileModel.findOne({ userId: userId }); if (!user) { return res.status(Constants.NOT_FOUND).send({ error: "UserNotFound" }); @@ -180,13 +177,11 @@ profileRouter.get("/id/:USERID", weakJwtVerification, async (req: Request, res: * HTTP/1.1 200 OK * { * "_id": "abc12345", - * "firstName": "Hack", - * "lastName": "Illinois", - * "discord": "HackIllinois", + * "displayName": "Illinois", + * "discordName": "HackIllinois", * "avatarUrl": "na", * "points": 0, - * "id": "12345", - * "foodWave": 0 + * "userId": "12345", * } * * @apiError (400: Bad Request) {String} UserAlreadyExists The user profile already exists. @@ -221,58 +216,13 @@ profileRouter.post("/", strongJwtVerification, async (req: Request, res: Respons const profileMetadata: AttendeeMetadata = new AttendeeMetadata(profile.userId, Constants.DEFAULT_FOOD_WAVE); try { - await AttendeeProfileModel.create(profile); + const newProfile = await AttendeeProfileModel.create(profile); await AttendeeMetadataModel.create(profileMetadata); + return res.status(Constants.SUCCESS).send(newProfile); } catch (error) { console.error(error); return res.status(Constants.FAILURE).send({ error: "InvalidParams" }); } - - return res.status(Constants.SUCCESS).send(profile); -}); - -/** - * @api {put} /profile/points PUT /profile/points - * @apiGroup Profile - * @apiDescription Update a user's points. Only STAFF and ADMIN roles can edit this. - * - * @apiBody {String} points new number of points - * - * @apiSuccess (200: Success) {Json} profile Updated user point number - * @apiSuccessExample Example Success Response: - * HTTP/1.1 200 OK - * { - * "points": 5 - * } - * - * @apiError (500: Internal Error) {String} InternalError An internal server error occurred. - * @apiErrorExample Example Error Response (InternalError): - * HTTP/1.1 500 Internal Server Error - * {"error": "InternalError"} - */ - -profileRouter.put("/points", strongJwtVerification, async (req: Request, res: Response) => { - const profile: AttendeeProfile | null = req.body as AttendeeProfile; - - if (!isValidProfileModel(profile)) { - return res.status(Constants.BAD_REQUEST).send({ error: "InvalidPutData" }); - } - - const decodedData: JwtPayload = res.locals.payload as JwtPayload; - - if (!hasElevatedPerms(decodedData)) { - return res.status(Constants.FORBIDDEN).send({ error: "NotAuthorizedToUseEndpoint" }); - } - - const update: UpdateQuery = { - $set: { - points: profile.points, - }, - }; - - await AttendeeProfileModel.updateOne({ userId: decodedData.id }, update); - - return res.status(Constants.SUCCESS).send({ points: profile.points }); }); /**