@@ -28,99 +28,86 @@ use actix_web::{
2828 HttpRequest , HttpResponse , Responder ,
2929} ;
3030use http:: StatusCode ;
31- use serde_json:: { Error as SerdeError , Map } ;
31+ use serde_json:: Error as SerdeError ;
3232
33- pub async fn list ( ) -> Result < impl Responder , DashboardError > {
33+ pub async fn list_dashboards ( ) -> Result < impl Responder , DashboardError > {
3434 let dashboards = DASHBOARDS . list_dashboards ( ) . await ;
35- //dashboards list should contain the title, author and modified date
36- let dashboards: Vec < Map < String , serde_json:: Value > > = dashboards
35+ let dashboard_summaries = dashboards
3736 . iter ( )
38- . map ( |dashboard| {
39- let mut map = Map :: new ( ) ;
40- map. insert (
41- "title" . to_string ( ) ,
42- serde_json:: Value :: String ( dashboard. title . clone ( ) ) ,
43- ) ;
44- if let Some ( author) = & dashboard. author {
45- map. insert (
46- "author" . to_string ( ) ,
47- serde_json:: Value :: String ( author. to_string ( ) ) ,
48- ) ;
49- }
50- if let Some ( modified) = & dashboard. modified {
51- map. insert (
52- "modified" . to_string ( ) ,
53- serde_json:: Value :: String ( modified. to_string ( ) ) ,
54- ) ;
55- }
56- if let Some ( dashboard_id) = & dashboard. dashboard_id {
57- map. insert (
58- "dashboard_id" . to_string ( ) ,
59- serde_json:: Value :: String ( dashboard_id. to_string ( ) ) ,
60- ) ;
61- }
62- map
63- } )
64- . collect ( ) ;
65- Ok ( ( web:: Json ( dashboards) , StatusCode :: OK ) )
37+ . map ( |dashboard| dashboard. to_summary ( ) )
38+ . collect :: < Vec < _ > > ( ) ;
39+
40+ Ok ( ( web:: Json ( dashboard_summaries) , StatusCode :: OK ) )
6641}
6742
68- pub async fn get ( dashboard_id : Path < String > ) -> Result < impl Responder , DashboardError > {
43+ pub async fn get_dashboard ( dashboard_id : Path < String > ) -> Result < impl Responder , DashboardError > {
6944 let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
7045
71- if let Some ( dashboard) = DASHBOARDS . get_dashboard ( dashboard_id) . await {
72- return Ok ( ( web:: Json ( dashboard) , StatusCode :: OK ) ) ;
73- }
46+ let dashboard = DASHBOARDS
47+ . get_dashboard ( dashboard_id)
48+ . await
49+ . ok_or_else ( || DashboardError :: Metadata ( "Dashboard does not exist" ) ) ?;
7450
75- Err ( DashboardError :: Metadata ( "Dashboard does not exist" ) )
51+ Ok ( ( web :: Json ( dashboard ) , StatusCode :: OK ) )
7652}
7753
78- pub async fn post (
54+ pub async fn create_dashboard (
7955 req : HttpRequest ,
8056 Json ( mut dashboard) : Json < Dashboard > ,
8157) -> Result < impl Responder , DashboardError > {
8258 if dashboard. title . is_empty ( ) {
8359 return Err ( DashboardError :: Metadata ( "Title must be provided" ) ) ;
8460 }
85- let mut user_id = get_user_from_request ( & req) ?;
86- user_id = get_hash ( & user_id) ;
87- dashboard. author = Some ( user_id. clone ( ) ) ;
61+
62+ let user_id = get_hash ( & get_user_from_request ( & req) ?) ;
8863
8964 DASHBOARDS . create ( & user_id, & mut dashboard) . await ?;
9065 Ok ( ( web:: Json ( dashboard) , StatusCode :: OK ) )
9166}
9267
93- pub async fn update (
68+ pub async fn update_dashboard (
9469 req : HttpRequest ,
9570 dashboard_id : Path < String > ,
9671 Json ( mut dashboard) : Json < Dashboard > ,
9772) -> Result < impl Responder , DashboardError > {
98- let mut user_id = get_user_from_request ( & req) ?;
99- user_id = get_hash ( & user_id) ;
73+ let user_id = get_hash ( & get_user_from_request ( & req) ?) ;
10074 let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
10175
102- for tile in dashboard. tiles . as_ref ( ) . unwrap_or ( & Vec :: new ( ) ) {
103- if tile. tile_id . is_nil ( ) {
104- return Err ( DashboardError :: Metadata (
105- "Tile ID must be provided by the client" ,
106- ) ) ;
76+ // Validate all tiles have valid IDs
77+ if let Some ( tiles) = & dashboard. tiles {
78+ if tiles. iter ( ) . any ( |tile| tile. tile_id . is_nil ( ) ) {
79+ return Err ( DashboardError :: Metadata ( "Tile ID must be provided" ) ) ;
80+ }
81+ }
82+
83+ // Check if tile_id are unique
84+ if let Some ( tiles) = & dashboard. tiles {
85+ let unique_tiles: Vec < _ > = tiles
86+ . iter ( )
87+ . map ( |tile| tile. tile_id )
88+ . collect :: < std:: collections:: HashSet < _ > > ( )
89+ . into_iter ( )
90+ . collect ( ) ;
91+
92+ if unique_tiles. len ( ) != tiles. len ( ) {
93+ return Err ( DashboardError :: Metadata ( "Tile IDs must be unique" ) ) ;
10794 }
10895 }
109- dashboard. author = Some ( user_id. clone ( ) ) ;
11096
11197 DASHBOARDS
11298 . update ( & user_id, dashboard_id, & mut dashboard)
11399 . await ?;
100+
114101 Ok ( ( web:: Json ( dashboard) , StatusCode :: OK ) )
115102}
116103
117- pub async fn delete (
104+ pub async fn delete_dashboard (
118105 req : HttpRequest ,
119106 dashboard_id : Path < String > ,
120107) -> Result < HttpResponse , DashboardError > {
121- let mut user_id = get_user_from_request ( & req) ?;
122- user_id = get_hash ( & user_id) ;
108+ let user_id = get_hash ( & get_user_from_request ( & req) ?) ;
123109 let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
110+
124111 DASHBOARDS . delete_dashboard ( & user_id, dashboard_id) . await ?;
125112
126113 Ok ( HttpResponse :: Ok ( ) . finish ( ) )
@@ -131,22 +118,26 @@ pub async fn add_tile(
131118 dashboard_id : Path < String > ,
132119 Json ( tile) : Json < Tile > ,
133120) -> Result < impl Responder , DashboardError > {
134- let mut user_id = get_user_from_request ( & req) ?;
135- user_id = get_hash ( & user_id) ;
136- let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
137-
138121 if tile. tile_id . is_nil ( ) {
139- return Err ( DashboardError :: Metadata (
140- "Tile ID must be provided by the client" ,
141- ) ) ;
122+ return Err ( DashboardError :: Metadata ( "Tile ID must be provided" ) ) ;
142123 }
143124
125+ let user_id = get_hash ( & get_user_from_request ( & req) ?) ;
126+ let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
127+
144128 let mut dashboard = DASHBOARDS
145129 . get_dashboard_by_user ( dashboard_id, & user_id)
146130 . await
147131 . ok_or ( DashboardError :: Unauthorized ) ?;
132+
148133 let tiles = dashboard. tiles . get_or_insert_with ( Vec :: new) ;
149- tiles. push ( tile. clone ( ) ) ;
134+
135+ // check if the tile already exists
136+ if tiles. iter ( ) . any ( |t| t. tile_id == tile. tile_id ) {
137+ return Err ( DashboardError :: Metadata ( "Tile already exists" ) ) ;
138+ }
139+ tiles. push ( tile) ;
140+
150141 DASHBOARDS
151142 . update ( & user_id, dashboard_id, & mut dashboard)
152143 . await ?;
@@ -166,7 +157,7 @@ pub enum DashboardError {
166157 UserDoesNotExist ( #[ from] RBACError ) ,
167158 #[ error( "Error: {0}" ) ]
168159 Custom ( String ) ,
169- #[ error( "Unauthorized to access resource " ) ]
160+ #[ error( "Dashboard does not exist or is not accessible " ) ]
170161 Unauthorized ,
171162}
172163
0 commit comments