19
19
use crate :: {
20
20
handlers:: http:: rbac:: RBACError ,
21
21
storage:: ObjectStorageError ,
22
- users:: dashboards:: { Dashboard , Tile , DASHBOARDS } ,
22
+ users:: dashboards:: { validate_dashboard_id , Dashboard , Tile , DASHBOARDS } ,
23
23
utils:: { get_hash, get_user_from_request} ,
24
24
} ;
25
25
use actix_web:: {
@@ -29,7 +29,6 @@ use actix_web::{
29
29
} ;
30
30
use http:: StatusCode ;
31
31
use serde_json:: { Error as SerdeError , Map } ;
32
- use ulid:: Ulid ;
33
32
34
33
pub async fn list ( ) -> Result < impl Responder , DashboardError > {
35
34
let dashboards = DASHBOARDS . list_dashboards ( ) . await ;
@@ -42,30 +41,32 @@ pub async fn list() -> Result<impl Responder, DashboardError> {
42
41
"title" . to_string ( ) ,
43
42
serde_json:: Value :: String ( dashboard. title . clone ( ) ) ,
44
43
) ;
45
- map. insert (
46
- "author" . to_string ( ) ,
47
- serde_json:: Value :: String ( dashboard. author . as_ref ( ) . unwrap ( ) . clone ( ) ) ,
48
- ) ;
49
- map. insert (
50
- "modified" . to_string ( ) ,
51
- serde_json:: Value :: String ( dashboard. modified . unwrap ( ) . to_string ( ) ) ,
52
- ) ;
53
- map. insert (
54
- "dashboard_id" . to_string ( ) ,
55
- serde_json:: Value :: String ( dashboard. dashboard_id . unwrap ( ) . to_string ( ) ) ,
56
- ) ;
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
+ }
57
62
map
58
63
} )
59
64
. collect ( ) ;
60
65
Ok ( ( web:: Json ( dashboards) , StatusCode :: OK ) )
61
66
}
62
67
63
68
pub async fn get ( dashboard_id : Path < String > ) -> Result < impl Responder , DashboardError > {
64
- let dashboard_id = if let Ok ( dashboard_id) = Ulid :: from_string ( & dashboard_id. into_inner ( ) ) {
65
- dashboard_id
66
- } else {
67
- return Err ( DashboardError :: Metadata ( "Invalid dashboard ID" ) ) ;
68
- } ;
69
+ let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
69
70
70
71
if let Some ( dashboard) = DASHBOARDS . get_dashboard ( dashboard_id) . await {
71
72
return Ok ( ( web:: Json ( dashboard) , StatusCode :: OK ) ) ;
@@ -78,6 +79,9 @@ pub async fn post(
78
79
req : HttpRequest ,
79
80
Json ( mut dashboard) : Json < Dashboard > ,
80
81
) -> Result < impl Responder , DashboardError > {
82
+ if dashboard. title . is_empty ( ) {
83
+ return Err ( DashboardError :: Metadata ( "Title must be provided" ) ) ;
84
+ }
81
85
let mut user_id = get_user_from_request ( & req) ?;
82
86
user_id = get_hash ( & user_id) ;
83
87
dashboard. author = Some ( user_id. clone ( ) ) ;
@@ -93,11 +97,15 @@ pub async fn update(
93
97
) -> Result < impl Responder , DashboardError > {
94
98
let mut user_id = get_user_from_request ( & req) ?;
95
99
user_id = get_hash ( & user_id) ;
96
- let dashboard_id = if let Ok ( dashboard_id) = Ulid :: from_string ( & dashboard_id. into_inner ( ) ) {
97
- dashboard_id
98
- } else {
99
- return Err ( DashboardError :: Metadata ( "Invalid dashboard ID" ) ) ;
100
- } ;
100
+ let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
101
+
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
+ ) ) ;
107
+ }
108
+ }
101
109
dashboard. author = Some ( user_id. clone ( ) ) ;
102
110
103
111
DASHBOARDS
@@ -112,11 +120,7 @@ pub async fn delete(
112
120
) -> Result < HttpResponse , DashboardError > {
113
121
let mut user_id = get_user_from_request ( & req) ?;
114
122
user_id = get_hash ( & user_id) ;
115
- let dashboard_id = if let Ok ( dashboard_id) = Ulid :: from_string ( & dashboard_id. into_inner ( ) ) {
116
- dashboard_id
117
- } else {
118
- return Err ( DashboardError :: Metadata ( "Invalid dashboard ID" ) ) ;
119
- } ;
123
+ let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
120
124
DASHBOARDS . delete_dashboard ( & user_id, dashboard_id) . await ?;
121
125
122
126
Ok ( HttpResponse :: Ok ( ) . finish ( ) )
@@ -129,17 +133,20 @@ pub async fn add_tile(
129
133
) -> Result < impl Responder , DashboardError > {
130
134
let mut user_id = get_user_from_request ( & req) ?;
131
135
user_id = get_hash ( & user_id) ;
132
- let dashboard_id = if let Ok ( dashboard_id) = Ulid :: from_string ( & dashboard_id. into_inner ( ) ) {
133
- dashboard_id
134
- } else {
135
- return Err ( DashboardError :: Metadata ( "Invalid dashboard ID" ) ) ;
136
- } ;
136
+ let dashboard_id = validate_dashboard_id ( dashboard_id. into_inner ( ) ) ?;
137
+
138
+ if tile. tile_id . is_nil ( ) {
139
+ return Err ( DashboardError :: Metadata (
140
+ "Tile ID must be provided by the client" ,
141
+ ) ) ;
142
+ }
137
143
138
144
let mut dashboard = DASHBOARDS
139
145
. get_dashboard_by_user ( dashboard_id, & user_id)
140
146
. await
141
- . ok_or ( DashboardError :: Metadata ( "Dashboard does not exist" ) ) ?;
142
- dashboard. tiles . as_mut ( ) . unwrap ( ) . push ( tile. clone ( ) ) ;
147
+ . ok_or ( DashboardError :: Unauthorized ) ?;
148
+ let tiles = dashboard. tiles . get_or_insert_with ( Vec :: new) ;
149
+ tiles. push ( tile. clone ( ) ) ;
143
150
DASHBOARDS
144
151
. update ( & user_id, dashboard_id, & mut dashboard)
145
152
. await ?;
@@ -159,6 +166,8 @@ pub enum DashboardError {
159
166
UserDoesNotExist ( #[ from] RBACError ) ,
160
167
#[ error( "Error: {0}" ) ]
161
168
Custom ( String ) ,
169
+ #[ error( "Unauthorized to access resource" ) ]
170
+ Unauthorized ,
162
171
}
163
172
164
173
impl actix_web:: ResponseError for DashboardError {
@@ -169,6 +178,7 @@ impl actix_web::ResponseError for DashboardError {
169
178
Self :: Metadata ( _) => StatusCode :: BAD_REQUEST ,
170
179
Self :: UserDoesNotExist ( _) => StatusCode :: NOT_FOUND ,
171
180
Self :: Custom ( _) => StatusCode :: INTERNAL_SERVER_ERROR ,
181
+ Self :: Unauthorized => StatusCode :: UNAUTHORIZED ,
172
182
}
173
183
}
174
184
0 commit comments