Skip to content

Commit c0b295f

Browse files
Merge #999
999: Issue #680 : Crate owners can now remove themselves as owner r=carols10cents If there is at least one other owner remaining, then an owner can remove themselves from a crate.
2 parents dc195a3 + f25ec1c commit c0b295f

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

src/krate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,8 +1404,8 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult<Response> {
14041404
} else {
14051405
// Removing the team that gives you rights is prevented because
14061406
// team members only have Rights::Publish
1407-
if *login == user.gh_login {
1408-
return Err(human("cannot remove yourself as an owner"));
1407+
if owners.len() == 1 {
1408+
return Err(human("cannot remove the sole owner of a crate"));
14091409
}
14101410
krate.owner_remove(&conn, user, login)?;
14111411
}

src/tests/krate.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,71 @@ fn following() {
12631263
assert_eq!(::json::<CrateList>(&mut response).crates.len(), 0);
12641264
}
12651265

1266+
// Ensures that so long as at least one owner remains associated with the crate,
1267+
// a user can still remove their own login as an owner
1268+
#[test]
1269+
fn owners_can_remove_self() {
1270+
#[derive(Deserialize)]
1271+
struct R {
1272+
users: Vec<EncodablePublicUser>,
1273+
}
1274+
#[derive(Deserialize)]
1275+
struct O {
1276+
ok: bool,
1277+
}
1278+
1279+
let (_b, app, middle) = ::app();
1280+
let mut req = ::req(
1281+
app.clone(),
1282+
Method::Get,
1283+
"/api/v1/crates/owners_selfremove/owners",
1284+
);
1285+
{
1286+
let conn = app.diesel_database.get().unwrap();
1287+
::new_user("secondowner").create_or_update(&conn).unwrap();
1288+
let user = ::new_user("firstowner").create_or_update(&conn).unwrap();
1289+
::sign_in_as(&mut req, &user);
1290+
::CrateBuilder::new("owners_selfremove", user.id).expect_build(&conn);
1291+
}
1292+
1293+
let mut response = ok_resp!(middle.call(&mut req));
1294+
let r: R = ::json(&mut response);
1295+
assert_eq!(r.users.len(), 1);
1296+
1297+
// Deleting yourself when you're the only owner isn't allowed.
1298+
let body = r#"{"users":["firstowner"]}"#;
1299+
let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(
1300+
body.as_bytes(),
1301+
)));
1302+
let json = ::json::<::Bad>(&mut response);
1303+
assert!(json.errors[0].detail.contains(
1304+
"cannot remove the sole owner of a crate",
1305+
));
1306+
1307+
let body = r#"{"users":["secondowner"]}"#;
1308+
let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body(
1309+
body.as_bytes(),
1310+
)));
1311+
assert!(::json::<O>(&mut response).ok);
1312+
1313+
// Deleting yourself when there are other owners is allowed.
1314+
let body = r#"{"users":["firstowner"]}"#;
1315+
let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(
1316+
body.as_bytes(),
1317+
)));
1318+
assert!(::json::<O>(&mut response).ok);
1319+
1320+
// After you delete yourself, you no longer have permisions to manage the crate.
1321+
let body = r#"{"users":["secondowner"]}"#;
1322+
let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(
1323+
body.as_bytes(),
1324+
)));
1325+
let json = ::json::<::Bad>(&mut response);
1326+
assert!(json.errors[0].detail.contains(
1327+
"only owners have permission to modify owners",
1328+
));
1329+
}
1330+
12661331
#[test]
12671332
fn owners() {
12681333
#[derive(Deserialize)]

0 commit comments

Comments
 (0)