asaihost-nodejs 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/InterventionLog-WNVDQFAH.cjs.map +1 -1
- package/dist/LogStore-AP4T2CFD.cjs.map +1 -1
- package/dist/asaihost-nodejs.cjs +708 -513
- package/dist/asaihost-nodejs.cjs.map +1 -1
- package/dist/asaihost-nodejs.es.js +319 -124
- package/dist/asaihost-nodejs.es.js.map +1 -1
- package/dist/chunk-2BCIIKRG.cjs.map +1 -1
- package/dist/{chunk-OTL2B4WS.es.js → chunk-3E4Y5ATG.es.js} +2 -2
- package/dist/{chunk-ZK4O4Z2O.cjs → chunk-5EWEKXQI.cjs} +20 -20
- package/dist/chunk-5EWEKXQI.cjs.map +1 -0
- package/dist/chunk-ARHPHWT5.cjs.map +1 -1
- package/dist/{chunk-GXOFLFFW.cjs → chunk-FRPN33BY.cjs} +3 -2
- package/dist/chunk-FRPN33BY.cjs.map +1 -0
- package/dist/{chunk-WXW5DYNU.cjs → chunk-H2QP5J7X.cjs} +9 -9
- package/dist/chunk-H2QP5J7X.cjs.map +1 -0
- package/dist/chunk-HR5JKN7Y.cjs.map +1 -1
- package/dist/{chunk-BOIRAQXE.es.js → chunk-M3NURHGU.es.js} +2 -1
- package/dist/chunk-O6LVLSNB.cjs.map +1 -1
- package/dist/chunk-OCEBEEP5.cjs.map +1 -1
- package/dist/chunk-SMVZ3ZDJ.cjs.map +1 -1
- package/dist/chunk-U2YJH2RW.cjs.map +1 -1
- package/dist/{chunk-5WJQD4RZ.es.js → chunk-UKZ3DP37.es.js} +3 -3
- package/dist/intervention-hooks-4NAAAZK3.cjs.map +1 -1
- package/dist/log-alert-LAJ6VSAG.cjs.map +1 -1
- package/dist/log-formats-TUXGMCCU.cjs.map +1 -1
- package/dist/{password-4P7IZUDQ.es.js → password-2ZBHQQBF.es.js} +3 -3
- package/dist/password-T762KJOI.cjs +20 -0
- package/dist/password-T762KJOI.cjs.map +1 -0
- package/dist/user-store-6QNAL4CK.cjs +12 -0
- package/dist/user-store-6QNAL4CK.cjs.map +1 -0
- package/dist/{user-store-FXD2N55G.es.js → user-store-ZI67TXSI.es.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-GXOFLFFW.cjs.map +0 -1
- package/dist/chunk-WXW5DYNU.cjs.map +0 -1
- package/dist/chunk-ZK4O4Z2O.cjs.map +0 -1
- package/dist/password-MDYRL6ZD.cjs +0 -20
- package/dist/password-MDYRL6ZD.cjs.map +0 -1
- package/dist/user-store-55HOLHEM.cjs +0 -12
- package/dist/user-store-55HOLHEM.cjs.map +0 -1
- /package/dist/{chunk-OTL2B4WS.es.js.map → chunk-3E4Y5ATG.es.js.map} +0 -0
- /package/dist/{chunk-BOIRAQXE.es.js.map → chunk-M3NURHGU.es.js.map} +0 -0
- /package/dist/{chunk-5WJQD4RZ.es.js.map → chunk-UKZ3DP37.es.js.map} +0 -0
- /package/dist/{password-4P7IZUDQ.es.js.map → password-2ZBHQQBF.es.js.map} +0 -0
- /package/dist/{user-store-FXD2N55G.es.js.map → user-store-ZI67TXSI.es.js.map} +0 -0
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
secureCompare,
|
|
51
51
|
validatePasswordChange,
|
|
52
52
|
verifyPassword
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-3E4Y5ATG.es.js";
|
|
54
54
|
import {
|
|
55
55
|
USER_LV,
|
|
56
56
|
applySecretsToHostConfig,
|
|
@@ -62,20 +62,21 @@ import {
|
|
|
62
62
|
resolveHttpsCertFromPaths,
|
|
63
63
|
stripForbiddenSecretsFromHostConfig,
|
|
64
64
|
validateAsaiSecrets
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-UKZ3DP37.es.js";
|
|
66
66
|
import {
|
|
67
67
|
getDefaultResetPassword,
|
|
68
68
|
getPasswordPolicy,
|
|
69
69
|
getPermissionThreshold,
|
|
70
70
|
getPublicSecurityConfig,
|
|
71
71
|
getUserLevelConfigSync,
|
|
72
|
+
getUserStoreConfig,
|
|
72
73
|
isPasswordExpired,
|
|
73
74
|
isValidUserLv,
|
|
74
75
|
loadUserLevelConfig,
|
|
75
76
|
resolveRoleForLevel,
|
|
76
77
|
saveUserLevelConfig,
|
|
77
78
|
validatePasswordWithPolicy
|
|
78
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-M3NURHGU.es.js";
|
|
79
80
|
import {
|
|
80
81
|
getDataServerForAsDb
|
|
81
82
|
} from "./chunk-ZQBHJRAO.es.js";
|
|
@@ -993,19 +994,24 @@ function terminateWs(wsclient) {
|
|
|
993
994
|
}
|
|
994
995
|
}
|
|
995
996
|
__name(terminateWs, "terminateWs");
|
|
996
|
-
async function clearStaleWsIfDead($asai, hostdir, us, existingWs) {
|
|
997
|
+
async function clearStaleWsIfDead($asai, hostdir, us, existingWs, timeoutMs) {
|
|
997
998
|
if (!us || us === "asai") return true;
|
|
998
999
|
const map = $asai.connectionsws?.[hostdir];
|
|
999
1000
|
if (!existingWs) {
|
|
1000
1001
|
if (map?.[us]) delete map[us];
|
|
1001
1002
|
return true;
|
|
1002
1003
|
}
|
|
1004
|
+
if (existingWs._asaiKicked) {
|
|
1005
|
+
terminateWs(existingWs);
|
|
1006
|
+
if (map?.[us] === existingWs) delete map[us];
|
|
1007
|
+
return true;
|
|
1008
|
+
}
|
|
1003
1009
|
if (!isWsStillActive(existingWs)) {
|
|
1004
1010
|
terminateWs(existingWs);
|
|
1005
1011
|
if (map?.[us] === existingWs) delete map[us];
|
|
1006
1012
|
return true;
|
|
1007
1013
|
}
|
|
1008
|
-
const alive = await probeWsAlive($asai, existingWs);
|
|
1014
|
+
const alive = await probeWsAlive($asai, existingWs, timeoutMs);
|
|
1009
1015
|
if (alive) return false;
|
|
1010
1016
|
terminateWs(existingWs);
|
|
1011
1017
|
if (map?.[us] === existingWs) delete map[us];
|
|
@@ -1025,22 +1031,38 @@ function getWsUserinfo(req, $asai) {
|
|
|
1025
1031
|
}
|
|
1026
1032
|
__name(getWsUserinfo, "getWsUserinfo");
|
|
1027
1033
|
function listOnlineWsUsers($asai, hostdir) {
|
|
1034
|
+
return listOnlineWsEntries($asai, hostdir).map((e) => e.us);
|
|
1035
|
+
}
|
|
1036
|
+
__name(listOnlineWsUsers, "listOnlineWsUsers");
|
|
1037
|
+
function listOnlineWsEntries($asai, hostdir) {
|
|
1028
1038
|
const users = [];
|
|
1039
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1029
1040
|
const map = $asai.connectionsws || {};
|
|
1030
1041
|
const dirs = hostdir ? [hostdir] : Object.keys(map);
|
|
1031
1042
|
for (const dir of dirs) {
|
|
1032
1043
|
for (const [us, ws2] of Object.entries(map[dir] || {})) {
|
|
1033
1044
|
if (!us || us === "asai") continue;
|
|
1034
1045
|
if (isWsStillActive(ws2)) {
|
|
1035
|
-
|
|
1046
|
+
if (seen.has(us)) continue;
|
|
1047
|
+
seen.add(us);
|
|
1048
|
+
const rawLv = ws2?.Userinfo?.[1];
|
|
1049
|
+
if (rawLv === "" || rawLv == null) {
|
|
1050
|
+
users.push({ us, lv: null });
|
|
1051
|
+
} else {
|
|
1052
|
+
const lvNum = Number(rawLv);
|
|
1053
|
+
users.push({
|
|
1054
|
+
us,
|
|
1055
|
+
lv: Number.isFinite(lvNum) ? lvNum : null
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1036
1058
|
} else if (map[dir]?.[us] === ws2) {
|
|
1037
1059
|
delete map[dir][us];
|
|
1038
1060
|
}
|
|
1039
1061
|
}
|
|
1040
1062
|
}
|
|
1041
|
-
return
|
|
1063
|
+
return users;
|
|
1042
1064
|
}
|
|
1043
|
-
__name(
|
|
1065
|
+
__name(listOnlineWsEntries, "listOnlineWsEntries");
|
|
1044
1066
|
function isUserOnlineOnWs($asai, us, hostdir) {
|
|
1045
1067
|
if (!us || us === "asai") return false;
|
|
1046
1068
|
const map = $asai.connectionsws || {};
|
|
@@ -1054,19 +1076,73 @@ function isUserOnlineOnWs($asai, us, hostdir) {
|
|
|
1054
1076
|
return false;
|
|
1055
1077
|
}
|
|
1056
1078
|
__name(isUserOnlineOnWs, "isUserOnlineOnWs");
|
|
1057
|
-
function kickUserWs($asai, us, hostdir) {
|
|
1079
|
+
async function kickUserWs($asai, us, hostdir) {
|
|
1058
1080
|
if (!us || us === "asai") return;
|
|
1059
1081
|
const map = $asai.connectionsws || {};
|
|
1060
1082
|
const dirs = hostdir ? [hostdir] : Object.keys(map);
|
|
1083
|
+
const waits = [];
|
|
1061
1084
|
for (const dir of dirs) {
|
|
1062
1085
|
const ws2 = map[dir]?.[us];
|
|
1063
1086
|
if (!ws2) continue;
|
|
1087
|
+
if (map[dir]?.[us] === ws2) delete map[dir][us];
|
|
1064
1088
|
try {
|
|
1065
|
-
ws2.
|
|
1089
|
+
ws2._asaiKicked = Date.now();
|
|
1066
1090
|
} catch {
|
|
1067
1091
|
}
|
|
1068
|
-
|
|
1092
|
+
waits.push(
|
|
1093
|
+
new Promise((resolve6) => {
|
|
1094
|
+
let done = false;
|
|
1095
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
1096
|
+
if (done) return;
|
|
1097
|
+
done = true;
|
|
1098
|
+
try {
|
|
1099
|
+
ws2.off?.("close", finish);
|
|
1100
|
+
} catch {
|
|
1101
|
+
}
|
|
1102
|
+
resolve6();
|
|
1103
|
+
}, "finish");
|
|
1104
|
+
try {
|
|
1105
|
+
ws2.once?.("close", finish);
|
|
1106
|
+
} catch {
|
|
1107
|
+
}
|
|
1108
|
+
const payload = JSON.stringify({
|
|
1109
|
+
ty: "publish/web",
|
|
1110
|
+
db: {
|
|
1111
|
+
exit: 1,
|
|
1112
|
+
type: "err",
|
|
1113
|
+
lang: "forcedout",
|
|
1114
|
+
langpm: `${us}`,
|
|
1115
|
+
con: `${us} forced out by another login`
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
const hardClose = /* @__PURE__ */ __name(() => {
|
|
1119
|
+
try {
|
|
1120
|
+
if (typeof ws2.terminate === "function") ws2.terminate();
|
|
1121
|
+
else ws2.close();
|
|
1122
|
+
} catch {
|
|
1123
|
+
try {
|
|
1124
|
+
ws2.close();
|
|
1125
|
+
} catch {
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}, "hardClose");
|
|
1129
|
+
try {
|
|
1130
|
+
ws2.send(payload, () => {
|
|
1131
|
+
hardClose();
|
|
1132
|
+
finish();
|
|
1133
|
+
});
|
|
1134
|
+
} catch {
|
|
1135
|
+
hardClose();
|
|
1136
|
+
finish();
|
|
1137
|
+
}
|
|
1138
|
+
setTimeout(() => {
|
|
1139
|
+
hardClose();
|
|
1140
|
+
finish();
|
|
1141
|
+
}, 150);
|
|
1142
|
+
})
|
|
1143
|
+
);
|
|
1069
1144
|
}
|
|
1145
|
+
if (waits.length) await Promise.all(waits);
|
|
1070
1146
|
}
|
|
1071
1147
|
__name(kickUserWs, "kickUserWs");
|
|
1072
1148
|
async function removeSessionOnWsClose($asai, us, token) {
|
|
@@ -1105,27 +1181,31 @@ async function isOkWs($asai, hostdir, ws2, _req, hostcfg) {
|
|
|
1105
1181
|
if (us !== "asai" && $asai.connectionsws[hostdir]?.[us]) {
|
|
1106
1182
|
const existingWs = $asai.connectionsws[hostdir][us];
|
|
1107
1183
|
if (existingWs?.Userinfo?.[2] === tk) {
|
|
1108
|
-
if (isWsStillActive(existingWs)) {
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
return
|
|
1115
|
-
}
|
|
1116
|
-
try {
|
|
1117
|
-
existingWs.close();
|
|
1118
|
-
} catch {
|
|
1184
|
+
if (!isWsStillActive(existingWs)) {
|
|
1185
|
+
try {
|
|
1186
|
+
existingWs.close();
|
|
1187
|
+
} catch {
|
|
1188
|
+
}
|
|
1189
|
+
delete $asai.connectionsws[hostdir][us];
|
|
1190
|
+
return true;
|
|
1119
1191
|
}
|
|
1120
|
-
|
|
1121
|
-
return true;
|
|
1192
|
+
const cleared2 = await clearStaleWsIfDead($asai, hostdir, us, existingWs, 800);
|
|
1193
|
+
if (cleared2) return true;
|
|
1194
|
+
rejectIncomingWs(ws2, {
|
|
1195
|
+
lang: "pageworking",
|
|
1196
|
+
langpm: `${us}`,
|
|
1197
|
+
con: `${us} page already running`,
|
|
1198
|
+
online: listOnlineWsEntries($asai, hostdir)
|
|
1199
|
+
});
|
|
1200
|
+
return false;
|
|
1122
1201
|
}
|
|
1123
1202
|
const cleared = await clearStaleWsIfDead($asai, hostdir, us, existingWs);
|
|
1124
1203
|
if (!cleared) {
|
|
1125
1204
|
rejectIncomingWs(ws2, {
|
|
1126
1205
|
lang: "logged",
|
|
1127
1206
|
langpm: `${us}`,
|
|
1128
|
-
con: `${us} logged in
|
|
1207
|
+
con: `${us} logged in!`,
|
|
1208
|
+
online: listOnlineWsEntries($asai, hostdir)
|
|
1129
1209
|
});
|
|
1130
1210
|
return false;
|
|
1131
1211
|
}
|
|
@@ -1137,19 +1217,22 @@ async function isOkWs($asai, hostdir, ws2, _req, hostcfg) {
|
|
|
1137
1217
|
(item) => item.Userinfo?.[2] === tk && item.Userinfo?.[0] !== us
|
|
1138
1218
|
);
|
|
1139
1219
|
const maxOnline = hostcfg.maxonline || 100;
|
|
1220
|
+
const online = listOnlineWsEntries($asai, hostdir);
|
|
1140
1221
|
if (sameTkWs) {
|
|
1141
1222
|
rejectIncomingWs(ws2, {
|
|
1142
1223
|
lang: "loggedsametk",
|
|
1143
1224
|
langpm: `${us}(${sameTkWs.Userinfo[0]})`,
|
|
1144
|
-
con: `${us}(${sameTkWs.Userinfo[0]}) logged in
|
|
1225
|
+
con: `${us}(${sameTkWs.Userinfo[0]}) logged in!`,
|
|
1226
|
+
online
|
|
1145
1227
|
});
|
|
1146
1228
|
return false;
|
|
1147
1229
|
}
|
|
1148
|
-
if (
|
|
1230
|
+
if (online.length >= maxOnline) {
|
|
1149
1231
|
rejectIncomingWs(ws2, {
|
|
1150
1232
|
lang: "maxlogged",
|
|
1151
1233
|
langpm: `${maxOnline}`,
|
|
1152
|
-
con: `max ${maxOnline} users online
|
|
1234
|
+
con: `max ${maxOnline} users online!`,
|
|
1235
|
+
online
|
|
1153
1236
|
});
|
|
1154
1237
|
return false;
|
|
1155
1238
|
}
|
|
@@ -1533,11 +1616,11 @@ function createSkipChecker($asai) {
|
|
|
1533
1616
|
}
|
|
1534
1617
|
if (exact.size === 0 && prefixes.length === 0) return () => false;
|
|
1535
1618
|
return (url) => {
|
|
1536
|
-
const
|
|
1537
|
-
if (!
|
|
1538
|
-
if (exact.has(
|
|
1619
|
+
const path9 = normalizeRequestPath(url);
|
|
1620
|
+
if (!path9) return false;
|
|
1621
|
+
if (exact.has(path9)) return true;
|
|
1539
1622
|
for (let i = 0; i < prefixes.length; i++) {
|
|
1540
|
-
if (
|
|
1623
|
+
if (path9.startsWith(prefixes[i])) return true;
|
|
1541
1624
|
}
|
|
1542
1625
|
return false;
|
|
1543
1626
|
};
|
|
@@ -2424,7 +2507,7 @@ async function attachServerUserLevel(req, $asai) {
|
|
|
2424
2507
|
if (!Array.isArray(userinfo) || !userinfo[0]) return;
|
|
2425
2508
|
const us = String(userinfo[0]);
|
|
2426
2509
|
try {
|
|
2427
|
-
const { createUserStore: createUserStore2 } = await import("./user-store-
|
|
2510
|
+
const { createUserStore: createUserStore2 } = await import("./user-store-ZI67TXSI.es.js");
|
|
2428
2511
|
const user = await createUserStore2($asai).findByUsername(us);
|
|
2429
2512
|
if (user && user.status === "active") {
|
|
2430
2513
|
req._serverUser = { us: user.us, lv: user.lv, status: user.status };
|
|
@@ -2455,11 +2538,11 @@ function getSecurityConfig($asai) {
|
|
|
2455
2538
|
return $asai?.hostconfig?.security || {};
|
|
2456
2539
|
}
|
|
2457
2540
|
__name(getSecurityConfig, "getSecurityConfig");
|
|
2458
|
-
function pathMatchesPattern(
|
|
2541
|
+
function pathMatchesPattern(path9, pattern) {
|
|
2459
2542
|
if (pattern.endsWith("*")) {
|
|
2460
|
-
return
|
|
2543
|
+
return path9.startsWith(pattern.slice(0, -1));
|
|
2461
2544
|
}
|
|
2462
|
-
return
|
|
2545
|
+
return path9 === pattern;
|
|
2463
2546
|
}
|
|
2464
2547
|
__name(pathMatchesPattern, "pathMatchesPattern");
|
|
2465
2548
|
function isAuthSkipped($asai, pathname) {
|
|
@@ -4066,6 +4149,37 @@ async function purgeOfflineSessions($asai, hostdir, store) {
|
|
|
4066
4149
|
__name(purgeOfflineSessions, "purgeOfflineSessions");
|
|
4067
4150
|
|
|
4068
4151
|
// src/sysserver/api/login/index.ts
|
|
4152
|
+
import fs9 from "fs";
|
|
4153
|
+
import path4 from "path";
|
|
4154
|
+
async function resolveUserLv($asai, store, us, wsLv) {
|
|
4155
|
+
if (!us) return null;
|
|
4156
|
+
try {
|
|
4157
|
+
const user = await store.findByUsername(us);
|
|
4158
|
+
if (user && user.lv != null && Number.isFinite(Number(user.lv))) {
|
|
4159
|
+
return Number(user.lv);
|
|
4160
|
+
}
|
|
4161
|
+
} catch {
|
|
4162
|
+
}
|
|
4163
|
+
try {
|
|
4164
|
+
const cfg = getUserStoreConfig($asai);
|
|
4165
|
+
const dir = String(cfg?.opt?.dir || "");
|
|
4166
|
+
if (dir) {
|
|
4167
|
+
const base = path4.isAbsolute(dir) ? dir : path4.join(process.cwd(), dir);
|
|
4168
|
+
const safeUs = us.replace(/[\\/:*?"<>|]/g, "");
|
|
4169
|
+
const file = path4.join(base, "json", `${safeUs}.json`);
|
|
4170
|
+
if (safeUs && fs9.existsSync(file)) {
|
|
4171
|
+
const raw = JSON.parse(fs9.readFileSync(file, "utf8"));
|
|
4172
|
+
const lv = Number(raw?.lv);
|
|
4173
|
+
if (Number.isFinite(lv)) return lv;
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
} catch {
|
|
4177
|
+
}
|
|
4178
|
+
if (wsLv === null || wsLv === void 0 || wsLv === "") return null;
|
|
4179
|
+
const n = Number(wsLv);
|
|
4180
|
+
return Number.isFinite(n) ? n : null;
|
|
4181
|
+
}
|
|
4182
|
+
__name(resolveUserLv, "resolveUserLv");
|
|
4069
4183
|
function getSecurity($asai) {
|
|
4070
4184
|
return $asai?.hostconfig?.security || {};
|
|
4071
4185
|
}
|
|
@@ -4229,10 +4343,7 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4229
4343
|
if (hostcfg.ckws) {
|
|
4230
4344
|
const existingWs = $asai.connectionsws?.[hostdir]?.[us];
|
|
4231
4345
|
if (existingWs) {
|
|
4232
|
-
|
|
4233
|
-
if (!cleared) {
|
|
4234
|
-
kickUserWs($asai, us, hostdir);
|
|
4235
|
-
}
|
|
4346
|
+
await clearStaleWsIfDead($asai, hostdir, us, existingWs);
|
|
4236
4347
|
}
|
|
4237
4348
|
}
|
|
4238
4349
|
const quotaCheck = await canLogin($asai, us, hostdir);
|
|
@@ -4279,6 +4390,56 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4279
4390
|
return sendFail(res, err?.message || err, opt);
|
|
4280
4391
|
}
|
|
4281
4392
|
}
|
|
4393
|
+
if (url.startsWith("/api/user/login/force/")) {
|
|
4394
|
+
try {
|
|
4395
|
+
const us = sanitizeString(String(req?.Userinfo?.[0] || ""), 64);
|
|
4396
|
+
if (!us) return sendErr(res, "AUTH_MISSING", void 0, opt);
|
|
4397
|
+
const myLv = Number(req?.Userinfo?.[1] ?? 0);
|
|
4398
|
+
const targetUs = sanitizeString(String(body?.targetUs || body?.us || ""), 64);
|
|
4399
|
+
const kicked = [];
|
|
4400
|
+
if (isUserOnlineOnWs($asai, us, hostdir)) {
|
|
4401
|
+
await kickUserWs($asai, us, hostdir);
|
|
4402
|
+
kicked.push(us);
|
|
4403
|
+
}
|
|
4404
|
+
const onlineRaw = listOnlineWsEntries($asai, hostdir).filter((e) => e.us !== us);
|
|
4405
|
+
const online = await Promise.all(
|
|
4406
|
+
onlineRaw.map(async (e) => ({
|
|
4407
|
+
us: e.us,
|
|
4408
|
+
lv: await resolveUserLv($asai, store, e.us, e.lv)
|
|
4409
|
+
}))
|
|
4410
|
+
);
|
|
4411
|
+
const candidates = targetUs ? online.filter((e) => e.us === targetUs) : online;
|
|
4412
|
+
for (const entry of candidates) {
|
|
4413
|
+
const entryLv = entry.lv == null ? NaN : Number(entry.lv);
|
|
4414
|
+
if (!Number.isFinite(entryLv) || myLv < entryLv) {
|
|
4415
|
+
if (targetUs) {
|
|
4416
|
+
return sendErr(res, "AUTH_FORBIDDEN", void 0, opt);
|
|
4417
|
+
}
|
|
4418
|
+
continue;
|
|
4419
|
+
}
|
|
4420
|
+
await kickUserWs($asai, entry.us, hostdir);
|
|
4421
|
+
kicked.push(entry.us);
|
|
4422
|
+
}
|
|
4423
|
+
if (!kicked.length && online.length) {
|
|
4424
|
+
return sendErr(res, "AUTH_FORBIDDEN", void 0, opt);
|
|
4425
|
+
}
|
|
4426
|
+
logSecurityEvent($asai, {
|
|
4427
|
+
type: "AUTH_SUCCESS",
|
|
4428
|
+
path: url,
|
|
4429
|
+
method: "POST",
|
|
4430
|
+
user: us,
|
|
4431
|
+
ip,
|
|
4432
|
+
detail: `force_login_kick:${kicked.join(",") || "none"}`
|
|
4433
|
+
});
|
|
4434
|
+
return sendSuccess(
|
|
4435
|
+
res,
|
|
4436
|
+
{ ok: true, us, kicked, online: listOnlineWsEntries($asai, hostdir) },
|
|
4437
|
+
opt
|
|
4438
|
+
);
|
|
4439
|
+
} catch (err) {
|
|
4440
|
+
return sendFail(res, err?.message || err, opt);
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4282
4443
|
if (url.startsWith("/api/user/login/admin/kick/")) {
|
|
4283
4444
|
if (!await checkAdmin(req, url, getPermissionThreshold($asai, "adminWrite"))) {
|
|
4284
4445
|
return sendErr(res, "AUTH_FORBIDDEN", void 0, opt);
|
|
@@ -4292,7 +4453,7 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4292
4453
|
if (!isSessionUserOnline($asai, target.us, hostdir)) {
|
|
4293
4454
|
return sendErr(res, "SESSION_NOT_ONLINE", void 0, opt);
|
|
4294
4455
|
}
|
|
4295
|
-
kickUserWs($asai, target.us, hostdir);
|
|
4456
|
+
await kickUserWs($asai, target.us, hostdir);
|
|
4296
4457
|
await store.removeSession(sessionId);
|
|
4297
4458
|
const operator = String(req?.Userinfo?.[0] || "");
|
|
4298
4459
|
await logSessionTerminate($asai, {
|
|
@@ -4491,6 +4652,39 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4491
4652
|
await loadUserLevelConfig($asai);
|
|
4492
4653
|
return sendSuccess(res, getPublicSecurityConfig($asai, lang), opt);
|
|
4493
4654
|
}
|
|
4655
|
+
if (url.startsWith("/api/user/login/online/")) {
|
|
4656
|
+
try {
|
|
4657
|
+
const us = sanitizeString(String(req?.Userinfo?.[0] || ""), 64);
|
|
4658
|
+
if (!us) return sendErr(res, "AUTH_MISSING", void 0, opt);
|
|
4659
|
+
const rawOnline = listOnlineWsEntries($asai, hostdir);
|
|
4660
|
+
const online = await Promise.all(
|
|
4661
|
+
rawOnline.map(async (e) => ({
|
|
4662
|
+
us: e.us,
|
|
4663
|
+
lv: await resolveUserLv($asai, store, e.us, e.lv)
|
|
4664
|
+
}))
|
|
4665
|
+
);
|
|
4666
|
+
const rawMy = req?.Userinfo?.[1];
|
|
4667
|
+
const wsMyLv = rawMy === null || rawMy === void 0 || rawMy === "" ? null : Number(rawMy);
|
|
4668
|
+
const myLvOut = await resolveUserLv(
|
|
4669
|
+
$asai,
|
|
4670
|
+
store,
|
|
4671
|
+
us,
|
|
4672
|
+
Number.isFinite(wsMyLv) ? wsMyLv : null
|
|
4673
|
+
);
|
|
4674
|
+
return sendSuccess(
|
|
4675
|
+
res,
|
|
4676
|
+
{
|
|
4677
|
+
us,
|
|
4678
|
+
lv: myLvOut,
|
|
4679
|
+
online,
|
|
4680
|
+
maxonline: $asai.getHost?.(hostdir)?.maxonline ?? 100
|
|
4681
|
+
},
|
|
4682
|
+
opt
|
|
4683
|
+
);
|
|
4684
|
+
} catch (err) {
|
|
4685
|
+
return sendFail(res, err?.message || err, opt);
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4494
4688
|
if (url.startsWith("/api/user/login/admin/levels/")) {
|
|
4495
4689
|
if (!await checkAdmin(req, url, getPermissionThreshold($asai, "adminRead"))) {
|
|
4496
4690
|
return sendErr(res, "AUTH_FORBIDDEN", void 0, opt);
|
|
@@ -4613,10 +4807,10 @@ var As_default = {
|
|
|
4613
4807
|
return relativePath;
|
|
4614
4808
|
},
|
|
4615
4809
|
//创建多层文件夹 同步
|
|
4616
|
-
ensureDir(
|
|
4810
|
+
ensureDir(fs12, relativePath) {
|
|
4617
4811
|
const absPathDir = this.toDirPath(relativePath);
|
|
4618
4812
|
const absPath = this.toAbsolutePath(relativePath);
|
|
4619
|
-
if (!
|
|
4813
|
+
if (!fs12.existsSync(absPath)) {
|
|
4620
4814
|
let pathTmp = "";
|
|
4621
4815
|
absPathDir.split("/").forEach((el) => {
|
|
4622
4816
|
if (el) {
|
|
@@ -4624,8 +4818,8 @@ var As_default = {
|
|
|
4624
4818
|
pathTmp += "/";
|
|
4625
4819
|
}
|
|
4626
4820
|
pathTmp += el;
|
|
4627
|
-
if (!
|
|
4628
|
-
if (!
|
|
4821
|
+
if (!fs12.existsSync(pathTmp)) {
|
|
4822
|
+
if (!fs12.mkdirSync(pathTmp, { recursive: true })) {
|
|
4629
4823
|
return absPath;
|
|
4630
4824
|
}
|
|
4631
4825
|
}
|
|
@@ -4634,10 +4828,10 @@ var As_default = {
|
|
|
4634
4828
|
}
|
|
4635
4829
|
return absPath;
|
|
4636
4830
|
},
|
|
4637
|
-
makeDir(
|
|
4831
|
+
makeDir(fs12, filePaths) {
|
|
4638
4832
|
return new Promise((resolve6, reject) => {
|
|
4639
4833
|
try {
|
|
4640
|
-
const newPath = this.ensureDir(
|
|
4834
|
+
const newPath = this.ensureDir(fs12, filePaths);
|
|
4641
4835
|
resolve6(newPath);
|
|
4642
4836
|
} catch (err) {
|
|
4643
4837
|
reject(err);
|
|
@@ -5234,7 +5428,7 @@ var AsDb_default = /* @__PURE__ */ __name(($asai, cfg) => {
|
|
|
5234
5428
|
}, "default");
|
|
5235
5429
|
|
|
5236
5430
|
// src/sysserver/lib/common/reqWork.ts
|
|
5237
|
-
import * as
|
|
5431
|
+
import * as path5 from "path";
|
|
5238
5432
|
var reqWork_default = /* @__PURE__ */ __name(($asai) => {
|
|
5239
5433
|
function hostDefault2(mod) {
|
|
5240
5434
|
if (mod && typeof mod === "object" && "default" in mod) {
|
|
@@ -5250,28 +5444,29 @@ var reqWork_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
5250
5444
|
throw new Error("Missing path");
|
|
5251
5445
|
}
|
|
5252
5446
|
const decoded = decodeURIComponent(String(rawPath));
|
|
5253
|
-
if (
|
|
5254
|
-
|
|
5447
|
+
if (decoded.includes("\0")) {
|
|
5448
|
+
throw new Error("Invalid path");
|
|
5255
5449
|
}
|
|
5256
|
-
const
|
|
5257
|
-
const
|
|
5258
|
-
if (
|
|
5259
|
-
|
|
5260
|
-
const abs = path4.resolve(absRoot, rel);
|
|
5261
|
-
const relCheck = path4.relative(absRoot, abs);
|
|
5262
|
-
if (relCheck === "" || !relCheck.startsWith("..") && !path4.isAbsolute(relCheck)) {
|
|
5263
|
-
return abs;
|
|
5264
|
-
}
|
|
5450
|
+
const serverRoot = path5.resolve($asai?.serverRoot || process.cwd() || ".");
|
|
5451
|
+
const cleaned = String(decoded).replace(/\\/g, "/").trim();
|
|
5452
|
+
if (path5.isAbsolute(cleaned) || /^[a-zA-Z]:/.test(cleaned) || cleaned.startsWith("//")) {
|
|
5453
|
+
return path5.normalize(cleaned);
|
|
5265
5454
|
}
|
|
5455
|
+
const absTarget = path5.resolve(serverRoot, cleaned.replace(/^\.\//, ""));
|
|
5266
5456
|
const roots = $asai?.asaihost?.getHostAllowedRoots?.($asai?.hostconfig) || [];
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
if (
|
|
5457
|
+
const allow = /* @__PURE__ */ new Set();
|
|
5458
|
+
for (const r of roots) {
|
|
5459
|
+
if (r) allow.add(path5.resolve(r));
|
|
5270
5460
|
}
|
|
5271
|
-
|
|
5272
|
-
|
|
5461
|
+
allow.add(serverRoot);
|
|
5462
|
+
allow.add(path5.resolve(serverRoot, ".."));
|
|
5463
|
+
for (const root of allow) {
|
|
5464
|
+
const rel = path5.relative(root, absTarget);
|
|
5465
|
+
if (rel === "" || !rel.startsWith("..") && !path5.isAbsolute(rel)) {
|
|
5466
|
+
return absTarget;
|
|
5467
|
+
}
|
|
5273
5468
|
}
|
|
5274
|
-
|
|
5469
|
+
throw new Error("Path not allowed");
|
|
5275
5470
|
}
|
|
5276
5471
|
__name(getPathFromOpt, "getPathFromOpt");
|
|
5277
5472
|
function sendSuccess(res, data, opt) {
|
|
@@ -5319,18 +5514,18 @@ __export(AsFs_exports, {
|
|
|
5319
5514
|
write: () => write,
|
|
5320
5515
|
writeJson: () => writeJson
|
|
5321
5516
|
});
|
|
5322
|
-
import
|
|
5323
|
-
import
|
|
5517
|
+
import fs10 from "fs/promises";
|
|
5518
|
+
import path6 from "path";
|
|
5324
5519
|
async function ensureFile(filePath) {
|
|
5325
|
-
const normalized =
|
|
5326
|
-
await
|
|
5327
|
-
const fh = await
|
|
5520
|
+
const normalized = path6.normalize(filePath);
|
|
5521
|
+
await fs10.mkdir(path6.dirname(normalized), { recursive: true });
|
|
5522
|
+
const fh = await fs10.open(normalized, "a");
|
|
5328
5523
|
await fh.close();
|
|
5329
5524
|
}
|
|
5330
5525
|
__name(ensureFile, "ensureFile");
|
|
5331
5526
|
async function pathExists(filePath) {
|
|
5332
5527
|
try {
|
|
5333
|
-
await
|
|
5528
|
+
await fs10.access(path6.normalize(filePath));
|
|
5334
5529
|
return true;
|
|
5335
5530
|
} catch {
|
|
5336
5531
|
return false;
|
|
@@ -5338,7 +5533,7 @@ async function pathExists(filePath) {
|
|
|
5338
5533
|
}
|
|
5339
5534
|
__name(pathExists, "pathExists");
|
|
5340
5535
|
async function readJson(filePath) {
|
|
5341
|
-
const raw = await
|
|
5536
|
+
const raw = await fs10.readFile(path6.normalize(filePath), "utf8");
|
|
5342
5537
|
return JSON.parse(raw);
|
|
5343
5538
|
}
|
|
5344
5539
|
__name(readJson, "readJson");
|
|
@@ -5349,34 +5544,34 @@ function resolvePathUnderBase(baseDir, relPath) {
|
|
|
5349
5544
|
if (relPath.includes("\0")) {
|
|
5350
5545
|
throw new Error("Invalid path");
|
|
5351
5546
|
}
|
|
5352
|
-
const base =
|
|
5353
|
-
const target =
|
|
5354
|
-
const rel =
|
|
5355
|
-
if (rel.startsWith("..") ||
|
|
5547
|
+
const base = path6.resolve(baseDir);
|
|
5548
|
+
const target = path6.resolve(base, relPath.replace(/\\/g, "/"));
|
|
5549
|
+
const rel = path6.relative(base, target);
|
|
5550
|
+
if (rel.startsWith("..") || path6.isAbsolute(rel)) {
|
|
5356
5551
|
throw new Error("Path not allowed");
|
|
5357
5552
|
}
|
|
5358
5553
|
return target;
|
|
5359
5554
|
}
|
|
5360
5555
|
__name(resolvePathUnderBase, "resolvePathUnderBase");
|
|
5361
5556
|
async function readLogDir(dir) {
|
|
5362
|
-
const resolved =
|
|
5363
|
-
const stats = await
|
|
5557
|
+
const resolved = path6.resolve(dir);
|
|
5558
|
+
const stats = await fs10.stat(resolved);
|
|
5364
5559
|
if (!stats.isDirectory()) {
|
|
5365
5560
|
throw new Error("Not a directory");
|
|
5366
5561
|
}
|
|
5367
|
-
const dirName =
|
|
5368
|
-
const entries = await
|
|
5562
|
+
const dirName = path6.basename(resolved);
|
|
5563
|
+
const entries = await fs10.readdir(resolved, { withFileTypes: true });
|
|
5369
5564
|
const children = await Promise.all(
|
|
5370
5565
|
entries.map(async (entry) => {
|
|
5371
|
-
const fullPath =
|
|
5372
|
-
const st = await
|
|
5566
|
+
const fullPath = path6.join(resolved, entry.name);
|
|
5567
|
+
const st = await fs10.stat(fullPath);
|
|
5373
5568
|
const dot = entry.name.lastIndexOf(".");
|
|
5374
5569
|
const type = entry.isDirectory() ? "dir" : dot > -1 ? entry.name.substring(dot) : "file";
|
|
5375
5570
|
return {
|
|
5376
5571
|
name: entry.name,
|
|
5377
5572
|
size: st.size,
|
|
5378
5573
|
time: st.mtime.toISOString(),
|
|
5379
|
-
path:
|
|
5574
|
+
path: path6.normalize(fullPath),
|
|
5380
5575
|
type,
|
|
5381
5576
|
created: st.birthtime.toISOString(),
|
|
5382
5577
|
permissions: st.mode.toString(8).slice(-3)
|
|
@@ -5387,7 +5582,7 @@ async function readLogDir(dir) {
|
|
|
5387
5582
|
name: dirName,
|
|
5388
5583
|
size: stats.size,
|
|
5389
5584
|
time: stats.mtime.toISOString(),
|
|
5390
|
-
path:
|
|
5585
|
+
path: path6.normalize(resolved),
|
|
5391
5586
|
type: "dir",
|
|
5392
5587
|
created: stats.birthtime.toISOString(),
|
|
5393
5588
|
permissions: stats.mode.toString(8).slice(-3),
|
|
@@ -5397,7 +5592,7 @@ async function readLogDir(dir) {
|
|
|
5397
5592
|
__name(readLogDir, "readLogDir");
|
|
5398
5593
|
async function removeFile(filePath) {
|
|
5399
5594
|
try {
|
|
5400
|
-
await
|
|
5595
|
+
await fs10.unlink(path6.normalize(filePath));
|
|
5401
5596
|
} catch (err) {
|
|
5402
5597
|
if (err?.code !== "ENOENT") throw err;
|
|
5403
5598
|
}
|
|
@@ -5405,13 +5600,13 @@ async function removeFile(filePath) {
|
|
|
5405
5600
|
__name(removeFile, "removeFile");
|
|
5406
5601
|
var remove = removeFile;
|
|
5407
5602
|
async function write(filePath, content) {
|
|
5408
|
-
const normalized =
|
|
5409
|
-
await
|
|
5410
|
-
await
|
|
5603
|
+
const normalized = path6.normalize(filePath);
|
|
5604
|
+
await fs10.mkdir(path6.dirname(normalized), { recursive: true });
|
|
5605
|
+
await fs10.writeFile(normalized, content, "utf8");
|
|
5411
5606
|
}
|
|
5412
5607
|
__name(write, "write");
|
|
5413
5608
|
async function read(filePath) {
|
|
5414
|
-
return
|
|
5609
|
+
return fs10.readFile(path6.normalize(filePath), "utf8");
|
|
5415
5610
|
}
|
|
5416
5611
|
__name(read, "read");
|
|
5417
5612
|
async function writeJson(filePath, data) {
|
|
@@ -5447,7 +5642,7 @@ __export(common_exports, {
|
|
|
5447
5642
|
toSetObject: () => toSetObject,
|
|
5448
5643
|
toWherePairs: () => toWherePairs
|
|
5449
5644
|
});
|
|
5450
|
-
import * as
|
|
5645
|
+
import * as path7 from "path";
|
|
5451
5646
|
function promisifySqlDb(query, sql) {
|
|
5452
5647
|
return new Promise((resolve6, reject) => {
|
|
5453
5648
|
query(sql, (err, result) => {
|
|
@@ -5512,11 +5707,11 @@ function toInsertRows(sql) {
|
|
|
5512
5707
|
}
|
|
5513
5708
|
__name(toInsertRows, "toInsertRows");
|
|
5514
5709
|
function isPathInside(baseDir, targetPath) {
|
|
5515
|
-
const base =
|
|
5516
|
-
const target =
|
|
5517
|
-
const relative5 =
|
|
5710
|
+
const base = path7.resolve(baseDir);
|
|
5711
|
+
const target = path7.resolve(targetPath);
|
|
5712
|
+
const relative5 = path7.relative(base, target);
|
|
5518
5713
|
if (!relative5) return true;
|
|
5519
|
-
return !relative5.startsWith("..") && !
|
|
5714
|
+
return !relative5.startsWith("..") && !path7.isAbsolute(relative5);
|
|
5520
5715
|
}
|
|
5521
5716
|
__name(isPathInside, "isPathInside");
|
|
5522
5717
|
function joinTablePath(table, ...segments) {
|
|
@@ -5697,8 +5892,8 @@ var Sql_default = {
|
|
|
5697
5892
|
};
|
|
5698
5893
|
|
|
5699
5894
|
// src/sysserver/db/src/file/Index.ts
|
|
5700
|
-
import * as
|
|
5701
|
-
import * as
|
|
5895
|
+
import * as fs11 from "fs";
|
|
5896
|
+
import * as path8 from "path";
|
|
5702
5897
|
function dbDriver(opt = {}) {
|
|
5703
5898
|
const { Sql, DbCommon } = opt;
|
|
5704
5899
|
const { isPathInside: isPathInside2, joinTablePath: joinTablePath2 } = DbCommon;
|
|
@@ -5712,20 +5907,20 @@ function dbDriver(opt = {}) {
|
|
|
5712
5907
|
this.fileDel = (config.del || 0) !== 0;
|
|
5713
5908
|
this.createDir = config.create || false;
|
|
5714
5909
|
const root = config.$asai?.serverRoot || getPrimaryServerRoot();
|
|
5715
|
-
this.baseDirAbs =
|
|
5910
|
+
this.baseDirAbs = path8.resolve(root, config.dir);
|
|
5716
5911
|
}
|
|
5717
5912
|
dbLog(...args) {
|
|
5718
5913
|
(this.config?.$asai?.$log || console.log)("FILE", ...args);
|
|
5719
5914
|
}
|
|
5720
5915
|
checkFile(file) {
|
|
5721
|
-
return
|
|
5916
|
+
return fs11.existsSync(this.getAbsPath(file, false));
|
|
5722
5917
|
}
|
|
5723
5918
|
/** 解析相对路径并限制在数据根目录内,防止路径穿越(跨平台) */
|
|
5724
5919
|
resolvePath(relPath) {
|
|
5725
5920
|
if (!relPath) {
|
|
5726
5921
|
return this.baseDirAbs;
|
|
5727
5922
|
}
|
|
5728
|
-
const abs =
|
|
5923
|
+
const abs = path8.isAbsolute(relPath) ? path8.normalize(relPath) : path8.resolve(this.baseDirAbs, relPath);
|
|
5729
5924
|
if (!isPathInside2(this.baseDirAbs, abs)) {
|
|
5730
5925
|
throw new Error("Path not allowed");
|
|
5731
5926
|
}
|
|
@@ -5739,15 +5934,15 @@ function dbDriver(opt = {}) {
|
|
|
5739
5934
|
if (!relPath) {
|
|
5740
5935
|
return "";
|
|
5741
5936
|
}
|
|
5742
|
-
return
|
|
5937
|
+
return path8.isAbsolute(relPath) ? path8.relative(this.baseDirAbs, relPath) : relPath;
|
|
5743
5938
|
}
|
|
5744
5939
|
ensureDir(relPath) {
|
|
5745
5940
|
const relative5 = this.normalizeRelPath(relPath);
|
|
5746
|
-
const dirPath =
|
|
5941
|
+
const dirPath = path8.dirname(relative5);
|
|
5747
5942
|
const absDir = this.resolvePath(dirPath === "." ? "" : dirPath);
|
|
5748
|
-
if (this.createDir && !
|
|
5943
|
+
if (this.createDir && !fs11.existsSync(absDir)) {
|
|
5749
5944
|
this.dbLog("mkdir", "[MKDIR]", absDir);
|
|
5750
|
-
|
|
5945
|
+
fs11.mkdirSync(absDir, { recursive: true });
|
|
5751
5946
|
}
|
|
5752
5947
|
return absDir;
|
|
5753
5948
|
}
|
|
@@ -5763,34 +5958,34 @@ function dbDriver(opt = {}) {
|
|
|
5763
5958
|
}
|
|
5764
5959
|
deldir(relativePath) {
|
|
5765
5960
|
const absPath = this.resolvePath(relativePath);
|
|
5766
|
-
if (!
|
|
5961
|
+
if (!fs11.existsSync(absPath)) {
|
|
5767
5962
|
return;
|
|
5768
5963
|
}
|
|
5769
5964
|
this.dbLog("delete", "[RMDIR]", absPath);
|
|
5770
|
-
const entries =
|
|
5965
|
+
const entries = fs11.readdirSync(absPath, { withFileTypes: true });
|
|
5771
5966
|
for (const entry of entries) {
|
|
5772
|
-
const current =
|
|
5967
|
+
const current = path8.join(absPath, entry.name);
|
|
5773
5968
|
if (entry.isDirectory()) {
|
|
5774
|
-
this.deldir(
|
|
5969
|
+
this.deldir(path8.join(relativePath, entry.name));
|
|
5775
5970
|
} else {
|
|
5776
5971
|
this.dbLog("delete", "[UNLINK]", current);
|
|
5777
|
-
|
|
5972
|
+
fs11.unlinkSync(current);
|
|
5778
5973
|
}
|
|
5779
5974
|
}
|
|
5780
|
-
|
|
5975
|
+
fs11.rmdirSync(absPath);
|
|
5781
5976
|
}
|
|
5782
5977
|
getReadPath(file, sql) {
|
|
5783
5978
|
const candidates = [];
|
|
5784
5979
|
if (sql?.filename) {
|
|
5785
|
-
candidates.push({ dir:
|
|
5786
|
-
candidates.push({ dir:
|
|
5980
|
+
candidates.push({ dir: path8.join(file, sql.filename) });
|
|
5981
|
+
candidates.push({ dir: path8.join(file + ".delete" + this.fileExt, sql.filename) });
|
|
5787
5982
|
} else {
|
|
5788
5983
|
candidates.push({ dir: file });
|
|
5789
5984
|
candidates.push({ dir: file + this.fileExt + ".delete" });
|
|
5790
5985
|
}
|
|
5791
5986
|
for (const candidate of candidates) {
|
|
5792
5987
|
const abs = this.getAbsPath(candidate.dir, false);
|
|
5793
|
-
if (
|
|
5988
|
+
if (fs11.existsSync(abs)) {
|
|
5794
5989
|
return { path: abs, dir: candidate.dir };
|
|
5795
5990
|
}
|
|
5796
5991
|
}
|
|
@@ -5802,13 +5997,13 @@ function dbDriver(opt = {}) {
|
|
|
5802
5997
|
return { path: "", dir: read2.dir };
|
|
5803
5998
|
}
|
|
5804
5999
|
if (sql?.filename) {
|
|
5805
|
-
return { path:
|
|
6000
|
+
return { path: path8.dirname(read2.path), dir: path8.dirname(read2.dir) };
|
|
5806
6001
|
}
|
|
5807
6002
|
return { path: read2.path, dir: read2.dir };
|
|
5808
6003
|
}
|
|
5809
6004
|
getNewPath(file, sql) {
|
|
5810
6005
|
if (sql?.filename) {
|
|
5811
|
-
return this.getAbsPath(
|
|
6006
|
+
return this.getAbsPath(path8.join(file, sql.filename), true);
|
|
5812
6007
|
}
|
|
5813
6008
|
return this.getAbsPath(file, true);
|
|
5814
6009
|
}
|
|
@@ -5816,7 +6011,7 @@ function dbDriver(opt = {}) {
|
|
|
5816
6011
|
try {
|
|
5817
6012
|
const filePath = sql?.type === "insert" ? this.getNewPath(file, sql) : this.getReadPath(file, sql).path || this.getNewPath(file, sql);
|
|
5818
6013
|
this.dbLog("write", "[WRITE]", filePath);
|
|
5819
|
-
|
|
6014
|
+
fs11.writeFileSync(filePath, data, "utf8");
|
|
5820
6015
|
return "ok";
|
|
5821
6016
|
} catch (e) {
|
|
5822
6017
|
this.dbLog("write failed", "[WRITE ERROR]", e);
|
|
@@ -5830,7 +6025,7 @@ function dbDriver(opt = {}) {
|
|
|
5830
6025
|
return { error: "empty" };
|
|
5831
6026
|
}
|
|
5832
6027
|
this.dbLog("read", "[READ]", read2.path);
|
|
5833
|
-
const data =
|
|
6028
|
+
const data = fs11.readFileSync(read2.path, { encoding }) || "";
|
|
5834
6029
|
const fileName = this.fileExt && read2.dir.endsWith(this.fileExt) ? read2.dir : read2.dir + this.fileExt;
|
|
5835
6030
|
return [{ data, file: fileName }];
|
|
5836
6031
|
} catch (e) {
|
|
@@ -5847,12 +6042,12 @@ function dbDriver(opt = {}) {
|
|
|
5847
6042
|
if (this.fileDel && sql?.deltrue) {
|
|
5848
6043
|
const target = del.path + ".delete" + this.fileExt;
|
|
5849
6044
|
this.dbLog("soft delete", "[SOFT DELETE]", `${del.path} -> ${target}`);
|
|
5850
|
-
|
|
6045
|
+
fs11.renameSync(del.path, target);
|
|
5851
6046
|
} else if (sql?.filename) {
|
|
5852
6047
|
this.deldir(del.dir);
|
|
5853
6048
|
} else {
|
|
5854
6049
|
this.dbLog("delete", "[DELETE]", del.path);
|
|
5855
|
-
|
|
6050
|
+
fs11.unlinkSync(del.path);
|
|
5856
6051
|
}
|
|
5857
6052
|
return "ok";
|
|
5858
6053
|
} catch (e) {
|
|
@@ -5871,11 +6066,11 @@ function dbDriver(opt = {}) {
|
|
|
5871
6066
|
const original = del.path.replace(new RegExp(`.delete${extPattern}$`), "");
|
|
5872
6067
|
if (original !== del.path) {
|
|
5873
6068
|
this.dbLog("restore", "[RESTORE]", `${del.path} -> ${original}`);
|
|
5874
|
-
|
|
6069
|
+
fs11.renameSync(del.path, original);
|
|
5875
6070
|
}
|
|
5876
6071
|
} else {
|
|
5877
6072
|
this.dbLog("force delete", "[FORCE DELETE]", del.path);
|
|
5878
|
-
|
|
6073
|
+
fs11.unlinkSync(del.path);
|
|
5879
6074
|
}
|
|
5880
6075
|
return "ok";
|
|
5881
6076
|
} catch (e) {
|
|
@@ -5889,7 +6084,7 @@ function dbDriver(opt = {}) {
|
|
|
5889
6084
|
this.dbLog("list", "[LIST]", absDir);
|
|
5890
6085
|
let entries;
|
|
5891
6086
|
try {
|
|
5892
|
-
entries =
|
|
6087
|
+
entries = fs11.readdirSync(absDir, { withFileTypes: true });
|
|
5893
6088
|
} catch {
|
|
5894
6089
|
return sql?.list ? { open: [], delete: [] } : [];
|
|
5895
6090
|
}
|
|
@@ -5901,9 +6096,9 @@ function dbDriver(opt = {}) {
|
|
|
5901
6096
|
const isDelete = fileName.endsWith(deleteSuffix);
|
|
5902
6097
|
const baseName = isDelete ? fileName.slice(0, -deleteSuffix.length) : fileName;
|
|
5903
6098
|
if (this.fileExt && !baseName.endsWith(this.fileExt)) continue;
|
|
5904
|
-
const fullPath =
|
|
6099
|
+
const fullPath = path8.join(absDir, fileName);
|
|
5905
6100
|
try {
|
|
5906
|
-
const data =
|
|
6101
|
+
const data = fs11.readFileSync(fullPath, "utf8");
|
|
5907
6102
|
const entryData = { data, file: baseName };
|
|
5908
6103
|
if (isDelete) {
|
|
5909
6104
|
if (sql?.list) result.delete.push(entryData);
|
|
@@ -6669,7 +6864,7 @@ var initAsaiHostNodejs2 = {
|
|
|
6669
6864
|
createTransportDataHandler,
|
|
6670
6865
|
wireTransportConnectionLogs
|
|
6671
6866
|
};
|
|
6672
|
-
var PLUGIN_VERSION = true ? "0.0.
|
|
6867
|
+
var PLUGIN_VERSION = true ? "0.0.11" : "0.0.1";
|
|
6673
6868
|
var index_default = initAsaiHostNodejs2;
|
|
6674
6869
|
export {
|
|
6675
6870
|
Index_default as AsaiCommon,
|