nodebb-plugin-phone-verification 1.2.4 → 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,63 +96,48 @@ 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
- // --- תיקון: בדיקת כל הווריאציות האפשריות (כולל fromuid באותיות קטנות) ---
105
107
  const uid = data.fromuid || data.fromUid || data.uid;
106
108
 
107
- // לוג לבדיקה שזה עובד עכשיו
108
- // console.log(`[Phone-Verify] Checking message from UID: ${uid}`);
109
-
110
- // אם עדיין לא מצאנו מזהה משתמש, מחזירים את המידע כמו שהוא
111
109
  if (!uid || parseInt(uid, 10) === 0) return data;
112
110
 
113
111
  const settings = await plugin.getSettings();
114
- // אם ההגדרות כבויות - משחררים
115
112
  if (!settings.blockUnverifiedUsers) return data;
116
113
 
117
- // מנהלים מורשים תמיד
118
114
  const isAdmin = await User.isAdministrator(uid);
119
115
  if (isAdmin) return data;
120
116
 
121
- // משתמשים מאומתים מורשים תמיד
122
117
  const phoneData = await plugin.getUserPhone(uid);
123
118
  if (phoneData && phoneData.phoneVerified) {
124
119
  return data;
125
120
  }
126
121
 
127
- // --- המשתמש לא מאומת -> בדיקת שאר המשתתפים ---
128
-
129
122
  const Messaging = require.main.require('./src/messaging');
130
123
 
131
- // וידוא שיש לנו roomId
132
124
  if (!data.roomId) return data;
133
125
 
134
- // שליפת המשתתפים בחדר
135
126
  const roomUids = await Messaging.getUidsInRoom(data.roomId, 0, -1);
136
127
 
137
- // סינון השולח עצמו
138
128
  const targetUids = roomUids.filter(id => parseInt(id, 10) !== parseInt(uid, 10));
139
129
 
140
- // הכנת הקישור לפרופיל
141
130
  const userSlug = await User.getUserField(uid, 'userslug');
142
- const editUrl = userSlug ? `/user/${userSlug}/edit` : '/user/me/edit';
131
+ const relativePath = nconf.get('relative_path');
132
+ const editUrl = userSlug ? `${relativePath}/user/${userSlug}/edit` : `${relativePath}/user/me/edit`;
143
133
  const errorMsg = `חובה לאמת מספר טלפון כדי לשלוח הודעות.<br/>אנא גש ל<a href="${editUrl}">הגדרות הפרופיל שלך</a>.`;
144
134
 
145
- // אם אין אף אחד אחר בשיחה (מדבר לעצמו) - חוסמים
146
135
  if (targetUids.length === 0) {
147
136
  throw new Error(errorMsg);
148
137
  }
149
138
 
150
- // בדיקה שכל המשתתפים האחרים הם מנהלים
151
139
  for (const targetUid of targetUids) {
152
140
  const isTargetAdmin = await User.isAdministrator(targetUid);
153
- // אם נמצא אפילו משתתף אחד שאינו מנהל -> חסימה
154
141
  if (!isTargetAdmin) {
155
142
  throw new Error(errorMsg);
156
143
  }
@@ -187,7 +174,6 @@ plugin.sendVoiceCall = async function (phone, code) {
187
174
 
188
175
  const url = `${baseUrl}?${params.toString()}`;
189
176
 
190
- // עקיפת בעיות SSL (אופציונלי)
191
177
  const agent = new https.Agent({ rejectUnauthorized: false });
192
178
 
193
179
  const response = await fetch(url, { method: 'GET', agent: agent });
@@ -300,7 +286,6 @@ plugin.clearVerifiedPhone = async function (phone) {
300
286
  plugin.savePhoneToUser = async function (uid, phone, verified = true, forceOverride = false) {
301
287
  if (!db || !User) return { success: false };
302
288
 
303
- // 1. מקרה של אימות ללא טלפון
304
289
  if (!phone) {
305
290
  await User.setUserFields(uid, {
306
291
  phoneVerified: verified ? 1 : 0,
@@ -317,25 +302,18 @@ plugin.savePhoneToUser = async function (uid, phone, verified = true, forceOverr
317
302
  const normalizedPhone = plugin.normalizePhone(phone);
318
303
  const existingUid = await db.sortedSetScore('phone:uid', normalizedPhone);
319
304
 
320
- // 2. בדיקת כפילות
321
305
  if (existingUid) {
322
- // אם המספר שייך למשתמש אחר
323
306
  if (parseInt(existingUid, 10) !== parseInt(uid, 10)) {
324
307
  if (forceOverride) {
325
- // === תיקון: דריסה בכוח (למנהלים) ===
326
- // מחיקת המספר מהמשתמש הישן
327
308
  console.log(`[phone-verification] Force overwriting phone ${normalizedPhone} from user ${existingUid} to ${uid}`);
328
309
 
329
- // הסרה מה-Set של המשתמש הישן
330
310
  await User.setUserFields(existingUid, {
331
311
  [PHONE_FIELD_KEY]: '',
332
312
  phoneVerified: 0,
333
313
  phoneVerifiedAt: 0
334
314
  });
335
315
  await db.sortedSetRemove('users:phone', existingUid);
336
- // (הערה: לא צריך להסיר מ-phone:uid כי אנחנו דורסים אותו מייד למטה)
337
316
  } else {
338
- // אם זה לא מנהל - זרוק שגיאה
339
317
  return { success: false, error: 'PHONE_EXISTS', message: 'המספר כבר רשום למשתמש אחר' };
340
318
  }
341
319
  }
@@ -348,7 +326,6 @@ plugin.savePhoneToUser = async function (uid, phone, verified = true, forceOverr
348
326
  phoneVerifiedAt: verified ? now : 0
349
327
  });
350
328
 
351
- // עדכון/דריסה של הרשומה ב-DB
352
329
  await db.sortedSetAdd('phone:uid', uid, normalizedPhone);
353
330
  await db.sortedSetAdd('users:phone', now, uid);
354
331
  return { success: true };
@@ -406,19 +383,16 @@ plugin.checkRegistration = async function (data) {
406
383
  const existingUid = await plugin.findUserByPhone(normalizedPhone);
407
384
 
408
385
  if (existingUid) {
409
- // אם המשתמש מחובר ומנסה לעדכן, או אם המספר תפוס על ידי מישהו אחר
410
386
  if (!req.uid || parseInt(existingUid, 10) !== parseInt(req.uid, 10)) {
411
387
  throw new Error('מספר הטלפון כבר רשום במערכת למשתמש אחר');
412
388
  }
413
389
  }
414
390
 
415
- // אם הגעת לכאן, הנתונים תקינים.
416
- // ב-Hook של checkRegistration, פשוט מחזירים את data כדי להמשיך ברישום.
417
391
  return data;
418
392
 
419
393
  } catch (err) {
420
394
  console.error('[phone-verification] Registration check error:', err);
421
- throw err; // NodeBB יציג את השגיאה הזו למשתמש בטופס הרישום
395
+ throw err;
422
396
  }
423
397
  };
424
398
 
@@ -478,7 +452,6 @@ plugin.init = async function (params) {
478
452
  // --- SOCKET.IO EVENTS ---
479
453
  SocketPlugins.call2all = {};
480
454
 
481
- // 1. פונקציה חדשה: מציאת משתמש לפי שם
482
455
  SocketPlugins.call2all.getUidByUsername = async function (socket, data) {
483
456
  if (!data || !data.username) throw new Error('נא לספק שם משתמש');
484
457
  const uid = await User.getUidByUsername(data.username);
@@ -486,7 +459,6 @@ plugin.init = async function (params) {
486
459
  return uid;
487
460
  };
488
461
 
489
- // 2. הוספת משתמש מאומת (מתוקן)
490
462
  SocketPlugins.call2all.adminAddVerifiedUser = async function (socket, data) {
491
463
  if (!data || !data.uid) throw new Error('חסר מזהה משתמש');
492
464
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -503,7 +475,6 @@ plugin.init = async function (params) {
503
475
  if (!result.success) throw new Error(result.message);
504
476
  };
505
477
 
506
- // 3. אימות ידני
507
478
  SocketPlugins.call2all.adminVerifyUser = async function (socket, data) {
508
479
  if (!data || !data.uid) throw new Error('שגיאה');
509
480
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -513,7 +484,6 @@ plugin.init = async function (params) {
513
484
  await db.sortedSetAdd('users:phone', Date.now(), data.uid);
514
485
  };
515
486
 
516
- // 4. ביטול אימות
517
487
  SocketPlugins.call2all.adminUnverifyUser = async function (socket, data) {
518
488
  if (!data || !data.uid) throw new Error('שגיאה');
519
489
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -522,7 +492,6 @@ plugin.init = async function (params) {
522
492
  await User.setUserFields(data.uid, { phoneVerified: 0, phoneVerifiedAt: 0 });
523
493
  };
524
494
 
525
- // 5. מחיקת טלפון
526
495
  SocketPlugins.call2all.adminDeleteUserPhone = async function (socket, data) {
527
496
  if (!data || !data.uid) throw new Error('שגיאה');
528
497
  const isAdmin = await User.isAdministrator(socket.uid);
@@ -573,8 +542,8 @@ plugin.getSettings = async function () {
573
542
  return {
574
543
  voiceServerUrl: settings.voiceServerUrl || defaultSettings.voiceServerUrl,
575
544
  voiceServerApiKey: settings.voiceServerApiKey || '',
576
- voiceServerEnabled: isTrue(settings.voiceServerEnabled), // בדיקה מורחבת
577
- blockUnverifiedUsers: isTrue(settings.blockUnverifiedUsers), // בדיקה מורחבת
545
+ voiceServerEnabled: isTrue(settings.voiceServerEnabled),
546
+ blockUnverifiedUsers: isTrue(settings.blockUnverifiedUsers),
578
547
  voiceTtsMode: settings.voiceTtsMode || '1',
579
548
  voiceMessageTemplate: settings.voiceMessageTemplate || defaultSettings.voiceMessageTemplate
580
549
  };
@@ -635,7 +604,6 @@ plugin.apiSendCode = async function (req, res) {
635
604
  if (!plugin.validatePhoneNumber(clean)) return res.json({ success: false, error: 'INVALID' });
636
605
 
637
606
  const existingUid = await plugin.findUserByPhone(clean);
638
- // בדיקת כפילות: אם המספר שייך למשתמש אחר
639
607
  if (existingUid && (!req.uid || parseInt(existingUid) !== parseInt(req.uid))) {
640
608
  return res.json({ success: false, error: 'EXISTS', message: 'המספר תפוס' });
641
609
  }
@@ -790,4 +758,4 @@ plugin.userDelete = async function (data) {
790
758
  } catch (e) {}
791
759
  };
792
760
 
793
- 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.4",
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
+ });