@@ -25,6 +25,9 @@ use crate::{
25
25
#[ derive( Debug , thiserror:: Error , OperationIo ) ]
26
26
#[ aide( output_with = "Json<ErrorResponse>" ) ]
27
27
pub enum RouteError {
28
+ #[ error( "A registration token with the same token already exists" ) ]
29
+ Conflict ( mas_data_model:: UserRegistrationToken ) ,
30
+
28
31
#[ error( transparent) ]
29
32
Internal ( Box < dyn std:: error:: Error + Send + Sync + ' static > ) ,
30
33
}
@@ -36,6 +39,7 @@ impl IntoResponse for RouteError {
36
39
let error = ErrorResponse :: from_error ( & self ) ;
37
40
let sentry_event_id = record_error ! ( self , Self :: Internal ( _) ) ;
38
41
let status = match self {
42
+ Self :: Conflict ( _) => StatusCode :: CONFLICT ,
39
43
Self :: Internal ( _) => StatusCode :: INTERNAL_SERVER_ERROR ,
40
44
} ;
41
45
( status, sentry_event_id, Json ( error) ) . into_response ( )
@@ -83,6 +87,12 @@ pub async fn handler(
83
87
. token
84
88
. unwrap_or_else ( || Alphanumeric . sample_string ( & mut rng, 12 ) ) ;
85
89
90
+ // See if we have an existing token with the same token
91
+ let existing_token = repo. user_registration_token ( ) . find_by_token ( & token) . await ?;
92
+ if let Some ( existing_token) = existing_token {
93
+ return Err ( RouteError :: Conflict ( existing_token) ) ;
94
+ }
95
+
86
96
let registration_token = repo
87
97
. user_registration_token ( )
88
98
. add (
@@ -196,4 +206,56 @@ mod tests {
196
206
}
197
207
"# ) ;
198
208
}
209
+
210
+ #[ sqlx:: test( migrator = "mas_storage_pg::MIGRATOR" ) ]
211
+ async fn test_create_conflict ( pool : PgPool ) {
212
+ setup ( ) ;
213
+ let mut state = TestState :: from_pool ( pool) . await . unwrap ( ) ;
214
+ let token = state. token_with_scope ( "urn:mas:admin" ) . await ;
215
+
216
+ let request = Request :: post ( "/api/admin/v1/user-registration-tokens" )
217
+ . bearer ( & token)
218
+ . json ( serde_json:: json!( {
219
+ "token" : "test_token_123" ,
220
+ "usage_limit" : 5
221
+ } ) ) ;
222
+ let response = state. request ( request) . await ;
223
+ response. assert_status ( StatusCode :: CREATED ) ;
224
+
225
+ let body: serde_json:: Value = response. json ( ) ;
226
+
227
+ assert_json_snapshot ! ( body, @r#"
228
+ {
229
+ "data": {
230
+ "type": "user-registration_token",
231
+ "id": "01FSHN9AG0MZAA6S4AF7CTV32E",
232
+ "attributes": {
233
+ "token": "test_token_123",
234
+ "valid": true,
235
+ "usage_limit": 5,
236
+ "times_used": 0,
237
+ "created_at": "2022-01-16T14:40:00Z",
238
+ "last_used_at": null,
239
+ "expires_at": null,
240
+ "revoked_at": null
241
+ },
242
+ "links": {
243
+ "self": "/api/admin/v1/user-registration-tokens/01FSHN9AG0MZAA6S4AF7CTV32E"
244
+ }
245
+ },
246
+ "links": {
247
+ "self": "/api/admin/v1/user-registration-tokens/01FSHN9AG0MZAA6S4AF7CTV32E"
248
+ }
249
+ }
250
+ "# ) ;
251
+
252
+ let request = Request :: post ( "/api/admin/v1/user-registration-tokens" )
253
+ . bearer ( & token)
254
+ . json ( serde_json:: json!( {
255
+ "token" : "test_token_123" ,
256
+ "usage_limit" : 5
257
+ } ) ) ;
258
+ let response = state. request ( request) . await ;
259
+ response. assert_status ( StatusCode :: CONFLICT ) ;
260
+ }
199
261
}
0 commit comments