@@ -45,7 +45,7 @@ pub fn self_user_router() -> Router<Body, ApiError> {
45
45
. delete ( "/invites/:scope" , util:: auth ( decline_invite_handler) )
46
46
. get ( "/tokens" , util:: auth ( util:: json ( list_tokens) ) )
47
47
. post ( "/tokens" , util:: auth ( util:: json ( create_token) ) )
48
- . delete ( "/tokens/:id" , util:: auth ( util :: json ( delete_token) ) )
48
+ . delete ( "/tokens/:id" , util:: auth ( delete_token) )
49
49
. build ( )
50
50
. unwrap ( )
51
51
}
@@ -257,7 +257,7 @@ async fn create_token(
257
257
}
258
258
259
259
#[ instrument( "DELETE /api/user/tokens/:id" ) ]
260
- async fn delete_token ( req : Request < Body > ) -> Result < ( ) , ApiError > {
260
+ async fn delete_token ( req : Request < Body > ) -> Result < Response < Body > , ApiError > {
261
261
let id = req. param_uuid ( "id" ) ?;
262
262
263
263
let iam = req. iam ( ) ;
@@ -269,5 +269,161 @@ async fn delete_token(req: Request<Body>) -> Result<(), ApiError> {
269
269
return Err ( ApiError :: TokenNotFound ) ;
270
270
} ;
271
271
272
- Ok ( ( ) )
272
+ let resp = Response :: builder ( )
273
+ . status ( hyper:: StatusCode :: NO_CONTENT )
274
+ . body ( Body :: empty ( ) )
275
+ . unwrap ( ) ;
276
+ Ok ( resp)
277
+ }
278
+
279
+ #[ cfg( test) ]
280
+ mod tests {
281
+ use hyper:: StatusCode ;
282
+ use serde_json:: json;
283
+
284
+ use crate :: api:: ApiCreatedToken ;
285
+ use crate :: api:: ApiFullUser ;
286
+ use crate :: api:: ApiToken ;
287
+ use crate :: api:: ApiTokenType ;
288
+ use crate :: util:: test:: ApiResultExt ;
289
+ use crate :: util:: test:: TestSetup ;
290
+
291
+ #[ tokio:: test]
292
+ async fn list_tokens ( ) {
293
+ let mut t = TestSetup :: new ( ) . await ;
294
+
295
+ let tokens: Vec < ApiToken > = t
296
+ . http ( )
297
+ . get ( "/api/user/tokens" )
298
+ . call ( )
299
+ . await
300
+ . unwrap ( )
301
+ . expect_ok ( )
302
+ . await ;
303
+
304
+ assert_eq ! ( tokens. len( ) , 1 ) ;
305
+ assert ! (
306
+ matches!( tokens[ 0 ] . r#type, ApiTokenType :: Web ) ,
307
+ "{:?}" ,
308
+ tokens[ 0 ] . r#type
309
+ ) ;
310
+ }
311
+
312
+ #[ tokio:: test]
313
+ async fn create_and_delete_token ( ) {
314
+ let mut t = TestSetup :: new ( ) . await ;
315
+
316
+ let token: ApiCreatedToken = t
317
+ . http ( )
318
+ . post ( "/api/user/tokens" )
319
+ . body_json ( json ! ( {
320
+ "description" : "test token" ,
321
+ "expires_at" : null,
322
+ "permissions" : null
323
+ } ) )
324
+ . call ( )
325
+ . await
326
+ . unwrap ( )
327
+ . expect_ok ( )
328
+ . await ;
329
+
330
+ let secret = token. secret ;
331
+
332
+ let user: ApiFullUser = t
333
+ . http ( )
334
+ . get ( "/api/user" )
335
+ . token ( Some ( & secret) )
336
+ . call ( )
337
+ . await
338
+ . unwrap ( )
339
+ . expect_ok ( )
340
+ . await ;
341
+ assert_eq ! ( user. id, t. user1. user. id) ;
342
+
343
+ let token = token. token ;
344
+ assert_eq ! ( token. description. unwrap( ) , "test token" ) ;
345
+ assert ! (
346
+ matches!( token. r#type, ApiTokenType :: Personal ) ,
347
+ "{:?}" ,
348
+ token. r#type
349
+ ) ;
350
+
351
+ let tokens: Vec < ApiToken > = t
352
+ . http ( )
353
+ . get ( "/api/user/tokens" )
354
+ . call ( )
355
+ . await
356
+ . unwrap ( )
357
+ . expect_ok ( )
358
+ . await ;
359
+ assert_eq ! ( tokens. len( ) , 2 ) ;
360
+ assert ! (
361
+ matches!( tokens[ 0 ] . r#type, ApiTokenType :: Personal ) ,
362
+ "{:?}" ,
363
+ tokens[ 1 ] . r#type
364
+ ) ;
365
+ assert ! (
366
+ matches!( tokens[ 1 ] . r#type, ApiTokenType :: Web ) ,
367
+ "{:?}" ,
368
+ tokens[ 0 ] . r#type
369
+ ) ;
370
+
371
+ // can't create another token with this token
372
+ t. http ( )
373
+ . post ( "/api/user/tokens" )
374
+ . token ( Some ( & secret) )
375
+ . body_json ( json ! ( {
376
+ "description" : "test token" ,
377
+ "expires_at" : null,
378
+ "permissions" : null
379
+ } ) )
380
+ . call ( )
381
+ . await
382
+ . unwrap ( )
383
+ . expect_err_code ( StatusCode :: FORBIDDEN , "credentialNotInteractive" )
384
+ . await ;
385
+
386
+ t. http ( )
387
+ . delete ( & format ! ( "/api/user/tokens/{}" , token. id) )
388
+ . call ( )
389
+ . await
390
+ . unwrap ( )
391
+ . expect_ok_no_content ( )
392
+ . await ;
393
+
394
+ let tokens: Vec < ApiToken > = t
395
+ . http ( )
396
+ . get ( "/api/user/tokens" )
397
+ . call ( )
398
+ . await
399
+ . unwrap ( )
400
+ . expect_ok ( )
401
+ . await ;
402
+
403
+ assert_eq ! ( tokens. len( ) , 1 ) ;
404
+ assert ! (
405
+ matches!( tokens[ 0 ] . r#type, ApiTokenType :: Web ) ,
406
+ "{:?}" ,
407
+ tokens[ 0 ] . r#type
408
+ ) ;
409
+
410
+ // can't delete the token again
411
+ t. http ( )
412
+ . delete ( & format ! ( "/api/user/tokens/{}" , token. id) )
413
+ . call ( )
414
+ . await
415
+ . unwrap ( )
416
+ . expect_err_code ( StatusCode :: NOT_FOUND , "tokenNotFound" )
417
+ . await ;
418
+
419
+ // can't use the token anymore
420
+ t. http ( )
421
+ . get ( "/api/user" )
422
+ . token ( Some ( & secret) )
423
+ . call ( )
424
+ . await
425
+ . unwrap ( )
426
+ . expect_err_code ( StatusCode :: UNAUTHORIZED , "invalidBearerToken" )
427
+ . await ;
428
+ }
273
429
}
0 commit comments