feat: delete "deleteSession" method, validate questId and sessionId

This commit is contained in:
wancat authored and Lin, Hung-Shin committed 2023-11-14 10:44:52 +08:00
1 parent a7422853fa
commit 5df4967a85
12 files changed
+67 -99

No files matched your search

@@ -13,7 +13,7 @@ export async function newCommand(req, res) {
return
}
const sessionId = req.user.session_id
const { sessionId } = req.user
const session = await Session.findById(sessionId)
@@ -64,7 +64,7 @@ export async function newCommand(req, res) {
}
export async function completedCommand(req, res) {
const sessionId = req.user.session_id
const { sessionId } = req.user
const session = await Session.findById(sessionId)
@@ -1,4 +1,5 @@
import { Quest } from '@linux-odyssey/models'
import { matchedData } from 'express-validator'
export async function getQuests(req, res) {
const quests = await Quest.find({}).sort({ order: 1 })
@@ -12,8 +13,8 @@ export async function getQuests(req, res) {
}
export async function getQuestDetail(req, res) {
const { id } = req.params
const quest = await Quest.findById(id)
const { questId } = matchedData(req)
const quest = await Quest.findById(questId)
if (!quest) {
res.status(404).json({ message: 'Quest not found.' })
return
+10 -26
View File
@@ -28,10 +28,11 @@ function sessionDetail(session) {
export async function getSessionList(req, res) {
try {
const query = { user: req.user._id }
if (req.query.quest_id) {
query.quest = req.query.quest_id
const { questId, status } = matchedData(req)
if (questId) {
query.quest = questId
}
query.status = req.query.status || 'active'
query.status = status || 'active'
const sessions = await Session.find(query)
res.json(sessions.map(sessionSummary))
} catch (err) {
@@ -41,9 +42,9 @@ export async function getSessionList(req, res) {
}
export async function createSession(req, res) {
const { quest_id } = matchedData(req)
const { questId } = matchedData(req)
try {
const session = await createNewSession(req.user, quest_id)
const session = await createNewSession(req.user, questId)
res.status(201).json(sessionDetail(session))
} catch (err) {
console.error(err)
@@ -53,8 +54,9 @@ export async function createSession(req, res) {
export async function getSessionById(req, res) {
try {
const { sessionId } = matchedData(req)
const session = await Session.findOne({
_id: req.params.id,
_id: sessionId,
user: req.user._id,
})
@@ -69,28 +71,10 @@ export async function getSessionById(req, res) {
}
}
export async function deleteSessionById(req, res) {
try {
const session = await Session.findOneAndDelete({
_id: req.params.id,
user: req.user._id,
})
if (!session) {
res.status(404).json({ message: 'Session not found.' })
return
}
res.status(204).end()
} catch (err) {
res.status(500).json({ message: err.message })
}
}
export async function getOrCreateSession(req, res) {
const { quest_id } = matchedData(req)
const { questId } = matchedData(req)
try {
const session = await getOrCreateActiveSession(req.user, quest_id)
const session = await getOrCreateActiveSession(req.user, questId)
res.json(sessionDetail(session))
} catch (err) {
console.error(err)
+2 -1
View File
@@ -1,9 +1,10 @@
import { Router } from 'express'
import * as questController from '../controllers/questController.js'
import { questIdValidator } from '../validators/questValidator.js'
const router = Router()
router.get('/', questController.getQuests)
router.get('/:id', questController.getQuestDetail)
router.get('/:questId', questIdValidator, questController.getQuestDetail)
export default router
+4 -3
View File
@@ -4,11 +4,13 @@ import { sessionRateLimit } from '../../middleware/rateLimiter.js'
import {
createSessionValidator,
activeSessionValidator,
sessionListValidator,
sessionDetailValidator,
} from '../validators/sessionValidator.js'
const router = Router()
router.get('/', sessionController.getSessionList)
router.get('/', sessionListValidator, sessionController.getSessionList)
router.post(
'/',
createSessionValidator,
@@ -20,7 +22,6 @@ router.post(
activeSessionValidator,
sessionController.getOrCreateSession
)
router.get('/:id', sessionController.getSessionById)
router.delete('/:id', sessionController.deleteSessionById)
router.get('/:id', sessionDetailValidator, sessionController.getSessionById)
export default router
+15 -17
View File
@@ -1,8 +1,10 @@
import { Server } from 'socket.io'
import validator from 'validator'
import { Session } from '@linux-odyssey/models'
import { getAndStartContainer, attachContainer } from '../containers/docker.js'
import SessionMiddleware from '../middleware/session.js'
import { genJWT } from '../utils/auth.js'
import { checkSessionId } from './validators/sessionValidator.js'
const sessions = new Map()
@@ -26,33 +28,26 @@ export function pushToSession(sessionId, event, ...args) {
}
}
async function connectClient(socket) {
async function connectClient(socket, next) {
const user = socket.request.session?.passport?.user
if (!user) {
socket.send('User not found.')
socket.disconnect()
next(new Error('User not found.'))
return
}
const sessionId = socket.handshake.query.session_id
if (!sessionId) {
socket.emit('error', 'Session ID not found.')
socket.disconnect()
const { sessionId } = socket.handshake.query
if (!validator.isMongoId(sessionId)) {
next(new Error('Invalid Session ID.'))
return
}
const session = await Session.findOne({
_id: sessionId,
user,
status: 'active',
})
const session = await Session.findById(sessionId)
if (!session) {
socket.emit('error', 'Session not found.')
socket.disconnect()
next(new Error('Session not found.'))
return
}
const token = await genJWT({
session_id: session.id,
sessionId: session.id,
})
let container
@@ -61,8 +56,7 @@ async function connectClient(socket) {
container = await getAndStartContainer(session.containerId)
stream = await attachContainer(container, { token })
} catch (err) {
socket.emit('error', 'Failed to start container.')
socket.disconnect()
next(new Error('Failed to start container.'))
return
}
@@ -95,6 +89,10 @@ export default (server) => {
const io = new Server(server)
io.engine.use(SessionMiddleware)
io.engine.use(checkSessionId())
io.on('connection', connectClient)
io.on('connect_error', (err) => {
console.error(err)
})
}
@@ -0,0 +1,11 @@
import { check } from 'express-validator'
import { noError } from '../../middleware/validator.js'
export const checkQuestId = () =>
check('questId').notEmpty().isString().isAlphanumeric().isLength({ max: 64 })
export const questIdValidator = [checkQuestId(), noError]
export default {
questIdValidator,
}
+14 -2
View File
@@ -1,8 +1,20 @@
import { check } from 'express-validator'
import { checkQuestId } from './questValidator.js'
import { noError } from '../../middleware/validator.js'
const checkQuestId = () =>
check('quest_id').notEmpty().isString().isLowercase().isLength({ max: 64 })
const checkSessionStatus = () =>
check('status')
.isString()
.custom((value) => ['active', 'inactive', 'finished'].includes(value))
export const checkSessionId = () =>
check('sessionId').notEmpty().isString().isMongoId()
export const sessionListValidator = [
checkQuestId(),
checkSessionStatus(),
noError,
]
export const sessionDetailValidator = [checkSessionId(), noError]
export const createSessionValidator = [checkQuestId(), noError]
export const activeSessionValidator = [checkQuestId(), noError]