@@ -14,6 +14,7 @@ use cargo_registry::{
14
14
Emails ,
15
15
} ;
16
16
17
+ use cargo_registry:: models:: token:: { CrateScope , EndpointScope } ;
17
18
use chrono:: { Duration , Utc } ;
18
19
use conduit:: StatusCode ;
19
20
use diesel:: prelude:: * ;
@@ -305,6 +306,108 @@ fn owner_change_via_token() {
305
306
) ;
306
307
}
307
308
309
+ #[ test]
310
+ fn owner_change_via_change_owner_token ( ) {
311
+ let ( app, _, _, token) =
312
+ TestApp :: full ( ) . with_scoped_token ( None , Some ( vec ! [ EndpointScope :: ChangeOwners ] ) ) ;
313
+
314
+ let user2 = app. db_new_user ( "user-2" ) ;
315
+ let user2 = user2. as_model ( ) ;
316
+
317
+ let krate =
318
+ app. db ( |conn| CrateBuilder :: new ( "foo_crate" , token. as_model ( ) . user_id ) . expect_build ( conn) ) ;
319
+
320
+ let url = format ! ( "/api/v1/crates/{}/owners" , krate. name) ;
321
+ let body = json ! ( { "owners" : [ user2. gh_login] } ) ;
322
+ let body = serde_json:: to_vec ( & body) . unwrap ( ) ;
323
+ let response = token. put :: < ( ) > ( & url, & body) ;
324
+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
325
+ assert_eq ! (
326
+ response. into_json( ) ,
327
+ json!( { "ok" : true , "msg" : "user user-2 has been invited to be an owner of crate foo_crate" } )
328
+ ) ;
329
+ }
330
+
331
+ #[ test]
332
+ fn owner_change_via_change_owner_token_with_matching_crate_scope ( ) {
333
+ let crate_scopes = Some ( vec ! [ CrateScope :: try_from( "foo_crate" ) . unwrap( ) ] ) ;
334
+ let endpoint_scopes = Some ( vec ! [ EndpointScope :: ChangeOwners ] ) ;
335
+ let ( app, _, _, token) = TestApp :: full ( ) . with_scoped_token ( crate_scopes, endpoint_scopes) ;
336
+
337
+ let user2 = app. db_new_user ( "user-2" ) ;
338
+ let user2 = user2. as_model ( ) ;
339
+
340
+ let krate =
341
+ app. db ( |conn| CrateBuilder :: new ( "foo_crate" , token. as_model ( ) . user_id ) . expect_build ( conn) ) ;
342
+
343
+ let url = format ! ( "/api/v1/crates/{}/owners" , krate. name) ;
344
+ let body = json ! ( { "owners" : [ user2. gh_login] } ) ;
345
+ let body = serde_json:: to_vec ( & body) . unwrap ( ) ;
346
+ let response = token. put :: < ( ) > ( & url, & body) ;
347
+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
348
+ assert_eq ! (
349
+ response. into_json( ) ,
350
+ json!( { "ok" : true , "msg" : "user user-2 has been invited to be an owner of crate foo_crate" } )
351
+ ) ;
352
+ }
353
+
354
+ #[ test]
355
+ fn owner_change_via_change_owner_token_with_wrong_crate_scope ( ) {
356
+ let crate_scopes = Some ( vec ! [ CrateScope :: try_from( "bar" ) . unwrap( ) ] ) ;
357
+ let endpoint_scopes = Some ( vec ! [ EndpointScope :: ChangeOwners ] ) ;
358
+ let ( app, _, _, token) = TestApp :: full ( ) . with_scoped_token ( crate_scopes, endpoint_scopes) ;
359
+
360
+ let user2 = app. db_new_user ( "user-2" ) ;
361
+ let user2 = user2. as_model ( ) ;
362
+
363
+ let krate =
364
+ app. db ( |conn| CrateBuilder :: new ( "foo_crate" , token. as_model ( ) . user_id ) . expect_build ( conn) ) ;
365
+
366
+ let url = format ! ( "/api/v1/crates/{}/owners" , krate. name) ;
367
+ let body = json ! ( { "owners" : [ user2. gh_login] } ) ;
368
+ let body = serde_json:: to_vec ( & body) . unwrap ( ) ;
369
+ let response = token. put :: < ( ) > ( & url, & body) ;
370
+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
371
+ assert_eq ! (
372
+ response. into_json( ) ,
373
+ json!( { "ok" : true , "msg" : "user user-2 has been invited to be an owner of crate foo_crate" } )
374
+ ) ;
375
+ // TODO this should return "403 Forbidden" once token scopes are implemented for this endpoint
376
+ // assert_eq!(response.status(), StatusCode::FORBIDDEN);
377
+ // assert_eq!(
378
+ // response.into_json(),
379
+ // json!({ "errors": [{ "detail": "must be logged in to perform that action" }] })
380
+ // );
381
+ }
382
+
383
+ #[ test]
384
+ fn owner_change_via_publish_token ( ) {
385
+ let ( app, _, _, token) =
386
+ TestApp :: full ( ) . with_scoped_token ( None , Some ( vec ! [ EndpointScope :: PublishUpdate ] ) ) ;
387
+
388
+ let user2 = app. db_new_user ( "user-2" ) ;
389
+ let user2 = user2. as_model ( ) ;
390
+
391
+ let krate =
392
+ app. db ( |conn| CrateBuilder :: new ( "foo_crate" , token. as_model ( ) . user_id ) . expect_build ( conn) ) ;
393
+
394
+ let url = format ! ( "/api/v1/crates/{}/owners" , krate. name) ;
395
+ let body = json ! ( { "owners" : [ user2. gh_login] } ) ;
396
+ let body = serde_json:: to_vec ( & body) . unwrap ( ) ;
397
+ let response = token. put :: < ( ) > ( & url, & body) ;
398
+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
399
+ assert_eq ! (
400
+ response. into_json( ) ,
401
+ json!( { "ok" : true , "msg" : "user user-2 has been invited to be an owner of crate foo_crate" } )
402
+ ) ;
403
+ // TODO this should return "403 Forbidden" once token scopes are implemented for this endpoint
404
+ // assert_eq!(response.status(), StatusCode::FORBIDDEN);
405
+ // assert_eq!(
406
+ // response.into_json(),
407
+ // json!({ "errors": [{ "detail": "must be logged in to perform that action" }] })
408
+ // );
409
+ }
410
+
308
411
#[ test]
309
412
fn owner_change_without_auth ( ) {
310
413
let ( app, anon, cookie) = TestApp :: full ( ) . with_user ( ) ;
0 commit comments