From f23a607148d047c3f96286ffc3346cd080074a26 Mon Sep 17 00:00:00 2001 From: "Qumolama.d" Date: Mon, 16 May 2022 13:19:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20mongoose=20=E8=B0=83?= =?UTF-8?q?=E7=94=A8=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=9B=B4=E5=A4=9A=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 27 ++++++++++++++++----------- src/models/index.js | 11 ----------- src/models/invite.js | 9 --------- src/models/player.js | 5 ++--- src/models/token.js | 5 ++--- src/routes/api.js | 3 ++- src/routes/authenticate.js | 21 +++++++++++---------- src/routes/session.js | 11 ++++++----- src/telegram/player-commands.js | 9 +++++---- tests/routings/authenticate.test.js | 2 +- 10 files changed, 45 insertions(+), 58 deletions(-) delete mode 100644 src/models/index.js delete mode 100644 src/models/invite.js diff --git a/src/index.js b/src/index.js index b087478..57a1933 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,5 @@ import { fastify } from 'fastify' import { mongoose } from 'mongoose' -import { registerModels } from './models/index.js'; import * as Hooks from './hooks.js' import * as AuthenticateRoutings from './routes/authenticate.js' import * as SessionServerRoutings from './routes/session.js' @@ -10,6 +9,7 @@ import { config } from './config.js' import { readFileSync } from 'fs' import { Scenes, session, Telegraf } from 'telegraf' import { allScenes, registerAllPlayerCommands } from './telegram/player-commands.js'; +import { Player } from './models/player.js' export const server = fastify({ logger: { @@ -21,13 +21,12 @@ export const server = fastify({ export const telegraf = new Telegraf(config.telegram.token) export const setup = async () => { - const mongooseClient = await mongoose.connect(config.database.url) - const models = registerModels(mongooseClient) + server.log.info("老色批世界树 > 初始化中...") + + await mongoose.connect(config.database.url) const publicKey = readFileSync(config.signing.public).toString() const privateKey = readFileSync(config.signing.private).toString() - server.decorate('mongoose', mongooseClient) - server.decorate('models', models) server.decorate('keys', { publicKey, privateKey }) config.custom.preHooks(server) @@ -55,7 +54,7 @@ export const setup = async () => { if(process.env["UNIT_TEST"] || process.env["DEVEL_FIRST_RUN"]) { // Create a test player - await new models.Player({ + await new Player({ username: 'test', password: '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', email: 'i@lama.icu', @@ -81,9 +80,8 @@ export const setup = async () => { } const launch = async () => { - process.on('SIGINT', () => { - new Promise(shutdown) - }) + process.on('SIGINT', shutdown) + process.on('SIGTERM', shutdown) telegraf.launch() @@ -93,9 +91,16 @@ const launch = async () => { } export const shutdown = async () => { - server.close() - telegraf.stop() + await server.close() + server.log.info("老色批世界树 > HTTP 服务器已关闭") + try { + telegraf.stop() + server.log.info("老色批世界树 > Telegram Bot 已关闭") + } catch(err) { + server.log.info("老色批世界树 > Telegram Bot 未运行,已跳过") + } mongoose.disconnect() + server.log.info("老色批世界树 > 数据库连接已断开,服务器已关闭") } (async () => { diff --git a/src/models/index.js b/src/models/index.js deleted file mode 100644 index 054a3bd..0000000 --- a/src/models/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import { TokenSchema } from "./token.js"; -import { PlayerSchema } from "./player.js"; -import { InviteTokenSchema } from "./invite.js"; - -export function registerModels(mongoose) { - return { - Token: mongoose.model("Token", TokenSchema), - Player: mongoose.model("Player", PlayerSchema), - Invitation: mongoose.model('Invitation', InviteTokenSchema) - } -} \ No newline at end of file diff --git a/src/models/invite.js b/src/models/invite.js deleted file mode 100644 index b0ec129..0000000 --- a/src/models/invite.js +++ /dev/null @@ -1,9 +0,0 @@ -import mongoose from 'mongoose' -const { Schema } = mongoose - -export const InviteTokenSchema = new Schema({ - by: String, // Telegram username - token: String -}) - -// { from: string, id: number, sign: string } \ No newline at end of file diff --git a/src/models/player.js b/src/models/player.js index cfa605f..324a6cf 100644 --- a/src/models/player.js +++ b/src/models/player.js @@ -1,9 +1,8 @@ import mongoose from 'mongoose' -const { Schema } = mongoose import { uuidToNoSymboUUID } from '../generator.js' import { ImageSecurity } from '../secure.js' -export const PlayerSchema = new Schema({ +export const Player = mongoose.model("Player", new mongoose.Schema({ username: String, // 有符号 UUID password: String, email: String, @@ -18,7 +17,7 @@ export const PlayerSchema = new Schema({ username: String, verified: Boolean, } -}) +})) export const PlayerSeriliazationSchema = { "type": "object", diff --git a/src/models/token.js b/src/models/token.js index 0e5e634..9369652 100644 --- a/src/models/token.js +++ b/src/models/token.js @@ -1,10 +1,9 @@ import mongoose from 'mongoose' -const { Schema } = mongoose -export const TokenSchema = new Schema({ +export const Token = mongoose.model("Token", new mongoose.Schema({ uuid: String, token: String, clientToken: String, expireDate: Number, deadDate: Number, -}) \ No newline at end of file +})) \ No newline at end of file diff --git a/src/routes/api.js b/src/routes/api.js index aab5f56..05c380c 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -1,5 +1,6 @@ import { getOverrideHandler, getOverridePreHandler } from "../config.js" import { uuidToNoSymboUUID } from "../generator.js" +import { Player } from "../models/player.js" export const profiles = { method: 'POST', @@ -39,7 +40,7 @@ export const profiles = { }, handler: getOverrideHandler('/api/profiles/minecraft') ?? async function (req, rep) { const { body } = req - const profiles = await this.models.Player.find({ username: { $in: body } }) + const profiles = await Player.find({ username: { $in: body } }) return await rep.code(200).send(profiles.map(profile => ({ id: uuidToNoSymboUUID(profile.uuid), name: profile.username diff --git a/src/routes/authenticate.js b/src/routes/authenticate.js index 9fe587a..442dbec 100644 --- a/src/routes/authenticate.js +++ b/src/routes/authenticate.js @@ -2,6 +2,7 @@ import * as PlayerModel from '../models/player.js' import { createHash } from 'crypto' import { generateToken, uuidToNoSymboUUID } from '../generator.js' import { getOverrideHandler, getOverridePreHandler } from '../config.js' +import { Token } from '../models/token.js' export const authenticate = { method: 'POST', @@ -67,7 +68,7 @@ export const authenticate = { }) } - const player = await this.models.Player.findOne({ email: username, password: createHash('sha256').update(password).digest().toString('hex').toLowerCase() }) + const player = await PlayerModel.Player.findOne({ email: username, password: createHash('sha256').update(password).digest().toString('hex').toLowerCase() }) if(!player || !player.permissions.some((it) => { return it.node === 'login' && it.allowed && (it.duration === 0 || it.startDate + it.duration > Date.now()) })) { @@ -104,7 +105,7 @@ export const authenticate = { const profile = PlayerModel.getPlayerSerialization(player) - new this.models.Token({ + new Token({ uuid: player.uuid, token: token, clientToken: clientToken, @@ -173,7 +174,7 @@ export const refresh = { if(clientToken) { query.clientToken = clientToken } - const token = await this.models.Token.findOne(query) + const token = await Token.findOne(query) if(!token) { return await rep.code(401).send({ @@ -196,7 +197,7 @@ export const refresh = { const [newToken, key] = generateToken(token.uuid) this.log.info(`/authserver/authenticate > 为玩家 ${token.uuid} 刷新令牌: ${token.uuid} 为 ${newToken} | 随机 key = ${key}`) - await this.models.Token.updateOne({ + await Token.updateOne({ token: accessToken, clientToken: clientToken ?? undefined }, { @@ -206,7 +207,7 @@ export const refresh = { } }) - new this.models.Token({ + new Token({ uuid: uuid, token: newToken, clientToken: clientToken ?? token.clientToken, @@ -220,7 +221,7 @@ export const refresh = { } if(requestUser || selectedProfile) { - const player = await this.models.Player.findOne({ uuid }) + const player = await PlayerModel.Player.findOne({ uuid }) if(requestUser) { response.user = { @@ -276,7 +277,7 @@ export const validate = { if(clientToken) { query.clientToken = clientToken } - const token = await this.models.Token.findOne(query) + const token = await Token.findOne(query) if(!token) { return await rep.code(401).send({ @@ -327,7 +328,7 @@ export const invalidate = { handler: getOverrideHandler("/authserver/authenticate") ?? async function (req, rep) { const { accessToken } = req.body - const { modifiedCount } = await this.models.Token.updateOne({ + const { modifiedCount } = await Token.updateOne({ token: accessToken }, { $set: { @@ -373,7 +374,7 @@ export const signout = { handler: getOverrideHandler("/authserver/signout") ?? async function (req, rep) { const { username, password } = req.body - const player = await this.models.Player.findOne({ email: username, password: createHash('sha256').update(password).digest().toString('hex').toLowerCase() }) + const player = await PlayerModel.Player.findOne({ email: username, password: createHash('sha256').update(password).digest().toString('hex').toLowerCase() }) if(!player) { return await rep.code(401).send({ error: "Unauthorized", @@ -382,7 +383,7 @@ export const signout = { }) } - await this.models.Token.deleteMany({ + await Token.deleteMany({ uuid: player.uuid }) diff --git a/src/routes/session.js b/src/routes/session.js index 83ac921..0d0c3a0 100644 --- a/src/routes/session.js +++ b/src/routes/session.js @@ -1,6 +1,7 @@ import { getOverrideHandler, getOverridePreHandler } from '../config.js' import { toSymboUUID } from '../generator.js' -import { getPlayerSerialization, PlayerSeriliazationSchema } from '../models/player.js' +import { getPlayerSerialization, Player, PlayerSeriliazationSchema } from '../models/player.js' +import { Token } from '../models/token.js' /* Key: string Username @@ -36,7 +37,7 @@ export const join = { preHandler: getOverridePreHandler('/sessionserver/session/minecraft/join'), handler: getOverrideHandler('/sessionserver/session/minecraft/join') ?? async function (req, rep) { const { accessToken, selectedProfile, serverId } = req.body - const user = await await this.models.Player.findOne({ uuid: toSymboUUID(selectedProfile) }) + const user = await await Player.findOne({ uuid: toSymboUUID(selectedProfile) }) if (!user) { return await rep.code(400).send({ error: "IllegalArgumentException", @@ -45,7 +46,7 @@ export const join = { }) } - const session = await this.models.Token.findOne({ token: accessToken }) + const session = await Token.findOne({ token: accessToken }) if (!session) { return await rep.code(401).send({ error: "IllegalArgumentException", @@ -99,7 +100,7 @@ export const hasJoined = { handler: getOverrideHandler('/sessionserver/session/minecraft/hasJoined') ?? async function (req, rep) { const { username, serverId, ip } = req.query - const player = await this.models.Player.findOne({ username }) + const player = await Player.findOne({ username }) if (!player) { return await rep.code(400).send({ error: "IllegalArgumentException", @@ -155,7 +156,7 @@ export const profile = { preHandler: getOverridePreHandler('/sessionserver/session/minecraft/profile/:uuid'), handler: getOverrideHandler('/sessionserver/session/minecraft/profile/:uuid') ?? async function (req, rep) { const { uuid } = req.params - const player = await this.models.Player.findOne({ uuid: toSymboUUID(uuid) }) + const player = await Player.findOne({ uuid: toSymboUUID(uuid) }) if (!player) { return await rep.code(204).send() } diff --git a/src/telegram/player-commands.js b/src/telegram/player-commands.js index 066b7d2..b3d3d2f 100644 --- a/src/telegram/player-commands.js +++ b/src/telegram/player-commands.js @@ -3,6 +3,7 @@ import { telegraf, server } from '../index.js' import { createHash } from 'crypto' import axios from 'axios' import { uuid } from '../generator.js' +import { Player } from '../models/player.js' export const registerAllPlayerCommands = async () => { await register() @@ -38,7 +39,7 @@ const registerWizard = new Scenes.WizardScene('REGISTRIATION_WIZARD', ctx.scene.session.data.password = createHash('sha256').update(ctx.message.text).digest('hex') - const duplicated = await server.models.Player.findOne({ password: ctx.scene.session.data.password }) + const duplicated = await Player.findOne({ password: ctx.scene.session.data.password }) if(duplicated) { return ctx.reply(`该密码hash为:${ctx.scene.session.data.password.substring(3,10)} 已检测到数据库中存在重复密码(${JSON.stringify({d: duplicated})}),为了安全请重新输入`) } @@ -139,7 +140,7 @@ const registerWizard = new Scenes.WizardScene('REGISTRIATION_WIZARD', let verified = false if(ctx.scene.session.data.inviteCode) { await telegraf.telegram.editMessageText(ctx.chat.id, message.message_id, null, message.text + '\n验证邀请码中...') - const invi = server.models.Invitation.findOne({ + const invi = Invitation.findOne({ token: ctx.scene.session.data.inviteCode }) if(invi) { @@ -150,7 +151,7 @@ const registerWizard = new Scenes.WizardScene('REGISTRIATION_WIZARD', } } - const player = new server.models.Player({ + const player = new Player({ uuid: uuid("LSP-yggdrasil:" + ctx.scene.session.data.playerUsername), username: ctx.scene.session.data.playerUsername, password: ctx.scene.session.data.password, @@ -192,7 +193,7 @@ const register = async () => { return ctx.reply("请设置 Telegram 用户名!") } - const player = await server.models.Player.findOne({ "telegramBind.username": username }) + const player = await Player.findOne({ "telegramBind.username": username }) server.log.info(player) if(!player) { return ctx.scene.enter('REGISTRIATION_WIZARD') diff --git a/tests/routings/authenticate.test.js b/tests/routings/authenticate.test.js index e0fd462..d2ace4b 100644 --- a/tests/routings/authenticate.test.js +++ b/tests/routings/authenticate.test.js @@ -20,7 +20,7 @@ beforeAll(() => { writeFileSync('private.key', privateKey) } - config.database.url = 'mongodb://setup-database:27017/yggdrasil?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false' + //config.database.url = 'mongodb://setup-database:27017/yggdrasil?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false' return setup() })