Files
ToneAPI_backend/src/server/server.ts
T

274 lines
7.4 KiB
TypeScript

import { Router } from 'express'
import { body, header } from 'express-validator'
import { CreateKillRecord, CheckServerToken } from '../db/db'
import { validateErrors } from '../common'
const router = Router()
//auth middleware
router.post(
'/*',
header('authorization')
.exists({ checkFalsy: true })
.withMessage('Missing Authorization Header')
.bail()
.custom(e => e.split(' ')[0].toLowerCase() == 'bearer')
.withMessage('Authorization Token is not Bearer'),
validateErrors,
async (req, res, next) => {
if (!req) return res.sendStatus(500)
if (!req.headers.authorization) return res.sendStatus(403)
const query = await CheckServerToken(req.headers.authorization.split(' ')[1])
if (!query || !query.id) return res.sendStatus(403)
next()
}
)
//Route to check auth
router.post('/', (req, res) => {
res.sendStatus(200)
})
const serversCount: { [id: string]: number } = {}
const serversTimeout: { [id: string]: NodeJS.Timeout } = {}
//same rate limiting code as register. max 10 kills per server every 1 sec. should be enough.
/*router.post('/kill', (req, res, next) => {
let host = Number(req.query.serverId)
if (serversCount[serverId] > 2) {
return res.status(429).json({
error: 'too many requests. Are players really making that much kills ?'
})
}
clearTimeout(serversTimeout[serverId])
serversCount[serverId] =
serversCount[serverId] ?? (serversCount[serverId] + 1) | 1
serversTimeout[serverId] = setTimeout(() => {
serversCount[serverId] = 0
}, 1000)
next()
})*/
router.post(
'/kill',
body([
'attacker_current_weapon_mods',
'attacker_weapon_1_mods',
'attacker_weapon_2_mods',
'attacker_weapon_3_mods',
'attacker_offhand_weapon_1_mods',
'attacker_offhand_weapon_2_mods',
'victim_current_weapon_mods',
'victim_weapon_1_mods',
'victim_weapon_2_mods',
'victim_weapon_3_mods',
'victim_offhand_weapon_1_mods',
'victim_offhand_weapon_2_mods'
]).customSanitizer((value) => {
if (isNaN(value) || !value) {
value = 0
}
return value
}),
body([
'attacker_current_weapon_mods',
'attacker_weapon_1_mods',
'attacker_weapon_2_mods',
'attacker_weapon_3_mods',
'attacker_offhand_weapon_1_mods',
'attacker_offhand_weapon_2_mods',
'victim_current_weapon_mods',
'victim_weapon_1_mods',
'victim_weapon_2_mods',
'victim_weapon_3_mods',
'victim_offhand_weapon_1_mods',
'victim_offhand_weapon_2_mods'
])
.toInt()
.isInt()
.withMessage('must be a valid int'),
body(['distance', 'player_count'])
.toInt()
.isInt()
.withMessage('must be a valid int'),
body(['distance', 'game_time'])
.toFloat()
.isFloat()
.withMessage('must be a valid float'),
body(
[
'attacker_id',
'victim_id',
'killstat_version',
'match_id',
'game_mode',
'map',
'attacker_name',
'attacker_current_weapon',
'attacker_weapon_1',
'attacker_weapon_2',
'attacker_weapon_3',
'attacker_offhand_weapon_1',
'attacker_offhand_weapon_2',
'victim_name',
'victim_current_weapon',
'victim_weapon_1',
'victim_weapon_2',
'victim_weapon_3',
'victim_offhand_weapon_1',
'victim_offhand_weapon_2',
'cause_of_death',
'victim_titan',
'attacker_titan'
],
'must be composed of a maximum of 50 valid ascii characters'
)
.isString()
.isLength({ max: 50 })
.isAscii(),
body('servername',).isString()
.isLength({ max: 100 })
.isAscii(),
body(['distance', 'game_time'], 'must be postitive floats').isFloat({
min: 0
}),
body(['cause_of_death', 'victim_id'], 'mandatory').exists().notEmpty(),
//do we need this ?
//body('servername').customSanitizer(e => e.replace(/[^a-z0-9]/gi, '')),
validateErrors,
async (req, res) => {
if (!req.headers.authorization) return res.sendStatus(403)
const headers = req.headers.authorization.split(' ')
if (headers[0].toLowerCase() != "bearer") return res.status(403).send("authorization must be token bearer")
const query = (await CheckServerToken(headers[1]))
if (!query) return res.sendStatus(403)
const host = query.id
const {
servername,
killstat_version,
match_id,
game_mode,
map,
game_time,
player_count,
attacker_name,
attacker_id,
attacker_current_weapon,
attacker_current_weapon_mods,
attacker_weapon_1,
attacker_weapon_1_mods,
attacker_weapon_2,
attacker_weapon_2_mods,
attacker_weapon_3,
attacker_weapon_3_mods,
attacker_offhand_weapon_1,
attacker_offhand_weapon_1_mods,
attacker_offhand_weapon_2,
attacker_offhand_weapon_2_mods,
victim_name,
victim_id,
victim_current_weapon,
victim_current_weapon_mods,
victim_weapon_1,
victim_weapon_1_mods,
victim_weapon_2,
victim_weapon_2_mods,
victim_weapon_3,
victim_weapon_3_mods,
victim_offhand_weapon_1,
victim_offhand_weapon_1_mods,
victim_offhand_weapon_2,
victim_offhand_weapon_2_mods,
cause_of_death,
distance
} = req.body
CreateKillRecord({
killstat_version,
servername,
host,
match_id,
game_mode,
map,
game_time,
player_count,
attacker_name,
attacker_id,
attacker_current_weapon,
attacker_current_weapon_mods,
attacker_weapon_1,
attacker_weapon_1_mods,
attacker_weapon_2,
attacker_weapon_2_mods,
attacker_weapon_3,
attacker_weapon_3_mods,
attacker_offhand_weapon_1,
attacker_offhand_weapon_1_mods,
attacker_offhand_weapon_2,
attacker_offhand_weapon_2_mods,
victim_name,
victim_id,
victim_current_weapon,
victim_current_weapon_mods,
victim_weapon_1,
victim_weapon_1_mods,
victim_weapon_2,
victim_weapon_2_mods,
victim_weapon_3,
victim_weapon_3_mods,
victim_offhand_weapon_1,
victim_offhand_weapon_1_mods,
victim_offhand_weapon_2,
victim_offhand_weapon_2_mods,
cause_of_death,
distance
})
.then((e) => {
res.sendStatus(201)
console.log(
`[${Date.now().toLocaleString()}] Kill submitted for server ${servername}, ${attacker_name} killed ${victim_name}`
)
})
.catch((e) => {
res.sendStatus(500)
console.log({
killstat_version,
servername,
host,
match_id,
game_mode,
map,
game_time,
player_count,
attacker_name,
attacker_id,
attacker_current_weapon,
attacker_current_weapon_mods,
attacker_weapon_1,
attacker_weapon_1_mods,
attacker_weapon_2,
attacker_weapon_2_mods,
attacker_weapon_3,
attacker_weapon_3_mods,
attacker_offhand_weapon_1,
attacker_offhand_weapon_2,
victim_name,
victim_id,
victim_current_weapon,
victim_current_weapon_mods,
victim_weapon_1,
victim_weapon_1_mods,
victim_weapon_2,
victim_weapon_2_mods,
victim_weapon_3,
victim_weapon_3_mods,
victim_offhand_weapon_1,
victim_offhand_weapon_2,
cause_of_death,
distance
})
console.error(e)
})
}
)
export default router