Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"dotenv": "^16.4.5",
"express": "^4.21.2",
"express-asyncify": "^2.1.2",
"express-cargo": "^0.4.0",
"express-winston": "^4.2.0",
"firebase-admin": "^13.4.0",
"helmet": "^8.0.0",
Expand All @@ -33,6 +34,7 @@
"mongoose-paginate-v2": "^1.8.5",
"node-fetch": "^2.7.0",
"node-schedule": "^2.1.1",
"reflect-metadata": "^0.2.2",
"winston": "^3.16.0",
"winston-daily-rotate-file": "^5.0.0"
},
Expand Down
10 changes: 7 additions & 3 deletions apps/server/src/controllers/v1/enquiries.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import express, { Request, Response, Router } from 'express'
import asyncify from 'express-asyncify'
import { bindingCargo, getCargo } from 'express-cargo'

import { EnquiryModel } from '@/models'
import { verifyToken } from '@/middlewares/auth'
import { PostEnquiryPayload } from '@/types/payload/enquiry'

const router: Router = asyncify(express.Router())

router.post('/', verifyToken, async (req: Request, res: Response) => {
router.post('/', verifyToken, bindingCargo(PostEnquiryPayload), async (req: Request, res: Response) => {
const { title, body } = getCargo<PostEnquiryPayload>(req)

const enquiry = await EnquiryModel.create({
userId: req.user._id,
title: req.body.title,
body: req.body.body,
title,
body,
})
res.status(200).json({
enquiryId: enquiry._id,
Expand Down
239 changes: 122 additions & 117 deletions apps/server/src/controllers/v1/events.ts

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions apps/server/src/controllers/v1/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import express, { Router } from 'express'
import asyncify from 'express-asyncify'
import { bindingCargo, getCargo } from 'express-cargo'

import { NotificationModel, NotificationTokenModel } from '@/models'
import { verifyToken } from '@/middlewares/auth'
import { GetNotificationPayload, PostNotificationReadPayload, PutNotificationTokenPayload } from '@/types/payload'

const router: Router = asyncify(express.Router())

router.get('/', verifyToken, async (req, res) => {
const options = { sort: { createdAt: -1 }, page: Number(req.query.page) || 1, limit: Number(req.query.limit) || 10 }
router.get('/', verifyToken, bindingCargo(GetNotificationPayload), async (req, res) => {
const { page, limit } = getCargo<GetNotificationPayload>(req)
const options = { sort: { createdAt: -1 }, page, limit }
const result = await NotificationModel.findByUserId(req.user._id, options)
res.status(200).json({
notifications: result.docs,
Expand All @@ -22,12 +25,13 @@ router.get('/', verifyToken, async (req, res) => {
})
})

router.put('/token', verifyToken, async (req, res) => {
router.put('/token', verifyToken, bindingCargo(PutNotificationTokenPayload), async (req, res) => {
const { deviceId, token, platform } = getCargo<PutNotificationTokenPayload>(req)
await NotificationTokenModel.findOneAndUpdate(
{ deviceId: req.body.deviceId },
{ deviceId: deviceId },
{
token: req.body.token,
platform: req.body.platform,
token: token,
platform: platform,
userId: req.user._id,
},
{
Expand All @@ -37,8 +41,9 @@ router.put('/token', verifyToken, async (req, res) => {
res.sendStatus(204)
})

router.post('/:id/read', verifyToken, async (req, res) => {
await NotificationModel.updateOne({ _id: req.params.id }, { isRead: true })
router.post('/:id/read', verifyToken, bindingCargo(PostNotificationReadPayload), async (req, res) => {
const { id } = getCargo<PostNotificationReadPayload>(req)
await NotificationModel.updateOne({ _id: id }, { isRead: true })
res.sendStatus(204)
})

Expand Down
11 changes: 7 additions & 4 deletions apps/server/src/controllers/v1/s3.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import express, { Router } from 'express'
import asyncify from 'express-asyncify'
import { bindingCargo, getCargo } from 'express-cargo'

import { s3 } from '@/services/aws'
import { AWS_S3_BUCKET } from '@/config'
import { GetS3UploadUrlPayload, GetS3ViewUrlPayload } from '@/types/payload'

const router: Router = asyncify(express.Router())

router.get('/upload-url', async (req, res) => {
const fileName = String(req.query.fileName)
router.get('/upload-url', bindingCargo(GetS3UploadUrlPayload), async (req, res) => {
const { fileName } = getCargo<GetS3UploadUrlPayload>(req)

const params = {
Bucket: AWS_S3_BUCKET!,
Expand All @@ -18,8 +21,8 @@ router.get('/upload-url', async (req, res) => {
res.json({ presignedUrl })
})

router.get('/view-url', async (req, res) => {
const key = req.query.key as string
router.get('/view-url', bindingCargo(GetS3ViewUrlPayload), async (req, res) => {
const { key } = getCargo<GetS3ViewUrlPayload>(req)

const params = {
Bucket: AWS_S3_BUCKET!,
Expand Down
56 changes: 24 additions & 32 deletions apps/server/src/controllers/v1/schedules.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import asyncify from 'express-asyncify'
import express, { Request, Response, Router } from 'express'
import { bindingCargo, getCargo } from 'express-cargo'

import { ScheduleModel } from '@/models'
import middlewares from '@/middlewares'
import { getUserDailyScheduleCount } from '@/services/schedule'
import { GetScheduleDailyCountPayload, GetSchedulePayload, IdPayload, PostSchedulePayload, PutSchedulePayload } from '@/types/payload'

const router: Router = asyncify(express.Router())
router.use(middlewares.auth.verifyToken)

router.post('/', middlewares.schedules.addScheduleMiddleware, async (req: Request, res: Response) => {
const { name, eventId, startDate, endDate, address, location, description, isAllDay } = req.body
router.post('/', bindingCargo(PostSchedulePayload), middlewares.schedules.addScheduleMiddleware, async (req: Request, res: Response) => {
const { name, eventId, startDate, endDate, address, location, description, isAllDay } = getCargo<PostSchedulePayload>(req)
const schedule = await ScheduleModel.create({
name: name,
eventId: eventId,
Expand All @@ -26,55 +28,45 @@ router.post('/', middlewares.schedules.addScheduleMiddleware, async (req: Reques
})
})

router.get('/', async (req: Request, res: Response) => {
const options = {
page: Number(req.query.page) || 0,
limit: Number(req.query.limit) || 100,
}

const filterOption = {
from: new Date(req.query.from as string) || new Date(0),
to: new Date(req.query.to as string) || new Date(),
}
router.get('/', bindingCargo(GetSchedulePayload), async (req: Request, res: Response) => {
const { from: fromString, to: toString, page, limit } = getCargo<GetSchedulePayload>(req)
const today = new Date()
const from = fromString ? new Date(fromString) : new Date(today.getFullYear(), today.getMonth(), today.getDate())
const to = toString ? new Date(toString) : new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1)
Comment thread
yuchem2 marked this conversation as resolved.
Outdated

const userId = req.user?._id.toString()
const schedules = await ScheduleModel.findByUserId(userId, filterOption, options)
const schedules = await ScheduleModel.findByUserId(userId, { from, to }, { page, limit })

res.status(200).json(schedules)
})

router.get('/dailyCount', async (req: Request, res: Response) => {
const from = new Date(req.query.from as string) || new Date(0)
const to = new Date(req.query.to as string) || new Date()
const timezone = (req.query.timezone as string) || 'Asia/Seoul'
router.get('/dailyCount', bindingCargo(GetScheduleDailyCountPayload), async (req: Request, res: Response) => {
const { from: fromString, to: toString, timezone } = getCargo<GetScheduleDailyCountPayload>(req)
const today = new Date()
const from = fromString ? new Date(fromString) : new Date(today.getFullYear(), today.getMonth(), today.getDate())
const to = toString ? new Date(toString) : new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1)
Comment thread
yuchem2 marked this conversation as resolved.
Outdated

const dailyScheduleCount = await getUserDailyScheduleCount(req.user, from, to, timezone)
res.status(200).json(dailyScheduleCount)
})

router.get('/:id', middlewares.schedules.verifyAuthorMiddleware, async (req: Request, res: Response) => {
const schedule = await ScheduleModel.findOne({ _id: req.params.id })
router.get('/:id', bindingCargo(IdPayload), middlewares.schedules.verifyAuthorMiddleware, async (req: Request, res: Response) => {
const { id } = getCargo<IdPayload>(req)
const schedule = await ScheduleModel.findOne({ _id: id })
res.status(200).json(schedule)
})

router.delete('/:id', middlewares.schedules.verifyAuthorMiddleware, async (req: Request, res: Response) => {
await ScheduleModel.deleteOne({ _id: req.params.id })
router.delete('/:id', bindingCargo(IdPayload), middlewares.schedules.verifyAuthorMiddleware, async (req: Request, res: Response) => {
const { id } = getCargo<IdPayload>(req)
await ScheduleModel.deleteOne({ _id: id })
res.sendStatus(204)
})

router.put('/:id', middlewares.schedules.verifyAuthorMiddleware, async (req: Request, res: Response) => {
const { id } = req.params
const { name, startDate, endDate, description, location, address } = req.body
router.put('/:id', bindingCargo(PutSchedulePayload), middlewares.schedules.verifyAuthorMiddleware, async (req: Request, res: Response) => {
const { id, name, startDate, endDate, isAllDay, description, location, address } = getCargo<PutSchedulePayload>(req)
const updated = await ScheduleModel.findOneAndUpdate(
{ _id: id },
{
name: name,
startDate: startDate,
endDate: endDate,
description: description,
address: address,
location: location,
},
{ name, startDate, endDate, isAllDay, description, address, location },
{ new: true },
)
res.status(200).json(updated)
Expand Down
30 changes: 15 additions & 15 deletions apps/server/src/controllers/v1/users.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import asyncify from 'express-asyncify'
import express, { Request, Response, Router } from 'express'

import { loginRequest, loginResponse, refreshResponse, registerRequest, registerResponse } from '@fienmee/types'
import asyncify from 'express-asyncify'
import { bindingCargo, getCargo } from 'express-cargo'
import { loginResponse, refreshResponse, registerResponse } from '@fienmee/types'

import { DeletedUserError, UnknownUserError } from '@/types/errors/oauth'
import { InvalidTokenTypeError } from '@/types/errors'
import { UserModel } from '@/models'
import { issueAccessToken, getOAuthUser, expireJwt, issueRefreshToken, unlinkUser } from '@/services/oauth'
import { verifyToken } from '@/middlewares/auth'
import { registerUser } from '@/services/user'
import { PostRegisterPayload, PostUserGoogleTokenPayload, PostUserInterestPayload, PostUserLoginPayload } from '@/types/payload'

const router: Router = asyncify(express.Router())

router.post('/login', async (req: Request, res: Response) => {
const request: loginRequest = req.body
router.post('/login', bindingCargo(PostUserLoginPayload), async (req: Request, res: Response) => {
const request = getCargo<PostUserLoginPayload>(req)

const oauthUser = await getOAuthUser(request)
const user = await UserModel.findByProviderId(oauthUser.providerId)
Expand Down Expand Up @@ -41,11 +42,9 @@ router.delete('/logout', async (req: Request, res: Response) => {
res.sendStatus(204)
})

router.post('/register', async (req: Request, res: Response) => {
const request: registerRequest = req.body

router.post('/register', bindingCargo(PostRegisterPayload), async (req: Request, res: Response) => {
const request = getCargo<PostRegisterPayload>(req)
const oauthUser = await getOAuthUser(request)

const user = await registerUser(oauthUser)

const accessToken = issueAccessToken(user)
Expand Down Expand Up @@ -92,8 +91,8 @@ router.delete('/', verifyToken, async (req: Request, res: Response) => {
res.sendStatus(204)
})

router.post('/google-token', async (req: Request, res: Response) => {
const serverAuthCode = req.body.code as string
router.post('/google-token', bindingCargo(PostUserGoogleTokenPayload), async (req: Request, res: Response) => {
const { code: serverAuthCode } = getCargo<PostUserGoogleTokenPayload>(req)

const params = new URLSearchParams()
params.append('code', serverAuthCode)
Expand All @@ -114,13 +113,14 @@ router.post('/google-token', async (req: Request, res: Response) => {
res.json(data.refresh_token)
})

router.put('/interest', verifyToken, async (req: Request, res: Response) => {
const isInterested = req.user.interests.some(category => category._id === req.body.interest)
router.put('/interest', verifyToken, bindingCargo(PostUserInterestPayload), async (req: Request, res: Response) => {
const { interest } = getCargo<PostUserInterestPayload>(req)
const isInterested = req.user.interests.some(category => category._id === interest)

if (isInterested) {
await UserModel.removeInterest(req.user._id, req.body.interest)
await UserModel.removeInterest(req.user._id, interest)
} else {
await UserModel.addInterest(req.user._id, req.body.interest)
await UserModel.addInterest(req.user._id, interest)
}

res.sendStatus(204)
Expand Down
27 changes: 27 additions & 0 deletions apps/server/src/types/payload/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { array, body, defaultValue, equal, params, query, validate } from 'express-cargo'

export class LocationType {
@body()
@equal('Point')
type: string

@body()
@array(Number)
@validate(value => Array.isArray(value) && value.length === 2)
coordinates: number[]
}

export class PaginationPayload {
@query()
@defaultValue(1)
page!: number

@query()
@defaultValue(10)
limit!: number
}

export class IdPayload {
@params()
id: string
}
10 changes: 10 additions & 0 deletions apps/server/src/types/payload/enquiry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { body } from 'express-cargo'
import { IEnquiryFormInputs } from '@fienmee/types'

export class PostEnquiryPayload implements IEnquiryFormInputs {
@body()
title: string

@body()
body: string
}
Loading