omni_orchestrator/schemas/v1/api/
notifications.rs

1//! Notification management module for handling CRUD operations on notifications.
2//! 
3//! This module provides functionality to create, read, update, and delete
4//! notifications in the system. It includes endpoints for managing both
5//! user notifications and role-based notifications.
6
7use std::sync::Arc;
8use crate::DatabaseManager;
9use crate::models::{
10    user::User,
11    notification::{
12        NotificationAcknowledgment,
13        NotificationWithCount,
14        RoleNotification,
15        UserNotification,
16        UserNotificationWithRoleNotifications
17    },
18};
19use crate::schemas::v1::db::queries::{self as db};
20use rocket::http::Status;
21use rocket::serde::json::{json, Json, Value};
22use rocket::{delete, get, post, put, State};
23use serde::{Deserialize, Serialize};
24use chrono::{DateTime, Utc};
25
26// Request and response structs
27
28#[derive(Debug, Serialize, Deserialize)]
29pub struct CreateUserNotificationRequest {
30    pub message: String,
31    pub notification_type: String,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub org_id: Option<i64>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub app_id: Option<i64>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub importance: Option<String>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub action_url: Option<String>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub action_label: Option<String>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub expires_at: Option<DateTime<Utc>>,
44}
45
46#[derive(Debug, Serialize, Deserialize)]
47pub struct CreateRoleNotificationRequest {
48    pub role_id: i64,
49    pub message: String,
50    pub notification_type: String,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub org_id: Option<i64>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub app_id: Option<i64>,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub importance: Option<String>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub action_url: Option<String>,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub action_label: Option<String>,
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub expires_at: Option<DateTime<Utc>>,
63}
64
65#[derive(Debug, Serialize, Deserialize)]
66pub struct AcknowledgeNotificationRequest {
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub notification_id: Option<i64>,
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub role_notification_id: Option<i64>,
71}
72
73// API Routes
74
75/// Get a paginated list of notifications for a user
76#[get("/platform/<platform_id>/notifications/user/<user_id>?<page>&<per_page>&<include_read>")]
77pub async fn list_user_notifications(
78    platform_id: i64,
79    user_id: i64,
80    page: Option<i64>,
81    per_page: Option<i64>,
82    include_read: Option<bool>,
83    user: User, // For authentication
84    db_manager: &State<Arc<DatabaseManager>>,
85) -> Result<Json<Value>, (Status, Json<Value>)> {
86    // Get platform information
87    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
88        Ok(platform) => platform,
89        Err(_) => {
90            return Err((
91                Status::NotFound,
92                Json(json!({
93                    "error": "Platform not found",
94                    "message": format!("Platform with ID {} does not exist", platform_id)
95                }))
96            ));
97        }
98    };
99
100    // Get platform-specific database pool
101    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
102        Ok(pool) => pool,
103        Err(_) => {
104            return Err((
105                Status::InternalServerError,
106                Json(json!({
107                    "error": "Database error",
108                    "message": "Failed to connect to platform database"
109                }))
110            ));
111        }
112    };
113
114    // Authorization - only allow users to see their own notifications
115    // or administrators to see others' notifications
116    if user.id != user_id {
117        return Err((
118            Status::Forbidden,
119            Json(json!({
120                "error": "Forbidden",
121                "message": "You do not have permission to view this user's notifications"
122            }))
123        ));
124    }
125
126    // Default pagination parameters
127    let page = page.unwrap_or(0);
128    let per_page = per_page.unwrap_or(20);
129    let include_read = include_read.unwrap_or(false);
130
131    match db::notification::list_user_notifications(
132        &pool,
133        user_id,
134        page,
135        per_page,
136        include_read,
137    ).await {
138        Ok(notifications) => Ok(Json(json!({
139            "notifications": notifications,
140            "pagination": {
141                "page": page,
142                "per_page": per_page
143            }
144        }))),
145        Err(e) => {
146            log::error!("Failed to fetch user notifications: {}", e);
147            Err((
148                Status::InternalServerError,
149                Json(json!({
150                    "error": "Database error",
151                    "message": "Failed to fetch user notifications"
152                }))
153            ))
154        }
155    }
156}
157
158/// Count unread notifications for a user (for badges)
159#[get("/platform/<platform_id>/notifications/user/count/<user_id>")]
160pub async fn count_unread_user_notifications(
161    platform_id: i64,
162    user_id: i64,
163    user: User, // For authentication
164    db_manager: &State<Arc<DatabaseManager>>,
165) -> Result<Json<Value>, (Status, Json<Value>)> {
166    // Get platform information
167    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
168        Ok(platform) => platform,
169        Err(_) => {
170            return Err((
171                Status::NotFound,
172                Json(json!({
173                    "error": "Platform not found",
174                    "message": format!("Platform with ID {} does not exist", platform_id)
175                }))
176            ));
177        }
178    };
179
180    // Get platform-specific database pool
181    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
182        Ok(pool) => pool,
183        Err(_) => {
184            return Err((
185                Status::InternalServerError,
186                Json(json!({
187                    "error": "Database error",
188                    "message": "Failed to connect to platform database"
189                }))
190            ));
191        }
192    };
193
194    // Authorization - only allow users to see their own count
195    // or administrators to see others' counts
196    if user.id != user_id {
197        return Err((
198            Status::Forbidden,
199            Json(json!({
200                "error": "Forbidden",
201                "message": "You do not have permission to view this user's notification count"
202            }))
203        ));
204    }
205
206    match db::notification::count_unread_user_notifications(
207        &pool,
208        user_id,
209    ).await {
210        Ok(count) => Ok(Json(json!({ "unread_count": count }))),
211        Err(e) => {
212            log::error!("Failed to count unread notifications: {}", e);
213            Err((
214                Status::InternalServerError,
215                Json(json!({
216                    "error": "Database error",
217                    "message": "Failed to count unread notifications"
218                }))
219            ))
220        }
221    }
222}
223
224/// Get a specific notification by ID
225#[get("/platform/<platform_id>/notifications/<id>")]
226pub async fn get_user_notification_by_id(
227    platform_id: i64,
228    id: i64,
229    user: User, // For authentication
230    db_manager: &State<Arc<DatabaseManager>>,
231) -> Result<Json<Value>, (Status, Json<Value>)> {
232    // Get platform information
233    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
234        Ok(platform) => platform,
235        Err(_) => {
236            return Err((
237                Status::NotFound,
238                Json(json!({
239                    "error": "Platform not found",
240                    "message": format!("Platform with ID {} does not exist", platform_id)
241                }))
242            ));
243        }
244    };
245
246    // Get platform-specific database pool
247    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
248        Ok(pool) => pool,
249        Err(_) => {
250            return Err((
251                Status::InternalServerError,
252                Json(json!({
253                    "error": "Database error",
254                    "message": "Failed to connect to platform database"
255                }))
256            ));
257        }
258    };
259
260    let notification = match db::notification::get_user_notification_by_id(
261        &pool,
262        id,
263    ).await {
264        Ok(notification) => notification,
265        Err(e) => {
266            log::error!("Failed to fetch notification: {}", e);
267            if e.to_string().contains("no rows") {
268                return Err((
269                    Status::NotFound,
270                    Json(json!({
271                        "error": "Not found",
272                        "message": format!("Notification with ID {} does not exist", id)
273                    }))
274                ));
275            } else {
276                return Err((
277                    Status::InternalServerError,
278                    Json(json!({
279                        "error": "Database error",
280                        "message": "Failed to fetch notification"
281                    }))
282                ));
283            }
284        }
285    };
286
287    // Authorization - only allow users to see their own notifications
288    // or administrators to see others' notifications
289    if notification.user_id != user.id {
290        return Err((
291            Status::Forbidden,
292            Json(json!({
293                "error": "Forbidden",
294                "message": "You do not have permission to view this notification"
295            }))
296        ));
297    }
298
299    Ok(Json(json!({ "notification": notification })))
300}
301
302/// Create a new notification for a user
303#[post("/platform/<platform_id>/notifications/user", format = "json", data = "<notification_data>")]
304pub async fn create_user_notification(
305    platform_id: i64,
306    notification_data: Json<CreateUserNotificationRequest>,
307    user: User, // For authentication
308    db_manager: &State<Arc<DatabaseManager>>,
309) -> Result<Json<Value>, (Status, Json<Value>)> {
310    // Get platform information
311    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
312        Ok(platform) => platform,
313        Err(_) => {
314            return Err((
315                Status::NotFound,
316                Json(json!({
317                    "error": "Platform not found",
318                    "message": format!("Platform with ID {} does not exist", platform_id)
319                }))
320            ));
321        }
322    };
323
324    // Get platform-specific database pool
325    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
326        Ok(pool) => pool,
327        Err(_) => {
328            return Err((
329                Status::InternalServerError,
330                Json(json!({
331                    "error": "Database error",
332                    "message": "Failed to connect to platform database"
333                }))
334            ));
335        }
336    };
337
338    // Only administrators and certain roles can create notifications
339    // if !user.roles.contains(&"admin".to_string()) && !user.roles.contains(&"notifier".to_string()) {
340    //     return Err((
341    //         Status::Forbidden,
342    //         Json(json!({
343    //             "error": "Forbidden",
344    //             "message": "You do not have permission to create notifications"
345    //         }))
346    //     ));
347    // }
348
349    let data = notification_data.into_inner();
350    
351    // Target user ID would normally come from the request
352    // For this example, we're using the authenticated user's ID
353    let target_user_id = user.id;
354
355    match db::notification::create_user_notification(
356        &pool,
357        target_user_id,
358        &data.message,
359        &data.notification_type,
360        data.org_id,
361        data.app_id,
362        data.importance.as_deref(),
363        data.action_url.as_deref(),
364        data.action_label.as_deref(),
365        data.expires_at,
366    ).await {
367        Ok(notification) => Ok(Json(json!({
368            "message": "Notification created successfully",
369            "notification": notification
370        }))),
371        Err(e) => {
372            log::error!("Failed to create notification: {}", e);
373            Err((
374                Status::InternalServerError,
375                Json(json!({
376                    "error": "Database error",
377                    "message": "Failed to create notification"
378                }))
379            ))
380        }
381    }
382}
383
384/// Mark a notification as read
385#[put("/platform/<platform_id>/notifications/<id>/read")]
386pub async fn mark_user_notification_as_read(
387    platform_id: i64,
388    id: i64,
389    user: User, // For authentication
390    db_manager: &State<Arc<DatabaseManager>>,
391) -> Result<Json<Value>, (Status, Json<Value>)> {
392    // Get platform information
393    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
394        Ok(platform) => platform,
395        Err(_) => {
396            return Err((
397                Status::NotFound,
398                Json(json!({
399                    "error": "Platform not found",
400                    "message": format!("Platform with ID {} does not exist", platform_id)
401                }))
402            ));
403        }
404    };
405
406    // Get platform-specific database pool
407    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
408        Ok(pool) => pool,
409        Err(_) => {
410            return Err((
411                Status::InternalServerError,
412                Json(json!({
413                    "error": "Database error",
414                    "message": "Failed to connect to platform database"
415                }))
416            ));
417        }
418    };
419
420    // First, get the notification to check ownership
421    let notification = match db::notification::get_user_notification_by_id(
422        &pool,
423        id,
424    ).await {
425        Ok(notification) => notification,
426        Err(e) => {
427            log::error!("Failed to fetch notification: {}", e);
428            if e.to_string().contains("no rows") {
429                return Err((
430                    Status::NotFound,
431                    Json(json!({
432                        "error": "Not found",
433                        "message": format!("Notification with ID {} does not exist", id)
434                    }))
435                ));
436            } else {
437                return Err((
438                    Status::InternalServerError,
439                    Json(json!({
440                        "error": "Database error",
441                        "message": "Failed to fetch notification"
442                    }))
443                ));
444            }
445        }
446    };
447
448    // Authorization - only allow users to mark their own notifications as read
449    // or administrators to mark others' notifications
450    if notification.user_id != user.id {
451        return Err((
452            Status::Forbidden,
453            Json(json!({
454                "error": "Forbidden",
455                "message": "You do not have permission to mark this notification as read"
456            }))
457        ));
458    }
459
460    match db::notification::mark_user_notification_as_read(
461        &pool,
462        id,
463    ).await {
464        Ok(updated_notification) => Ok(Json(json!({
465            "message": "Notification marked as read",
466            "notification": updated_notification
467        }))),
468        Err(e) => {
469            log::error!("Failed to mark notification as read: {}", e);
470            Err((
471                Status::InternalServerError,
472                Json(json!({
473                    "error": "Database error",
474                    "message": "Failed to mark notification as read"
475                }))
476            ))
477        }
478    }
479}
480
481/// Mark all notifications for a user as read
482#[put("/platform/<platform_id>/notifications/user/<user_id>/read-all")]
483pub async fn mark_all_user_notifications_as_read(
484    platform_id: i64,
485    user_id: i64,
486    user: User, // For authentication
487    db_manager: &State<Arc<DatabaseManager>>,
488) -> Result<Json<Value>, (Status, Json<Value>)> {
489    // Get platform information
490    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
491        Ok(platform) => platform,
492        Err(_) => {
493            return Err((
494                Status::NotFound,
495                Json(json!({
496                    "error": "Platform not found",
497                    "message": format!("Platform with ID {} does not exist", platform_id)
498                }))
499            ));
500        }
501    };
502
503    // Get platform-specific database pool
504    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
505        Ok(pool) => pool,
506        Err(_) => {
507            return Err((
508                Status::InternalServerError,
509                Json(json!({
510                    "error": "Database error",
511                    "message": "Failed to connect to platform database"
512                }))
513            ));
514        }
515    };
516
517    // Authorization - only allow users to mark their own notifications as read
518    // or administrators to mark others' notifications
519    if user.id != user_id {
520        return Err((
521            Status::Forbidden,
522            Json(json!({
523                "error": "Forbidden",
524                "message": "You do not have permission to mark this user's notifications as read"
525            }))
526        ));
527    }
528
529    match db::notification::mark_all_user_notifications_as_read(
530        &pool,
531        user_id,
532    ).await {
533        Ok(_) => Ok(Json(json!({
534            "message": "All notifications marked as read",
535        }))),
536        Err(e) => {
537            log::error!("Failed to mark all notifications as read: {}", e);
538            Err((
539                Status::InternalServerError,
540                Json(json!({
541                    "error": "Database error",
542                    "message": "Failed to mark all notifications as read"
543                }))
544            ))
545        }
546    }
547}
548
549/// Delete a notification
550#[delete("/platform/<platform_id>/notifications/<id>")]
551pub async fn delete_user_notification(
552    platform_id: i64,
553    id: i64,
554    user: User, // For authentication
555    db_manager: &State<Arc<DatabaseManager>>,
556) -> Result<Json<Value>, (Status, Json<Value>)> {
557    // Get platform information
558    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
559        Ok(platform) => platform,
560        Err(_) => {
561            return Err((
562                Status::NotFound,
563                Json(json!({
564                    "error": "Platform not found",
565                    "message": format!("Platform with ID {} does not exist", platform_id)
566                }))
567            ));
568        }
569    };
570
571    // Get platform-specific database pool
572    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
573        Ok(pool) => pool,
574        Err(_) => {
575            return Err((
576                Status::InternalServerError,
577                Json(json!({
578                    "error": "Database error",
579                    "message": "Failed to connect to platform database"
580                }))
581            ));
582        }
583    };
584
585    // First, get the notification to check ownership
586    let notification = match db::notification::get_user_notification_by_id(
587        &pool,
588        id,
589    ).await {
590        Ok(notification) => notification,
591        Err(e) => {
592            log::error!("Failed to fetch notification: {}", e);
593            if e.to_string().contains("no rows") {
594                return Err((
595                    Status::NotFound,
596                    Json(json!({
597                        "error": "Not found",
598                        "message": format!("Notification with ID {} does not exist", id)
599                    }))
600                ));
601            } else {
602                return Err((
603                    Status::InternalServerError,
604                    Json(json!({
605                        "error": "Database error",
606                        "message": "Failed to fetch notification"
607                    }))
608                ));
609            }
610        }
611    };
612
613    // Authorization - only allow users to delete their own notifications
614    // or administrators to delete others' notifications
615    if notification.user_id != user.id {
616        return Err((
617            Status::Forbidden,
618            Json(json!({
619                "error": "Forbidden",
620                "message": "You do not have permission to delete this notification"
621            }))
622        ));
623    }
624
625    match db::notification::delete_user_notification(
626        &pool,
627        id,
628    ).await {
629        Ok(_) => Ok(Json(json!({
630            "message": "Notification deleted successfully",
631        }))),
632        Err(e) => {
633            log::error!("Failed to delete notification: {}", e);
634            Err((
635                Status::InternalServerError,
636                Json(json!({
637                    "error": "Database error",
638                    "message": "Failed to delete notification"
639                }))
640            ))
641        }
642    }
643}
644
645/// Delete all read notifications for a user
646#[delete("/platform/<platform_id>/notifications/user/<user_id>/read")]
647pub async fn delete_read_user_notifications(
648    platform_id: i64,
649    user_id: i64,
650    user: User, // For authentication
651    db_manager: &State<Arc<DatabaseManager>>,
652) -> Result<Json<Value>, (Status, Json<Value>)> {
653    // Get platform information
654    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
655        Ok(platform) => platform,
656        Err(_) => {
657            return Err((
658                Status::NotFound,
659                Json(json!({
660                    "error": "Platform not found",
661                    "message": format!("Platform with ID {} does not exist", platform_id)
662                }))
663            ));
664        }
665    };
666
667    // Get platform-specific database pool
668    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
669        Ok(pool) => pool,
670        Err(_) => {
671            return Err((
672                Status::InternalServerError,
673                Json(json!({
674                    "error": "Database error",
675                    "message": "Failed to connect to platform database"
676                }))
677            ));
678        }
679    };
680
681    // Authorization - only allow users to delete their own notifications
682    // or administrators to delete others' notifications
683    if user.id != user_id {
684        return Err((
685            Status::Forbidden,
686            Json(json!({
687                "error": "Forbidden",
688                "message": "You do not have permission to delete this user's notifications"
689            }))
690        ));
691    }
692
693    match db::notification::delete_read_user_notifications(
694        &pool,
695        user_id,
696    ).await {
697        Ok(count) => Ok(Json(json!({
698            "message": "Read notifications deleted successfully",
699            "count": count
700        }))),
701        Err(e) => {
702            log::error!("Failed to delete read notifications: {}", e);
703            Err((
704                Status::InternalServerError,
705                Json(json!({
706                    "error": "Database error",
707                    "message": "Failed to delete read notifications"
708                }))
709            ))
710        }
711    }
712}
713
714/// Get a paginated list of role notifications
715#[get("/platform/<platform_id>/notifications/role/<role_id>?<page>&<per_page>")]
716pub async fn list_role_notifications(
717    platform_id: i64,
718    role_id: i64,
719    page: Option<i64>,
720    per_page: Option<i64>,
721    user: User, // For authentication
722    db_manager: &State<Arc<DatabaseManager>>,
723) -> Result<Json<Value>, (Status, Json<Value>)> {
724    // Get platform information
725    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
726        Ok(platform) => platform,
727        Err(_) => {
728            return Err((
729                Status::NotFound,
730                Json(json!({
731                    "error": "Platform not found",
732                    "message": format!("Platform with ID {} does not exist", platform_id)
733                }))
734            ));
735        }
736    };
737
738    // Get platform-specific database pool
739    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
740        Ok(pool) => pool,
741        Err(_) => {
742            return Err((
743                Status::InternalServerError,
744                Json(json!({
745                    "error": "Database error",
746                    "message": "Failed to connect to platform database"
747                }))
748            ));
749        }
750    };
751
752    // Authorization - only users with the role or administrators can view role notifications
753    // This would require a check against user roles from your auth system
754    // if !user.roles.contains(&"admin".to_string()) {
755    //     // In a real implementation, we'd check if the user has the specific role
756    //     // For this example, we'll use a simplified check
757    //     return Err((
758    //         Status::Forbidden,
759    //         Json(json!({
760    //             "error": "Forbidden",
761    //             "message": "You do not have permission to view notifications for this role"
762    //         }))
763    //     ));
764    // }
765
766    // Default pagination parameters
767    let page = page.unwrap_or(0);
768    let per_page = per_page.unwrap_or(20);
769
770    match db::notification::list_role_notifications(
771        &pool,
772        role_id,
773        page,
774        per_page,
775    ).await {
776        Ok(notifications) => Ok(Json(json!({
777            "notifications": notifications,
778            "pagination": {
779                "page": page,
780                "per_page": per_page
781            }
782        }))),
783        Err(e) => {
784            log::error!("Failed to fetch role notifications: {}", e);
785            Err((
786                Status::InternalServerError,
787                Json(json!({
788                    "error": "Database error",
789                    "message": "Failed to fetch role notifications"
790                }))
791            ))
792        }
793    }
794}
795
796/// Create a new notification for a role
797#[post("/platform/<platform_id>/notifications/role", format = "json", data = "<notification_data>")]
798pub async fn create_role_notification(
799    platform_id: i64,
800    notification_data: Json<CreateRoleNotificationRequest>,
801    user: User, // For authentication
802    db_manager: &State<Arc<DatabaseManager>>,
803) -> Result<Json<Value>, (Status, Json<Value>)> {
804    // Get platform information
805    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
806        Ok(platform) => platform,
807        Err(_) => {
808            return Err((
809                Status::NotFound,
810                Json(json!({
811                    "error": "Platform not found",
812                    "message": format!("Platform with ID {} does not exist", platform_id)
813                }))
814            ));
815        }
816    };
817
818    // Get platform-specific database pool
819    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
820        Ok(pool) => pool,
821        Err(_) => {
822            return Err((
823                Status::InternalServerError,
824                Json(json!({
825                    "error": "Database error",
826                    "message": "Failed to connect to platform database"
827                }))
828            ));
829        }
830    };
831
832    // Only administrators and certain roles can create notifications
833    // if !user.roles.contains(&"admin".to_string()) && !user.roles.contains(&"notifier".to_string()) {
834    //     return Err((
835    //         Status::Forbidden,
836    //         Json(json!({
837    //             "error": "Forbidden",
838    //             "message": "You do not have permission to create role notifications"
839    //         }))
840    //     ));
841    // }
842
843    let data = notification_data.into_inner();
844
845    match db::notification::create_role_notification(
846        &pool,
847        data.role_id,
848        &data.message,
849        &data.notification_type,
850        data.org_id,
851        data.app_id,
852        data.importance.as_deref(),
853        data.action_url.as_deref(),
854        data.action_label.as_deref(),
855        data.expires_at,
856    ).await {
857        Ok(notification) => Ok(Json(json!({
858            "message": "Role notification created successfully",
859            "notification": notification
860        }))),
861        Err(e) => {
862            log::error!("Failed to create role notification: {}", e);
863            Err((
864                Status::InternalServerError,
865                Json(json!({
866                    "error": "Database error",
867                    "message": "Failed to create role notification"
868                }))
869            ))
870        }
871    }
872}
873
874/// Acknowledge a notification
875#[post("/platform/<platform_id>/notifications/acknowledge", format = "json", data = "<ack_data>")]
876pub async fn acknowledge_notification(
877    platform_id: i64,
878    ack_data: Json<AcknowledgeNotificationRequest>,
879    user: User, // For authentication
880    db_manager: &State<Arc<DatabaseManager>>,
881) -> Result<Json<Value>, (Status, Json<Value>)> {
882    // Get platform information
883    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
884        Ok(platform) => platform,
885        Err(_) => {
886            return Err((
887                Status::NotFound,
888                Json(json!({
889                    "error": "Platform not found",
890                    "message": format!("Platform with ID {} does not exist", platform_id)
891                }))
892            ));
893        }
894    };
895
896    // Get platform-specific database pool
897    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
898        Ok(pool) => pool,
899        Err(_) => {
900            return Err((
901                Status::InternalServerError,
902                Json(json!({
903                    "error": "Database error",
904                    "message": "Failed to connect to platform database"
905                }))
906            ));
907        }
908    };
909
910    let data = ack_data.into_inner();
911
912    // Validate input - either notification_id or role_notification_id must be provided
913    if data.notification_id.is_none() && data.role_notification_id.is_none() {
914        return Err((
915            Status::BadRequest,
916            Json(json!({
917                "error": "Bad request",
918                "message": "Either notification_id or role_notification_id must be provided"
919            }))
920        ));
921    }
922    if data.notification_id.is_some() && data.role_notification_id.is_some() {
923        return Err((
924            Status::BadRequest,
925            Json(json!({
926                "error": "Bad request",
927                "message": "Only one of notification_id or role_notification_id should be provided"
928            }))
929        ));
930    }
931
932    // If it's a user notification, verify ownership
933    if let Some(notification_id) = data.notification_id {
934        let notification = match db::notification::get_user_notification_by_id(
935            &pool,
936            notification_id,
937        ).await {
938            Ok(notification) => notification,
939            Err(e) => {
940                log::error!("Failed to fetch notification: {}", e);
941                if e.to_string().contains("no rows") {
942                    return Err((
943                        Status::NotFound,
944                        Json(json!({
945                            "error": "Not found",
946                            "message": format!("Notification with ID {} does not exist", notification_id)
947                        }))
948                    ));
949                } else {
950                    return Err((
951                        Status::InternalServerError,
952                        Json(json!({
953                            "error": "Database error",
954                            "message": "Failed to fetch notification"
955                        }))
956                    ));
957                }
958            }
959        };
960
961        // Authorization - only allow users to acknowledge their own notifications
962        // or administrators to acknowledge others' notifications
963        if notification.user_id != user.id {
964            return Err((
965                Status::Forbidden,
966                Json(json!({
967                    "error": "Forbidden",
968                    "message": "You do not have permission to acknowledge this notification"
969                }))
970            ));
971        }
972    }
973
974    match db::notification::create_notification_acknowledgment(
975        &pool,
976        user.id,
977        data.notification_id,
978        data.role_notification_id,
979    ).await {
980        Ok(acknowledgment) => Ok(Json(json!({
981            "message": "Notification acknowledged successfully",
982            "acknowledgment": acknowledgment
983        }))),
984        Err(e) => {
985            log::error!("Failed to acknowledge notification: {}", e);
986            Err((
987                Status::InternalServerError,
988                Json(json!({
989                    "error": "Database error",
990                    "message": "Failed to acknowledge notification"
991                }))
992            ))
993        }
994    }
995}
996
997/// Get all notifications for a user including role notifications
998#[get("/platform/<platform_id>/notifications/user/<user_id>/all?<page>&<per_page>")]
999pub async fn get_all_user_notifications_with_count(
1000    platform_id: i64,
1001    user_id: i64,
1002    page: Option<i64>,
1003    per_page: Option<i64>,
1004    user: User, // For authentication
1005    db_manager: &State<Arc<DatabaseManager>>,
1006) -> Result<Json<Value>, (Status, Json<Value>)> {
1007    // Get platform information
1008    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
1009        Ok(platform) => platform,
1010        Err(_) => {
1011            return Err((
1012                Status::NotFound,
1013                Json(json!({
1014                    "error": "Platform not found",
1015                    "message": format!("Platform with ID {} does not exist", platform_id)
1016                }))
1017            ));
1018        }
1019    };
1020
1021    // Get platform-specific database pool
1022    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
1023        Ok(pool) => pool,
1024        Err(_) => {
1025            return Err((
1026                Status::InternalServerError,
1027                Json(json!({
1028                    "error": "Database error",
1029                    "message": "Failed to connect to platform database"
1030                }))
1031            ));
1032        }
1033    };
1034
1035    // Authorization - only allow users to see their own notifications
1036    // or administrators to see others' notifications
1037    if user.id != user_id {
1038        return Err((
1039            Status::Forbidden,
1040            Json(json!({
1041                "error": "Forbidden",
1042                "message": "You do not have permission to view this user's notifications"
1043            }))
1044        ));
1045    }
1046
1047    // Default pagination parameters
1048    let page = page.unwrap_or(0);
1049    let per_page = per_page.unwrap_or(20);
1050
1051    match db::notification::get_all_user_notifications_with_count(
1052        &pool,
1053        user_id,
1054        page,
1055        per_page,
1056    ).await {
1057        Ok(notifications_with_count) => Ok(Json(json!(notifications_with_count))),
1058        Err(e) => {
1059            log::error!("Failed to fetch notifications with count: {}", e);
1060            Err((
1061                Status::InternalServerError,
1062                Json(json!({
1063                    "error": "Database error",
1064                    "message": "Failed to fetch notifications with count"
1065                }))
1066            ))
1067        }
1068    }
1069}