Skip to content

Commit

Permalink
Fixed tiny nits in profile service (#86)
Browse files Browse the repository at this point in the history
* Fixed small nits in profile service

* Extracted post endpoint

* Fixed formatting
  • Loading branch information
AydanPirani authored Oct 15, 2023
1 parent cf97d7c commit a19d6cc
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 74 deletions.
19 changes: 18 additions & 1 deletion src/services/profile/profile-lib.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<AttendeeProfile | null> {
const updateQuery: UpdateQuery<AttendeeProfile> = {
$inc: {
points: amount,
},
};

return AttendeeProfileModel.findOneAndUpdate({ userId: userId }, updateQuery);
}
96 changes: 23 additions & 73 deletions src/services/profile/profile-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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,
},
]
}
Expand Down Expand Up @@ -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
* }
*
Expand All @@ -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" });
Expand All @@ -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.
Expand All @@ -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" });
Expand All @@ -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.
Expand Down Expand Up @@ -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<AttendeeProfile> = {
$set: {
points: profile.points,
},
};

await AttendeeProfileModel.updateOne({ userId: decodedData.id }, update);

return res.status(Constants.SUCCESS).send({ points: profile.points });
});

/**
Expand Down

0 comments on commit a19d6cc

Please sign in to comment.