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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/static/security.js +86 -60
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-anti-account-sharing",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Prevents account sharing by enforcing a single active session policy for desktop devices.",
5
5
  "main": "library.js",
6
6
  "keywords": [
@@ -1,71 +1,97 @@
1
1
  'use strict';
2
2
 
3
- $(document).ready(function() {
4
- // 1. URL Kontrolü (Sayfa yenileyince atıldıysa)
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
- showSecurityModal();
61
+ showSecurityModal();
8
62
  }
63
+ }
9
64
 
10
- // 2. AJAX Kontrolü (Sayfada gezerken atıldıysa)
11
- $(document).ajaxError(function(event, jqxhr) {
12
- if (jqxhr.status === 401 && jqxhr.responseJSON && jqxhr.responseJSON.error === 'session_terminated') {
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
- function showSecurityModal() {
18
- // Varsa eski modalları temizle
19
- $('#antishare-modal').remove();
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
- // Niki'den bağımsız, genel ve şık bir tasarım
22
- const modalHtml = `
23
- <div id="antishare-modal" style="
24
- position: fixed; top: 0; left: 0; width: 100%; height: 100%;
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
- <div style="
38
- width: 70px; height: 70px; background: #fdf2f2; border-radius: 50%;
39
- display: flex; align-items: center; justify-content: center; margin: 0 auto 20px;
40
- ">
41
- <i class="fa fa-shield" style="font-size: 32px; color: #d9534f;"></i>
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
- $('body').append(modalHtml);
69
- $('body').css('overflow', 'hidden'); // Scrollu kilitle
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
+ })();