nodebb-plugin-anti-account-sharing 1.0.1 → 1.0.2
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/package.json +1 -1
- package/static/security.js +86 -60
package/package.json
CHANGED
package/static/security.js
CHANGED
|
@@ -1,71 +1,97 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
(function () {
|
|
4
|
+
function showSecurityModal() {
|
|
5
|
+
// Varsa eski modalları temizle
|
|
6
|
+
$('#antishare-modal').remove();
|
|
7
|
+
|
|
8
|
+
const modalHtml = `
|
|
9
|
+
<div id="antishare-modal" style="
|
|
10
|
+
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
|
11
|
+
background: rgba(0,0,0,0.92); z-index: 999999;
|
|
12
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
13
|
+
text-align: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
14
|
+
animation: fadeIn 0.3s ease;
|
|
15
|
+
">
|
|
16
|
+
<div style="
|
|
17
|
+
background: #ffffff; padding: 40px; border-radius: 16px;
|
|
18
|
+
max-width: 90%; width: 400px; box-shadow: 0 10px 40px rgba(0,0,0,0.5);
|
|
19
|
+
position: relative; overflow: hidden;
|
|
20
|
+
">
|
|
21
|
+
<div style="position: absolute; top:0; left:0; width:100%; height:6px; background:#d9534f;"></div>
|
|
22
|
+
|
|
23
|
+
<div style="
|
|
24
|
+
width: 70px; height: 70px; background: #fdf2f2; border-radius: 50%;
|
|
25
|
+
display: flex; align-items: center; justify-content: center; margin: 0 auto 20px;
|
|
26
|
+
">
|
|
27
|
+
<i class="fa fa-shield" style="font-size: 32px; color: #d9534f;"></i>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<h2 style="color: #333; margin: 0 0 10px; font-size: 22px; font-weight: 700;">Oturum Sonlandırıldı</h2>
|
|
31
|
+
|
|
32
|
+
<p style="color: #666; font-size: 14px; line-height: 1.6; margin: 0 0 30px;">
|
|
33
|
+
Hesabınıza <strong>başka bir bilgisayardan</strong> giriş yapıldığı tespit edildi.<br><br>
|
|
34
|
+
Hesap güvenliğiniz için önceki cihazdaki oturum otomatik olarak kapatılmıştır.
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
<a href="/login" style="
|
|
38
|
+
display: block; width: 100%; padding: 14px 0;
|
|
39
|
+
background: #d9534f; color: #fff; text-decoration: none;
|
|
40
|
+
font-weight: 600; border-radius: 8px; font-size: 15px;
|
|
41
|
+
transition: background 0.2s;
|
|
42
|
+
" onmouseover="this.style.background='#c9302c'" onmouseout="this.style.background='#d9534f'">
|
|
43
|
+
TEKRAR GİRİŞ YAP
|
|
44
|
+
</a>
|
|
45
|
+
|
|
46
|
+
<div style="margin-top: 20px; font-size: 12px; color: #999;">
|
|
47
|
+
Mobil cihazlarınız bu durumdan etkilenmez.
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<style>@keyframes fadeIn { from { opacity:0; transform:scale(0.95); } to { opacity:1; transform:scale(1); } }</style>
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
$('body').append(modalHtml);
|
|
55
|
+
$('body').css('overflow', 'hidden');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function checkUrlParam() {
|
|
5
59
|
const urlParams = new URLSearchParams(window.location.search);
|
|
6
60
|
if (urlParams.get('error') === 'session-conflict') {
|
|
7
|
-
|
|
61
|
+
showSecurityModal();
|
|
8
62
|
}
|
|
63
|
+
}
|
|
9
64
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
showSecurityModal();
|
|
14
|
-
}
|
|
15
|
-
});
|
|
65
|
+
// --- 1) İlk yükleme + SPA geçişleri ---
|
|
66
|
+
$(document).ready(checkUrlParam);
|
|
67
|
+
$(window).on('action:ajaxify.end', checkUrlParam);
|
|
16
68
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
69
|
+
// --- 2) jQuery AJAX 401 yakala ---
|
|
70
|
+
$(document).ajaxError(function (event, jqxhr) {
|
|
71
|
+
if (jqxhr && jqxhr.status === 401 && jqxhr.responseJSON && jqxhr.responseJSON.error === 'session_terminated') {
|
|
72
|
+
showSecurityModal();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
20
75
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
background: rgba(0,0,0,0.92); z-index: 999999;
|
|
26
|
-
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
27
|
-
text-align: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
28
|
-
animation: fadeIn 0.3s ease;
|
|
29
|
-
">
|
|
30
|
-
<div style="
|
|
31
|
-
background: #ffffff; padding: 40px; border-radius: 16px;
|
|
32
|
-
max-width: 90%; width: 400px; box-shadow: 0 10px 40px rgba(0,0,0,0.5);
|
|
33
|
-
position: relative; overflow: hidden;
|
|
34
|
-
">
|
|
35
|
-
<div style="position: absolute; top:0; left:0; width:100%; height:6px; background:#d9534f;"></div>
|
|
76
|
+
// --- 3) FETCH 401 yakala (asıl eksik buydu) ---
|
|
77
|
+
const _fetch = window.fetch;
|
|
78
|
+
window.fetch = async function (...args) {
|
|
79
|
+
const res = await _fetch.apply(this, args);
|
|
36
80
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<h2 style="color: #333; margin: 0 0 10px; font-size: 22px; font-weight: 700;">Oturum Sonlandırıldı</h2>
|
|
45
|
-
|
|
46
|
-
<p style="color: #666; font-size: 14px; line-height: 1.6; margin: 0 0 30px;">
|
|
47
|
-
Hesabınıza <strong>başka bir bilgisayardan</strong> giriş yapıldığı tespit edildi.<br><br>
|
|
48
|
-
Hesap güvenliğiniz için önceki cihazdaki oturum otomatik olarak kapatılmıştır.
|
|
49
|
-
</p>
|
|
50
|
-
|
|
51
|
-
<a href="/login" style="
|
|
52
|
-
display: block; width: 100%; padding: 14px 0;
|
|
53
|
-
background: #d9534f; color: #fff; text-decoration: none;
|
|
54
|
-
font-weight: 600; border-radius: 8px; font-size: 15px;
|
|
55
|
-
transition: background 0.2s;
|
|
56
|
-
" onmouseover="this.style.background='#c9302c'" onmouseout="this.style.background='#d9534f'">
|
|
57
|
-
TEKRAR GİRİŞ YAP
|
|
58
|
-
</a>
|
|
59
|
-
|
|
60
|
-
<div style="margin-top: 20px; font-size: 12px; color: #999;">
|
|
61
|
-
Mobil cihazlarınız bu durumdan etkilenmez.
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
<style>@keyframes fadeIn { from { opacity:0; transform:scale(0.95); } to { opacity:1; transform:scale(1); } }</style>
|
|
66
|
-
`;
|
|
81
|
+
try {
|
|
82
|
+
if (res && res.status === 401) {
|
|
83
|
+
// response body json olabilir; klonlayıp okuyalım
|
|
84
|
+
const clone = res.clone();
|
|
85
|
+
const data = await clone.json().catch(() => null);
|
|
67
86
|
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
if (data && data.error === 'session_terminated') {
|
|
88
|
+
showSecurityModal();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} catch (e) {
|
|
92
|
+
// sessiz geç
|
|
70
93
|
}
|
|
71
|
-
|
|
94
|
+
|
|
95
|
+
return res;
|
|
96
|
+
};
|
|
97
|
+
})();
|