feat: hide game masters

This commit is contained in:
Axel Cocat 2022-02-26 12:56:17 +01:00
parent 04ea344bb2
commit 1fd6b326dc
8 changed files with 201 additions and 4213 deletions

View file

@ -1,10 +1,13 @@
{
"aowowUrl": "https://wotlkdb.com",
"loadDbcs": true,
"hideGameMasters": true,
"realms": [
{
"name": "AzerothCore",
"database": {
"realmId": 1,
"authDatabase": "acore_auth",
"charactersDatabase": {
"host": "localhost",
"port": 3306,
"user": "root",

4308
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "azerothcore-armory",
"version": "0.5.0",
"version": "0.6.0",
"description": "",
"scripts": {
"build": "tsc -p tsconfig.json",
@ -18,26 +18,25 @@
"@types/express": "^4.17.13",
"@types/glob": "^7.2.0",
"@types/mkdirp": "^1.0.2",
"@types/node": "^17.0.5",
"@types/node-fetch": "^2.5.12",
"@types/node": "^17.0.21",
"@types/node-fetch": "^2.6.1",
"@types/pako": "^1.0.3",
"concurrently": "^6.5.1",
"concurrently": "^7.0.0",
"nodemon": "^2.0.15",
"rimraf": "^3.0.2",
"typescript": "^4.5.4"
"typescript": "^4.5.5"
},
"dependencies": {
"@supercharge/promise-pool": "^2.1.0",
"camelcase": "^6.2.1",
"cli-progress": "^3.9.1",
"express": "^4.17.2",
"camelcase": "^6.3.0",
"cli-progress": "^3.10.0",
"express": "^4.17.3",
"express-handlebars": "^6.0.2",
"glob": "^7.2.0",
"glob-promise": "^4.2.2",
"handlebars-helpers": "^0.10.0",
"mkdirp": "^1.0.4",
"mysql2": "^2.3.3",
"node-fetch": "^2.6.6",
"node-fetch": "^2.6.7",
"pako": "^2.0.4",
"pretty-ms": "^7.0.1",
"source-map-support": "^0.5.21"

View file

@ -39,7 +39,7 @@ export class Armory {
console.log("Connecting to databases...");
this.worldDb = await createConnection(this.config.worldDatabase);
for (const realm of this.config.realms) {
this.charsDbs[realm.name.toLowerCase()] = await createConnection(realm.database);
this.charsDbs[realm.name.toLowerCase()] = await createConnection(realm.charactersDatabase);
}
console.log("Starting server...");
@ -49,7 +49,6 @@ export class Armory {
partialsDir: path.join(process.cwd(), "static", "partials"),
layoutsDir: path.join(process.cwd(), "static"),
defaultLayout: "layout.html",
helpers: require("handlebars-helpers")(),
}));
app.set("view engine", "handlebars");
app.set("views", path.join(process.cwd(), "static"));

View file

@ -11,12 +11,15 @@ export interface IDatabaseConfig {
export interface IRealmConfig {
name: string;
database: IDatabaseConfig;
realmId: number;
authDatabase: string;
charactersDatabase: IDatabaseConfig;
}
export class Config {
public aowowUrl: string;
public loadDbcs: boolean;
public hideGameMasters: boolean;
public realms: IRealmConfig[];
public worldDatabase: IDatabaseConfig;

View file

@ -13,6 +13,7 @@ export interface IColumnSettings {
collation?: string;
formatter?: (data: string | number | null, row: any) => string;
table?: string;
database?: string;
}
export interface IColumnJoin {
@ -20,6 +21,7 @@ export interface IColumnJoin {
column1: string;
table2: string;
column2: string;
database2?: string;
kind: "INNER" | "FULL OUTER" | "LEFT" | "RIGHT";
}
@ -90,6 +92,11 @@ export class DataTablesSsp {
this.columnSettings = columnSettings;
}
private colSettingsToStr(colSettings: IColumnSettings) {
const db = colSettings.database ? ("`" + colSettings.database + "`.") : "";
return `${db}\`${colSettings.table || this.table}\`.\`${colSettings.name}\``;
}
private limit() {
if (this.start !== undefined && this.length !== -1) {
this.limitSql = `LIMIT ${this.length} OFFSET ${this.start}`;
@ -110,7 +117,7 @@ export class DataTablesSsp {
}
const colSettings = this.columnSettings[requestColumn.data];
orderBy.push(`\`${colSettings.table || this.table}\`.\`${colSettings.name}\` ${order.dir}`);
orderBy.push(`${this.colSettingsToStr(colSettings)} ${order.dir}`);
}
orderBy.push(`\`${this.table}\`.\`${this.primaryKey}\``);
@ -123,7 +130,8 @@ export class DataTablesSsp {
private join() {
for (const join of this.joins) {
this.joinSql += `${join.kind} JOIN \`${join.table2}\` ON \`${join.table2}\`.\`${join.column2}\` = \`${join.table1}\`.\`${join.column1}\`\n`;
const db2 = join.database2 ? "`" + join.database2 + "`." : "";
this.joinSql += `${join.kind} JOIN ${db2}\`${join.table2}\` ON ${db2}\`${join.table2}\`.\`${join.column2}\` = \`${join.table1}\`.\`${join.column1}\`\n`;
}
return this;
@ -141,7 +149,7 @@ export class DataTablesSsp {
const colSettings = this.columnSettings[col.data];
const collate = colSettings.collation !== undefined ? `COLLATE ${colSettings.collation} ` : "";
filterWheres.push(`\`${colSettings.table || this.table}\`.\`${colSettings.name}\` ${collate}LIKE ?`);
filterWheres.push(`${this.colSettingsToStr(colSettings)} ${collate}LIKE ?`);
this.filterBindings.push(`%${this.search.value}%`);
}
if (filterWheres.length > 0) {
@ -153,9 +161,9 @@ export class DataTablesSsp {
return this;
}
private buildSql(): string {
public sql(): string {
const columns = [
...this.columnSettings.map(c => `\`${c.table || this.table}\`.\`${c.name}\``),
...this.columnSettings.map(c => this.colSettingsToStr(c)),
...this.extraDataColumns,
];
return `
@ -205,7 +213,7 @@ export class DataTablesSsp {
const recordsFiltered = rows[0].count;
[rows, fields] = await this.db.query({
sql: this.buildSql(),
sql: this.sql(),
rowsAsArray: true,
values: bindings,
});

View file

@ -157,7 +157,7 @@ export class CharacterController {
return;
}
const charData = await this.getCharacterData(realmName, charName);
const charData = await this.getCharacterData(realm, charName);
if (charData === null) {
// Could not find character
res.sendStatus(404);
@ -203,7 +203,7 @@ export class CharacterController {
return;
}
const charData = await this.getCharacterData(realm.name, charName);
const charData = await this.getCharacterData(realm, charName);
if (charData === null) {
// Could not find character
res.sendStatus(404);
@ -232,7 +232,7 @@ export class CharacterController {
return;
}
const charData = await this.getCharacterData(realm.name, charName);
const charData = await this.getCharacterData(realm, charName);
if (charData === null) {
// Could not find character
res.sendStatus(404);
@ -256,7 +256,7 @@ export class CharacterController {
return;
}
const charData = await this.getCharacterData(realm.name, character);
const charData = await this.getCharacterData(realm, character);
if (charData === null) {
// Could not find character
res.sendStatus(404);
@ -285,13 +285,16 @@ export class CharacterController {
return this.armory.config.realms.find(r => r.name.toLowerCase() === realm.toLowerCase());
}
private async getCharacterData(realm: string, character: string | number): Promise<ICharacterData> {
private async getCharacterData(realm: IRealmConfig, character: string | number): Promise<ICharacterData> {
const where = typeof character === "string" ? "LOWER(name) = LOWER(?)" : "guid = ?";
const [rows, fields] = await this.armory.getCharactersDb(realm).query(`
SELECT guid, name, race, class, gender, level, skin, face, hairStyle, hairColor, facialStyle, playerFlags, online
FROM characters
WHERE ${where}
`, [character]);
const [rows, fields] = await this.armory.getCharactersDb(realm.name).query(`
SELECT \`guid\`, \`name\`, \`race\`, \`class\`, \`gender\`, \`level\`, \`skin\`, \`face\`, \`hairStyle\`, \`hairColor\`, \`facialStyle\`, \`playerFlags\`, \`online\`
FROM \`characters\`
LEFT JOIN \`${realm.authDatabase}\`.\`account_access\` ON \`account_access\`.\`id\` = \`characters\`.\`account\`
WHERE
${where}
AND (\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0 OR ? = 0)
`, [character, this.armory.config.hideGameMasters ? 1 : 0]);
if ((rows as RowDataPacket[]).length === 0) {
return null;

View file

@ -30,9 +30,11 @@ const classFiles = {
export class IndexController {
private armory: Armory;
private charsetCache: { [key: string]: string };
public constructor(armory: Armory) {
this.armory = armory;
this.charsetCache = {};
}
public async index(req: express.Request, res: express.Response): Promise<void> {
@ -53,6 +55,8 @@ export class IndexController {
}
const db = this.armory.getCharactersDb(realm.name);
if (!(realm.name in this.charsetCache)) {
let [rows, fields] = await db.query(`
SELECT CCSA.character_set_name FROM information_schema.\`TABLES\` T,
information_schema.\`COLLATION_CHARACTER_SET_APPLICABILITY\` CCSA
@ -60,11 +64,13 @@ export class IndexController {
AND T.table_schema = "${db.config.database}"
AND T.table_name = "characters"
`);
const charSet = rows[0].character_set_name;
this.charsetCache[realm.name] = rows[0].character_set_name;
}
const charSet = this.charsetCache[realm.name];
const ssp = new DataTablesSsp(req.query, db, "characters", "guid", [
let ssp = new DataTablesSsp(req.query, db, "characters", "guid", [
{ name: "name", collation: `${charSet}_general_ci` },
{ name: "name", table: "guild" },
{ table: "guild", name: "name" },
{ name: "level" },
{ name: "race", formatter: (race, row) => `${raceFiles[race]}_${row[6] === 0 ? "male" : "female"}` },
{ name: "class", formatter: cls => classFiles[cls] },
@ -76,6 +82,11 @@ export class IndexController {
];
ssp.extraDataColumns = ["`characters`.`gender`"];
if (this.armory.config.hideGameMasters) {
ssp.joins.push({ table1: "characters", column1: "account", table2: "account_access", column2: "id", database2: realm.authDatabase, kind: "LEFT" });
ssp = ssp.where(`\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`);
}
const result = await ssp
.where("`deleteInfos_Account` IS NULL")
.run();