Commit 9b6ebc77 authored by nanahira's avatar nanahira

move ban to mysql

parent ca04a1e9
Pipeline #1215 passed with stage
in 7 minutes and 41 seconds
...@@ -8,6 +8,7 @@ const moment_1 = __importDefault(require("moment")); ...@@ -8,6 +8,7 @@ const moment_1 = __importDefault(require("moment"));
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
const CloudReplay_1 = require("./entities/CloudReplay"); const CloudReplay_1 = require("./entities/CloudReplay");
const CloudReplayPlayer_1 = require("./entities/CloudReplayPlayer"); const CloudReplayPlayer_1 = require("./entities/CloudReplayPlayer");
const Ban_1 = require("./entities/Ban");
class DataManager { class DataManager {
constructor(config, log) { constructor(config, log) {
this.config = config; this.config = config;
...@@ -51,9 +52,8 @@ class DataManager { ...@@ -51,9 +52,8 @@ class DataManager {
try { try {
return await this.db.createQueryBuilder(CloudReplay_1.CloudReplay, "replay") return await this.db.createQueryBuilder(CloudReplay_1.CloudReplay, "replay")
.orderBy("rand()") .orderBy("rand()")
.limit(4) .limit(4) //there may be 4 players
.leftJoinAndSelect("replay.players", "player") .leftJoinAndSelect("replay.players", "player")
.printSql()
.getOne(); .getOne();
} }
catch (e) { catch (e) {
...@@ -83,6 +83,48 @@ class DataManager { ...@@ -83,6 +83,48 @@ class DataManager {
} }
}); });
} }
async checkBan(field, value) {
const banQuery = {};
banQuery[field] = value;
try {
return await this.db.getRepository(Ban_1.Ban).findOne(banQuery);
}
catch (e) {
this.log.warn(`Failed to load ban ${field} ${value}: ${e.toString()}`);
return null;
}
}
async checkBanWithNameAndIP(name, ip) {
try {
return await this.db.getRepository(Ban_1.Ban).findOne({ name, ip });
}
catch (e) {
this.log.warn(`Failed to load ban ${name} ${ip}: ${e.toString()}`);
return null;
}
}
getBan(name, ip) {
const ban = new Ban_1.Ban();
ban.ip = ip;
ban.name = name;
return ban;
}
async banPlayer(ban) {
try {
const repo = this.db.getRepository(Ban_1.Ban);
if (await repo.findOne({
ip: ban.ip,
name: ban.name
})) {
return;
}
return await repo.save(ban);
}
catch (e) {
this.log.warn(`Failed to update ban ${JSON.stringify(ban)}: ${e.toString()}`);
return null;
}
}
} }
exports.DataManager = DataManager; exports.DataManager = DataManager;
//# sourceMappingURL=DataManager.js.map //# sourceMappingURL=DataManager.js.map
\ No newline at end of file
...@@ -2,8 +2,9 @@ import moment from "moment"; ...@@ -2,8 +2,9 @@ import moment from "moment";
import { Moment } from "moment"; import { Moment } from "moment";
import bunyan from "bunyan"; import bunyan from "bunyan";
import { Connection, ConnectionOptions, createConnection, Transaction } from "typeorm"; import { Connection, ConnectionOptions, createConnection, Transaction } from "typeorm";
import { CloudReplay} from "./entities/CloudReplay"; import { CloudReplay } from "./entities/CloudReplay";
import { CloudReplayPlayer } from "./entities/CloudReplayPlayer"; import { CloudReplayPlayer } from "./entities/CloudReplayPlayer";
import { Ban } from "./entities/Ban";
export interface CloudReplayPlayerInfo { export interface CloudReplayPlayerInfo {
...@@ -34,22 +35,22 @@ export class DataManager { ...@@ -34,22 +35,22 @@ export class DataManager {
async getCloudReplaysFromKey(key: string) { async getCloudReplaysFromKey(key: string) {
try { try {
const replays = await this.db.createQueryBuilder(CloudReplay, "replay") const replays = await this.db.createQueryBuilder(CloudReplay, "replay")
.where("exists (select id from cloud_replay_player where cloud_replay_player.cloudReplayId = replay.id and cloud_replay_player.key = :key)", { key }) .where("exists (select id from cloud_replay_player where cloud_replay_player.cloudReplayId = replay.id and cloud_replay_player.key = :key)", { key })
.orderBy("replay.date", "DESC") .orderBy("replay.date", "DESC")
.limit(10) .limit(10)
.leftJoinAndSelect("replay.players", "player") .leftJoinAndSelect("replay.players", "player")
.getMany(); .getMany();
return replays; return replays;
} catch (e) { } catch (e) {
this.log.warn(`Failed to load replay of ${key}: ${e.toString()}`); this.log.warn(`Failed to load replay of ${key}: ${e.toString()}`);
return []; return [];
} }
} }
async getCloudReplayFromId(id: number) { async getCloudReplayFromId(id: number) {
try { try {
return await this.db.getRepository(CloudReplay).findOne(id, {relations: ["players"]}); return await this.db.getRepository(CloudReplay).findOne(id, { relations: ["players"] });
} catch (e) { } catch (e) {
this.log.warn(`Failed to load replay R#${id}: ${e.toString()}`); this.log.warn(`Failed to load replay R#${id}: ${e.toString()}`);
return null; return null;
...@@ -91,4 +92,46 @@ export class DataManager { ...@@ -91,4 +92,46 @@ export class DataManager {
}); });
} }
async checkBan(field: string, value: string) {
const banQuery: any = {};
banQuery[field] = value;
try {
return await this.db.getRepository(Ban).findOne(banQuery);
} catch (e) {
this.log.warn(`Failed to load ban ${field} ${value}: ${e.toString()}`);
return null;
}
}
async checkBanWithNameAndIP(name: string, ip: string) {
try {
return await this.db.getRepository(Ban).findOne({ name, ip });
} catch (e) {
this.log.warn(`Failed to load ban ${name} ${ip}: ${e.toString()}`);
return null;
}
}
getBan(name: string, ip: string) {
const ban = new Ban();
ban.ip = ip;
ban.name = name;
return ban;
}
async banPlayer(ban: Ban) {
try {
const repo = this.db.getRepository(Ban);
if (await repo.findOne({
ip: ban.ip,
name: ban.name
})) {
return;
}
return await repo.save(ban);
} catch (e) {
this.log.warn(`Failed to update ban ${JSON.stringify(ban)}: ${e.toString()}`);
return null;
}
}
} }
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ban = void 0;
const typeorm_1 = require("typeorm");
let Ban = /** @class */ (() => {
let Ban = class Ban {
};
__decorate([
typeorm_1.PrimaryGeneratedColumn({ unsigned: true, type: "bigint" }),
__metadata("design:type", Number)
], Ban.prototype, "id", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 64, nullable: true }),
__metadata("design:type", String)
], Ban.prototype, "ip", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column({ type: "varchar", length: 20, nullable: true }),
__metadata("design:type", String)
], Ban.prototype, "name", void 0);
Ban = __decorate([
typeorm_1.Entity()
], Ban);
return Ban;
})();
exports.Ban = Ban;
//# sourceMappingURL=Ban.js.map
\ No newline at end of file
import { Column, Entity, Index, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Ban {
@PrimaryGeneratedColumn({ unsigned: true, type: "bigint" })
id: number;
@Index()
@Column({ type: "varchar", length: 64, nullable: true })
ip: string;
@Index()
@Column({ type: "varchar", length: 20, nullable: true })
name: string;
}
...@@ -320,8 +320,6 @@ ...@@ -320,8 +320,6 @@
} }
}, },
"ban": { "ban": {
"banned_user": [],
"banned_ip": [],
"illegal_id": [ "illegal_id": [
"^Lv\\.-*\\d+\\s*(.*)", "^Lv\\.-*\\d+\\s*(.*)",
"^VIP\\.\\d+\\s*(.*)" "^VIP\\.\\d+\\s*(.*)"
......
...@@ -330,8 +330,13 @@ users_cache = {} ...@@ -330,8 +330,13 @@ users_cache = {}
if settings.modules.mysql.enabled if settings.modules.mysql.enabled
DataManager = require('./data-manager/DataManager.js').DataManager DataManager = require('./data-manager/DataManager.js').DataManager
dataManager = new DataManager(settings.modules.mysql.db, log) dataManager = global.dataManager = new DataManager(settings.modules.mysql.db, log)
dataManager.init().then(() -> log.info("Database ready.")) dataManager.init().then(() -> log.info("Database ready."))
else
if settings.modules.cloud_replay.enabled
settings.modules.cloud_replay.enabled = false
setting_save(settings)
log.warn("Cloud replay cannot be enabled because no MySQL.")
if settings.modules.mycard.enabled if settings.modules.mycard.enabled
pgClient = require('pg').Client pgClient = require('pg').Client
...@@ -484,27 +489,18 @@ ROOM_connected_ip = global.ROOM_connected_ip = {} ...@@ -484,27 +489,18 @@ ROOM_connected_ip = global.ROOM_connected_ip = {}
ROOM_bad_ip = global.ROOM_bad_ip = {} ROOM_bad_ip = global.ROOM_bad_ip = {}
# ban a user manually and permanently # ban a user manually and permanently
ban_user = global.ban_user = (name, callback) -> ban_user = global.ban_user = (name) ->
settings.ban.banned_user.push(name) bans = [dataManager.getBan(name, null)]
setting_save(settings) for room in ROOM_all when room and room.established
bad_ip = [] for playerType in ["players", "watchers"]
_async.each(ROOM_all, (room, done)-> for player in room[playerType] when player.name == name or bans.find(ban => player.ip == ban.ip)
if !(room and room.established) bans.push(dataManager.getBan(name, player.ip))
done() ROOM_bad_ip[player.ip]=99
return ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
_async.each(["players", "watchers"], (player_type, _done)-> CLIENT_send_replays(player, room)
_async.each(room[player_type], (player, __done)-> CLIENT_kick(player)
if player and (player.name == name or bad_ip.indexOf(player.ip) != -1) for ban in bans
bad_ip.push(player.ip) await dataManager.banPlayer(ban)
ROOM_bad_ip[bad_ip]=99
settings.ban.banned_ip.push(player.ip)
ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
CLIENT_send_replays(player, room)
CLIENT_kick(player)
__done()
, _done)
, done)
, callback)
return return
# automatically ban user to use random duel # automatically ban user to use random duel
...@@ -2254,13 +2250,15 @@ ygopro.ctos_follow 'JOIN_GAME', true, (buffer, info, client, server, datas)-> ...@@ -2254,13 +2250,15 @@ ygopro.ctos_follow 'JOIN_GAME', true, (buffer, info, client, server, datas)->
log.warn("MULTI LOGIN", client.name, client.ip) log.warn("MULTI LOGIN", client.name, client.ip)
ygopro.stoc_die(client, "${too_much_connection}" + client.ip) ygopro.stoc_die(client, "${too_much_connection}" + client.ip)
else if _.indexOf(settings.ban.banned_user, client.name) > -1 #账号被封 else if settings.modules.mysql.enabled and await dataManager.checkBan("name", client.name) #账号被封
settings.ban.banned_ip.push(client.ip) exactBan = await dataManager.checkBanWithNameAndIP(client.name, client.ip)
setting_save(settings) if !exactBan
exactBan = dataManager.getBan(client.name, client.ip)
await dataManager.banPlayer(exactBan)
log.warn("BANNED USER LOGIN", client.name, client.ip) log.warn("BANNED USER LOGIN", client.name, client.ip)
ygopro.stoc_die(client, "${banned_user_login}") ygopro.stoc_die(client, "${banned_user_login}")
else if _.indexOf(settings.ban.banned_ip, client.ip) > -1 #IP被封 else if settings.modules.mysql.enabled and await dataManager.checkBan("ip", client.ip) #IP被封
log.warn("BANNED IP LOGIN", client.name, client.ip) log.warn("BANNED IP LOGIN", client.name, client.ip)
ygopro.stoc_die(client, "${banned_ip_login}") ygopro.stoc_die(client, "${banned_ip_login}")
...@@ -3885,13 +3883,15 @@ if settings.modules.http ...@@ -3885,13 +3883,15 @@ if settings.modules.http
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
ban_user(u.query.ban, (err)-> try
await ban_user(u.query.ban)
catch e
log.warn("ban fail", e.toString())
response.writeHead(200) response.writeHead(200)
if(err) response.end(addCallback(u.query.callback, "['ban fail', '" + u.query.ban + "']"))
response.end(addCallback(u.query.callback, "['ban fail', '" + u.query.ban + "']")) return
else response.writeHead(200)
response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']")) response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"))
)
else if u.query.kick else if u.query.kick
if !await auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user") if !await auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user")
......
...@@ -426,10 +426,16 @@ ...@@ -426,10 +426,16 @@
if (settings.modules.mysql.enabled) { if (settings.modules.mysql.enabled) {
DataManager = require('./data-manager/DataManager.js').DataManager; DataManager = require('./data-manager/DataManager.js').DataManager;
dataManager = new DataManager(settings.modules.mysql.db, log); dataManager = global.dataManager = new DataManager(settings.modules.mysql.db, log);
dataManager.init().then(function() { dataManager.init().then(function() {
return log.info("Database ready."); return log.info("Database ready.");
}); });
} else {
if (settings.modules.cloud_replay.enabled) {
settings.modules.cloud_replay.enabled = false;
setting_save(settings);
log.warn("Cloud replay cannot be enabled because no MySQL.");
}
} }
if (settings.modules.mycard.enabled) { if (settings.modules.mycard.enabled) {
...@@ -633,30 +639,36 @@ ...@@ -633,30 +639,36 @@
ROOM_bad_ip = global.ROOM_bad_ip = {}; ROOM_bad_ip = global.ROOM_bad_ip = {};
// ban a user manually and permanently // ban a user manually and permanently
ban_user = global.ban_user = function(name, callback) { ban_user = global.ban_user = async function(name) {
var bad_ip; var ban, bans, len3, len4, len5, len6, n, o, p, player, playerType, q, ref3, ref4, room;
settings.ban.banned_user.push(name); bans = [dataManager.getBan(name, null)];
setting_save(settings); for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
bad_ip = []; room = ROOM_all[n];
_async.each(ROOM_all, function(room, done) { if (room && room.established) {
if (!(room && room.established)) { ref3 = ["players", "watchers"];
done(); for (o = 0, len4 = ref3.length; o < len4; o++) {
return; playerType = ref3[o];
} ref4 = room[playerType];
return _async.each(["players", "watchers"], function(player_type, _done) { for (p = 0, len5 = ref4.length; p < len5; p++) {
return _async.each(room[player_type], function(player, __done) { player = ref4[p];
if (player && (player.name === name || bad_ip.indexOf(player.ip) !== -1)) { if (!(player.name === name || bans.find(ban(() => {
bad_ip.push(player.ip); return player.ip === ban.ip;
ROOM_bad_ip[bad_ip] = 99; })))) {
settings.ban.banned_ip.push(player.ip); continue;
}
bans.push(dataManager.getBan(name, player.ip));
ROOM_bad_ip[player.ip] = 99;
ygopro.stoc_send_chat_to_room(room, `${player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED); ygopro.stoc_send_chat_to_room(room, `${player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
CLIENT_send_replays(player, room); CLIENT_send_replays(player, room);
CLIENT_kick(player); CLIENT_kick(player);
} }
return __done(); }
}, _done); }
}, done); }
}, callback); for (q = 0, len6 = bans.length; q < len6; q++) {
ban = bans[q];
await dataManager.banPlayer(ban);
}
}; };
// automatically ban user to use random duel // automatically ban user to use random duel
...@@ -2313,7 +2325,6 @@ ...@@ -2313,7 +2325,6 @@
ygopro.stoc_die(client, "${cloud_replay_no}"); ygopro.stoc_die(client, "${cloud_replay_no}");
return; return;
} }
console.log(replay.players);
buffer = replay.toBuffer(); buffer = replay.toBuffer();
replay_buffer = null; replay_buffer = null;
try { try {
...@@ -2506,7 +2517,7 @@ ...@@ -2506,7 +2517,7 @@
}); });
ygopro.ctos_follow('JOIN_GAME', true, async function(buffer, info, client, server, datas) { ygopro.ctos_follow('JOIN_GAME', true, async function(buffer, info, client, server, datas) {
var available_logs, check_buffer_indentity, create_room_with_action, index, len3, len4, len5, n, name, o, p, pre_room, recover_match, ref3, ref4, replay, replay_id, replays, room, struct; var available_logs, check_buffer_indentity, create_room_with_action, exactBan, index, len3, len4, len5, n, name, o, p, pre_room, recover_match, ref3, ref4, replay, replay_id, replays, room, struct;
//log.info info //log.info info
info.pass = info.pass.trim(); info.pass = info.pass.trim();
client.pass = info.pass; client.pass = info.pass;
...@@ -2975,12 +2986,15 @@ ...@@ -2975,12 +2986,15 @@
} else if (ROOM_connected_ip[client.ip] > 5) { } else if (ROOM_connected_ip[client.ip] > 5) {
log.warn("MULTI LOGIN", client.name, client.ip); log.warn("MULTI LOGIN", client.name, client.ip);
ygopro.stoc_die(client, "${too_much_connection}" + client.ip); ygopro.stoc_die(client, "${too_much_connection}" + client.ip);
} else if (_.indexOf(settings.ban.banned_user, client.name) > -1) { //账号被封 } else if (settings.modules.mysql.enabled && (await dataManager.checkBan("name", client.name))) { //账号被封
settings.ban.banned_ip.push(client.ip); exactBan = (await dataManager.checkBanWithNameAndIP(client.name, client.ip));
setting_save(settings); if (!exactBan) {
exactBan = dataManager.getBan(client.name, client.ip);
await dataManager.banPlayer(exactBan);
}
log.warn("BANNED USER LOGIN", client.name, client.ip); log.warn("BANNED USER LOGIN", client.name, client.ip);
ygopro.stoc_die(client, "${banned_user_login}"); ygopro.stoc_die(client, "${banned_user_login}");
} else if (_.indexOf(settings.ban.banned_ip, client.ip) > -1) { //IP被封 } else if (settings.modules.mysql.enabled && (await dataManager.checkBan("ip", client.ip))) { //IP被封
log.warn("BANNED IP LOGIN", client.name, client.ip); log.warn("BANNED IP LOGIN", client.name, client.ip);
ygopro.stoc_die(client, "${banned_ip_login}"); ygopro.stoc_die(client, "${banned_ip_login}");
} else if (!settings.modules.tournament_mode.enabled && !settings.modules.challonge.enabled && _.any(badwords.level3, function(badword) { } else if (!settings.modules.tournament_mode.enabled && !settings.modules.challonge.enabled && _.any(badwords.level3, function(badword) {
...@@ -5163,14 +5177,17 @@ ...@@ -5163,14 +5177,17 @@
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
ban_user(u.query.ban, function(err) { try {
await ban_user(u.query.ban);
} catch (error1) {
e = error1;
log.warn("ban fail", e.toString());
response.writeHead(200); response.writeHead(200);
if (err) { response.end(addCallback(u.query.callback, "['ban fail', '" + u.query.ban + "']"));
return response.end(addCallback(u.query.callback, "['ban fail', '" + u.query.ban + "']")); return;
} else { }
return response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']")); response.writeHead(200);
} response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"));
});
} else if (u.query.kick) { } else if (u.query.kick) {
if (!(await auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user"))) { if (!(await auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user"))) {
response.writeHead(200); response.writeHead(200);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment