forked from mirror/MCSManager
Feat: services ch to en
This commit is contained in:
parent
d190eb1618
commit
1a3ed3f6f6
@ -2,7 +2,7 @@
|
||||
|
||||
import { Socket } from "socket.io";
|
||||
|
||||
// 应用实例数据流转发适配器
|
||||
// Application instance data stream forwarding adapter
|
||||
|
||||
export default class InstanceStreamListener {
|
||||
// Instance uuid -> Socket[]
|
||||
@ -13,7 +13,9 @@ export default class InstanceStreamListener {
|
||||
const sockets = this.listenMap.get(instanceUuid);
|
||||
for (const iterator of sockets)
|
||||
if (iterator.id === socket.id)
|
||||
throw new Error(`此 Socket ${socket.id} 已经存在于指定实例监听表中`);
|
||||
throw new Error(
|
||||
`This Socket ${socket.id} already exists in the specified instance listening table`
|
||||
);
|
||||
sockets.push(socket);
|
||||
} else {
|
||||
this.listenMap.set(instanceUuid, [socket]);
|
||||
@ -22,7 +24,7 @@ export default class InstanceStreamListener {
|
||||
|
||||
public cannelForward(socket: Socket, instanceUuid: string) {
|
||||
if (!this.listenMap.has(instanceUuid))
|
||||
throw new Error(`指定 ${instanceUuid} 并不存在于监听表中`);
|
||||
throw new Error(`The specified ${instanceUuid} does not exist in the listening table`);
|
||||
const socketList = this.listenMap.get(instanceUuid);
|
||||
socketList.forEach((v, index) => {
|
||||
if (v.id === socket.id) socketList.splice(index, 1);
|
||||
|
@ -13,7 +13,7 @@ interface Page<T> {
|
||||
data: T[];
|
||||
}
|
||||
|
||||
// 供给路由层使用的MAP型查询接口
|
||||
// Provide the MAP query interface used by the routing layer
|
||||
export class QueryMapWrapper {
|
||||
constructor(public map: IMap) {}
|
||||
|
||||
@ -43,7 +43,7 @@ export class QueryMapWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
// 供 QueryWrapper 使用的数据源接口
|
||||
// Data source interface for QueryWrapper to use
|
||||
export interface IDataSource<T> {
|
||||
selectPage: (condition: any, page: number, pageSize: number) => Page<T>;
|
||||
select: (condition: any) => any[];
|
||||
@ -52,7 +52,7 @@ export interface IDataSource<T> {
|
||||
insert: (data: any) => void;
|
||||
}
|
||||
|
||||
// MYSQL 数据源
|
||||
// MYSQL data source
|
||||
export class MySqlSource<T> implements IDataSource<T> {
|
||||
selectPage: (condition: any, page: number, pageSize: number) => Page<T>;
|
||||
select: (condition: any) => any[];
|
||||
@ -61,7 +61,7 @@ export class MySqlSource<T> implements IDataSource<T> {
|
||||
insert: (data: any) => void;
|
||||
}
|
||||
|
||||
// 本地文件数据源(内嵌式微型数据库)
|
||||
// local file data source (embedded microdatabase)
|
||||
export class LocalFileSource<T> implements IDataSource<T> {
|
||||
constructor(public data: any) {}
|
||||
|
||||
@ -108,7 +108,7 @@ export class LocalFileSource<T> implements IDataSource<T> {
|
||||
insert(data: any) {}
|
||||
}
|
||||
|
||||
// 供给路由层使用的统一数据查询接口
|
||||
// Provide the unified data query interface used by the routing layer
|
||||
export class QueryWrapper<T> {
|
||||
constructor(public dataSource: IDataSource<T>) {}
|
||||
|
||||
|
@ -25,7 +25,7 @@ interface ISystemInfo {
|
||||
loadavg: number[];
|
||||
}
|
||||
|
||||
// 系统详细信息每一段时间更新一次
|
||||
// System details are updated every time
|
||||
const info: ISystemInfo = {
|
||||
type: os.type(),
|
||||
hostname: os.hostname(),
|
||||
@ -42,7 +42,7 @@ const info: ISystemInfo = {
|
||||
processMem: 0
|
||||
};
|
||||
|
||||
// 定时刷新缓存
|
||||
// periodically refresh the cache
|
||||
setInterval(() => {
|
||||
if (os.platform() === "linux") {
|
||||
return setLinuxSystemInfo();
|
||||
@ -69,7 +69,7 @@ function setWindowsSystemInfo() {
|
||||
|
||||
function setLinuxSystemInfo() {
|
||||
try {
|
||||
// 基于 /proc/meminfo 的内存数据读取
|
||||
// read memory data based on /proc/meminfo
|
||||
const data = fs.readFileSync("/proc/meminfo", { encoding: "utf-8" });
|
||||
const list = data.split("\n");
|
||||
const infoTable: IInfoTable = {};
|
||||
@ -91,7 +91,7 @@ function setLinuxSystemInfo() {
|
||||
info.memUsage = (info.totalmem - info.freemem) / info.totalmem;
|
||||
osUtils.cpuUsage((p) => (info.cpuUsage = p));
|
||||
} catch (error) {
|
||||
// 若读取错误,则自动采用默认通用读取法
|
||||
// If the reading is wrong, the default general reading method is automatically used
|
||||
otherSystemInfo();
|
||||
}
|
||||
}
|
||||
|
@ -21,20 +21,18 @@ class StorageSubsystem {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类定义和标识符储存成本地文件
|
||||
*/
|
||||
// Stored in local file based on class definition and identifier
|
||||
public store(category: string, uuid: string, object: any) {
|
||||
const dirPath = path.join(StorageSubsystem.STIRAGE_DATA_PATH, category);
|
||||
if (!fs.existsSync(dirPath)) fs.mkdirsSync(dirPath);
|
||||
if (!this.checkFileName(uuid)) throw new Error(`UUID ${uuid} 不符合规范`);
|
||||
if (!this.checkFileName(uuid))
|
||||
throw new Error(`UUID ${uuid} does not conform to specification`);
|
||||
const filePath = path.join(dirPath, `${uuid}.json`);
|
||||
const data = JSON.stringify(object, null, 4);
|
||||
fs.writeFileSync(filePath, data, { encoding: "utf-8" });
|
||||
}
|
||||
|
||||
// 以复制目标方为原型的基本类型的深复制
|
||||
// target 复制目标 object 复制源
|
||||
// deep copy of the primitive type with the copy target as the prototype
|
||||
protected defineAttr(target: any, object: any): any {
|
||||
for (const v of Object.keys(target)) {
|
||||
const objectValue = object[v];
|
||||
@ -53,26 +51,27 @@ class StorageSubsystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类定义和标识符实例化成对象
|
||||
* Instantiate an object based on the class definition and identifier
|
||||
*/
|
||||
public load(category: string, classz: any, uuid: string) {
|
||||
const dirPath = path.join(StorageSubsystem.STIRAGE_DATA_PATH, category);
|
||||
if (!fs.existsSync(dirPath)) fs.mkdirsSync(dirPath);
|
||||
if (!this.checkFileName(uuid)) throw new Error(`UUID ${uuid} 不符合规范`);
|
||||
if (!this.checkFileName(uuid))
|
||||
throw new Error(`UUID ${uuid} does not conform to specification`);
|
||||
const filePath = path.join(dirPath, `${uuid}.json`);
|
||||
if (!fs.existsSync(filePath)) return null;
|
||||
const data = fs.readFileSync(filePath, { encoding: "utf-8" });
|
||||
const dataObject = JSON.parse(data);
|
||||
const target = new classz();
|
||||
// for (const v of Object.keys(target)) {
|
||||
// if (dataObject[v] !== undefined) target[v] = dataObject[v];
|
||||
// for (const v of Object. keys(target)) {
|
||||
// if (dataObject[v] !== undefined) target[v] = dataObject[v];
|
||||
// }
|
||||
// 深层对象复制
|
||||
// deep object copy
|
||||
return this.defineAttr(target, dataObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过类定义返回所有与此类有关的标识符
|
||||
* Return all identifiers related to this class through the class definition
|
||||
*/
|
||||
public list(category: string) {
|
||||
const dirPath = path.join(StorageSubsystem.STIRAGE_DATA_PATH, category);
|
||||
@ -86,7 +85,7 @@ class StorageSubsystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过类定义删除指定类型的标识符实例
|
||||
* Delete an identifier instance of the specified type through the class definition
|
||||
*/
|
||||
public delete(category: string, uuid: string) {
|
||||
const filePath = path.join(StorageSubsystem.STIRAGE_DATA_PATH, category, `${uuid}.json`);
|
||||
|
@ -22,10 +22,10 @@ export default class RemoteService {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
// 连接远程服务
|
||||
// connect to remote service
|
||||
public connect(connectOpts?: SocketIOClient.ConnectOpts) {
|
||||
if (connectOpts) this.config.connectOpts = connectOpts;
|
||||
// 开始正式连接远程Socket程序
|
||||
// Start the formal connection to the remote Socket program
|
||||
let addr = `ws://${this.config.ip}:${this.config.port}`;
|
||||
if (this.config.ip.indexOf("wss://") === 0 || this.config.ip.indexOf("ws://") === 0) {
|
||||
addr = `${this.config.ip}:${this.config.port}`;
|
||||
@ -37,7 +37,7 @@ export default class RemoteService {
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
// 防止重复注册事件
|
||||
// prevent duplicate registration of events
|
||||
if (this.socket && this.socket.hasListeners("connect")) {
|
||||
logger.info(`${$t("daemonInfo.replaceConnect")}:${daemonInfo}`);
|
||||
return this.refreshReconnect();
|
||||
@ -46,7 +46,7 @@ export default class RemoteService {
|
||||
logger.info(`${$t("daemonInfo.tryConnect")}:${daemonInfo}`);
|
||||
this.socket = io.connect(addr, connectOpts);
|
||||
|
||||
// 注册内置事件
|
||||
// register built-in events
|
||||
this.socket.on("connect", async () => {
|
||||
logger.info($t("daemonInfo.connect", { v: daemonInfo }));
|
||||
await this.onConnect();
|
||||
|
@ -2,30 +2,30 @@
|
||||
|
||||
// @Entity
|
||||
export default class SystemConfig {
|
||||
// HTTP 服务端口与IP
|
||||
// HTTP service port and IP
|
||||
httpPort: number = 23333;
|
||||
httpIp: string = null;
|
||||
|
||||
// 数据传输端口
|
||||
// data transfer port
|
||||
dataPort: number = 23334;
|
||||
|
||||
// 分布式转发模式
|
||||
// Distributed forwarding mode
|
||||
forwardType: number = 1;
|
||||
|
||||
// 是否准许跨域请求
|
||||
// Whether to allow cross-domain requests
|
||||
crossDomain: boolean = false;
|
||||
// 是否采用 Gzip 压缩 HTTP 返回信息
|
||||
// Whether to use Gzip compression for HTTP return information
|
||||
gzip: boolean = false;
|
||||
// 最大同时压缩任务
|
||||
// Maximum simultaneous compression tasks
|
||||
maxCompress: number = 1;
|
||||
// 最大同时下载任务
|
||||
// Maximum simultaneous download tasks
|
||||
maxDonwload: number = 10;
|
||||
// 解压缩实现形式
|
||||
// Decompression implementation form
|
||||
zipType: number = 1;
|
||||
// 登录次数IP限制
|
||||
// Login times IP limit
|
||||
loginCheckIp: boolean = true;
|
||||
// 登录界面文案
|
||||
// login interface copy
|
||||
loginInfo: string = "";
|
||||
// 是否对普通用户开启文件管理功能
|
||||
// Whether to open the file management function for ordinary users
|
||||
canFileManager = true;
|
||||
}
|
||||
|
@ -27,10 +27,10 @@ function apiError(ctx: Koa.ParameterizedContext) {
|
||||
ctx.body = `[Forbidden] ${$t("permission.apiError")}`;
|
||||
}
|
||||
|
||||
// 基本用户权限中间件
|
||||
// Basic user permission middleware
|
||||
export = (parameter: any) => {
|
||||
return async (ctx: Koa.ParameterizedContext, next: Function) => {
|
||||
// 若为 API 请求,则进行 API 级的权限判断
|
||||
// If it is an API request, perform API-level permission judgment
|
||||
if (ctx.query.apikey) {
|
||||
const apiKey = String(ctx.query.apikey);
|
||||
const user = getUuidByApiKey(apiKey);
|
||||
@ -41,7 +41,7 @@ export = (parameter: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 若路由需要 Token 验证则进行验证,默认是自动验证
|
||||
// If the route requires Token verification, it will be verified, the default is automatic verification
|
||||
if (parameter["token"] !== false) {
|
||||
if (!isAjax(ctx)) return ajaxError(ctx);
|
||||
const requestToken = ctx.query.token;
|
||||
@ -51,12 +51,12 @@ export = (parameter: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 若权限属性为数字则自动执行权限判定
|
||||
// If the permission attribute is a number, the permission determination is automatically executed
|
||||
if (!isNaN(parseInt(parameter["level"]))) {
|
||||
// 最基础的身份认证判定
|
||||
// The most basic authentication decision
|
||||
if (ctx.session["login"] === true && ctx.session["uuid"] && ctx.session["userName"]) {
|
||||
const user = userSystem.getInstance(ctx.session["uuid"]);
|
||||
// 普通用户与管理用户的权限判断
|
||||
// Judgment of permissions for ordinary users and administrative users
|
||||
if (user && user.permission >= parameter["level"]) {
|
||||
return await next();
|
||||
}
|
||||
@ -65,7 +65,7 @@ export = (parameter: any) => {
|
||||
return await next();
|
||||
}
|
||||
|
||||
// 记录越权访问次数
|
||||
// record the number of unauthorized access
|
||||
GlobalVariable.set(ILLEGAL_ACCESS_KEY, GlobalVariable.get(ILLEGAL_ACCESS_KEY, 0) + 1);
|
||||
return verificationFailed(ctx);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user