nodebb-plugin-anti-account-sharing 1.0.2 → 1.0.3
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/library.js +44 -28
- package/package.json +1 -1
package/library.js
CHANGED
|
@@ -6,7 +6,7 @@ const user = require.main.require('./src/user');
|
|
|
6
6
|
const Plugin = {};
|
|
7
7
|
|
|
8
8
|
// --- AYARLAR ---
|
|
9
|
-
const MAX_DEVICES = 1; //
|
|
9
|
+
const MAX_DEVICES = 1; // kaç bilgisayar?
|
|
10
10
|
|
|
11
11
|
function isMobile(req) {
|
|
12
12
|
const ua = req?.headers?.['user-agent'] || '';
|
|
@@ -14,52 +14,71 @@ function isMobile(req) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
Plugin.init = async function () {
|
|
17
|
-
console.log(`[Anti-Share]
|
|
17
|
+
console.log(`[Anti-Share] Aktif ✅ (Limit: ${MAX_DEVICES} PC)`);
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// Login olduğunda session ekle (req gelmezse bile sorun değil, aşağıda fallback var)
|
|
21
21
|
Plugin.recordSession = async function (data) {
|
|
22
22
|
const req = data?.req;
|
|
23
23
|
const uid = data?.uid;
|
|
24
24
|
|
|
25
|
-
// req yoksa sessizce çık (bazı akışlarda gelemeyebiliyor)
|
|
26
25
|
if (!req || !uid || !req.sessionID) return;
|
|
27
|
-
|
|
28
|
-
// Mobil girişleri takip etmiyoruz
|
|
29
26
|
if (isMobile(req)) return;
|
|
30
27
|
|
|
31
|
-
const key = `antishare:
|
|
28
|
+
const key = `antishare:sessionsz:${uid}`; // <-- DİKKAT: yeni key (zset)
|
|
29
|
+
const sid = req.sessionID;
|
|
30
|
+
|
|
31
|
+
// Eğer yoksa ekle (varsa score'u güncelleme!)
|
|
32
|
+
const all = await db.getSortedSetRevRange(key, 0, -1);
|
|
33
|
+
if (!all.includes(sid)) {
|
|
34
|
+
await db.sortedSetAdd(key, Date.now(), sid);
|
|
35
|
+
}
|
|
32
36
|
|
|
33
|
-
//
|
|
34
|
-
await db.
|
|
35
|
-
|
|
37
|
+
// sadece son MAX_DEVICES tut
|
|
38
|
+
const newest = await db.getSortedSetRevRange(key, 0, -1);
|
|
39
|
+
const toRemove = newest.slice(MAX_DEVICES);
|
|
40
|
+
if (toRemove.length) {
|
|
41
|
+
await db.sortedSetRemove(key, toRemove);
|
|
42
|
+
}
|
|
36
43
|
};
|
|
37
44
|
|
|
38
|
-
//
|
|
45
|
+
// Her page + api isteğinde kontrol
|
|
39
46
|
Plugin.checkSession = async function (data) {
|
|
40
47
|
const req = data?.req;
|
|
41
48
|
const res = data?.res;
|
|
42
49
|
|
|
43
50
|
if (!req || !res) return data;
|
|
44
|
-
|
|
45
|
-
// login değilse veya mobilse karışma
|
|
46
51
|
if (!req.uid || req.uid <= 0 || isMobile(req)) return data;
|
|
47
52
|
|
|
48
|
-
// admin ise karışma
|
|
49
53
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
50
54
|
if (isAdmin) return data;
|
|
51
55
|
|
|
52
|
-
const
|
|
53
|
-
|
|
56
|
+
const sid = req.sessionID;
|
|
57
|
+
if (!sid) return data;
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
const key = `antishare:sessionsz:${req.uid}`; // <-- yeni key
|
|
60
|
+
|
|
61
|
+
// allowed = en yeni MAX_DEVICES session
|
|
62
|
+
let newest = await db.getSortedSetRevRange(key, 0, -1);
|
|
63
|
+
|
|
64
|
+
// Fallback: eğer hiç kayıt yoksa veya bu sid listede yoksa (ilk defa görüyorsak) ekle
|
|
65
|
+
// (AMA mevcut sid varsa score'u güncelleme! yoksa eski session kendini "yeniler" ve kick yemez)
|
|
66
|
+
if (!newest.includes(sid)) {
|
|
67
|
+
await db.sortedSetAdd(key, Date.now(), sid);
|
|
68
|
+
newest = await db.getSortedSetRevRange(key, 0, -1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Trim (fazla varsa sil)
|
|
72
|
+
const toRemove = newest.slice(MAX_DEVICES);
|
|
73
|
+
if (toRemove.length) {
|
|
74
|
+
await db.sortedSetRemove(key, toRemove);
|
|
75
|
+
newest = newest.slice(0, MAX_DEVICES);
|
|
76
|
+
}
|
|
57
77
|
|
|
58
|
-
//
|
|
59
|
-
if (!req.sessionID) return data;
|
|
78
|
+
const allowed = newest; // en yeni MAX_DEVICES
|
|
60
79
|
|
|
61
|
-
|
|
62
|
-
|
|
80
|
+
// Bu session allowed değilse -> kick
|
|
81
|
+
if (!allowed.includes(sid)) {
|
|
63
82
|
try { req.logout?.(); } catch (e) {}
|
|
64
83
|
if (req.session) {
|
|
65
84
|
try { req.session.destroy(() => {}); } catch (e) {}
|
|
@@ -71,15 +90,12 @@ Plugin.checkSession = async function (data) {
|
|
|
71
90
|
req.originalUrl?.startsWith('/api/');
|
|
72
91
|
|
|
73
92
|
if (wantsJson) {
|
|
74
|
-
res.status(401).json({
|
|
75
|
-
|
|
76
|
-
message: 'Maksimum cihaz sınırına ulaşıldı.',
|
|
77
|
-
});
|
|
78
|
-
return; // IMPORTANT: response bitti
|
|
93
|
+
res.status(401).json({ error: 'session_terminated', message: 'Maksimum cihaz sınırına ulaşıldı.' });
|
|
94
|
+
return;
|
|
79
95
|
}
|
|
80
96
|
|
|
81
97
|
res.redirect('/login?error=session-conflict');
|
|
82
|
-
return;
|
|
98
|
+
return;
|
|
83
99
|
}
|
|
84
100
|
|
|
85
101
|
return data;
|
package/package.json
CHANGED