nodebb-plugin-phone-verification 1.2.3 → 1.2.5

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 CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const crypto = require('crypto');
4
- const https = require('https'); // הוספנו עבור SSL
4
+ const https = require('https');
5
+ const nconf = require.main.require('nconf');
5
6
 
6
7
  // NodeBB modules
7
8
  let db;
@@ -75,7 +76,8 @@ plugin.checkPostingPermissions = async function (data) {
75
76
  const phoneData = await plugin.getUserPhone(uid);
76
77
  if (!phoneData || !phoneData.phoneVerified) {
77
78
  const userSlug = await User.getUserField(uid, 'userslug');
78
- const editUrl = userSlug ? `/user/${userSlug}/edit` : '/user/me/edit';
79
+ const relativePath = nconf.get('relative_path');
80
+ const editUrl = userSlug ? `${relativePath}/user/${userSlug}/edit` : `${relativePath}/user/me/edit`;
79
81
  throw new Error(`חובה לאמת מספר טלפון כדי להמשיך את הפעילות בפורום.<br/>אנא גש ל<a href="${editUrl}">הגדרות הפרופיל שלך</a>.`);
80
82
  }
81
83
  return data;
@@ -94,16 +96,18 @@ plugin.checkVotingPermissions = async function (data) {
94
96
  const phoneData = await plugin.getUserPhone(uid);
95
97
  if (!phoneData || !phoneData.phoneVerified) {
96
98
  const userSlug = await User.getUserField(uid, 'userslug');
97
- const editUrl = userSlug ? `/user/${userSlug}/edit` : '/user/me/edit';
99
+ const relativePath = nconf.get('relative_path');
100
+ const editUrl = userSlug ? `${relativePath}/user/${userSlug}/edit` : `${relativePath}/user/me/edit`;
98
101
  throw new Error(`חובה לאמת מספר טלפון כדי להמשיך את הפעילות בפורום.<br/>אנא גש ל<a href="${editUrl}">הגדרות הפרופיל שלך</a>.`);
99
102
  }
100
103
  return data;
101
104
  };
102
105
 
103
106
  plugin.checkMessagingPermissions = async function (data) {
104
- const uid = data.fromUid;
105
- if (!uid || parseInt(uid, 10) === 0) return data;
107
+ const uid = data.fromuid || data.fromUid || data.uid;
106
108
 
109
+ if (!uid || parseInt(uid, 10) === 0) return data;
110
+
107
111
  const settings = await plugin.getSettings();
108
112
  if (!settings.blockUnverifiedUsers) return data;
109
113
 
@@ -113,23 +117,32 @@ plugin.checkMessagingPermissions = async function (data) {
113
117
  const phoneData = await plugin.getUserPhone(uid);
114
118
  if (phoneData && phoneData.phoneVerified) {
115
119
  return data;
116
- }
120
+ }
121
+
117
122
  const Messaging = require.main.require('./src/messaging');
123
+
124
+ if (!data.roomId) return data;
125
+
118
126
  const roomUids = await Messaging.getUidsInRoom(data.roomId, 0, -1);
127
+
119
128
  const targetUids = roomUids.filter(id => parseInt(id, 10) !== parseInt(uid, 10));
129
+
130
+ const userSlug = await User.getUserField(uid, 'userslug');
131
+ const relativePath = nconf.get('relative_path');
132
+ const editUrl = userSlug ? `${relativePath}/user/${userSlug}/edit` : `${relativePath}/user/me/edit`;
133
+ const errorMsg = `חובה לאמת מספר טלפון כדי לשלוח הודעות.<br/>אנא גש ל<a href="${editUrl}">הגדרות הפרופיל שלך</a>.`;
134
+
120
135
  if (targetUids.length === 0) {
121
- const userSlug = await User.getUserField(uid, 'userslug');
122
- const editUrl = userSlug ? `/user/${userSlug}/edit` : '/user/me/edit';
123
- throw new Error(`חובה לאמת מספר טלפון כדי להמשיך את הפעילות בפורום.<br/>אנא גש ל<a href="${editUrl}">הגדרות הפרופיל שלך</a>.`);
136
+ throw new Error(errorMsg);
124
137
  }
138
+
125
139
  for (const targetUid of targetUids) {
126
140
  const isTargetAdmin = await User.isAdministrator(targetUid);
127
141
  if (!isTargetAdmin) {
128
- const userSlug = await User.getUserField(uid, 'userslug');
129
- const editUrl = userSlug ? `/user/${userSlug}/edit` : '/user/me/edit';
130
- throw new Error(`חובה לאמת מספר טלפון כדי להמשיך את הפעילות בפורום.<br/>אנא גש ל<a href="${editUrl}">הגדרות הפרופיל שלך</a>.`);
142
+ throw new Error(errorMsg);
131
143
  }
132
144
  }
145
+
133
146
  return data;
134
147
  };
135
148
 
@@ -161,7 +174,6 @@ plugin.sendVoiceCall = async function (phone, code) {
161
174
 
162
175
  const url = `${baseUrl}?${params.toString()}`;
163
176
 
164
- // עקיפת בעיות SSL (אופציונלי)
165
177
  const agent = new https.Agent({ rejectUnauthorized: false });
166
178
 
167
179
  const response = await fetch(url, { method: 'GET', agent: agent });
@@ -274,7 +286,6 @@ plugin.clearVerifiedPhone = async function (phone) {
274
286
  plugin.savePhoneToUser = async function (uid, phone, verified = true, forceOverride = false) {
275
287
  if (!db || !User) return { success: false };
276
288
 
277
- // 1. מקרה של אימות ללא טלפון
278
289
  if (!phone) {
279
290
  await User.setUserFields(uid, {
280
291
  phoneVerified: verified ? 1 : 0,
@@ -291,25 +302,18 @@ plugin.savePhoneToUser = async function (uid, phone, verified = true, forceOverr
291
302
  const normalizedPhone = plugin.normalizePhone(phone);
292
303
  const existingUid = await db.sortedSetScore('phone:uid', normalizedPhone);
293
304
 
294
- // 2. בדיקת כפילות
295
305
  if (existingUid) {
296
- // אם המספר שייך למשתמש אחר
297
306
  if (parseInt(existingUid, 10) !== parseInt(uid, 10)) {
298
307
  if (forceOverride) {
299
- // === תיקון: דריסה בכוח (למנהלים) ===
300
- // מחיקת המספר מהמשתמש הישן
301
308
  console.log(`[phone-verification] Force overwriting phone ${normalizedPhone} from user ${existingUid} to ${uid}`);
302
309
 
303
- // הסרה מה-Set של המשתמש הישן
304
310
  await User.setUserFields(existingUid, {
305
311
  [PHONE_FIELD_KEY]: '',
306
312
  phoneVerified: 0,
307
313
  phoneVerifiedAt: 0
308
314
  });
309
315
  await db.sortedSetRemove('users:phone', existingUid);
310
- // (הערה: לא צריך להסיר מ-phone:uid כי אנחנו דורסים אותו מייד למטה)
311
316
  } else {
312
- // אם זה לא מנהל - זרוק שגיאה
313
317
  return { success: false, error: 'PHONE_EXISTS', message: 'המספר כבר רשום למשתמש אחר' };
314
318
  }
315
319
  }
@@ -322,7 +326,6 @@ plugin.savePhoneToUser = async function (uid, phone, verified = true, forceOverr
322
326
  phoneVerifiedAt: verified ? now : 0
323
327
  });
324
328
 
325
- // עדכון/דריסה של הרשומה ב-DB
326
329
  await db.sortedSetAdd('phone:uid', uid, normalizedPhone);
327
330
  await db.sortedSetAdd('users:phone', now, uid);
328
331
  return { success: true };
@@ -380,19 +383,16 @@ plugin.checkRegistration = async function (data) {
380
383
  const existingUid = await plugin.findUserByPhone(normalizedPhone);
381
384
 
382
385
  if (existingUid) {
383
- // אם המשתמש מחובר ומנסה לעדכן, או אם המספר תפוס על ידי מישהו אחר
384
386
  if (!req.uid || parseInt(existingUid, 10) !== parseInt(req.uid, 10)) {
385
387
  throw new Error('מספר הטלפון כבר רשום במערכת למשתמש אחר');
386
388
  }
387
389
  }
388
390
 
389
- // אם הגעת לכאן, הנתונים תקינים.
390
- // ב-Hook של checkRegistration, פשוט מחזירים את data כדי להמשיך ברישום.
391
391
  return data;
392
392
 
393
393
  } catch (err) {
394
394
  console.error('[phone-verification] Registration check error:', err);
395
- throw err; // NodeBB יציג את השגיאה הזו למשתמש בטופס הרישום
395
+ throw err;
396
396
  }
397
397
  };
398
398
 
@@ -452,7 +452,6 @@ plugin.init = async function (params) {
452
452
  // --- SOCKET.IO EVENTS ---
453
453
  SocketPlugins.call2all = {};
454
454
 
455
- // 1. פונקציה חדשה: מציאת משתמש לפי שם
456
455
  SocketPlugins.call2all.getUidByUsername = async function (socket, data) {
457
456
  if (!data || !data.username) throw new Error('נא לספק שם משתמש');
458
457
  const uid = await User.getUidByUsername(data.username);
@@ -460,7 +459,6 @@ plugin.init = async function (params) {
460
459
  return uid;
461
460
  };
462
461
 
463
- // 2. הוספת משתמש מאומת (מתוקן)
464
462
  SocketPlugins.call2all.adminAddVerifiedUser = async function (socket, data) {
465
463
  if (!data || !data.uid) throw new Error('חסר מזהה משתמש');
466
464
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -477,7 +475,6 @@ plugin.init = async function (params) {
477
475
  if (!result.success) throw new Error(result.message);
478
476
  };
479
477
 
480
- // 3. אימות ידני
481
478
  SocketPlugins.call2all.adminVerifyUser = async function (socket, data) {
482
479
  if (!data || !data.uid) throw new Error('שגיאה');
483
480
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -487,7 +484,6 @@ plugin.init = async function (params) {
487
484
  await db.sortedSetAdd('users:phone', Date.now(), data.uid);
488
485
  };
489
486
 
490
- // 4. ביטול אימות
491
487
  SocketPlugins.call2all.adminUnverifyUser = async function (socket, data) {
492
488
  if (!data || !data.uid) throw new Error('שגיאה');
493
489
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -496,7 +492,6 @@ plugin.init = async function (params) {
496
492
  await User.setUserFields(data.uid, { phoneVerified: 0, phoneVerifiedAt: 0 });
497
493
  };
498
494
 
499
- // 5. מחיקת טלפון
500
495
  SocketPlugins.call2all.adminDeleteUserPhone = async function (socket, data) {
501
496
  if (!data || !data.uid) throw new Error('שגיאה');
502
497
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -547,8 +542,8 @@ plugin.getSettings = async function () {
547
542
  return {
548
543
  voiceServerUrl: settings.voiceServerUrl || defaultSettings.voiceServerUrl,
549
544
  voiceServerApiKey: settings.voiceServerApiKey || '',
550
- voiceServerEnabled: isTrue(settings.voiceServerEnabled), // בדיקה מורחבת
551
- blockUnverifiedUsers: isTrue(settings.blockUnverifiedUsers), // בדיקה מורחבת
545
+ voiceServerEnabled: isTrue(settings.voiceServerEnabled),
546
+ blockUnverifiedUsers: isTrue(settings.blockUnverifiedUsers),
552
547
  voiceTtsMode: settings.voiceTtsMode || '1',
553
548
  voiceMessageTemplate: settings.voiceMessageTemplate || defaultSettings.voiceMessageTemplate
554
549
  };
@@ -609,7 +604,6 @@ plugin.apiSendCode = async function (req, res) {
609
604
  if (!plugin.validatePhoneNumber(clean)) return res.json({ success: false, error: 'INVALID' });
610
605
 
611
606
  const existingUid = await plugin.findUserByPhone(clean);
612
- // בדיקת כפילות: אם המספר שייך למשתמש אחר
613
607
  if (existingUid && (!req.uid || parseInt(existingUid) !== parseInt(req.uid))) {
614
608
  return res.json({ success: false, error: 'EXISTS', message: 'המספר תפוס' });
615
609
  }
@@ -764,4 +758,4 @@ plugin.userDelete = async function (data) {
764
758
  } catch (e) {}
765
759
  };
766
760
 
767
- module.exports = plugin;
761
+ module.exports = plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-phone-verification",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "אימות מספר טלפון נייד בתהליך ההרשמה לפורום NodeBB",
5
5
  "main": "library.js",
6
6
  "repository": {
package/plugin.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "nodebb-plugin-phone-verification",
3
3
  "name": "Phone Verification",
4
4
  "description": "אימות מספר טלפון נייד בתהליך ההרשמה לפורום ובפרופיל המשתמש",
5
- "version": "1.2.3",
5
+ "version": "1.2.5",
6
6
  "library": "./library.js",
7
7
  "hooks": [
8
8
  { "hook": "filter:register.check", "method": "checkRegistration" },
@@ -1,17 +1,14 @@
1
1
  'use strict';
2
2
 
3
- /* globals $, app, socket, config */
4
3
 
5
4
  define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], function(Settings, bootbox, alerts) {
6
5
  var ACP = {};
7
6
 
8
7
  ACP.init = function() {
9
- // הגדרת משתנים בראש הפונקציה כדי שיהיו זמינים לכולם בתוכה
10
8
  var usersTbody = $('#users-tbody');
11
9
  var paginationUl = $('#users-pagination');
12
10
  var currentPage = 1;
13
11
 
14
- // 1. טעינת הגדרות
15
12
  Settings.load('phone-verification', $('#voice-settings-form'));
16
13
 
17
14
  $('#save-settings-btn').on('click', function(e) {
@@ -21,11 +18,10 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
21
18
  });
22
19
  });
23
20
 
24
- // --- פונקציות עזר (הועברו פנימה כדי להכיר את המשתנים) ---
25
21
 
26
22
  function renderPagination(curr, total) {
27
23
  currentPage = curr;
28
- paginationUl.empty(); // כעת הפונקציה מכירה את paginationUl
24
+ paginationUl.empty();
29
25
  if(total <= 1) return;
30
26
  for(var i=1; i<=total; i++) {
31
27
  var active = i === curr ? 'active' : '';
@@ -35,13 +31,11 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
35
31
 
36
32
  function buildUserRow(user) {
37
33
  var displayName = user.username || ('משתמש ' + user.uid);
38
- // מניעת XSS בסיסית לשם המשתמש
39
34
  var safeName = $('<div>').text(displayName).html();
40
- var userLink = '/admin/manage/users?searchBy=uid&query=' + user.uid + '&page=1&sortBy=lastonline';
35
+ var userLink = config.relative_path + '/admin/manage/users?searchBy=uid&query=' + user.uid + '&page=1&sortBy=lastonline';
41
36
 
42
37
  var statusBadge = user.phoneVerified ? '<span class="label label-success">מאומת</span>' : '<span class="label label-warning">ממתין</span>';
43
38
 
44
- // מניעת XSS לטלפון
45
39
  var safePhone = user.phone ? $('<div>').text(user.phone).html() : '<span class="text-muted">-- ללא --</span>';
46
40
  var dateStr = user.phoneVerifiedAt ? new Date(user.phoneVerifiedAt).toLocaleDateString('he-IL') : '-';
47
41
 
@@ -65,7 +59,7 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
65
59
  page = page || 1;
66
60
  usersTbody.html('<tr><td colspan="6" class="text-center"><i class="fa fa-spinner fa-spin"></i> טוען נתונים...</td></tr>');
67
61
 
68
- $.get('/api/admin/plugins/phone-verification/users', { page: page }, function(data) {
62
+ $.get(config.relative_path + '/api/admin/plugins/phone-verification/users', { page: page }, function(data) {
69
63
  if (!data || !data.success) {
70
64
  usersTbody.html('<tr><td colspan="6" class="text-center text-danger">שגיאה בטעינת נתונים</td></tr>');
71
65
  return;
@@ -81,17 +75,14 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
81
75
  });
82
76
  }
83
77
 
84
- // --- הפעלת ברירת מחדל ---
85
78
  loadUsers(1);
86
79
 
87
- // --- אירועים (Event Listeners) ---
88
80
 
89
81
  paginationUl.on('click', 'a.page-link', function(e) {
90
82
  e.preventDefault();
91
83
  loadUsers($(this).data('page'));
92
84
  });
93
85
 
94
- // הוספה ידנית
95
86
  $('#btn-add-manual-user').on('click', function() {
96
87
  bootbox.prompt("הזן את <b>שם המשתמש</b> שברצונך להוסיף לרשימת המאומתים:", function(username) {
97
88
  if (!username) return;
@@ -103,7 +94,6 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
103
94
  title: "הזן מספר טלפון עבור " + username + " (אופציונלי)",
104
95
  inputType: 'text',
105
96
  callback: function(phone) {
106
- // תיקון קריטי: אם לחצו ביטול, עצור
107
97
  if (phone === null) return;
108
98
 
109
99
  var confirmMsg = "<h4>סיכום פעולה</h4>" +
@@ -130,7 +120,7 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
130
120
  var phone = $('#test-phone').val();
131
121
  if(!phone) return alerts.error('נא להזין מספר לבדיקה');
132
122
 
133
- $.post('/api/admin/plugins/phone-verification/test-call', { phoneNumber: phone, _csrf: config.csrf_token }, function(res) {
123
+ $.post(config.relative_path + '/api/admin/plugins/phone-verification/test-call', { phoneNumber: phone, _csrf: config.csrf_token }, function(res) {
134
124
  if(res.success) alerts.success(res.message);
135
125
  else alerts.error(res.message);
136
126
  });
@@ -175,7 +165,7 @@ define('admin/plugins/phone-verification', ['settings', 'bootbox', 'alerts'], fu
175
165
  $('#search-btn').on('click', function() {
176
166
  var phone = $('#phone-search').val();
177
167
  if (!phone) { loadUsers(1); return; }
178
- $.get('/api/admin/plugins/phone-verification/search', { phone: phone }, function(data) {
168
+ $.get(config.relative_path + '/api/admin/plugins/phone-verification/search', { phone: phone }, function(data) {
179
169
  usersTbody.empty();
180
170
  if (data.success && data.found) usersTbody.append(buildUserRow(data.user));
181
171
  else usersTbody.html('<tr><td colspan="6" class="text-center">לא נמצא משתמש</td></tr>');
@@ -63,9 +63,8 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
63
63
  const self = this;
64
64
  const $form = $('[component="register/local"]');
65
65
  if (!$form.length) return;
66
- if ($('#phoneNumber').length) return; // מניעת כפילות
66
+ if ($('#phoneNumber').length) return;
67
67
 
68
- // איפוס משתנים
69
68
  self.phoneVerified = false;
70
69
 
71
70
  const phoneHtml = `
@@ -120,16 +119,10 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
120
119
  attachEventListeners: function() {
121
120
  const self = this;
122
121
 
123
- // שליחת קוד
124
122
  $('#send-code-btn').off('click').on('click', function () {
125
123
  const phone = $('#phoneNumber').val().trim();
126
124
  self.hideMessages();
127
125
 
128
- // if (!isValidIsraeliPhone(phone)) {
129
- // self.showError('מספר הטלפון אינו תקין (05X-XXXXXXX)');
130
- // return;
131
- // }
132
-
133
126
  const $btn = $(this);
134
127
  $btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> שולח...');
135
128
 
@@ -157,7 +150,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
157
150
  });
158
151
  });
159
152
 
160
- // אימות קוד
161
153
  $('#verify-code-btn').off('click').on('click', function () {
162
154
  const phone = $('#phoneNumber').val().trim();
163
155
  const code = $('#verificationCode').val().trim();
@@ -179,7 +171,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
179
171
  $('#verification-code-container, #phone-verification-container').addClass('hidden');
180
172
  $('#phone-verified-badge').removeClass('hidden');
181
173
 
182
- // טיפול בשדה הנסתר לטופס
183
174
  $('#phoneNumber').prop('disabled', true).removeAttr('name');
184
175
  if (!$('#phoneNumberVerified').length) {
185
176
  $('<input>').attr({type: 'hidden', name: 'phoneNumber', id: 'phoneNumberVerified', value: phone}).appendTo('[component="register/local"]');
@@ -193,7 +184,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
193
184
  });
194
185
  });
195
186
 
196
- // חסימת שליחת טופס
197
187
  $('[component="register/local"]').off('submit.phone').on('submit.phone', function (e) {
198
188
  if (!self.phoneVerified) {
199
189
  e.preventDefault();
@@ -207,7 +197,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
207
197
  checkExistingVerification: function() {
208
198
  const phone = $('#phoneNumber').val();
209
199
  if (phone && this.validatePhone(phone)) {
210
- // לוגיקה לבדיקה אם כבר אומת
211
200
  }
212
201
  }
213
202
  };
@@ -215,14 +204,11 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
215
204
  // ==================== לוגיקה לעריכת פרופיל (Edit Profile) ====================
216
205
 
217
206
  function handleProfileEdit() {
218
- // בדיקת כפילות קפדנית לפי ID
219
207
  if ($('#sidebar-phone-li').length > 0) return;
220
208
 
221
209
  const userslug = ajaxify.data.userslug;
222
210
 
223
- // שליפת הנתונים הנוכחיים
224
211
  $.getJSON(config.relative_path + '/api/user/' + userslug + '/phone', function (response) {
225
- // בדיקה נוספת בתוך ה-callback למקרה של טעינה כפולה מהירה
226
212
  if ($('#sidebar-phone-li').length > 0) return;
227
213
 
228
214
  if (!response.success) return;
@@ -233,7 +219,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
233
219
 
234
220
  const hasPhone = response.phone && response.phone.length > 0;
235
221
 
236
- // עדכון הטקסט שיהיה ברור יותר
237
222
  const buttonLabel = hasPhone ? 'אמת מספר טלפון' : 'הוסף מספר טלפון';
238
223
 
239
224
  const menuHtml = `
@@ -258,7 +243,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
258
243
  });
259
244
  }
260
245
 
261
- // פונקציה חדשה לניהול החלונית הקופצת בעריכה
262
246
  function openPhoneManagementModal(currentPhone, isVerified, userslug) {
263
247
  const phoneVal = currentPhone || '';
264
248
 
@@ -294,15 +278,13 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
294
278
  callback: function() {
295
279
  const newPhone = $('#modal-phoneNumber').val();
296
280
 
297
- // שימוש בפונקציית הבדיקה המתוקנת
298
281
  if (!isValidIsraeliPhone(newPhone)) {
299
282
  showModalAlert('נא להזין מספר תקין (05X-XXXXXXX)', 'danger');
300
- return false; // מונע סגירה
283
+ return false;
301
284
  }
302
285
 
303
- // התחלת תהליך האימות
304
286
  performPhoneUpdate(newPhone, userslug, dialog);
305
- return false; // מונע סגירה אוטומטית
287
+ return false;
306
288
  }
307
289
  }
308
290
  }
@@ -315,10 +297,9 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
315
297
  }
316
298
 
317
299
  function performPhoneUpdate(phone, userslug, dialog) {
318
- const $btn = dialog.find('.bootbox-accept'); // הכפתור הכחול
300
+ const $btn = dialog.find('.bootbox-accept');
319
301
  $btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> שולח...');
320
302
 
321
- // 1. שמירה זמנית
322
303
  $.post(config.relative_path + '/api/user/' + userslug + '/phone', {
323
304
  phoneNumber: phone,
324
305
  _csrf: config.csrf_token
@@ -329,15 +310,13 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
329
310
  return;
330
311
  }
331
312
 
332
- // 2. שליחת השיחה
333
313
  $.post(config.relative_path + '/api/phone-verification/send-code', {
334
314
  phoneNumber: phone,
335
315
  _csrf: config.csrf_token
336
316
  }, function(callRes) {
337
317
  if (callRes.success) {
338
- dialog.modal('hide'); // סגירת החלון הראשון
318
+ dialog.modal('hide');
339
319
 
340
- // 3. פתיחת חלון הזנת קוד
341
320
  bootbox.prompt({
342
321
  title: "הזן את הקוד שקיבלת בשיחה",
343
322
  inputType: 'number',
@@ -350,7 +329,7 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
350
329
  }, function(verifyRes){
351
330
  if(verifyRes.success) {
352
331
  app.alertSuccess('הטלפון עודכן ואומת בהצלחה!');
353
- ajaxify.refresh(); // רענון הדף
332
+ ajaxify.refresh();
354
333
  } else {
355
334
  app.alertError(verifyRes.message || 'קוד שגוי');
356
335
  }
@@ -368,7 +347,6 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
368
347
  // ==================== לוגיקה לצפייה בפרופיל (View Profile) ====================
369
348
 
370
349
  function handleProfileView() {
371
- // בדיקה ראשונית למניעת כפילות עוד לפני הקריאה לשרת
372
350
  if ($('#user-phone-stat-item').length > 0) return;
373
351
 
374
352
  const userslug = ajaxify.data.userslug;
@@ -376,15 +354,13 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
376
354
  $.getJSON(config.relative_path + '/api/user/' + userslug + '/phone', function (response) {
377
355
  if (!response.success) return;
378
356
 
379
- // אם אין מספר טלפון - לא מציגים את הקוביה בכלל (גם לא לבעל הפרופיל)
380
357
  if (!response.phone) return;
381
358
 
382
- // בדיקה נוספת למניעת כפילות
383
359
  if ($('#user-phone-stat-item').length > 0) return;
384
360
 
385
361
  const verifyBadge = response.phoneVerified
386
362
  ? '<i class="" title=""></i>'
387
- : '<i class="fa fa-exclamation-triangle text-warning" title="לא מאומת" style="cursor:pointer;" onclick="location.href=\'/user/'+userslug+'/edit\'"></i>';
363
+ : '<i class="fa fa-exclamation-triangle text-warning" title="לא מאומת" style="cursor:pointer;" onclick="location.href=\'' + config.relative_path + '/user/' + userslug + '/edit\'"></i>';
388
364
 
389
365
  const privacyLabel = response.isOwner
390
366
  ? ' <span class="text-lowercase">(מוסתר)</span>'
@@ -453,4 +429,4 @@ define('forum/phone-verification', ['hooks', 'translator'], function (hooks, tra
453
429
  }
454
430
 
455
431
  return Plugin;
456
- });
432
+ });