Feat: services ch to en

This commit is contained in:
Suwings 2022-07-29 15:11:55 +08:00
parent d190eb1618
commit 1a3ed3f6f6
7 changed files with 48 additions and 47 deletions

View File

@ -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);

View File

@ -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>) {}

View File

@ -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();
}
}

View File

@ -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`);

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
};