Commit bea6b1bc authored by nanahira's avatar nanahira

Merge branch 'master' of ../srvpro

parents a76fe295 0129e335
......@@ -80,12 +80,12 @@ class Challonge {
return false;
}
}
// POST /v1/tournaments/${tournament_id}/participants/bulk_add.json { api_key: string, participants: { name: string }[] } returns ANY
async uploadParticipants(participantNames) {
// POST /v1/tournaments/${tournament_id}/participants/bulk_add.json { api_key: string, participants: { name: string, deckbuf?: string }[] } returns ANY
async uploadParticipants(participants) {
try {
await axios_1.default.post(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/bulk_add.json`, {
api_key: this.config.api_key,
participants: participantNames.map(name => ({ name })),
participants,
});
return true;
}
......
......@@ -134,12 +134,12 @@ export class Challonge {
}
}
// POST /v1/tournaments/${tournament_id}/participants/bulk_add.json { api_key: string, participants: { name: string }[] } returns ANY
async uploadParticipants(participantNames: string[]) {
// POST /v1/tournaments/${tournament_id}/participants/bulk_add.json { api_key: string, participants: { name: string, deckbuf?: string }[] } returns ANY
async uploadParticipants(participants: { name: string, deckbuf?: string }[]) {
try {
await axios.post(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/bulk_add.json`, {
api_key: this.config.api_key,
participants: participantNames.map(name => ({ name })),
participants,
});
return true;
} catch (e) {
......
......@@ -204,9 +204,9 @@
"post_score": false,
"get_score": false,
"punish_quit_before_match": false,
"init_post": {
"match_api": {
"enabled": false,
"url": "https://sapi.moecube.com:444/ygopro/match/clear",
"url": "https://sapi.moecube.com:444/ygopro/match",
"accesskey": "momobako"
}
},
......
......@@ -44,7 +44,7 @@
"invalid_password_existed": "Password invalid (Already Existed)",
"invalid_password_not_found": "Password invalid (Not Found)",
"invalid_password_action": "Password invalid (Invalid Action)",
"invalid_password_checksum": "Password incorrect (Checksum Failed) (Please re-login your account.)",
"invalid_password_checksum": "Password incorrect (Checksum Failed) (Please re-login and wait for 5 minutes for fix)",
"bad_user_name": "Please enter the correct ID",
"server_full": "Server is full, please try again later.",
"too_much_connection": "Too many clients running at the moment! ",
......@@ -405,7 +405,7 @@
"invalid_password_existed": "主机密码不正确 (Already Existed)",
"invalid_password_not_found": "主机密码不正确 (Not Found)",
"invalid_password_action": "主机密码不正确 (Invalid Action)",
"invalid_password_checksum": "主机密码不正确 (Checksum Failed) (请退出并重新登录你的账号)",
"invalid_password_checksum": "主机密码不正确 (Checksum Failed) (请重新登录你的账号,等待5分钟后重进)",
"bad_user_name": "请输入正确的用户名",
"server_full": "服务器已经爆满,请稍候再试",
"too_much_connection": "同时开启的客户端数量过多 ",
......
......@@ -39,11 +39,13 @@
"ygopro-deck-encode": "^1.0.14"
},
"devDependencies": {
"@types/async": "^3.2.25",
"@types/bunyan": "^1.8.8",
"@types/formidable": "^3.4.6",
"@types/ip6addr": "^0.2.3",
"@types/lzma": "^2.3.0",
"@types/node": "^16.18.126",
"@types/underscore": "^1.11.4",
"@types/underscore": "^1.13.0",
"@types/ws": "^8.5.3",
"coffeescript": "^2.7.0",
"typescript": "^5.8.3"
......@@ -95,6 +97,13 @@
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.2.tgz",
"integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q=="
},
"node_modules/@types/async": {
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.25.tgz",
"integrity": "sha512-O6Th/DI18XjrL9TX8LO9F/g26qAz5vynmQqlXt/qLGrskvzCKXKc5/tATz3G2N6lM8eOf3M8/StB14FncAmocg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/bunyan": {
"version": "1.8.8",
"resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.8.tgz",
......@@ -104,6 +113,16 @@
"@types/node": "*"
}
},
"node_modules/@types/formidable": {
"version": "3.4.6",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-3.4.6.tgz",
"integrity": "sha512-LI4Hk+KNsM5q7br4oMVoaWeb+gUqJpz1N8+Y2Q6Cz9cVH33ybahRKUWaRmMboVlkwSbOUGgwc/pEkS7yMSzoWg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/ip6addr": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@types/ip6addr/-/ip6addr-0.2.3.tgz",
......@@ -128,10 +147,11 @@
"license": "MIT"
},
"node_modules/@types/underscore": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz",
"integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg==",
"dev": true
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.13.0.tgz",
"integrity": "sha512-L6LBgy1f0EFQZ+7uSA57+n2g/s4Qs5r06Vwrwn0/nuK1de+adz00NWaztRQ30aEqw5qOaWbPI8u2cGQ52lj6VA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/ws": {
"version": "8.5.3",
......@@ -1565,6 +1585,7 @@
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz",
"integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
......@@ -3750,6 +3771,12 @@
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.2.tgz",
"integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q=="
},
"@types/async": {
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.25.tgz",
"integrity": "sha512-O6Th/DI18XjrL9TX8LO9F/g26qAz5vynmQqlXt/qLGrskvzCKXKc5/tATz3G2N6lM8eOf3M8/StB14FncAmocg==",
"dev": true
},
"@types/bunyan": {
"version": "1.8.8",
"resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.8.tgz",
......@@ -3759,6 +3786,15 @@
"@types/node": "*"
}
},
"@types/formidable": {
"version": "3.4.6",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-3.4.6.tgz",
"integrity": "sha512-LI4Hk+KNsM5q7br4oMVoaWeb+gUqJpz1N8+Y2Q6Cz9cVH33ybahRKUWaRmMboVlkwSbOUGgwc/pEkS7yMSzoWg==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/ip6addr": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@types/ip6addr/-/ip6addr-0.2.3.tgz",
......@@ -3781,9 +3817,9 @@
"dev": true
},
"@types/underscore": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz",
"integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg==",
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.13.0.tgz",
"integrity": "sha512-L6LBgy1f0EFQZ+7uSA57+n2g/s4Qs5r06Vwrwn0/nuK1de+adz00NWaztRQ30aEqw5qOaWbPI8u2cGQ52lj6VA==",
"dev": true
},
"@types/ws": {
......@@ -4831,6 +4867,7 @@
"version": "5.6.1",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz",
"integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==",
"peer": true,
"requires": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
......
......@@ -50,11 +50,13 @@
"webhook": "node ygopro-webhook.js"
},
"devDependencies": {
"@types/async": "^3.2.25",
"@types/bunyan": "^1.8.8",
"@types/formidable": "^3.4.6",
"@types/ip6addr": "^0.2.3",
"@types/lzma": "^2.3.0",
"@types/node": "^16.18.126",
"@types/underscore": "^1.11.4",
"@types/underscore": "^1.13.0",
"@types/ws": "^8.5.3",
"coffeescript": "^2.7.0",
"typescript": "^5.8.3"
......
###
Main script of new dashboard account system.
The account list file is stored at `./config/admin_user.json`. The users are stored at `users`.
The key is the username. The `permissions` field could be a string, using a permission set from the example, or an object, to define a specific set of permissions.
eg. An account for a judge could be as follows, to use the default permission of judges,
"username": {
"password": "123456",
"enabled": true,
"permissions": "judge"
},
or as follows, to use a specific set of permissions.
"username": {
"password": "123456",
"enabled": true,
"permissions": {
"get_rooms": true,
"duel_log": true,
"download_replay": true,
"deck_dashboard_read": true,
"deck_dashboard_write": true,
"shout": true,
"kick_user": true,
"start_death": true
}
},
###
fs = require 'fs'
loadJSON = require('load-json-file').sync
loadJSONPromise = require('load-json-file')
moment = require 'moment'
moment.updateLocale('zh-cn', {
relativeTime: {
future: '%s内',
past: '%s前',
s: '%d秒',
m: '1分钟',
mm: '%d分钟',
h: '1小时',
hh: '%d小时',
d: '1天',
dd: '%d天',
M: '1个月',
MM: '%d个月',
y: '1年',
yy: '%d年'
}
})
bunyan = require 'bunyan'
log = bunyan.createLogger name: "auth"
util = require 'util'
if not fs.existsSync('./logs')
fs.mkdirSync('./logs')
add_log = (message) ->
mt = moment()
log.info(message)
text = mt.format('YYYY-MM-DD HH:mm:ss') + " --> " + message + "\n"
res = false
try
await fs.promises.appendFile("./logs/"+mt.format('YYYY-MM-DD')+".log", text)
res = true
catch
res = false
return res
default_data = loadJSON('./data/default_data.json')
setting_save = (settings) ->
try
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2))
catch e
add_log("save fail");
return
default_data = loadJSON('./data/default_data.json')
try
users = loadJSON('./config/admin_user.json')
catch
users = default_data.users
setting_save(users)
save = () ->
return await setting_save(users)
reload = () ->
user_backup = users
try
users = await loadJSONPromise('./config/admin_user.json')
catch
users = user_backup
await add_log("Invalid user data JSON")
return
check_permission = (user, permission_required) ->
_permission = user.permissions
permission = _permission
if typeof(permission) != 'object'
permission = users.permission_examples[_permission]
if !permission
await add_log("Permision not set:"+_permission)
return false
return permission[permission_required]
@auth = (name, pass, permission_required, action = 'unknown', no_log) ->
await reload()
user = users.users[name]
if !user
await add_log("Unknown user login. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return false
if user.password != pass
await add_log("Unauthorized user login. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return false
if !user.enabled
await add_log("Disabled user login. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return false
if !await check_permission(user, permission_required)
await add_log("Permission denied. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return false
if !no_log
await add_log("Operation success. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return true
@add_user = (name, pass, enabled, permissions) ->
await reload()
if users.users[name]
return false
users.users[name] = {
"password": pass,
"enabled": enabled,
"permissions": permissions
}
await save()
return true
@delete_user = (name) ->
await reload()
if !users.users[name]
return false
delete users.users[name]
await save()
return
@update_user = (name, key, value) ->
await reload()
if !users.users[name]
return false
users.users[name][key] = value
await save()
return
// Generated by CoffeeScript 2.7.0
(function() {
/*
Main script of new dashboard account system.
The account list file is stored at `./config/admin_user.json`. The users are stored at `users`.
The key is the username. The `permissions` field could be a string, using a permission set from the example, or an object, to define a specific set of permissions.
eg. An account for a judge could be as follows, to use the default permission of judges,
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.update_user = exports.delete_user = exports.add_user = exports.auth = void 0;
/*
Main script of new dashboard account system.
The account list file is stored at `./config/admin_user.json`. The users are stored at `users`.
The key is the username. The `permissions` field could be a string, using a permission set from the example, or an object, to define a specific set of permissions.
eg. An account for a judge could be as follows, to use the default permission of judges,
"username": {
"password": "123456",
"enabled": true,
"permissions": "judge"
},
or as follows, to use a specific set of permissions.
or as follows, to use a specific set of permissions.
"username": {
"password": "123456",
"enabled": true,
......@@ -25,168 +29,171 @@
"start_death": true
}
},
*/
var add_log, bunyan, check_permission, default_data, fs, loadJSON, loadJSONPromise, log, moment, reload, save, setting_save, users, util;
fs = require('fs');
loadJSON = require('load-json-file').sync;
loadJSONPromise = require('load-json-file');
moment = require('moment');
moment.updateLocale('zh-cn', {
*/
const fs_1 = __importDefault(require("fs"));
const load_json_file_1 = require("load-json-file");
const load_json_file_2 = __importDefault(require("load-json-file"));
const moment_1 = __importDefault(require("moment"));
const bunyan_1 = __importDefault(require("bunyan"));
moment_1.default.updateLocale("zh-cn", {
relativeTime: {
future: '%s内',
past: '%s前',
s: '%d秒',
m: '1分钟',
mm: '%d分钟',
h: '1小时',
hh: '%d小时',
d: '1天',
dd: '%d天',
M: '1个月',
MM: '%d个月',
y: '1年',
yy: '%d年'
}
});
bunyan = require('bunyan');
log = bunyan.createLogger({
name: "auth"
});
util = require('util');
if (!fs.existsSync('./logs')) {
fs.mkdirSync('./logs');
}
add_log = async function(message) {
var mt, res, text;
mt = moment();
future: "%s内",
past: "%s前",
s: "%d秒",
m: "1分钟",
mm: "%d分钟",
h: "1小时",
hh: "%d小时",
d: "1天",
dd: "%d天",
M: "1个月",
MM: "%d个月",
y: "1年",
yy: "%d年",
},
});
const log = bunyan_1.default.createLogger({ name: "auth" });
if (!fs_1.default.existsSync("./logs")) {
fs_1.default.mkdirSync("./logs");
}
const add_log = async function (message) {
const mt = (0, moment_1.default)();
log.info(message);
text = mt.format('YYYY-MM-DD HH:mm:ss') + " --> " + message + "\n";
res = false;
const text = mt.format("YYYY-MM-DD HH:mm:ss") + " --> " + message + "\n";
let res = false;
try {
await fs.promises.appendFile("./logs/" + mt.format('YYYY-MM-DD') + ".log", text);
await fs_1.default.promises.appendFile(`./logs/${mt.format("YYYY-MM-DD")}.log`, text);
res = true;
} catch (error) {
}
catch {
res = false;
}
return res;
};
default_data = loadJSON('./data/default_data.json');
setting_save = async function(settings) {
var e;
};
const default_data = (0, load_json_file_1.sync)("./data/default_data.json");
const setting_save = async function (settings) {
try {
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2));
} catch (error) {
e = error;
await fs_1.default.promises.writeFile(settings.file, JSON.stringify(settings, null, 2));
}
catch (e) {
add_log("save fail");
}
};
default_data = loadJSON('./data/default_data.json');
try {
users = loadJSON('./config/admin_user.json');
} catch (error) {
};
let users;
try {
users = (0, load_json_file_1.sync)("./config/admin_user.json");
}
catch {
users = default_data.users;
setting_save(users);
}
save = async function() {
return (await setting_save(users));
};
reload = async function() {
var user_backup;
user_backup = users;
}
const save = async function () {
await setting_save(users);
};
const reload = async function () {
const user_backup = users;
try {
users = (await loadJSONPromise('./config/admin_user.json'));
} catch (error) {
users = (await (0, load_json_file_2.default)("./config/admin_user.json"));
}
catch {
users = user_backup;
await add_log("Invalid user data JSON");
}
};
check_permission = async function(user, permission_required) {
var _permission, permission;
_permission = user.permissions;
permission = _permission;
if (typeof permission !== 'object') {
};
const check_permission = async function (user, permission_required) {
const _permission = user.permissions;
let permission;
if (typeof _permission !== "object") {
permission = users.permission_examples[_permission];
}
else {
permission = _permission;
}
if (!permission) {
await add_log("Permision not set:" + _permission);
await add_log("Permision not set:" + String(_permission));
return false;
}
return permission[permission_required];
};
this.auth = async function(name, pass, permission_required, action = 'unknown', no_log) {
var user;
return Boolean(permission[permission_required]);
};
const auth = async function (name, pass, permission_required, action = "unknown", no_log) {
await reload();
user = users.users[name];
const user = users.users[name];
if (!user) {
await add_log("Unknown user login. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
await add_log("Unknown user login. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action);
return false;
}
if (user.password !== pass) {
await add_log("Unauthorized user login. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
await add_log("Unauthorized user login. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action);
return false;
}
if (!user.enabled) {
await add_log("Disabled user login. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
await add_log("Disabled user login. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action);
return false;
}
if (!(await check_permission(user, permission_required))) {
await add_log("Permission denied. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
await add_log("Permission denied. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action);
return false;
}
if (!no_log) {
await add_log("Operation success. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
await add_log("Operation success. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action);
}
return true;
};
this.add_user = async function(name, pass, enabled, permissions) {
};
exports.auth = auth;
const add_user = async function (name, pass, enabled, permissions) {
await reload();
if (users.users[name]) {
return false;
}
users.users[name] = {
"password": pass,
"enabled": enabled,
"permissions": permissions
password: pass,
enabled: enabled,
permissions: permissions,
};
await save();
return true;
};
this.delete_user = async function(name) {
};
exports.add_user = add_user;
const delete_user = async function (name) {
await reload();
if (!users.users[name]) {
return false;
return;
}
delete users.users[name];
await save();
};
this.update_user = async function(name, key, value) {
};
exports.delete_user = delete_user;
const update_user = async function (name, key, value) {
await reload();
if (!users.users[name]) {
return false;
return;
}
users.users[name][key] = value;
await save();
};
}).call(this);
};
exports.update_user = update_user;
/*
Main script of new dashboard account system.
The account list file is stored at `./config/admin_user.json`. The users are stored at `users`.
The key is the username. The `permissions` field could be a string, using a permission set from the example, or an object, to define a specific set of permissions.
eg. An account for a judge could be as follows, to use the default permission of judges,
"username": {
"password": "123456",
"enabled": true,
"permissions": "judge"
},
or as follows, to use a specific set of permissions.
"username": {
"password": "123456",
"enabled": true,
"permissions": {
"get_rooms": true,
"duel_log": true,
"download_replay": true,
"deck_dashboard_read": true,
"deck_dashboard_write": true,
"shout": true,
"kick_user": true,
"start_death": true
}
},
*/
import fs from "fs";
import { sync as loadJSON } from "load-json-file";
import loadJSONPromise from "load-json-file";
import moment from "moment";
import bunyan from "bunyan";
import util from "util";
moment.updateLocale("zh-cn", {
relativeTime: {
future: "%s内",
past: "%s前",
s: "%d秒",
m: "1分钟",
mm: "%d分钟",
h: "1小时",
hh: "%d小时",
d: "1天",
dd: "%d天",
M: "1个月",
MM: "%d个月",
y: "1年",
yy: "%d年",
},
});
const log = bunyan.createLogger({ name: "auth" });
if (!fs.existsSync("./logs")) {
fs.mkdirSync("./logs");
}
type PermissionSet = Record<string, boolean>;
type UserPermissions = string | PermissionSet;
interface UserEntry {
password: string;
enabled: boolean;
permissions: UserPermissions;
[key: string]: any;
}
interface UsersFile {
file?: string;
permission_examples: Record<string, PermissionSet>;
users: Record<string, UserEntry>;
}
const add_log = async function (message: string): Promise<boolean> {
const mt = moment();
log.info(message);
const text = mt.format("YYYY-MM-DD HH:mm:ss") + " --> " + message + "\n";
let res = false;
try {
await fs.promises.appendFile(`./logs/${mt.format("YYYY-MM-DD")}.log`, text);
res = true;
} catch {
res = false;
}
return res;
};
const default_data = loadJSON("./data/default_data.json") as {
users: UsersFile;
};
const setting_save = async function (settings: UsersFile): Promise<void> {
try {
await fs.promises.writeFile(settings.file as string, JSON.stringify(settings, null, 2));
} catch (e) {
add_log("save fail");
}
};
let users: UsersFile;
try {
users = loadJSON("./config/admin_user.json") as UsersFile;
} catch {
users = default_data.users;
setting_save(users);
}
const save = async function (): Promise<void> {
await setting_save(users);
};
const reload = async function (): Promise<void> {
const user_backup = users;
try {
users = (await loadJSONPromise("./config/admin_user.json")) as UsersFile;
} catch {
users = user_backup;
await add_log("Invalid user data JSON");
}
};
const check_permission = async function (
user: UserEntry,
permission_required: string
): Promise<boolean> {
const _permission = user.permissions;
let permission: PermissionSet | undefined;
if (typeof _permission !== "object") {
permission = users.permission_examples[_permission];
} else {
permission = _permission;
}
if (!permission) {
await add_log("Permision not set:" + String(_permission));
return false;
}
return Boolean(permission[permission_required]);
};
export const auth = async function (
name: string,
pass: string,
permission_required: string,
action = "unknown",
no_log?: boolean
): Promise<boolean> {
await reload();
const user = users.users[name];
if (!user) {
await add_log(
"Unknown user login. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action
);
return false;
}
if (user.password !== pass) {
await add_log(
"Unauthorized user login. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action
);
return false;
}
if (!user.enabled) {
await add_log(
"Disabled user login. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action
);
return false;
}
if (!(await check_permission(user, permission_required))) {
await add_log(
"Permission denied. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action
);
return false;
}
if (!no_log) {
await add_log(
"Operation success. User: " +
name +
", Permission needed: " +
permission_required +
", Action: " +
action
);
}
return true;
};
export const add_user = async function (
name: string,
pass: string,
enabled: boolean,
permissions: UserPermissions
): Promise<boolean> {
await reload();
if (users.users[name]) {
return false;
}
users.users[name] = {
password: pass,
enabled: enabled,
permissions: permissions,
};
await save();
return true;
};
export const delete_user = async function (name: string): Promise<void> {
await reload();
if (!users.users[name]) {
return;
}
delete users.users[name];
await save();
};
export const update_user = async function (
name: string,
key: string,
value: unknown
): Promise<void> {
await reload();
if (!users.users[name]) {
return;
}
users.users[name][key] = value;
await save();
};
......@@ -501,6 +501,25 @@ var packDatas = function (callback) {
async function requestListener(req, res) {
var u = url.parse(req.url, true);
// Allow all CORS + PNA (Private Network Access) requests.
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Private-Network", "true");
res.setHeader("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method");
if ((req.method || "").toLowerCase() === "options") {
const requestHeaders = req.headers["access-control-request-headers"];
res.writeHead(204, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": Array.isArray(requestHeaders)
? requestHeaders.join(", ")
: requestHeaders || "*",
"Access-Control-Allow-Private-Network": "true",
"Access-Control-Max-Age": "86400"
});
res.end();
return;
}
if (!await auth.auth(u.query.username, u.query.password, "pre_dashboard", "pre_dashboard")) {
res.writeHead(403);
res.end("Auth Failed.");
......
# 标准库
net = require 'net'
http = require 'http'
url = require 'url'
path = require 'path'
fs = require 'fs'
os = require 'os'
......@@ -296,7 +295,27 @@ loadLFList = (path) ->
lflists.push({date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"), tcg: list.indexOf('TCG') != -1})
catch
init = () ->
call_match_api = (method, path, params) ->
if not settings.modules.arena_mode.match_api.enabled
return null
match_api_url = new URL(settings.modules.arena_mode.match_api.url + "/" + path)
match_api_url.searchParams.append('ak', settings.modules.arena_mode.match_api.accesskey)
for entry in Object.entries(params)
key = entry[0]
val = entry[1]
match_api_url.searchParams.append(key, val)
try
res = await axios({
method: method
url: match_api_url.toString()
timeout: 30000
})
return res.data
catch e
log.warn 'MATCH API CALL ERROR', method, path, JSON.stringify(params), e.toString()
return null
init = () ->
log.info('Reading config.')
await createDirectoryIfNotExists("./config")
await importOldConfig()
......@@ -420,6 +439,13 @@ loadLFList = (path) ->
settings.modules.trusted_proxies = settings.modules.neos.trusted_proxies
delete settings.modules.neos.trusted_proxies
imported = true
# migrate arena_mode.init_post to match_api
if settings.modules.arena_mode.init_post
settings.modules.arena_mode.match_api = settings.modules.arena_mode.init_post
if settings.modules.arena_mode.match_api.url.endsWith('/clear')
settings.modules.arena_mode.match_api.url = settings.modules.arena_mode.match_api.url.slice(0, -6)
delete settings.modules.arena_mode.init_post
imported = true
#finish
keysFromEnv = Object.keys(process.env).filter((key) => key.startsWith('SRVPRO_'))
if keysFromEnv.length > 0
......@@ -591,16 +617,8 @@ loadLFList = (path) ->
# pg_client.on 'drain', pg_client.end.bind(pg_client)
# log.info "loading mycard user..."
# pg_client.connect()
if settings.modules.arena_mode.enabled and settings.modules.arena_mode.init_post.enabled
postData = qs.stringify({
ak: settings.modules.arena_mode.init_post.accesskey,
arena: settings.modules.arena_mode.mode
})
try
log.info("Sending arena init post.")
await axios.post(settings.modules.arena_mode.init_post.url + "?" + postData)
catch e
log.warn 'ARENA INIT POST ERROR', e
if settings.modules.arena_mode.enabled
await call_match_api('POST', 'clear', {arena: settings.modules.arena_mode.mode})
if settings.modules.challonge.enabled
Challonge = require('./challonge').Challonge
......@@ -1535,9 +1553,6 @@ class Room
lflist = parseInt(param[3]) - 1
@hostinfo.lflist = lflist
for extra_mode_func from extra_mode_list
extra_mode_func.call this, rule
if (rule.match /(^|,|,)(NOLFLIST|NF)(,|,|$)/)
@hostinfo.lflist = -1
......@@ -1586,6 +1601,11 @@ class Room
@recover_buffers = [[], [], [], []]
@welcome = "${recover_hint}"
param = name.match /(.+)#/
rule = if param then param[1].toUpperCase() else ''
for extra_mode_func from extra_mode_list
extra_mode_func.call this, rule, name
@hostinfo.replay_mode = 0
if settings.modules.tournament_mode.enabled # 0x1: Save the replays in file
......@@ -2628,6 +2648,11 @@ ygopro.ctos_follow 'JOIN_GAME', true, (buffer, info, client, server, datas)->
room.welcome = "${athletic_arena_tip}"
else
room.welcome = "${entertain_arena_tip}"
await call_match_api('POST', 'player-joined', {
username: client.name,
arena: room.arena,
roomname: room.name
})
when 5
title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ')
room = ROOM_find_by_title(title)
......@@ -2678,8 +2703,8 @@ ygopro.ctos_follow 'JOIN_GAME', true, (buffer, info, client, server, datas)->
# users_cache[client.name] = userData.user.id
possible_ids = [
userData.user.u16Secret,
userData.user.u16SecretPrevious,
userData.user.id, # TODO: remove this line after use u16Secret
userData.user.u16SecretPrevious
# userData.user.id,
].filter((id) -> id != null)
try_decrypt_buffer_with_id = (id) ->
secret = id % 65535 + 1
......@@ -3390,7 +3415,7 @@ load_tips = global.load_tips = ()->
load_tips_zh = global.load_tips_zh = ()->
return await loadRemoteData(tips, "tips_zh", settings.modules.tips.get_zh)
ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server, datas)->
ygopro.stoc_follow 'DUEL_START', true, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid]
return unless room and !client.reconnecting
if room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN #first start
......@@ -3400,7 +3425,8 @@ ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server, datas)->
roomlist.start room if !room.windbot and settings.modules.http.websocket_roomlist
#room.duels = []
room.dueling_players = []
for player in room.get_playing_player()
playing_players = room.get_playing_player()
for player in playing_players
room.dueling_players[player.pos] = player
room.scores[player.name_vpass] = 0
room.player_datas.push key: CLIENT_get_authorize_key(player), name: player.name, pos: player.pos
......@@ -3409,6 +3435,14 @@ ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server, datas)->
ROOM_players_oppentlist[player.ip] = null
if room.hostinfo.auto_death
ygopro.stoc_send_chat_to_room(room, "${auto_death_part1}#{room.hostinfo.auto_death}${auto_death_part2}", ygopro.constants.COLORS.BABYBLUE)
if room.arena
await call_match_api('POST', 'room-start', {
usernameA: playing_players[0].name,
usernameB: playing_players[1].name,
roomname: room.name,
starttime: room.start_time,
arena: room.arena
})
else if room.duel_stage == ygopro.constants.DUEL_STAGE.SIDING and client.pos < 4 # side deck verified
client.selected_preduel = true
if client.side_tcount
......@@ -4218,9 +4252,31 @@ if true
httpRequestListener = (request, response)->
parseQueryString = true
u = url.parse(request.url, parseQueryString)
base = "http://#{request.headers.host or 'localhost'}"
urlObj = new URL(request.url, base)
u =
pathname: urlObj.pathname
query: Object.fromEntries(urlObj.searchParams)
#pass_validated = u.query.pass == settings.modules.http.password
# Allow all CORS + PNA (Private Network Access) requests.
response.setHeader "Access-Control-Allow-Origin", "*"
response.setHeader "Access-Control-Allow-Private-Network", "true"
response.setHeader "Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method"
if (request.method or "").toLowerCase() == "options"
requestHeaders = request.headers["access-control-request-headers"]
allowHeaders = if Array.isArray(requestHeaders) then requestHeaders.join(", ") else (requestHeaders or "*")
response.writeHead(204, {
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Methods": "GET,POST,OPTIONS"
"Access-Control-Allow-Headers": allowHeaders
"Access-Control-Allow-Private-Network": "true"
"Access-Control-Max-Age": "86400"
})
response.end()
return
#console.log(u.query.username, u.query.pass)
if u.pathname == '/api/getrooms'
pass_validated = await auth.auth(u.query.username, u.query.pass, "get_rooms", "get_rooms", true)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -217,6 +217,25 @@ var pushHTMLs = function() {
async function requestListener(req, res) {
var u = url.parse(req.url, true);
// Allow all CORS + PNA (Private Network Access) requests.
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Private-Network", "true");
res.setHeader("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method");
if ((req.method || "").toLowerCase() === "options") {
const requestHeaders = req.headers["access-control-request-headers"];
res.writeHead(204, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": Array.isArray(requestHeaders)
? requestHeaders.join(", ")
: requestHeaders || "*",
"Access-Control-Allow-Private-Network": "true",
"Access-Control-Max-Age": "86400"
});
res.end();
return;
}
if (!await auth.auth(u.query.username, u.query.password, "update_dashboard", "update_dashboard")) {
res.writeHead(403);
res.end("Auth Failed.");
......
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