修正 mongoose 调用,添加更多输出提示
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
4d448d876e
commit
f23a607148
27
src/index.js
27
src/index.js
|
@ -1,6 +1,5 @@
|
||||||
import { fastify } from 'fastify'
|
import { fastify } from 'fastify'
|
||||||
import { mongoose } from 'mongoose'
|
import { mongoose } from 'mongoose'
|
||||||
import { registerModels } from './models/index.js';
|
|
||||||
import * as Hooks from './hooks.js'
|
import * as Hooks from './hooks.js'
|
||||||
import * as AuthenticateRoutings from './routes/authenticate.js'
|
import * as AuthenticateRoutings from './routes/authenticate.js'
|
||||||
import * as SessionServerRoutings from './routes/session.js'
|
import * as SessionServerRoutings from './routes/session.js'
|
||||||
|
@ -10,6 +9,7 @@ import { config } from './config.js'
|
||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
import { Scenes, session, Telegraf } from 'telegraf'
|
import { Scenes, session, Telegraf } from 'telegraf'
|
||||||
import { allScenes, registerAllPlayerCommands } from './telegram/player-commands.js';
|
import { allScenes, registerAllPlayerCommands } from './telegram/player-commands.js';
|
||||||
|
import { Player } from './models/player.js'
|
||||||
|
|
||||||
export const server = fastify({
|
export const server = fastify({
|
||||||
logger: {
|
logger: {
|
||||||
|
@ -21,13 +21,12 @@ export const server = fastify({
|
||||||
export const telegraf = new Telegraf(config.telegram.token)
|
export const telegraf = new Telegraf(config.telegram.token)
|
||||||
|
|
||||||
export const setup = async () => {
|
export const setup = async () => {
|
||||||
const mongooseClient = await mongoose.connect(config.database.url)
|
server.log.info("老色批世界树 > 初始化中...")
|
||||||
const models = registerModels(mongooseClient)
|
|
||||||
|
await mongoose.connect(config.database.url)
|
||||||
const publicKey = readFileSync(config.signing.public).toString()
|
const publicKey = readFileSync(config.signing.public).toString()
|
||||||
const privateKey = readFileSync(config.signing.private).toString()
|
const privateKey = readFileSync(config.signing.private).toString()
|
||||||
|
|
||||||
server.decorate('mongoose', mongooseClient)
|
|
||||||
server.decorate('models', models)
|
|
||||||
server.decorate('keys', { publicKey, privateKey })
|
server.decorate('keys', { publicKey, privateKey })
|
||||||
|
|
||||||
config.custom.preHooks(server)
|
config.custom.preHooks(server)
|
||||||
|
@ -55,7 +54,7 @@ export const setup = async () => {
|
||||||
|
|
||||||
if(process.env["UNIT_TEST"] || process.env["DEVEL_FIRST_RUN"]) {
|
if(process.env["UNIT_TEST"] || process.env["DEVEL_FIRST_RUN"]) {
|
||||||
// Create a test player
|
// Create a test player
|
||||||
await new models.Player({
|
await new Player({
|
||||||
username: 'test',
|
username: 'test',
|
||||||
password: '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92',
|
password: '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92',
|
||||||
email: 'i@lama.icu',
|
email: 'i@lama.icu',
|
||||||
|
@ -81,9 +80,8 @@ export const setup = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const launch = async () => {
|
const launch = async () => {
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', shutdown)
|
||||||
new Promise(shutdown)
|
process.on('SIGTERM', shutdown)
|
||||||
})
|
|
||||||
|
|
||||||
telegraf.launch()
|
telegraf.launch()
|
||||||
|
|
||||||
|
@ -93,9 +91,16 @@ const launch = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shutdown = async () => {
|
export const shutdown = async () => {
|
||||||
server.close()
|
await server.close()
|
||||||
telegraf.stop()
|
server.log.info("老色批世界树 > HTTP 服务器已关闭")
|
||||||
|
try {
|
||||||
|
telegraf.stop()
|
||||||
|
server.log.info("老色批世界树 > Telegram Bot 已关闭")
|
||||||
|
} catch(err) {
|
||||||
|
server.log.info("老色批世界树 > Telegram Bot 未运行,已跳过")
|
||||||
|
}
|
||||||
mongoose.disconnect()
|
mongoose.disconnect()
|
||||||
|
server.log.info("老色批世界树 > 数据库连接已断开,服务器已关闭")
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 }
|
|
|
@ -1,9 +1,8 @@
|
||||||
import mongoose from 'mongoose'
|
import mongoose from 'mongoose'
|
||||||
const { Schema } = mongoose
|
|
||||||
import { uuidToNoSymboUUID } from '../generator.js'
|
import { uuidToNoSymboUUID } from '../generator.js'
|
||||||
import { ImageSecurity } from '../secure.js'
|
import { ImageSecurity } from '../secure.js'
|
||||||
|
|
||||||
export const PlayerSchema = new Schema({
|
export const Player = mongoose.model("Player", new mongoose.Schema({
|
||||||
username: String, // 有符号 UUID
|
username: String, // 有符号 UUID
|
||||||
password: String,
|
password: String,
|
||||||
email: String,
|
email: String,
|
||||||
|
@ -18,7 +17,7 @@ export const PlayerSchema = new Schema({
|
||||||
username: String,
|
username: String,
|
||||||
verified: Boolean,
|
verified: Boolean,
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
|
|
||||||
export const PlayerSeriliazationSchema = {
|
export const PlayerSeriliazationSchema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import mongoose from 'mongoose'
|
import mongoose from 'mongoose'
|
||||||
const { Schema } = mongoose
|
|
||||||
|
|
||||||
export const TokenSchema = new Schema({
|
export const Token = mongoose.model("Token", new mongoose.Schema({
|
||||||
uuid: String,
|
uuid: String,
|
||||||
token: String,
|
token: String,
|
||||||
clientToken: String,
|
clientToken: String,
|
||||||
expireDate: Number,
|
expireDate: Number,
|
||||||
deadDate: Number,
|
deadDate: Number,
|
||||||
})
|
}))
|
|
@ -1,5 +1,6 @@
|
||||||
import { getOverrideHandler, getOverridePreHandler } from "../config.js"
|
import { getOverrideHandler, getOverridePreHandler } from "../config.js"
|
||||||
import { uuidToNoSymboUUID } from "../generator.js"
|
import { uuidToNoSymboUUID } from "../generator.js"
|
||||||
|
import { Player } from "../models/player.js"
|
||||||
|
|
||||||
export const profiles = {
|
export const profiles = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -39,7 +40,7 @@ export const profiles = {
|
||||||
},
|
},
|
||||||
handler: getOverrideHandler('/api/profiles/minecraft') ?? async function (req, rep) {
|
handler: getOverrideHandler('/api/profiles/minecraft') ?? async function (req, rep) {
|
||||||
const { body } = req
|
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 => ({
|
return await rep.code(200).send(profiles.map(profile => ({
|
||||||
id: uuidToNoSymboUUID(profile.uuid),
|
id: uuidToNoSymboUUID(profile.uuid),
|
||||||
name: profile.username
|
name: profile.username
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as PlayerModel from '../models/player.js'
|
||||||
import { createHash } from 'crypto'
|
import { createHash } from 'crypto'
|
||||||
import { generateToken, uuidToNoSymboUUID } from '../generator.js'
|
import { generateToken, uuidToNoSymboUUID } from '../generator.js'
|
||||||
import { getOverrideHandler, getOverridePreHandler } from '../config.js'
|
import { getOverrideHandler, getOverridePreHandler } from '../config.js'
|
||||||
|
import { Token } from '../models/token.js'
|
||||||
|
|
||||||
export const authenticate = {
|
export const authenticate = {
|
||||||
method: 'POST',
|
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) => {
|
if(!player || !player.permissions.some((it) => {
|
||||||
return it.node === 'login' && it.allowed && (it.duration === 0 || it.startDate + it.duration > Date.now())
|
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)
|
const profile = PlayerModel.getPlayerSerialization(player)
|
||||||
|
|
||||||
new this.models.Token({
|
new Token({
|
||||||
uuid: player.uuid,
|
uuid: player.uuid,
|
||||||
token: token,
|
token: token,
|
||||||
clientToken: clientToken,
|
clientToken: clientToken,
|
||||||
|
@ -173,7 +174,7 @@ export const refresh = {
|
||||||
if(clientToken) {
|
if(clientToken) {
|
||||||
query.clientToken = clientToken
|
query.clientToken = clientToken
|
||||||
}
|
}
|
||||||
const token = await this.models.Token.findOne(query)
|
const token = await Token.findOne(query)
|
||||||
|
|
||||||
if(!token) {
|
if(!token) {
|
||||||
return await rep.code(401).send({
|
return await rep.code(401).send({
|
||||||
|
@ -196,7 +197,7 @@ export const refresh = {
|
||||||
const [newToken, key] = generateToken(token.uuid)
|
const [newToken, key] = generateToken(token.uuid)
|
||||||
this.log.info(`/authserver/authenticate > 为玩家 ${token.uuid} 刷新令牌: ${token.uuid} 为 ${newToken} | 随机 key = ${key}`)
|
this.log.info(`/authserver/authenticate > 为玩家 ${token.uuid} 刷新令牌: ${token.uuid} 为 ${newToken} | 随机 key = ${key}`)
|
||||||
|
|
||||||
await this.models.Token.updateOne({
|
await Token.updateOne({
|
||||||
token: accessToken,
|
token: accessToken,
|
||||||
clientToken: clientToken ?? undefined
|
clientToken: clientToken ?? undefined
|
||||||
}, {
|
}, {
|
||||||
|
@ -206,7 +207,7 @@ export const refresh = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
new this.models.Token({
|
new Token({
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
token: newToken,
|
token: newToken,
|
||||||
clientToken: clientToken ?? token.clientToken,
|
clientToken: clientToken ?? token.clientToken,
|
||||||
|
@ -220,7 +221,7 @@ export const refresh = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(requestUser || selectedProfile) {
|
if(requestUser || selectedProfile) {
|
||||||
const player = await this.models.Player.findOne({ uuid })
|
const player = await PlayerModel.Player.findOne({ uuid })
|
||||||
|
|
||||||
if(requestUser) {
|
if(requestUser) {
|
||||||
response.user = {
|
response.user = {
|
||||||
|
@ -276,7 +277,7 @@ export const validate = {
|
||||||
if(clientToken) {
|
if(clientToken) {
|
||||||
query.clientToken = clientToken
|
query.clientToken = clientToken
|
||||||
}
|
}
|
||||||
const token = await this.models.Token.findOne(query)
|
const token = await Token.findOne(query)
|
||||||
|
|
||||||
if(!token) {
|
if(!token) {
|
||||||
return await rep.code(401).send({
|
return await rep.code(401).send({
|
||||||
|
@ -327,7 +328,7 @@ export const invalidate = {
|
||||||
handler: getOverrideHandler("/authserver/authenticate") ?? async function (req, rep) {
|
handler: getOverrideHandler("/authserver/authenticate") ?? async function (req, rep) {
|
||||||
const { accessToken } = req.body
|
const { accessToken } = req.body
|
||||||
|
|
||||||
const { modifiedCount } = await this.models.Token.updateOne({
|
const { modifiedCount } = await Token.updateOne({
|
||||||
token: accessToken
|
token: accessToken
|
||||||
}, {
|
}, {
|
||||||
$set: {
|
$set: {
|
||||||
|
@ -373,7 +374,7 @@ export const signout = {
|
||||||
handler: getOverrideHandler("/authserver/signout") ?? async function (req, rep) {
|
handler: getOverrideHandler("/authserver/signout") ?? async function (req, rep) {
|
||||||
const { username, password } = req.body
|
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) {
|
if(!player) {
|
||||||
return await rep.code(401).send({
|
return await rep.code(401).send({
|
||||||
error: "Unauthorized",
|
error: "Unauthorized",
|
||||||
|
@ -382,7 +383,7 @@ export const signout = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.models.Token.deleteMany({
|
await Token.deleteMany({
|
||||||
uuid: player.uuid
|
uuid: player.uuid
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { getOverrideHandler, getOverridePreHandler } from '../config.js'
|
import { getOverrideHandler, getOverridePreHandler } from '../config.js'
|
||||||
import { toSymboUUID } from '../generator.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
|
Key: string Username
|
||||||
|
@ -36,7 +37,7 @@ export const join = {
|
||||||
preHandler: getOverridePreHandler('/sessionserver/session/minecraft/join'),
|
preHandler: getOverridePreHandler('/sessionserver/session/minecraft/join'),
|
||||||
handler: getOverrideHandler('/sessionserver/session/minecraft/join') ?? async function (req, rep) {
|
handler: getOverrideHandler('/sessionserver/session/minecraft/join') ?? async function (req, rep) {
|
||||||
const { accessToken, selectedProfile, serverId } = req.body
|
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) {
|
if (!user) {
|
||||||
return await rep.code(400).send({
|
return await rep.code(400).send({
|
||||||
error: "IllegalArgumentException",
|
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) {
|
if (!session) {
|
||||||
return await rep.code(401).send({
|
return await rep.code(401).send({
|
||||||
error: "IllegalArgumentException",
|
error: "IllegalArgumentException",
|
||||||
|
@ -99,7 +100,7 @@ export const hasJoined = {
|
||||||
handler: getOverrideHandler('/sessionserver/session/minecraft/hasJoined') ?? async function (req, rep) {
|
handler: getOverrideHandler('/sessionserver/session/minecraft/hasJoined') ?? async function (req, rep) {
|
||||||
const { username, serverId, ip } = req.query
|
const { username, serverId, ip } = req.query
|
||||||
|
|
||||||
const player = await this.models.Player.findOne({ username })
|
const player = await Player.findOne({ username })
|
||||||
if (!player) {
|
if (!player) {
|
||||||
return await rep.code(400).send({
|
return await rep.code(400).send({
|
||||||
error: "IllegalArgumentException",
|
error: "IllegalArgumentException",
|
||||||
|
@ -155,7 +156,7 @@ export const profile = {
|
||||||
preHandler: getOverridePreHandler('/sessionserver/session/minecraft/profile/:uuid'),
|
preHandler: getOverridePreHandler('/sessionserver/session/minecraft/profile/:uuid'),
|
||||||
handler: getOverrideHandler('/sessionserver/session/minecraft/profile/:uuid') ?? async function (req, rep) {
|
handler: getOverrideHandler('/sessionserver/session/minecraft/profile/:uuid') ?? async function (req, rep) {
|
||||||
const { uuid } = req.params
|
const { uuid } = req.params
|
||||||
const player = await this.models.Player.findOne({ uuid: toSymboUUID(uuid) })
|
const player = await Player.findOne({ uuid: toSymboUUID(uuid) })
|
||||||
if (!player) {
|
if (!player) {
|
||||||
return await rep.code(204).send()
|
return await rep.code(204).send()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { telegraf, server } from '../index.js'
|
||||||
import { createHash } from 'crypto'
|
import { createHash } from 'crypto'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { uuid } from '../generator.js'
|
import { uuid } from '../generator.js'
|
||||||
|
import { Player } from '../models/player.js'
|
||||||
|
|
||||||
export const registerAllPlayerCommands = async () => {
|
export const registerAllPlayerCommands = async () => {
|
||||||
await register()
|
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')
|
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) {
|
if(duplicated) {
|
||||||
return ctx.reply(`该密码hash为:${ctx.scene.session.data.password.substring(3,10)} 已检测到数据库中存在重复密码(${JSON.stringify({d: 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
|
let verified = false
|
||||||
if(ctx.scene.session.data.inviteCode) {
|
if(ctx.scene.session.data.inviteCode) {
|
||||||
await telegraf.telegram.editMessageText(ctx.chat.id, message.message_id, null, message.text + '\n验证邀请码中...')
|
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
|
token: ctx.scene.session.data.inviteCode
|
||||||
})
|
})
|
||||||
if(invi) {
|
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),
|
uuid: uuid("LSP-yggdrasil:" + ctx.scene.session.data.playerUsername),
|
||||||
username: ctx.scene.session.data.playerUsername,
|
username: ctx.scene.session.data.playerUsername,
|
||||||
password: ctx.scene.session.data.password,
|
password: ctx.scene.session.data.password,
|
||||||
|
@ -192,7 +193,7 @@ const register = async () => {
|
||||||
return ctx.reply("请设置 Telegram 用户名!")
|
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)
|
server.log.info(player)
|
||||||
if(!player) {
|
if(!player) {
|
||||||
return ctx.scene.enter('REGISTRIATION_WIZARD')
|
return ctx.scene.enter('REGISTRIATION_WIZARD')
|
||||||
|
|
|
@ -20,7 +20,7 @@ beforeAll(() => {
|
||||||
writeFileSync('private.key', privateKey)
|
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()
|
return setup()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue