task-svr/src/plugins/apiauth.ts
2024-05-27 16:27:19 +08:00

88 lines
2.7 KiB
TypeScript

import { FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'
import fastifyPlugin from 'fastify-plugin'
import { ActivityInfo, ActivityInfoClass } from 'models/ActivityInfo'
import { ActivityUser, ActivityUserClass } from 'models/ActivityUser'
import { ROLE_ANON } from 'zutils'
import { DocumentType } from '@typegoose/typegoose'
import { ReadOnlyCache } from 'common/ReadOnlyCache'
import { ACTIVITY_NAME } from 'common/Constants'
declare module 'fastify' {
interface FastifyRequest {
roles?: string[]
user?: DocumentType<ActivityUserClass>
activity?: DocumentType<ActivityInfoClass>
token?: string
}
interface FastifyInstance {
apiAuth: (request: FastifyRequest, reply: FastifyReply) => {}
}
}
export interface ApiAuthOptions {
secret: string
expiresIn: string
}
const checkEndList = [
'/api/activity/upload_invite_code',
'/api/chest/enhance',
'/api/chest/open',
'/api/user/checkin',
'/api/user/checkin/claim',
'/api/user/checkin/claim_seq',
'/api/game/pre_step',
'/api/game/step',
'/api/ingame/claim',
'/api/ingame/draw',
'/api/partner/claim',
'/api/tasks/begin_task',
'/api/tasks/check_task',
'/api/tasks/claim',
'/api/voucher/claim',
]
const checkEndSet = new Set(checkEndList)
const apiAuthPlugin: FastifyPluginAsync<ApiAuthOptions> = async function (fastify, opts) {
fastify.register(require('@fastify/jwt'), {
secret: opts.secret,
sign: { expiresIn: opts.expiresIn },
})
// 只有路由配置的role为anon才不需要过滤
fastify.decorate('apiAuth', async function (request: FastifyRequest, reply: FastifyReply) {
let activity = new ReadOnlyCache().getData(ACTIVITY_NAME)
if (!activity) {
activity = await ActivityInfo.findById(ACTIVITY_NAME)
if (activity) {
new ReadOnlyCache().setData(ACTIVITY_NAME, activity)
}
}
if (activity) {
if (checkEndSet.has(request.url) && Date.now() > activity.endTime) {
return reply.send({ errcode: 90, errmsg: 'activity is end' })
}
request.activity = activity
}
if (!request.roles || request.roles.indexOf(ROLE_ANON) == -1 || request.token) {
try {
if (!request.token) {
return reply.send({ errcode: 11, errmsg: 'need login' })
}
//@ts-ignore
const data = this.jwt.verify(request.token)
if (!data || !data.id) {
return reply.send({ errcode: 10, errmsg: 'need login' })
}
let account = await ActivityUser.findById(data.id)
if (!account) {
return reply.send({ errcode: 10, errmsg: 'need login' })
}
request.user = account
} catch (err) {
return reply.send({ errcode: 401, errmsg: 'need auth' })
}
}
})
}
export default fastifyPlugin(apiAuthPlugin, '4.x')