1+ const mongoose = require ( 'mongoose' ) ;
2+
13const lbUserPrefController = function ( UserPreferences , Notification ) {
4+ const normalizeObjectId = ( value ) => {
5+ if ( typeof value !== 'string' ) return null ;
6+
7+ const trimmed = value . trim ( ) ;
8+ if ( ! mongoose . Types . ObjectId . isValid ( trimmed ) ) return null ;
9+
10+ return trimmed ;
11+ } ;
12+
13+ const normalizeObjectIdList = ( values ) => {
14+ if ( ! Array . isArray ( values ) ) return null ;
15+
16+ const normalizedIds = values . map ( normalizeObjectId ) ;
17+ return normalizedIds . every ( Boolean ) ? normalizedIds : null ;
18+ } ;
19+
20+ const normalizePhone = ( phone ) => {
21+ if ( ! phone ) return { normalized : '' , last4 : '' } ;
22+ const trimmed = String ( phone ) . trim ( ) ;
23+ const hasPlus = trimmed . startsWith ( '+' ) ;
24+ const digits = trimmed . replace ( / \D / g, '' ) ;
25+ const normalized = hasPlus ? `+${ digits } ` : digits ;
26+ return { normalized, last4 : digits . slice ( - 4 ) } ;
27+ } ;
28+
29+ const maskPhone = ( phone ) => {
30+ if ( ! phone ) return '' ;
31+ const digits = String ( phone ) . replace ( / \D / g, '' ) ;
32+ if ( digits . length <= 4 ) return digits ;
33+ return `***-***-${ digits . slice ( - 4 ) } ` ;
34+ } ;
235 const getPreferences = async ( req , res ) => {
336 try {
437 const { userId, selectedUserId } = req . body ;
38+ const normalizedUserId = normalizeObjectId ( userId ) ;
39+ const normalizedSelectedUserId = selectedUserId
40+ ? normalizeObjectId ( selectedUserId )
41+ : null ;
542
6- if ( ! userId ) {
7- return res . status ( 400 ) . json ( { message : 'User ID is required.' } ) ;
43+ if ( ! normalizedUserId ) {
44+ return res . status ( 400 ) . json ( { message : 'A valid user ID is required.' } ) ;
845 }
946
10- const preferences = await UserPreferences . findOne ( { user : userId } ) . populate (
47+ if ( selectedUserId && ! normalizedSelectedUserId ) {
48+ return res . status ( 400 ) . json ( { message : 'Selected user ID must be a valid ID.' } ) ;
49+ }
50+
51+ const preferences = await UserPreferences . findOne ( { user : normalizedUserId } ) . populate (
1152 'users.userNotifyingFor' ,
1253 ) ;
1354
1455 if ( ! preferences ) {
1556 return res . status ( 404 ) . json ( { message : 'Preferences not found for the user.' } ) ;
1657 }
1758
18- if ( selectedUserId ) {
59+ if ( normalizedSelectedUserId ) {
1960 const selectedUserPref = preferences . users . find (
20- ( pref ) => pref . userNotifyingFor . _id . toString ( ) === selectedUserId ,
61+ ( pref ) => pref . userNotifyingFor . _id . toString ( ) === normalizedSelectedUserId ,
2162 ) ;
2263
2364 return res . status ( 200 ) . json ( selectedUserPref || { notifyInApp : false , notifyEmail : false } ) ;
2465 }
2566
26- res . status ( 200 ) . json ( preferences ) ;
67+ const response = preferences . toObject ( ) ;
68+ response . smsPhoneMasked = maskPhone ( preferences . smsPhone ) ;
69+ res . status ( 200 ) . json ( response ) ;
2770 } catch ( error ) {
2871 console . error ( 'Error fetching preferences:' , error ) ;
2972 res . status ( 500 ) . json ( { message : 'Error fetching preferences' , error : error . message } ) ;
@@ -32,43 +75,69 @@ const lbUserPrefController = function (UserPreferences, Notification) {
3275
3376 const updatePreferences = async ( req , res ) => {
3477 try {
35- const { userId, selectedUserId, notifyInApp, notifyEmail } = req . body ;
78+ const { userId, selectedUserId, notifyInApp, notifyEmail, notifySms, smsPhone } = req . body ;
79+ const normalizedUserId = normalizeObjectId ( userId ) ;
80+ const normalizedSelectedUserId = selectedUserId
81+ ? normalizeObjectId ( selectedUserId )
82+ : null ;
83+
84+ if ( ! normalizedUserId ) {
85+ return res . status ( 400 ) . json ( { message : 'A valid user ID is required.' } ) ;
86+ }
3687
37- if ( ! userId || ! selectedUserId ) {
38- return res . status ( 400 ) . json ( { message : 'User ID and Selected User ID are required .' } ) ;
88+ if ( selectedUserId && ! normalizedSelectedUserId ) {
89+ return res . status ( 400 ) . json ( { message : 'Selected user ID must be a valid ID .' } ) ;
3990 }
4091
41- const preferences = await UserPreferences . findOne ( { user : userId } ) ;
92+ let preferences = await UserPreferences . findOne ( { user : normalizedUserId } ) ;
4293
4394 if ( ! preferences ) {
44- const newPreferences = new UserPreferences ( {
45- user : userId ,
46- users : [
47- {
48- userNotifyingFor : selectedUserId ,
49- notifyInApp : notifyInApp !== undefined ? notifyInApp : false ,
50- notifyEmail : notifyEmail !== undefined ? notifyEmail : false ,
51- } ,
52- ] ,
53- } ) ;
54-
55- await newPreferences . save ( ) ;
56- return res . status ( 200 ) . json ( newPreferences ) ;
95+ preferences = new UserPreferences ( { user : normalizedUserId , users : [ ] } ) ;
5796 }
5897
59- const userIndex = preferences . users . findIndex (
60- ( user ) => user . userNotifyingFor . toString ( ) === selectedUserId ,
61- ) ;
98+ if ( normalizedSelectedUserId ) {
99+ const userIndex = preferences . users . findIndex (
100+ ( user ) => user . userNotifyingFor . toString ( ) === normalizedSelectedUserId ,
101+ ) ;
102+
103+ if ( userIndex === - 1 ) {
104+ preferences . users . push ( {
105+ userNotifyingFor : normalizedSelectedUserId ,
106+ notifyInApp : notifyInApp !== undefined ? notifyInApp : false ,
107+ notifyEmail : notifyEmail !== undefined ? notifyEmail : false ,
108+ } ) ;
109+ } else {
110+ preferences . users [ userIndex ] . notifyInApp =
111+ notifyInApp !== undefined ? notifyInApp : false ;
112+ preferences . users [ userIndex ] . notifyEmail =
113+ notifyEmail !== undefined ? notifyEmail : false ;
114+ }
115+ } else if ( notifyInApp !== undefined || notifyEmail !== undefined ) {
116+ if ( notifyInApp !== undefined ) {
117+ preferences . notifyInApp = notifyInApp ;
118+ }
119+ if ( notifyEmail !== undefined ) {
120+ preferences . notifyEmail = notifyEmail ;
121+ }
122+ }
62123
63- if ( userIndex === - 1 ) {
64- preferences . users . push ( {
65- userNotifyingFor : selectedUserId ,
66- notifyInApp : notifyInApp !== undefined ? notifyInApp : false ,
67- notifyEmail : notifyEmail !== undefined ? notifyEmail : false ,
68- } ) ;
69- } else {
70- preferences . users [ userIndex ] . notifyInApp = notifyInApp !== undefined ? notifyInApp : false ;
71- preferences . users [ userIndex ] . notifyEmail = notifyEmail !== undefined ? notifyEmail : false ;
124+ if ( notifySms !== undefined || smsPhone !== undefined ) {
125+ const { normalized, last4 } = normalizePhone ( smsPhone ) ;
126+ const digits = normalized . replace ( / \D / g, '' ) ;
127+ const existingDigits = String ( preferences . smsPhone || '' ) . replace ( / \D / g, '' ) ;
128+ if ( notifySms && digits . length === 0 && existingDigits . length === 0 ) {
129+ return res . status ( 400 ) . json ( { message : 'SMS phone number is required.' } ) ;
130+ }
131+ if ( digits . length > 0 && ( digits . length < 8 || digits . length > 15 ) ) {
132+ return res . status ( 400 ) . json ( { message : 'Invalid phone number format.' } ) ;
133+ }
134+ if ( notifySms !== undefined ) {
135+ preferences . notifySms = notifySms ;
136+ }
137+ if ( smsPhone !== undefined && digits . length > 0 ) {
138+ preferences . smsPhone = normalized ;
139+ preferences . smsPhoneLast4 = last4 ;
140+ }
72141 }
73142
74143 const updatedPreferences = await preferences . save ( ) ;
@@ -82,15 +151,17 @@ const lbUserPrefController = function (UserPreferences, Notification) {
82151 const storeNotification = async ( req , res ) => {
83152 try {
84153 const { userId, senderId, message } = req . body ;
154+ const normalizedUserId = normalizeObjectId ( userId ) ;
155+ const normalizedSenderId = normalizeObjectId ( senderId ) ;
85156
86- if ( ! userId || ! senderId || ! message ) {
157+ if ( ! normalizedUserId || ! normalizedSenderId || ! message ) {
87158 return res . status ( 400 ) . json ( { message : 'User ID, Sender ID, and Message are required.' } ) ;
88159 }
89160
90161 const notification = new Notification ( {
91162 message,
92- sender : senderId ,
93- recipient : userId ,
163+ sender : normalizedSenderId ,
164+ recipient : normalizedUserId ,
94165 isSystemGenerated : false ,
95166 } ) ;
96167
@@ -105,13 +176,14 @@ const lbUserPrefController = function (UserPreferences, Notification) {
105176 const getUnreadNotifications = async ( req , res ) => {
106177 try {
107178 const { userId } = req . params ;
179+ const normalizedUserId = normalizeObjectId ( userId ) ;
108180
109- if ( ! userId ) {
181+ if ( ! normalizedUserId ) {
110182 console . error ( '❌ User ID is missing in the request.' ) ;
111- return res . status ( 400 ) . json ( { message : 'User ID is required.' } ) ;
183+ return res . status ( 400 ) . json ( { message : 'A valid user ID is required.' } ) ;
112184 }
113185
114- const notifications = await Notification . find ( { recipient : userId , isRead : false } )
186+ const notifications = await Notification . find ( { recipient : normalizedUserId , isRead : false } )
115187 . sort ( { createdTimeStamps : - 1 } )
116188 . populate ( 'sender' , 'firstName lastName' ) ; // Include sender's name
117189
@@ -127,12 +199,13 @@ const lbUserPrefController = function (UserPreferences, Notification) {
127199 const markNotificationsAsRead = async ( req , res ) => {
128200 try {
129201 const { notificationIds } = req . body ;
202+ const normalizedNotificationIds = normalizeObjectIdList ( notificationIds ) ;
130203
131- if ( ! notificationIds || ! Array . isArray ( notificationIds ) ) {
204+ if ( ! normalizedNotificationIds ) {
132205 return res . status ( 400 ) . json ( { message : 'Invalid notification IDs.' } ) ;
133206 }
134207 const result = await Notification . updateMany (
135- { _id : { $in : notificationIds } } ,
208+ { _id : { $in : normalizedNotificationIds } } ,
136209 { isRead : true } ,
137210 ) ;
138211
0 commit comments