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 activity?: DocumentType 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 = 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')