omni_orchestrator/schemas/v1/api/notifications/
user.rs

1use std::sync::Arc;
2use crate::DatabaseManager;
3use crate::schemas::v1::db::queries::{self as db};
4use super::types::CreateUserNotificationRequest;
5use rocket::http::Status;
6use rocket::serde::json::{json, Json, Value};
7use rocket::{delete, get, post, put, State};
8
9use libomni::types::db::v1 as types;
10use types::user::User;
11
12/// Get a paginated list of notifications for a user
13#[get("/platform/<platform_id>/notifications/user/<user_id>?<page>&<per_page>&<include_read>")]
14pub async fn list_user_notifications(
15    platform_id: i64,
16    user_id: i64,
17    page: Option<i64>,
18    per_page: Option<i64>,
19    include_read: Option<bool>,
20    user: User, // For authentication
21    db_manager: &State<Arc<DatabaseManager>>,
22) -> Result<Json<Value>, (Status, Json<Value>)> {
23    // Get platform information
24    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
25        Ok(platform) => platform,
26        Err(_) => {
27            return Err((
28                Status::NotFound,
29                Json(json!({
30                    "error": "Platform not found",
31                    "message": format!("Platform with ID {} does not exist", platform_id)
32                }))
33            ));
34        }
35    };
36
37    // Get platform-specific database pool
38    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
39        Ok(pool) => pool,
40        Err(_) => {
41            return Err((
42                Status::InternalServerError,
43                Json(json!({
44                    "error": "Database error",
45                    "message": "Failed to connect to platform database"
46                }))
47            ));
48        }
49    };
50
51    // Authorization - only allow users to see their own notifications
52    // or administrators to see others' notifications
53    if user.id != user_id {
54        return Err((
55            Status::Forbidden,
56            Json(json!({
57                "error": "Forbidden",
58                "message": "You do not have permission to view this user's notifications"
59            }))
60        ));
61    }
62
63    // Default pagination parameters
64    let page = page.unwrap_or(0);
65    let per_page = per_page.unwrap_or(20);
66    let include_read = include_read.unwrap_or(false);
67
68    match db::notification::list_user_notifications(
69        &pool,
70        user_id,
71        page,
72        per_page,
73        include_read,
74    ).await {
75        Ok(notifications) => Ok(Json(json!({
76            "notifications": notifications,
77            "pagination": {
78                "page": page,
79                "per_page": per_page
80            }
81        }))),
82        Err(e) => {
83            log::error!("Failed to fetch user notifications: {}", e);
84            Err((
85                Status::InternalServerError,
86                Json(json!({
87                    "error": "Database error",
88                    "message": "Failed to fetch user notifications"
89                }))
90            ))
91        }
92    }
93}
94
95/// Count unread notifications for a user (for badges)
96#[get("/platform/<platform_id>/notifications/user/count/<user_id>")]
97pub async fn count_unread_user_notifications(
98    platform_id: i64,
99    user_id: i64,
100    user: User, // For authentication
101    db_manager: &State<Arc<DatabaseManager>>,
102) -> Result<Json<Value>, (Status, Json<Value>)> {
103    // Get platform information
104    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
105        Ok(platform) => platform,
106        Err(_) => {
107            return Err((
108                Status::NotFound,
109                Json(json!({
110                    "error": "Platform not found",
111                    "message": format!("Platform with ID {} does not exist", platform_id)
112                }))
113            ));
114        }
115    };
116
117    // Get platform-specific database pool
118    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
119        Ok(pool) => pool,
120        Err(_) => {
121            return Err((
122                Status::InternalServerError,
123                Json(json!({
124                    "error": "Database error",
125                    "message": "Failed to connect to platform database"
126                }))
127            ));
128        }
129    };
130
131    // Authorization - only allow users to see their own count
132    // or administrators to see others' counts
133    if user.id != user_id {
134        return Err((
135            Status::Forbidden,
136            Json(json!({
137                "error": "Forbidden",
138                "message": "You do not have permission to view this user's notification count"
139            }))
140        ));
141    }
142
143    match db::notification::count_unread_user_notifications(
144        &pool,
145        user_id,
146    ).await {
147        Ok(count) => Ok(Json(json!({ "unread_count": count }))),
148        Err(e) => {
149            log::error!("Failed to count unread notifications: {}", e);
150            Err((
151                Status::InternalServerError,
152                Json(json!({
153                    "error": "Database error",
154                    "message": "Failed to count unread notifications"
155                }))
156            ))
157        }
158    }
159}
160
161/// Get a specific notification by ID
162#[get("/platform/<platform_id>/notifications/<id>")]
163pub async fn get_user_notification_by_id(
164    platform_id: i64,
165    id: i64,
166    user: User, // For authentication
167    db_manager: &State<Arc<DatabaseManager>>,
168) -> Result<Json<Value>, (Status, Json<Value>)> {
169    // Get platform information
170    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
171        Ok(platform) => platform,
172        Err(_) => {
173            return Err((
174                Status::NotFound,
175                Json(json!({
176                    "error": "Platform not found",
177                    "message": format!("Platform with ID {} does not exist", platform_id)
178                }))
179            ));
180        }
181    };
182
183    // Get platform-specific database pool
184    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
185        Ok(pool) => pool,
186        Err(_) => {
187            return Err((
188                Status::InternalServerError,
189                Json(json!({
190                    "error": "Database error",
191                    "message": "Failed to connect to platform database"
192                }))
193            ));
194        }
195    };
196
197    let notification = match db::notification::get_user_notification_by_id(
198        &pool,
199        id,
200    ).await {
201        Ok(notification) => notification,
202        Err(e) => {
203            log::error!("Failed to fetch notification: {}", e);
204            if e.to_string().contains("no rows") {
205                return Err((
206                    Status::NotFound,
207                    Json(json!({
208                        "error": "Not found",
209                        "message": format!("Notification with ID {} does not exist", id)
210                    }))
211                ));
212            } else {
213                return Err((
214                    Status::InternalServerError,
215                    Json(json!({
216                        "error": "Database error",
217                        "message": "Failed to fetch notification"
218                    }))
219                ));
220            }
221        }
222    };
223
224    // Authorization - only allow users to see their own notifications
225    // or administrators to see others' notifications
226    if notification.user_id != user.id {
227        return Err((
228            Status::Forbidden,
229            Json(json!({
230                "error": "Forbidden",
231                "message": "You do not have permission to view this notification"
232            }))
233        ));
234    }
235
236    Ok(Json(json!({ "notification": notification })))
237}
238
239/// Create a new notification for a user
240#[post("/platform/<platform_id>/notifications/user", format = "json", data = "<notification_data>")]
241pub async fn create_user_notification(
242    platform_id: i64,
243    notification_data: Json<CreateUserNotificationRequest>,
244    user: User, // For authentication
245    db_manager: &State<Arc<DatabaseManager>>,
246) -> Result<Json<Value>, (Status, Json<Value>)> {
247    // Get platform information
248    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
249        Ok(platform) => platform,
250        Err(_) => {
251            return Err((
252                Status::NotFound,
253                Json(json!({
254                    "error": "Platform not found",
255                    "message": format!("Platform with ID {} does not exist", platform_id)
256                }))
257            ));
258        }
259    };
260
261    // Get platform-specific database pool
262    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
263        Ok(pool) => pool,
264        Err(_) => {
265            return Err((
266                Status::InternalServerError,
267                Json(json!({
268                    "error": "Database error",
269                    "message": "Failed to connect to platform database"
270                }))
271            ));
272        }
273    };
274
275    let data = notification_data.into_inner();
276    
277    // Target user ID would normally come from the request
278    // For this example, we're using the authenticated user's ID
279    let target_user_id = user.id;
280
281    match db::notification::create_user_notification(
282        &pool,
283        target_user_id,
284        &data.message,
285        &data.notification_type,
286        data.org_id,
287        data.app_id,
288        data.importance.as_deref(),
289        data.action_url.as_deref(),
290        data.action_label.as_deref(),
291        data.expires_at,
292    ).await {
293        Ok(notification) => Ok(Json(json!({
294            "message": "Notification created successfully",
295            "notification": notification
296        }))),
297        Err(e) => {
298            log::error!("Failed to create notification: {}", e);
299            Err((
300                Status::InternalServerError,
301                Json(json!({
302                    "error": "Database error",
303                    "message": "Failed to create notification"
304                }))
305            ))
306        }
307    }
308}
309
310/// Mark a notification as read
311#[put("/platform/<platform_id>/notifications/<id>/read")]
312pub async fn mark_user_notification_as_read(
313    platform_id: i64,
314    id: i64,
315    user: User, // For authentication
316    db_manager: &State<Arc<DatabaseManager>>,
317) -> Result<Json<Value>, (Status, Json<Value>)> {
318    // Get platform information
319    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
320        Ok(platform) => platform,
321        Err(_) => {
322            return Err((
323                Status::NotFound,
324                Json(json!({
325                    "error": "Platform not found",
326                    "message": format!("Platform with ID {} does not exist", platform_id)
327                }))
328            ));
329        }
330    };
331
332    // Get platform-specific database pool
333    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
334        Ok(pool) => pool,
335        Err(_) => {
336            return Err((
337                Status::InternalServerError,
338                Json(json!({
339                    "error": "Database error",
340                    "message": "Failed to connect to platform database"
341                }))
342            ));
343        }
344    };
345
346    // First, get the notification to check ownership
347    let notification = match db::notification::get_user_notification_by_id(
348        &pool,
349        id,
350    ).await {
351        Ok(notification) => notification,
352        Err(e) => {
353            log::error!("Failed to fetch notification: {}", e);
354            if e.to_string().contains("no rows") {
355                return Err((
356                    Status::NotFound,
357                    Json(json!({
358                        "error": "Not found",
359                        "message": format!("Notification with ID {} does not exist", id)
360                    }))
361                ));
362            } else {
363                return Err((
364                    Status::InternalServerError,
365                    Json(json!({
366                        "error": "Database error",
367                        "message": "Failed to fetch notification"
368                    }))
369                ));
370            }
371        }
372    };
373
374    // Authorization - only allow users to mark their own notifications as read
375    // or administrators to mark others' notifications
376    if notification.user_id != user.id {
377        return Err((
378            Status::Forbidden,
379            Json(json!({
380                "error": "Forbidden",
381                "message": "You do not have permission to mark this notification as read"
382            }))
383        ));
384    }
385
386    match db::notification::mark_user_notification_as_read(
387        &pool,
388        id,
389    ).await {
390        Ok(updated_notification) => Ok(Json(json!({
391            "message": "Notification marked as read",
392            "notification": updated_notification
393        }))),
394        Err(e) => {
395            log::error!("Failed to mark notification as read: {}", e);
396            Err((
397                Status::InternalServerError,
398                Json(json!({
399                    "error": "Database error",
400                    "message": "Failed to mark notification as read"
401                }))
402            ))
403        }
404    }
405}
406
407/// Mark all notifications for a user as read
408#[put("/platform/<platform_id>/notifications/user/<user_id>/read-all")]
409pub async fn mark_all_user_notifications_as_read(
410    platform_id: i64,
411    user_id: i64,
412    user: User, // For authentication
413    db_manager: &State<Arc<DatabaseManager>>,
414) -> Result<Json<Value>, (Status, Json<Value>)> {
415    // Get platform information
416    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
417        Ok(platform) => platform,
418        Err(_) => {
419            return Err((
420                Status::NotFound,
421                Json(json!({
422                    "error": "Platform not found",
423                    "message": format!("Platform with ID {} does not exist", platform_id)
424                }))
425            ));
426        }
427    };
428
429    // Get platform-specific database pool
430    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
431        Ok(pool) => pool,
432        Err(_) => {
433            return Err((
434                Status::InternalServerError,
435                Json(json!({
436                    "error": "Database error",
437                    "message": "Failed to connect to platform database"
438                }))
439            ));
440        }
441    };
442
443    // Authorization - only allow users to mark their own notifications as read
444    // or administrators to mark others' notifications
445    if user.id != user_id {
446        return Err((
447            Status::Forbidden,
448            Json(json!({
449                "error": "Forbidden",
450                "message": "You do not have permission to mark this user's notifications as read"
451            }))
452        ));
453    }
454
455    match db::notification::mark_all_user_notifications_as_read(
456        &pool,
457        user_id,
458    ).await {
459        Ok(_) => Ok(Json(json!({
460            "message": "All notifications marked as read",
461        }))),
462        Err(e) => {
463            log::error!("Failed to mark all notifications as read: {}", e);
464            Err((
465                Status::InternalServerError,
466                Json(json!({
467                    "error": "Database error",
468                    "message": "Failed to mark all notifications as read"
469                }))
470            ))
471        }
472    }
473}
474
475/// Delete a notification
476#[delete("/platform/<platform_id>/notifications/<id>")]
477pub async fn delete_user_notification(
478    platform_id: i64,
479    id: i64,
480    user: User, // For authentication
481    db_manager: &State<Arc<DatabaseManager>>,
482) -> Result<Json<Value>, (Status, Json<Value>)> {
483    // Get platform information
484    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
485        Ok(platform) => platform,
486        Err(_) => {
487            return Err((
488                Status::NotFound,
489                Json(json!({
490                    "error": "Platform not found",
491                    "message": format!("Platform with ID {} does not exist", platform_id)
492                }))
493            ));
494        }
495    };
496
497    // Get platform-specific database pool
498    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
499        Ok(pool) => pool,
500        Err(_) => {
501            return Err((
502                Status::InternalServerError,
503                Json(json!({
504                    "error": "Database error",
505                    "message": "Failed to connect to platform database"
506                }))
507            ));
508        }
509    };
510
511    // First, get the notification to check ownership
512    let notification = match db::notification::get_user_notification_by_id(
513        &pool,
514        id,
515    ).await {
516        Ok(notification) => notification,
517        Err(e) => {
518            log::error!("Failed to fetch notification: {}", e);
519            if e.to_string().contains("no rows") {
520                return Err((
521                    Status::NotFound,
522                    Json(json!({
523                        "error": "Not found",
524                        "message": format!("Notification with ID {} does not exist", id)
525                    }))
526                ));
527            } else {
528                return Err((
529                    Status::InternalServerError,
530                    Json(json!({
531                        "error": "Database error",
532                        "message": "Failed to fetch notification"
533                    }))
534                ));
535            }
536        }
537    };
538
539    // Authorization - only allow users to delete their own notifications
540    // or administrators to delete others' notifications
541    if notification.user_id != user.id {
542        return Err((
543            Status::Forbidden,
544            Json(json!({
545                "error": "Forbidden",
546                "message": "You do not have permission to delete this notification"
547            }))
548        ));
549    }
550
551    match db::notification::delete_user_notification(
552        &pool,
553        id,
554    ).await {
555        Ok(_) => Ok(Json(json!({
556            "message": "Notification deleted successfully",
557        }))),
558        Err(e) => {
559            log::error!("Failed to delete notification: {}", e);
560            Err((
561                Status::InternalServerError,
562                Json(json!({
563                    "error": "Database error",
564                    "message": "Failed to delete notification"
565                }))
566            ))
567        }
568    }
569}
570
571/// Delete all read notifications for a user
572#[delete("/platform/<platform_id>/notifications/user/<user_id>/read")]
573pub async fn delete_read_user_notifications(
574    platform_id: i64,
575    user_id: i64,
576    user: User, // For authentication
577    db_manager: &State<Arc<DatabaseManager>>,
578) -> Result<Json<Value>, (Status, Json<Value>)> {
579    // Get platform information
580    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
581        Ok(platform) => platform,
582        Err(_) => {
583            return Err((
584                Status::NotFound,
585                Json(json!({
586                    "error": "Platform not found",
587                    "message": format!("Platform with ID {} does not exist", platform_id)
588                }))
589            ));
590        }
591    };
592
593    // Get platform-specific database pool
594    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
595        Ok(pool) => pool,
596        Err(_) => {
597            return Err((
598                Status::InternalServerError,
599                Json(json!({
600                    "error": "Database error",
601                    "message": "Failed to connect to platform database"
602                }))
603            ));
604        }
605    };
606
607    // Authorization - only allow users to delete their own notifications
608    // or administrators to delete others' notifications
609    if user.id != user_id {
610        return Err((
611            Status::Forbidden,
612            Json(json!({
613                "error": "Forbidden",
614                "message": "You do not have permission to delete this user's notifications"
615            }))
616        ));
617    }
618
619    match db::notification::delete_read_user_notifications(
620        &pool,
621        user_id,
622    ).await {
623        Ok(count) => Ok(Json(json!({
624            "message": "Read notifications deleted successfully",
625            "count": count
626        }))),
627        Err(e) => {
628            log::error!("Failed to delete read notifications: {}", e);
629            Err((
630                Status::InternalServerError,
631                Json(json!({
632                    "error": "Database error",
633                    "message": "Failed to delete read notifications"
634                }))
635            ))
636        }
637    }
638}
639
640/// Get all notifications for a user including role notifications
641#[get("/platform/<platform_id>/notifications/user/<user_id>/all?<page>&<per_page>")]
642pub async fn get_all_user_notifications_with_count(
643    platform_id: i64,
644    user_id: i64,
645    page: Option<i64>,
646    per_page: Option<i64>,
647    user: User, // For authentication
648    db_manager: &State<Arc<DatabaseManager>>,
649) -> Result<Json<Value>, (Status, Json<Value>)> {
650    // Get platform information
651    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
652        Ok(platform) => platform,
653        Err(_) => {
654            return Err((
655                Status::NotFound,
656                Json(json!({
657                    "error": "Platform not found",
658                    "message": format!("Platform with ID {} does not exist", platform_id)
659                }))
660            ));
661        }
662    };
663
664    // Get platform-specific database pool
665    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
666        Ok(pool) => pool,
667        Err(_) => {
668            return Err((
669                Status::InternalServerError,
670                Json(json!({
671                    "error": "Database error",
672                    "message": "Failed to connect to platform database"
673                }))
674            ));
675        }
676    };
677
678    // Authorization - only allow users to see their own notifications
679    // or administrators to see others' notifications
680    if user.id != user_id {
681        return Err((
682            Status::Forbidden,
683            Json(json!({
684                "error": "Forbidden",
685                "message": "You do not have permission to view this user's notifications"
686            }))
687        ));
688    }
689
690    // Default pagination parameters
691    let page = page.unwrap_or(0);
692    let per_page = per_page.unwrap_or(20);
693
694    match db::notification::get_all_user_notifications_with_count(
695        &pool,
696        user_id,
697        page,
698        per_page,
699    ).await {
700        Ok(notifications_with_count) => Ok(Json(json!(notifications_with_count))),
701        Err(e) => {
702            log::error!("Failed to fetch notifications with count: {}", e);
703            Err((
704                Status::InternalServerError,
705                Json(json!({
706                    "error": "Database error",
707                    "message": "Failed to fetch notifications with count"
708                }))
709            ))
710        }
711    }
712}