diff --git a/game-server/app.ts b/game-server/app.ts index 57ed9072a..ae001dfb9 100644 --- a/game-server/app.ts +++ b/game-server/app.ts @@ -16,7 +16,7 @@ import * as redisService from './app/services/redisService'; import './app/servers/user.rpc.define' import * as routeUtil from './app/util/routeUtil'; import { preload } from './preload'; -var checkEventFilter = require('./app/servers/battle/filter/checkEventFilter'); +var globalFilter = require('./app/servers/connector/filter/global'); import { connectRedis } from './config/redis'; import * as timeTaskService from './app/services/timeTaskService'; import * as redlockCacheService from './app/services/redlockCacheService'; @@ -198,7 +198,7 @@ app.configure(ALL_ENVS, function () { app.filter(new pinus.filters.time()); app.filter(new pinus.filters.timeout()); - app.filter(checkEventFilter(app)); + app.filter(globalFilter(app)); // RPC 启用TCP协议 app.set('proxyConfig', { diff --git a/game-server/app/servers/battle/filter/checkEventFilter.ts b/game-server/app/servers/battle/filter/checkEventFilter.ts deleted file mode 100644 index e346283cb..000000000 --- a/game-server/app/servers/battle/filter/checkEventFilter.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback} from "pinus"; -import {checkEvent} from '../../../services/eventSercive'; -import { refresh } from '../../../services/refreshService'; -module.exports = function(app: Application) { - return new Filter(app); -} - -var Filter = function(this: any, app: Application) { - this.app = app; -}; - -Filter.prototype.before = function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { - - next(null); -}; - -Filter.prototype.after = function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { - //刷新 - refresh(session); - return checkEvent(session).then(()=>{ - next(err); - }).catch(e => { - console.error(e); - next(err); - }); // 奇遇本检查 -}; \ No newline at end of file diff --git a/game-server/app/servers/chat/remote/chatRemote.ts b/game-server/app/servers/chat/remote/chatRemote.ts index e5900a5db..715e595b8 100644 --- a/game-server/app/servers/chat/remote/chatRemote.ts +++ b/game-server/app/servers/chat/remote/chatRemote.ts @@ -239,4 +239,17 @@ export class ChatRemote { if (!channel) return; channel.pushMessage(path, resResult(STATUS.SUCCESS, data)); } + + /** + * @description 全服推送维护 + * @param serverId + */ + public async sendServerMaintenance(serverId: number) { + + let roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); + let channel = this.channelService.getChannel(roomId, false); + if (!channel) return { result: false, serverId }; + channel.pushMessage('onServerMaintenance', resResult(STATUS.SERVER_MAINTENANCE)); + return { result: true, serverId }; + } } diff --git a/game-server/app/servers/connector/filter/global.ts b/game-server/app/servers/connector/filter/global.ts new file mode 100644 index 000000000..4028599cb --- /dev/null +++ b/game-server/app/servers/connector/filter/global.ts @@ -0,0 +1,45 @@ +import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback, pinus} from "pinus"; +import { checkEvent } from '../../../services/eventSercive'; +import { refresh } from '../../../services/refreshService'; +import { getWorldChannelSid } from "../../../services/chatService"; +import { resResult, checkWhiteListWithUid } from "../../../pubUtils/util"; +import { STATUS } from "../../../consts"; +import { UserModel } from "../../../db/User"; +module.exports = function(app: Application) { + return new Filter(app); +} + +var Filter = function(this: any, app: Application) { + this.app = app; +}; + +Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + const roleId: string = session.get('roleId'); + const uid: number = session.get('userid'); + + let connectorServers = pinus.app.getServersByType('connector'); + let { id } = connectorServers[0]; + let maintenServers = await pinus.app.rpc.connector.connectorRemote.getServerMainten.toServer(id); + if(maintenServers.indexOf(serverId) != -1) { // 该服务器维护 + let isWhiteList = await checkWhiteListWithUid(uid); + if(isWhiteList) next(null); + + pinus.app.get('channelService').pushMessageByUids('onServerMaintenance', resResult(STATUS.SERVER_MAINTENANCE), [{ uid: roleId, sid }]); + next(new Error(), resResult(STATUS.SERVER_MAINTENANCE)); + } + + next(null); +}; + +Filter.prototype.after = function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { + //刷新 + refresh(session); + return checkEvent(session).then(()=>{ + next(err); + }).catch(e => { + console.error(e); + next(err); + }); // 奇遇本检查 +}; \ No newline at end of file diff --git a/game-server/app/servers/connector/handler/entryHandler.ts b/game-server/app/servers/connector/handler/entryHandler.ts index 6398a6968..0172789ad 100644 --- a/game-server/app/servers/connector/handler/entryHandler.ts +++ b/game-server/app/servers/connector/handler/entryHandler.ts @@ -118,6 +118,7 @@ export class EntryHandler { async addSession(role: RoleType, session: FrontendSession) { const self = this; await session.abind(role.roleId); + session.set('userid', role.userInfo.uid); session.set('uid', role.roleId); session.set('roleId', role.roleId); let updatedMailAt = role.updatedMailAt ? role.updatedMailAt : 0; @@ -128,6 +129,7 @@ export class EntryHandler { session.set('serverId', role.serverId); session.set('funcs', role.funcs || []); session.set('guildCode', role.guildCode); + session.push('userid', () => { }); session.push('sid', () => { }); session.push('roleId', () => { }); session.push('roleName', () => { }); diff --git a/game-server/app/servers/connector/remote/connectorRemote.ts b/game-server/app/servers/connector/remote/connectorRemote.ts index 6f8b1b0a5..a9074e541 100644 --- a/game-server/app/servers/connector/remote/connectorRemote.ts +++ b/game-server/app/servers/connector/remote/connectorRemote.ts @@ -13,6 +13,7 @@ export class ConnectorRemote { this.channelService = app.get('channelService'); } private channelService: ChannelService; + private maintenServers: number[] = []; // 维护中的服务器 public async remoteLogin(uid: string) { let sessionService = this.app.get('sessionService'); @@ -22,7 +23,7 @@ export class ConnectorRemote { let roleId = session.get('roleId'); let sid = session.get('sid'); let uids = [{uid: roleId, sid}]; - this.channelService.pushMessageByUids('onRemoteLogin', resResult(STATUS.LOGIN_ERR ), uids); + this.channelService.pushMessageByUids('onRemoteLogin', resResult(STATUS.SERVER_MAINTENANCE ), uids); }); } await sessionService.akick(uid); @@ -42,4 +43,12 @@ export class ConnectorRemote { public async reloadResources() { reloadResources(); } + + public setServerMainten(maintenServers: number[]) { + return this.maintenServers = maintenServers; + } + + public getServerMainten() { + return this.maintenServers; + } } diff --git a/game-server/app/servers/gm/handler/gmHandler.ts b/game-server/app/servers/gm/handler/gmHandler.ts index 4001be3ca..5d23a264a 100644 --- a/game-server/app/servers/gm/handler/gmHandler.ts +++ b/game-server/app/servers/gm/handler/gmHandler.ts @@ -12,6 +12,8 @@ import { SendMailFun } from '../../../services/mailService'; import { GM_MAIL_TYPE } from '../../../consts'; import { RewardInter } from '../../../pubUtils/interface'; import { MarqueeModel } from '../../../db/Marquee'; +import { ServerlistModel } from '../../../db/Serverlist'; +import { getWorldChannelSid } from '../../../services/chatService'; export default function(app: Application) { return new GmHandler(app); } @@ -183,4 +185,24 @@ export class GmHandler { } return resResult(STATUS.SUCCESS); } + + async sendMaintenance(msg: { serverType: string }, session: BackendSession) { + const { serverType } = msg; + let allServers = await ServerlistModel.findByServerType(serverType); + let results = []; + for(let { serverId } of allServers) { + let chatSid = await getWorldChannelSid(serverId); + let result = await this.app.rpc.chat.chatRemote.sendServerMaintenance.toServer(chatSid, serverId); + results.push(result); + } + return resResult(STATUS.SUCCESS, results); + } + + async setMaintenance() { + let connectorServers = pinus.app.getServersByType('connector'); + for(let { id } of connectorServers) { + pinus.app.rpc.connector.connectorRemote.setServerMainten.toServer(id, [1]); + } + return resResult(STATUS.SUCCESS); + } } \ No newline at end of file diff --git a/game-server/app/servers/role/handler/roleHandler.ts b/game-server/app/servers/role/handler/roleHandler.ts index 8df004e99..f4860d7ff 100644 --- a/game-server/app/servers/role/handler/roleHandler.ts +++ b/game-server/app/servers/role/handler/roleHandler.ts @@ -66,7 +66,7 @@ export class RoleHandler { await checkPvp(role); return resResult(STATUS.SUCCESS, { - roleId, roleName, heroes + roleId, roleName, ...heroes }) } diff --git a/game-server/app/servers/systimer/remote/systimerRemote.ts b/game-server/app/servers/systimer/remote/systimerRemote.ts index a82a1dbce..f950b64fb 100644 --- a/game-server/app/servers/systimer/remote/systimerRemote.ts +++ b/game-server/app/servers/systimer/remote/systimerRemote.ts @@ -3,7 +3,7 @@ import { resetPvpSeasonTime, setPvpDefResult, guildActivityStart, gateActivityEn import PvpDefenseType from '../../../db/PvpDefense'; import { DicGuildActivity } from '../../../pubUtils/dictionary/DicGuildActivity'; import { reloadResources } from '../../../pubUtils/data'; -import { setMarquee, cancelMarquee } from '../../../services/marqueeService'; +import { setMarquee, cancelMarquee } from '../../../services/gmService'; export default function (app: Application) { return new SystimerRemote(app); diff --git a/game-server/app/services/marqueeService.ts b/game-server/app/services/gmService.ts similarity index 60% rename from game-server/app/services/marqueeService.ts rename to game-server/app/services/gmService.ts index eb7651468..3453c2157 100644 --- a/game-server/app/services/marqueeService.ts +++ b/game-server/app/services/gmService.ts @@ -1,10 +1,17 @@ import { MarqueeType, MarqueeModel } from "../db/Marquee"; -import { MARQUEE_TYPE, STATUS } from "../consts"; +import { MARQUEE_TYPE, STATUS, SERVER_STATUS } from "../consts"; import { scheduleJob, scheduledJobs, Job } from 'node-schedule'; import { createMarqueeMsg as sysCreateMarqueeMsg, pushMarqueeMsg as sysPushMarqueeMsg } from './sysChatService'; import { GroupMessageType } from "../db/GroupMessage"; import { resResult } from "../pubUtils/util"; +import { MaintenanceModel, MaintenanceType } from '../db/Maintenance'; +import { pinus } from "pinus"; +import { getWorldChannelSid } from "./chatChannelService"; +import { ServerlistModel } from "../db/Serverlist"; +import { NoticeModel, NoticeType } from "../db/Notice"; +// —————————————— 跑马灯 —————————————— // +// 初始 export async function initMarquee() { const marquees = await MarqueeModel.findEffectiveMarque(); for(let marquee of marquees) { @@ -24,6 +31,9 @@ export async function setMarquee(code: string) { } async function generateMarqueeSchedule(marquee: MarqueeType) { + let setSecondsMarquee = scheduledJobs[`setSeconds${marquee.code}`]; + if(setSecondsMarquee) return false; // 已经在运行中了 + if(marquee.type != MARQUEE_TYPE.SCHEDULE) return false; if(marquee.startTime.getTime() >= marquee.endTime.getTime()) return false; if(marquee.endTime.getTime() < Date.now()) return false; @@ -88,4 +98,44 @@ export async function cancelMarquee(code: string) { if(endMarquee) endMarquee.cancel(); await MarqueeModel.updateData(code, { isRunning: false }); return true +} + +// —————————————— 停服维护 —————————————— // +// 维护信息 +export async function initMaintenance() { + const maintenance = await MaintenanceModel.findOpenMaintenance(); + if(maintenance) { + let { startTime, marquee } = maintenance; + if(marquee) await generateMarqueeSchedule(marquee); + if(Date.now() > startTime.getTime()) { + await startMaintenance(maintenance); + } else { + let startJob = scheduleJob(`startMainten${maintenance.code}`, startTime.getTime(), async () => { + await startMaintenance(maintenance, startJob); + }); + } + } +} + +async function startMaintenance(maintenance: MaintenanceType, startJob?: Job) { + // 向全服发送 + let { serverIds, notice } = maintenance; + for(let serverId of serverIds) { + let chatSid = await getWorldChannelSid(serverId); + await pinus.app.rpc.chat.chatRemote.sendServerMaintenance.toServer(chatSid, serverId); + } + + // 更新serverlist上的status + await ServerlistModel.updateByServerIds(serverIds, { serverStatus: SERVER_STATUS.MAINTENANCE }); + // 更新notice的isEnable + if(notice) { + await NoticeModel.updateNotice((notice).id, { isEnable: true }); + } + + // 更新connectorRemote里面的 + let connectorServers = pinus.app.getServersByType('connector'); + for(let { id } of connectorServers) { + pinus.app.rpc.connector.connectorRemote.setServerMainten.toServer(id, serverIds); + } + if(startJob) startJob.cancel(); } \ No newline at end of file diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 3ffacee5b..ac6a474bc 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -1,5 +1,5 @@ -import { scheduleJob, Job } from 'node-schedule'; +import { scheduleJob, Job, scheduledJobs } from 'node-schedule'; import { SystemConfigModel } from '../db/SystemConfig'; import PvpDefenseType,{ PvpDefenseModel } from '../db/PvpDefense'; import { PVP } from '../pubUtils/dicParam'; @@ -27,7 +27,7 @@ import { dispatch } from '../util/dispatcher'; import { Rank } from './rankService'; import { checkTask } from './taskService'; import { everydayRefresh } from './connectorService'; -import { initMarquee } from './marqueeService'; +import { initMarquee, initMaintenance } from './gmService'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -87,6 +87,9 @@ export async function init() { // 跑马灯 await initMarquee(); + + // 维护信息 + await initMaintenance(); } function setPvpSeasonSchdule() { diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index aca01bd82..a40a2da46 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -675,4 +675,16 @@ export const GACHA_OCCUPY_HID = 9999; // 抽卡里占位的武将 export enum MARQUEE_TYPE { INSTANT = 1, // 发送后立刻推送 SCHEDULE = 2, // 定时器 +} + +export enum SERVER_STATUS { + NEW = 1, // 新服 + HOT = 2, // 火爆 + WILL_OPEN = 3, // 即将开启 + MAINTENANCE = 4, // 维护中 +} + +export enum WHITE_LIST_TYPE { + IP = 1, // ip地址 + TEL = 2, // 玩家手机号 } \ No newline at end of file diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index d84a40098..757958964 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -7,6 +7,7 @@ export const STATUS = { CONNECTOR_ERR: { code: 4, simStr: '连接服配置错误' }, LOGIN_ERR: { code: 5, simStr: '检测到您的账号异地登录,已被迫下线' }, REDLOCK_ERR: { code: 6, simStr: 'redlock错误' }, + SERVER_MAINTENANCE: { code: 7, simStr: '服务器维护中' }, GLOBAL_ERR: { code: 1003, simStr: '服务器内部错误' }, // 账号相关状态 10000 - 19999 diff --git a/shared/db/Maintenance.ts b/shared/db/Maintenance.ts new file mode 100644 index 000000000..2018527d3 --- /dev/null +++ b/shared/db/Maintenance.ts @@ -0,0 +1,52 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose'; +import Marquee from './Marquee'; +import Notice from './Notice'; +import GMMail from './GMMail'; + +/** + * 开服策略 +*/ +@index({ id: 1 }) + +export default class Maintenance extends BaseModel { + + @prop({ required: true }) + code: string; // 策略唯一标志 + + @prop({ required: true, type: Number }) + serverIds: number[]; // 服务器类型 + + @prop({ required: true }) + isOpen: boolean; // 维护是否使用 + + @prop({ required: true }) + startTime: Date; // 维护开始时间 + + @prop({ ref: 'Marquee', type: mongoose.Schema.Types.ObjectId }) + marquee: Ref; // 跑马灯,连接到marquee表 + + @prop({ ref: 'Notice', type: mongoose.Schema.Types.ObjectId }) + notice: Ref; // 维护公告 + + @prop({ ref: 'Notice', type: mongoose.Schema.Types.ObjectId }) + mail: Ref; // 维护结束邮件 + + + public static async findOpenMaintenance() { + const rec: MaintenanceType = await MaintenanceModel.findOne({ isOpen: true }, { _id: 0 }).populate('marquee').populate('notice').lean(); + return rec; + } + + public static async findByCode(code: string) { + const rec: MaintenanceType = await MaintenanceModel.findOne({ code }).lean(); + return rec; + } + + +} + +export const MaintenanceModel = getModelForClass(Maintenance); + +export interface MaintenanceType extends Pick, keyof Maintenance> { } +export type MaintenanceTypeParam = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/db/Serverlist.ts b/shared/db/Serverlist.ts index 010ec415d..a17c774eb 100644 --- a/shared/db/Serverlist.ts +++ b/shared/db/Serverlist.ts @@ -2,7 +2,7 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; import { GameModel } from './Game'; import { CounterModel } from './Counter'; -import { COUNTER } from '../consts'; +import { COUNTER, SERVER_STATUS } from '../consts'; import { ServerStategyTypeParam } from './ServerStategy'; import { getServerName, getServerGroupName } from '../pubUtils/data'; @@ -39,7 +39,7 @@ export default class Serverlist extends BaseModel { @prop({ required: false, default: 3014 }) port: number; // pinus端口 - @prop({ required: true, default: 1 }) + @prop({ required: true, default: 1, enum: SERVER_STATUS }) serverStatus: number; // 服务器状态 @prop({ required: true, type: Number }) @@ -50,7 +50,7 @@ export default class Serverlist extends BaseModel { if (now > this.openTime) { return this.serverStatus; } else { - return 3; // 未开服 + return SERVER_STATUS.WILL_OPEN; // 未开服 } } @@ -81,6 +81,11 @@ export default class Serverlist extends BaseModel { return server; } + public static async updateByServerIds(serverIds: number[], update: ServerlistUpdate) { + const result = await ServerlistModel.updateMany({ id: { $in: serverIds } }, { $set: update }); + return result; + } + public static async updateGroupName(groupId: number, groupName: string) { let server = await ServerlistModel.updateMany({ groupId }, { $set: { groupName } }); return server; @@ -175,6 +180,7 @@ export default class Serverlist extends BaseModel { let result = await ServerlistModel.updateMany({ activityGroupId: { $elemMatch: { $eq: groupId } }}, { $pull: { activityGroupId: groupId } }, { new: true }).lean(true); return result; } + } export const ServerlistModel = getModelForClass(Serverlist); diff --git a/shared/db/User.ts b/shared/db/User.ts index 3abde4bf0..5a4a12ace 100644 --- a/shared/db/User.ts +++ b/shared/db/User.ts @@ -105,7 +105,7 @@ export default class User extends BaseModel { @prop({ required: false, default: "" }) getuiCID: string; - public static async createUser(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, guestTime: number = 0) { + public static async createUser(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, guestTime: number = 0, ip: string = '') { let _tel = aesEncryptcfb(tel, ENCRYPT_KEY, ENCRYPT_IV); const curTime: Date = new Date(); @@ -113,7 +113,7 @@ export default class User extends BaseModel { const userCode = genCode(8); const doc = new UserModel(); let update = {}; - update = Object.assign(update, doc.toJSON(), { platform, pkgName, serverType, createTime: curTime, uid, userCode, username: `用户${uid}`, isGuest, token, lastLoginTime: curTime, guestTime }); + update = Object.assign(update, doc.toJSON(), { platform, pkgName, serverType, createTime: curTime, uid, userCode, username: `用户${uid}`, isGuest, token, lastLoginTime: curTime, guestTime, ip }); if (isGuest) update["guestId"] = _tel; delete update["device"]; @@ -126,11 +126,11 @@ export default class User extends BaseModel { return user; } - public static async updateToken(tel: string, token: string, deviceId: string) { + public static async updateToken(tel: string, token: string, deviceId: string, ip: string) { const curTime: Date = new Date(); - let user = await UserModel.findOneAndUpdate({ tel }, { $set: { token, lastLoginTime: curTime }, $addToSet: { device: deviceId } }, { new: true }).lean({ getters: true }); + let user = await UserModel.findOneAndUpdate({ tel }, { $set: { token, lastLoginTime: curTime, ip }, $addToSet: { device: deviceId } }, { new: true }).lean({ getters: true }); return user; } @@ -139,14 +139,14 @@ export default class User extends BaseModel { return user; } - public static async createOrUpdate(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string) { + public static async createOrUpdate(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, ip: string) { // console.log(tel); let user: UserType = await UserModel.findOne({ tel }).lean({ getters: true }); if (!user) { - user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId); + user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId, 0, ip); } else { - user = await UserModel.updateToken(tel, token, deviceId); + user = await UserModel.updateToken(tel, token, deviceId, ip); } return user; } @@ -185,7 +185,7 @@ export default class User extends BaseModel { } public static async findUserByToken(token: string) { - const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth tel userCode pkgName').lean({ getters: true }); + const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth tel userCode pkgName ip').lean({ getters: true }); return user; } diff --git a/shared/db/WhiteList.ts b/shared/db/WhiteList.ts new file mode 100644 index 000000000..796a27485 --- /dev/null +++ b/shared/db/WhiteList.ts @@ -0,0 +1,27 @@ +import BaseModel from './BaseModel'; +import { getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; +import { WHITE_LIST_TYPE } from '../consts'; + +export default class WhiteList extends BaseModel { + + @prop({ required: true, enum: WHITE_LIST_TYPE }) + type: WHITE_LIST_TYPE; // 区号 + + @prop({ required: true }) + str: string; // ip或手机号 + + public static async checkIp(ip: string) { + const rec: WhiteListModelType = await WhiteListModel.findOne({ type: WHITE_LIST_TYPE.IP, str: ip }).lean(); + return rec; + } + + public static async checkTel(tel: string) { + const rec: WhiteListModelType = await WhiteListModel.findOne({ type: WHITE_LIST_TYPE.TEL, str: tel }).lean(); + return rec; + } +} + +export const WhiteListModel = getModelForClass(WhiteList); + +export interface WhiteListModelType extends Pick, keyof WhiteList> { } +export type WhiteListModelTypeParam = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/pubUtils/util.ts b/shared/pubUtils/util.ts index ae468e1ca..67ae2fc53 100644 --- a/shared/pubUtils/util.ts +++ b/shared/pubUtils/util.ts @@ -9,6 +9,8 @@ import { HERO_CE_RATIO, ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME } from '../const import { findIndex } from 'underscore'; import { getTimeFunM } from './timeUtil'; import { Floor } from '../domain/activityField/gachaField'; +import { WhiteListModel } from '../db/WhiteList'; +import { UserModel } from '../db/User'; const randomName = require("chinese-random-name"); const moment = require('moment'); const crypto = require('crypto'); @@ -580,4 +582,26 @@ export function getFloorStatus(gachaId: number, floor: Floor[]) { count: floorMap.get(id) || 0 } }); +} + +export async function checkWhiteListWithUid(uid: number) { + let user = await UserModel.findUserByUid(uid); + if(!user) return false; + let { tel, ip, auth } = user; + return await checkWhiteList(tel, ip, auth); +} + +export async function checkWhiteList(tel: string, ip: string, auth: number) { + if(auth == 1) { + return true; + } + if(tel) { + let result = await WhiteListModel.checkTel(tel); + if(!!result) return true; + } + if(ip) { + let result = await WhiteListModel.checkIp(ip); + if(!!result) return true; + } + return false } \ No newline at end of file diff --git a/web-server/app.ts b/web-server/app.ts index 8f17a36f6..e01e353ce 100644 --- a/web-server/app.ts +++ b/web-server/app.ts @@ -27,6 +27,8 @@ export default class FooBoot implements IBoot { async willReady() { // All plugins have started, can do some thing before app ready. // await this.customLoadModel(); + const ctx = await this.app.createAnonymousContext(); + await ctx.service.game.readDbMaintenance(); } async didReady() { diff --git a/web-server/app/middleware/checkMainten.ts b/web-server/app/middleware/checkMainten.ts new file mode 100644 index 000000000..e00d0139a --- /dev/null +++ b/web-server/app/middleware/checkMainten.ts @@ -0,0 +1,22 @@ +import { STATUS } from '@consts'; +import { checkWhiteList } from 'app/pubUtils/util'; + +module.exports = () => { + return async function checkMainten(ctx, next) { + const { serverId } = ctx.request.body; + if (serverId) { + let maintenServers = ctx.service.game.getServerMainten(); + if (maintenServers.indexOf(serverId) != -1) { + let isWhiteList = await checkWhiteList(ctx.tel, ctx.request.ip, ctx.auth); + if (isWhiteList) { + await next(); + } else { + ctx.body = ctx.service.utils.resResult(STATUS.SERVER_MAINTENANCE); + return; + } + } + } + await next(); + }; +}; + diff --git a/web-server/app/middleware/tokenParser.ts b/web-server/app/middleware/tokenParser.ts index c7806f9f8..45d170b6d 100644 --- a/web-server/app/middleware/tokenParser.ts +++ b/web-server/app/middleware/tokenParser.ts @@ -19,6 +19,7 @@ module.exports = () => { ctx.auth = user.auth; ctx.userCode = user.userCode; ctx.pkgName = user.pkgName; + ctx.tel = user.tel; await next(); }; }; diff --git a/web-server/app/router.ts b/web-server/app/router.ts index fc6755a75..cc7ce9d4e 100644 --- a/web-server/app/router.ts +++ b/web-server/app/router.ts @@ -3,6 +3,7 @@ import { Application } from 'egg'; export default (app: Application) => { const { controller, router } = app; const tokenParser = app.middleware.tokenParser(); + const checkMainten = app.middleware.checkMainten(); router.get('/dev', controller.home.dev); router.get('/dev/smscode', controller.account.getSmsCode); router.get('/', controller.home.index); @@ -11,8 +12,8 @@ export default (app: Application) => { router.post('/user/smslogin', controller.account.smsLogin); router.post('/user/setpassword', tokenParser, controller.account.setPassword); router.post('/user/pwlogin', controller.account.pwLogin); - router.post('/user/checkrole', tokenParser, controller.account.checkRole); - router.post('/user/createrole', tokenParser, controller.account.createRole); + router.post('/user/checkrole', tokenParser, checkMainten, controller.account.checkRole); + router.post('/user/createrole', tokenParser, checkMainten, controller.account.createRole); router.post('/user/bind', tokenParser, controller.account.bind); router.post('/user/authentication', tokenParser, controller.account.authentication); router.post('/game/getserverlist', tokenParser, controller.game.getServerList); diff --git a/web-server/app/service/Auth.ts b/web-server/app/service/Auth.ts index 4fda240f6..a0d15f9f3 100644 --- a/web-server/app/service/Auth.ts +++ b/web-server/app/service/Auth.ts @@ -25,6 +25,7 @@ export default class Auth extends Service { public async deviceLogin(isGuest: boolean, token: string, deviceId: string, platform: string, pkgName: string, serverType: string, getuiCID: string) { const ctx = this.ctx; + const ip = ctx.request.ip; let user = await UserModel.findUserByToken(token); @@ -41,7 +42,7 @@ export default class Auth extends Service { }); } else { - user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId); + user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId, 0, ip); if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } @@ -61,7 +62,7 @@ export default class Auth extends Service { } } else { const token = ctx.service.utils.generateStr(256); - user = await UserModel.updateToken(user.tel, token, deviceId); + user = await UserModel.updateToken(user.tel, token, deviceId, ip); if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(user.tel, getuiCID); } @@ -187,6 +188,7 @@ export default class Auth extends Service { */ public async smsLogin(tel: string, deviceId: string, code: string, platform: string, pkgName: string, serverType: string, getuiCID: string) { const ctx = this.ctx; + const ip = ctx.request.ip; // 参数检查 const telVerify = this.checkTelNo(tel); if (telVerify.status !== 0) { @@ -216,7 +218,7 @@ export default class Auth extends Service { // 用户注册登录 const token = ctx.service.utils.generateStr(256); - const user = await UserModel.createOrUpdate(false, tel, token, platform, pkgName, serverType, deviceId); + const user = await UserModel.createOrUpdate(false, tel, token, platform, pkgName, serverType, deviceId, ip); if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } diff --git a/web-server/app/service/Game.ts b/web-server/app/service/Game.ts new file mode 100644 index 000000000..583eedfca --- /dev/null +++ b/web-server/app/service/Game.ts @@ -0,0 +1,26 @@ + +import { Service } from 'egg'; +import { MaintenanceModel } from '@db/Maintenance'; + +/** + * Test Service + */ +export default class Game extends Service { + + public setServerMainten(maintenServers: number[]) { + return this.app['maintenServers'] = maintenServers; + } + + public getServerMainten() { + return this.app['maintenServers']||[]; + } + + public async readDbMaintenance() { + const maintenance = await MaintenanceModel.findOpenMaintenance(); + if(maintenance) { + this.setServerMainten(maintenance.serverIds); + } + } + + +} diff --git a/web-server/typings/app/middleware/index.d.ts b/web-server/typings/app/middleware/index.d.ts index 73de247a7..f795f5782 100644 --- a/web-server/typings/app/middleware/index.d.ts +++ b/web-server/typings/app/middleware/index.d.ts @@ -2,12 +2,14 @@ // Do not modify this file!!!!!!!!! import 'egg'; +import ExportCheckMainten from '../../../app/middleware/checkMainten'; import ExportGmTokenParser from '../../../app/middleware/gmTokenParser'; import ExportParmsDecode from '../../../app/middleware/parmsDecode'; import ExportTokenParser from '../../../app/middleware/tokenParser'; declare module 'egg' { interface IMiddleware { + checkMainten: typeof ExportCheckMainten; gmTokenParser: typeof ExportGmTokenParser; parmsDecode: typeof ExportParmsDecode; tokenParser: typeof ExportTokenParser; diff --git a/web-server/typings/app/service/index.d.ts b/web-server/typings/app/service/index.d.ts index 4b808972a..348680ab7 100644 --- a/web-server/typings/app/service/index.d.ts +++ b/web-server/typings/app/service/index.d.ts @@ -7,6 +7,7 @@ type AnyFunc = (...args: any[]) => T; type CanExportFunc = AnyFunc> | AnyFunc>; type AutoInstanceType : T> = U extends AnyClass ? InstanceType : U; import ExportAuth from '../../../app/service/Auth'; +import ExportGame from '../../../app/service/Game'; import ExportTest from '../../../app/service/Test'; import ExportTurboCore from '../../../app/service/TurboCore'; import ExportUtils from '../../../app/service/Utils'; @@ -14,6 +15,7 @@ import ExportUtils from '../../../app/service/Utils'; declare module 'egg' { interface IService { auth: AutoInstanceType; + game: AutoInstanceType; test: AutoInstanceType; turboCore: AutoInstanceType; utils: AutoInstanceType;