From 0f200753b24c4e7b0308849137c6728041960148 Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Fri, 8 Mar 2024 11:29:31 -0600 Subject: [PATCH 1/7] feat(pages/api/teammatching/subscription/create.ts): Subscribe to Post Team matching api functionality: Subscribe to posting --- pages/api/teammatching/subscription/create.ts | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 pages/api/teammatching/subscription/create.ts diff --git a/pages/api/teammatching/subscription/create.ts b/pages/api/teammatching/subscription/create.ts new file mode 100644 index 00000000..306cfd7e --- /dev/null +++ b/pages/api/teammatching/subscription/create.ts @@ -0,0 +1,56 @@ +import { firestore } from 'firebase-admin'; +import { NextApiRequest, NextApiResponse } from 'next'; +import initializeApi from '../../../../lib/admin/init'; +import { userIsAuthorized } from '../../../../lib/authorization/check-authorization'; + +initializeApi(); +const db = firestore(); + +// interface of subscription data that contains the user id and the post id +interface SubscriptionData { + userId: string; + postId: string; +} + +// create a subscription for user that subscribe them to a post +async function createSubscription(req: NextApiRequest, res: NextApiResponse) { + try { + const subscriptionData: SubscriptionData = JSON.parse(req.body); + await db.collection('subscriptions').add(subscriptionData); + return res.status(201).json({ + msg: 'Subscription created', + }); + } catch (error) { + return res.status(500).json({ + msg: 'Unexpected error. Please try again later', + }); + } +} + +async function handlePostRequest(req: NextApiRequest, res: NextApiResponse) { + const userToken = req.headers['authorization'] as string; + const isAuthorized = await userIsAuthorized(userToken, ['hacker']); + + if (!isAuthorized) { + return res.status(403).json({ + statusCode: 403, + msg: 'Request is not authorized to perform this functionality', + }); + } + + return createSubscription(req, res); +} + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + const { method } = req; + switch (method) { + case 'POST': { + return handlePostRequest(req, res); + } + default: { + return res.status(404).json({ + msg: 'Route not found', + }); + } + } +} From d74ae15d6c387c74cb2457b54362528502bb0468 Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Fri, 8 Mar 2024 11:30:30 -0600 Subject: [PATCH 2/7] feat(pages/api/teammatching/subscription/delete.ts): Unsubscribe post Team matching api functionality: Unsubscibe to posting --- pages/api/teammatching/subscription/delete.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 pages/api/teammatching/subscription/delete.ts diff --git a/pages/api/teammatching/subscription/delete.ts b/pages/api/teammatching/subscription/delete.ts new file mode 100644 index 00000000..60a5f360 --- /dev/null +++ b/pages/api/teammatching/subscription/delete.ts @@ -0,0 +1,68 @@ +import { firestore } from 'firebase-admin'; +import { NextApiRequest, NextApiResponse } from 'next'; +import initializeApi from '../../../../lib/admin/init'; +import { userIsAuthorized } from '../../../../lib/authorization/check-authorization'; + +initializeApi(); +const db = firestore(); + +// interface of subscription data that contains the user id and the post id +interface SubscriptionData { + userId: string; + postId: string; +} + +// delete one subscription for user that unsubscribe them to a post +async function deleteSubscription(req: NextApiRequest, res: NextApiResponse) { + try { + const subscriptionData: SubscriptionData = JSON.parse(req.body); + const snapshot = await db + .collection('subscriptions') + .where('userId', '==', subscriptionData.userId) + .where('postId', '==', subscriptionData.postId) + .get(); + if (snapshot.empty) { + return res.status(404).json({ + msg: 'Subscription to posting not found', + }); + } + snapshot.forEach((doc) => { + doc.ref.delete(); + }); + return res.status(200).json({ + msg: 'Subscription to posting deleted', + }); + } catch (error) { + return res.status(500).json({ + msg: 'Unexpected error. Please try again later', + }); + } +} + +async function handleDeleteRequest(req: NextApiRequest, res: NextApiResponse) { + const userToken = req.headers['authorization'] as string; + const isAuthorized = await userIsAuthorized(userToken, ['hacker']); + + if (!isAuthorized) { + return res.status(403).json({ + statusCode: 403, + msg: 'Request is not authorized to perform this functionality', + }); + } + + return deleteSubscription(req, res); +} + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + const { method } = req; + switch (method) { + case 'POST': { + return handleDeleteRequest(req, res); + } + default: { + return res.status(404).json({ + msg: 'Route not found', + }); + } + } +} From 128fad4d5ea6a2757fdab9c008ceb4e093f10527 Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Fri, 8 Mar 2024 11:31:36 -0600 Subject: [PATCH 3/7] feat(pages/api/teammatching/subscription/get.ts): Get subscriptions Team matching api functionality: Get all user's subscription --- pages/api/teammatching/subscription/get.ts | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 pages/api/teammatching/subscription/get.ts diff --git a/pages/api/teammatching/subscription/get.ts b/pages/api/teammatching/subscription/get.ts new file mode 100644 index 00000000..19cc1484 --- /dev/null +++ b/pages/api/teammatching/subscription/get.ts @@ -0,0 +1,57 @@ +import { firestore } from 'firebase-admin'; +import { NextApiRequest, NextApiResponse } from 'next'; +import initializeApi from '../../../../lib/admin/init'; +import { userIsAuthorized } from '../../../../lib/authorization/check-authorization'; + +initializeApi(); +const db = firestore(); + +// get all subscriptions for user +async function getSubscriptions(req: NextApiRequest, res: NextApiResponse) { + try { + const userId = req.query.userId as string; + const snapshot = await db.collection('subscriptions').where('userId', '==', userId).get(); + if (snapshot.empty) { + return res.status(404).json({ + msg: 'Subscriptions not found', + }); + } + const subscriptions = []; + snapshot.forEach((doc) => { + subscriptions.push(doc.data()); + }); + return res.status(200).json(subscriptions); + } catch (error) { + return res.status(500).json({ + msg: 'Unexpected error. Please try again later', + }); + } +} + +async function handleGetRequest(req: NextApiRequest, res: NextApiResponse) { + const userToken = req.headers['authorization'] as string; + const isAuthorized = await userIsAuthorized(userToken, ['hacker']); + + if (!isAuthorized) { + return res.status(403).json({ + statusCode: 403, + msg: 'Request is not authorized to perform this functionality', + }); + } + + return getSubscriptions(req, res); +} + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + const { method } = req; + switch (method) { + case 'GET': { + return handleGetRequest(req, res); + } + default: { + return res.status(404).json({ + msg: 'Route not found', + }); + } + } +} From 1151d1512fe12b3d01fe915c400a5b2b24f654e4 Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Mon, 1 Apr 2024 15:15:30 -0500 Subject: [PATCH 4/7] fix(pages/api/teammatching/subscription): Add async delete snapshot --- pages/api/teammatching/subscription/delete.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/api/teammatching/subscription/delete.ts b/pages/api/teammatching/subscription/delete.ts index 60a5f360..4673ebd6 100644 --- a/pages/api/teammatching/subscription/delete.ts +++ b/pages/api/teammatching/subscription/delete.ts @@ -26,8 +26,8 @@ async function deleteSubscription(req: NextApiRequest, res: NextApiResponse) { msg: 'Subscription to posting not found', }); } - snapshot.forEach((doc) => { - doc.ref.delete(); + snapshot.forEach(async (doc) => { + await doc.ref.delete(); }); return res.status(200).json({ msg: 'Subscription to posting deleted', From 0d1cf3484c9f1de5d9c8483bca41d6f341c7be35 Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Mon, 1 Apr 2024 16:07:41 -0500 Subject: [PATCH 5/7] fix(pages/api/teammatching/subscription): Update delete --- pages/api/teammatching/subscription/delete.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/api/teammatching/subscription/delete.ts b/pages/api/teammatching/subscription/delete.ts index 4673ebd6..945f8852 100644 --- a/pages/api/teammatching/subscription/delete.ts +++ b/pages/api/teammatching/subscription/delete.ts @@ -26,9 +26,9 @@ async function deleteSubscription(req: NextApiRequest, res: NextApiResponse) { msg: 'Subscription to posting not found', }); } - snapshot.forEach(async (doc) => { - await doc.ref.delete(); - }); + + await Promise.all(snapshot.docs.map((doc) => doc.ref.delete())); + return res.status(200).json({ msg: 'Subscription to posting deleted', }); From bd07440cb21d69f1085eef2c864b52306c9e270a Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Tue, 23 Apr 2024 14:37:12 -0500 Subject: [PATCH 6/7] chore: Rename api/teammatching to matching --- pages/api/{teammatching => matching}/subscription/create.ts | 0 pages/api/{teammatching => matching}/subscription/delete.ts | 0 pages/api/{teammatching => matching}/subscription/get.ts | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename pages/api/{teammatching => matching}/subscription/create.ts (100%) rename pages/api/{teammatching => matching}/subscription/delete.ts (100%) rename pages/api/{teammatching => matching}/subscription/get.ts (100%) diff --git a/pages/api/teammatching/subscription/create.ts b/pages/api/matching/subscription/create.ts similarity index 100% rename from pages/api/teammatching/subscription/create.ts rename to pages/api/matching/subscription/create.ts diff --git a/pages/api/teammatching/subscription/delete.ts b/pages/api/matching/subscription/delete.ts similarity index 100% rename from pages/api/teammatching/subscription/delete.ts rename to pages/api/matching/subscription/delete.ts diff --git a/pages/api/teammatching/subscription/get.ts b/pages/api/matching/subscription/get.ts similarity index 100% rename from pages/api/teammatching/subscription/get.ts rename to pages/api/matching/subscription/get.ts From 6824cf3b6cd71d1b0868d7b2c933e0042338f567 Mon Sep 17 00:00:00 2001 From: nova_44056 Date: Tue, 23 Apr 2024 14:46:12 -0500 Subject: [PATCH 7/7] fix: Check request initiator with user id in req body --- pages/api/matching/subscription/delete.ts | 10 +++++++++- pages/api/matching/subscription/get.ts | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pages/api/matching/subscription/delete.ts b/pages/api/matching/subscription/delete.ts index 945f8852..e72c434c 100644 --- a/pages/api/matching/subscription/delete.ts +++ b/pages/api/matching/subscription/delete.ts @@ -1,4 +1,4 @@ -import { firestore } from 'firebase-admin'; +import { firestore, auth } from 'firebase-admin'; import { NextApiRequest, NextApiResponse } from 'next'; import initializeApi from '../../../../lib/admin/init'; import { userIsAuthorized } from '../../../../lib/authorization/check-authorization'; @@ -14,6 +14,14 @@ interface SubscriptionData { // delete one subscription for user that unsubscribe them to a post async function deleteSubscription(req: NextApiRequest, res: NextApiResponse) { + // check if check if current logged in user matches the user id in the subscription data + const loggedInUserId = (await auth().verifyIdToken(req.headers['authorization'] as string)).uid; + if (loggedInUserId !== JSON.parse(req.body).userId) { + return res.status(403).json({ + msg: 'Unauthorized to delete subscription', + }); + } + try { const subscriptionData: SubscriptionData = JSON.parse(req.body); const snapshot = await db diff --git a/pages/api/matching/subscription/get.ts b/pages/api/matching/subscription/get.ts index 19cc1484..fb4e3961 100644 --- a/pages/api/matching/subscription/get.ts +++ b/pages/api/matching/subscription/get.ts @@ -1,4 +1,4 @@ -import { firestore } from 'firebase-admin'; +import { firestore, auth } from 'firebase-admin'; import { NextApiRequest, NextApiResponse } from 'next'; import initializeApi from '../../../../lib/admin/init'; import { userIsAuthorized } from '../../../../lib/authorization/check-authorization'; @@ -10,6 +10,14 @@ const db = firestore(); async function getSubscriptions(req: NextApiRequest, res: NextApiResponse) { try { const userId = req.query.userId as string; + const loggedInUserId = (await auth().verifyIdToken(req.headers['authorization'] as string)).uid; + + if (userId !== loggedInUserId) { + return res.status(403).json({ + msg: 'Unauthorized to get subscriptions', + }); + } + const snapshot = await db.collection('subscriptions').where('userId', '==', userId).get(); if (snapshot.empty) { return res.status(404).json({