@nka212bg/backend-utils 0.1.31 → 0.1.33
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/misc.js +1 -1
- package/package.json +1 -1
- package/session.js +120 -12
package/misc.js
CHANGED
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -1,28 +1,138 @@
|
|
|
1
|
-
const { existsSync, readFileSync,
|
|
1
|
+
const { existsSync, readFileSync, mkdirSync } = require("fs");
|
|
2
|
+
const { writeFile } = require("fs/promises");
|
|
2
3
|
const { createToken } = require("./misc");
|
|
3
4
|
|
|
4
5
|
!existsSync(`${__basedir}/state`) && mkdirSync(`${__basedir}/state`, { recursive: true });
|
|
5
|
-
const sessionStateFile = `${__basedir}/state/session.json`;
|
|
6
6
|
|
|
7
|
+
/* -------------------- ban list -------------------- */
|
|
8
|
+
const banListFile = `${__basedir}/state/banList.json`;
|
|
9
|
+
const BAN_LIST = existsSync(banListFile) ? JSON.parse(readFileSync(banListFile, "utf8") || "{}") : {};
|
|
10
|
+
|
|
11
|
+
/* -------------------- session --------------------- */
|
|
12
|
+
const sessionStateFile = `${__basedir}/state/session.json`;
|
|
7
13
|
const SESSION = existsSync(sessionStateFile) ? JSON.parse(readFileSync(sessionStateFile, "utf8") || "{}") : {};
|
|
8
14
|
|
|
15
|
+
/* -------------------- state --------------------- */
|
|
16
|
+
const serverStateFile = `${__basedir}/state/state.json`;
|
|
17
|
+
const STATE = existsSync(serverStateFile) ? JSON.parse(readFileSync(serverStateFile, "utf8") || "{}") : {};
|
|
18
|
+
|
|
9
19
|
setInterval(() => {
|
|
10
|
-
// delete expired sessions
|
|
11
20
|
const now = Date.now();
|
|
21
|
+
|
|
22
|
+
// delete expired sessions
|
|
12
23
|
Object.keys(SESSION).forEach((e) => {
|
|
13
24
|
SESSION[e].expireTime < now && delete SESSION[e];
|
|
14
25
|
});
|
|
26
|
+
// save the sessions in file (non-blocking write, JSON.stringify itself still runs sync)
|
|
27
|
+
writeFile(sessionStateFile, JSON.stringify(SESSION)).catch((error) => console.error("session save failed:", error));
|
|
15
28
|
|
|
16
|
-
//
|
|
17
|
-
|
|
29
|
+
// delete expired entries
|
|
30
|
+
Object.keys(STATE).forEach((e) => {
|
|
31
|
+
STATE[e].expireTime < now && delete STATE[e];
|
|
32
|
+
});
|
|
33
|
+
// save the state in file (non-blocking write, JSON.stringify itself still runs sync)
|
|
34
|
+
writeFile(serverStateFile, JSON.stringify(STATE)).catch((error) => console.error("state save failed:", error));
|
|
18
35
|
}, 60000);
|
|
19
36
|
|
|
37
|
+
// document.cookie-style: reading serverState[token] gets it, assigning
|
|
38
|
+
// serverState[token] = {...} sets/updates it, assigning a falsy value
|
|
39
|
+
// deletes it (the same "expire it out" trick browsers use for cookies).
|
|
40
|
+
exports.serverState = new Proxy(
|
|
41
|
+
{},
|
|
42
|
+
{
|
|
43
|
+
// GET
|
|
44
|
+
// const s = serverState["abc123"]; // => {name: 'alice', ..., expireIn: 604859999}
|
|
45
|
+
// const s = serverState[req.headers.authorization];
|
|
46
|
+
// const all = serverState.getAll; // => whole STATE map
|
|
47
|
+
// const alices = serverState["name=alice"]; // => all entries where name == "alice", each with its token
|
|
48
|
+
get(_, token) {
|
|
49
|
+
if (!token) return false;
|
|
50
|
+
|
|
51
|
+
if (token === "getAll") return STATE;
|
|
52
|
+
|
|
53
|
+
if (token.includes("=")) {
|
|
54
|
+
const [field, value] = token.trim().split(/\s*=\s*/);
|
|
55
|
+
return Object.entries(STATE)
|
|
56
|
+
.filter(([, s]) => s[field] == value)
|
|
57
|
+
.map(([token, s]) => ({ ...s, token }));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!STATE[token]) return false;
|
|
61
|
+
return { ...STATE[token], expireIn: STATE[token].expireTime - Date.now() + 60000 };
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
// DELETE
|
|
65
|
+
// delete serverState["abc123"];
|
|
66
|
+
// delete serverState["name=alice"]; // bulk delete, removes every entry where name == "alice"
|
|
67
|
+
deleteProperty(_, token) {
|
|
68
|
+
if (!token) return false;
|
|
69
|
+
|
|
70
|
+
if (token.includes("=")) {
|
|
71
|
+
const [field, value] = token.trim().split(/\s*=\s*/);
|
|
72
|
+
let itemsCount = 0;
|
|
73
|
+
Object.entries(STATE).forEach(([t, s]) => {
|
|
74
|
+
if (s[field] == value) {
|
|
75
|
+
delete STATE[t];
|
|
76
|
+
itemsCount += 1;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return !itemsCount ? false : String(itemsCount);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
delete STATE[token];
|
|
83
|
+
return true;
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// SET / UPDATE / DELETE
|
|
87
|
+
// serverState["abc123"] = {name: 'alice'}; // create (stamps expirePeriod/expireTime/uuid)
|
|
88
|
+
// serverState["abc123"] = {name: 'alice2'}; // update (merges into existing)
|
|
89
|
+
// serverState["abc123"] = null; // delete, cookie-expiry trick
|
|
90
|
+
// serverState["name=alice"] = {name: 'john'}; // bulk update, merges into every entry where name == "alice"
|
|
91
|
+
set(_, token, fields) {
|
|
92
|
+
if (!token) return false;
|
|
93
|
+
|
|
94
|
+
if (!fields) {
|
|
95
|
+
delete STATE[token];
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (token.includes("=")) {
|
|
100
|
+
const [field, value] = token.trim().split(/\s*=\s*/);
|
|
101
|
+
let itemsCount = 0;
|
|
102
|
+
Object.entries(STATE).forEach(([t, s]) => {
|
|
103
|
+
if (s[field] == value) {
|
|
104
|
+
STATE[t] = { ...s, ...fields };
|
|
105
|
+
itemsCount += 1;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return !itemsCount ? false : String(itemsCount);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
|
|
113
|
+
if (STATE[token]) {
|
|
114
|
+
if (fields.expirePeriod) fields.expireTime = now + fields.expirePeriod;
|
|
115
|
+
STATE[token] = { ...STATE[token], ...fields };
|
|
116
|
+
return { ...STATE[token] };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fields.expirePeriod ||= 60000 * 60 * 24 * 7; // 7 days
|
|
120
|
+
fields.expireTime = now + fields.expirePeriod;
|
|
121
|
+
fields.uuid = createToken({ type: "date" });
|
|
122
|
+
|
|
123
|
+
STATE[token] = fields;
|
|
124
|
+
return { ...fields };
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
|
|
20
129
|
// session C.R.U.D.
|
|
21
130
|
exports.session = {
|
|
22
131
|
set(payload = {}) {
|
|
23
132
|
// payload.set => {token: 23456546, whatever: 'someValue', whatever_2: 'someValue'}
|
|
24
133
|
if (!payload.token) return { error: "missing_token" };
|
|
25
134
|
|
|
135
|
+
payload = { ...payload };
|
|
26
136
|
const token = payload.token;
|
|
27
137
|
delete payload.token;
|
|
28
138
|
|
|
@@ -64,6 +174,7 @@ exports.session = {
|
|
|
64
174
|
|
|
65
175
|
update(payload = {}) {
|
|
66
176
|
// payload => {id: 23456546, whatever: 'someValue', whatever_2: 'someValue'}
|
|
177
|
+
payload = { ...payload };
|
|
67
178
|
const _key = Object.keys(payload)[0];
|
|
68
179
|
const _value = Object.values(payload)[0];
|
|
69
180
|
delete payload[_key];
|
|
@@ -95,9 +206,6 @@ exports.session = {
|
|
|
95
206
|
},
|
|
96
207
|
};
|
|
97
208
|
|
|
98
|
-
// -------- check or get ban users --------
|
|
99
|
-
const banListFile = `${__basedir}/state/banList.json`;
|
|
100
|
-
const BAN_LIST = existsSync(banListFile) ? JSON.parse(readFileSync(banListFile, "utf8") || "{}") : {};
|
|
101
209
|
exports.banList = {
|
|
102
210
|
isBanned(payload) {
|
|
103
211
|
// payload = {ip: 123.67.432.43}
|
|
@@ -106,7 +214,7 @@ exports.banList = {
|
|
|
106
214
|
const _key = Object.keys(payload)[0];
|
|
107
215
|
const _value = Object.values(payload)[0];
|
|
108
216
|
|
|
109
|
-
BAN_LIST[_key]?.includes(_value);
|
|
217
|
+
return BAN_LIST[_key]?.includes(_value);
|
|
110
218
|
},
|
|
111
219
|
banUser(payload) {
|
|
112
220
|
// payload = {whatever: 'someValue'}
|
|
@@ -117,17 +225,17 @@ exports.banList = {
|
|
|
117
225
|
if (!BAN_LIST[_key]) BAN_LIST[_key] = [];
|
|
118
226
|
|
|
119
227
|
BAN_LIST[_key].push(_value);
|
|
120
|
-
|
|
228
|
+
writeFile(banListFile, JSON.stringify(BAN_LIST)).catch((error) => console.error("banList save failed:", error));
|
|
121
229
|
},
|
|
122
230
|
unBanUser(payload) {
|
|
123
231
|
// payload = {whatever: 'someValue'}
|
|
124
232
|
const _key = Object.keys(payload)[0];
|
|
125
233
|
const _value = Object.values(payload)[0];
|
|
126
234
|
|
|
127
|
-
const index = BAN_LIST[_key]?.indexOf(_value)
|
|
235
|
+
const index = BAN_LIST[_key]?.indexOf(_value) ?? -1;
|
|
128
236
|
if (index > -1) {
|
|
129
237
|
BAN_LIST[_key].splice(index, 1);
|
|
130
|
-
|
|
238
|
+
writeFile(banListFile, JSON.stringify(BAN_LIST)).catch((error) => console.error("banList save failed:", error));
|
|
131
239
|
}
|
|
132
240
|
},
|
|
133
241
|
};
|