Skip to content

Commit 7bdb382

Browse files
committed
Issue #680 : Crate owners can now remove themselves as owner if there is at least one other owner remaining.
1 parent 405b2ad commit 7bdb382

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

src/krate.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,15 +1363,15 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult<Response> {
13631363
if owners.iter().any(|owner| owner.login() == *login) {
13641364
return Err(human(&format_args!("`{}` is already an owner", login)));
13651365
}
1366-
krate.owner_add(req.app(), &conn, user, login)?;
1366+
krate.owner_add(req.app(), &conn, user, login)?;
13671367
} else {
13681368
// Removing the team that gives you rights is prevented because
13691369
// team members only have Rights::Publish
1370-
if *login == user.gh_login {
1371-
return Err(human("cannot remove yourself as an owner"));
1372-
}
1373-
krate.owner_remove(&conn, user, login)?;
1374-
}
1370+
if owners.len() == 1 {
1371+
return Err(human("cannot remove the sole owner of a crate"))
1372+
}
1373+
krate.owner_remove(&conn, user, login)?;
1374+
}
13751375
}
13761376

13771377
#[derive(Serialize)]

src/tests/krate.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,57 @@ fn following() {
12251225
assert_eq!(::json::<CrateList>(&mut response).crates.len(), 0);
12261226
}
12271227

1228+
// Ensures that so long as at least one owner remains associated with the crate,
1229+
// a user can still remove their own login as an owner
1230+
#[test]
1231+
fn owners_can_remove_self() {
1232+
#[derive(Deserialize)]
1233+
struct R {
1234+
users: Vec<EncodablePublicUser>,
1235+
}
1236+
#[derive(Deserialize)]
1237+
struct O {
1238+
ok: bool,
1239+
}
1240+
1241+
let (_b, app, middle) = ::app();
1242+
let mut req = ::req(app.clone(), Method::Get, "/api/v1/crates/owners_selfremove/owners");
1243+
{
1244+
let conn = app.diesel_database.get().unwrap();
1245+
::new_user("secondowner").create_or_update(&conn).unwrap();
1246+
let user = ::new_user("firstowner").create_or_update(&conn).unwrap();
1247+
::sign_in_as(&mut req, &user);
1248+
::CrateBuilder::new("owners_selfremove", user.id).expect_build(&conn);
1249+
}
1250+
1251+
let mut response = ok_resp!(middle.call(&mut req));
1252+
let r: R = ::json(&mut response);
1253+
assert_eq!(r.users.len(), 1);
1254+
1255+
let mut response = ok_resp!(middle.call(req.with_method(Method::Get)));
1256+
let r: R = ::json(&mut response);
1257+
assert_eq!(r.users.len(), 1);
1258+
1259+
let body = r#"{"users":["secondowner"]}"#;
1260+
let mut response = ok_resp!(middle.call(req.with_method(Method::Put).with_body(
1261+
body.as_bytes(),
1262+
)));
1263+
assert!(::json::<O>(&mut response).ok);
1264+
1265+
// This is a self delete from owners
1266+
let body = r#"{"users":["firstowner"]}"#;
1267+
let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(
1268+
body.as_bytes(),
1269+
)));
1270+
assert!(::json::<O>(&mut response).ok);
1271+
1272+
let body = r#"{"users":["secondowner"]}"#;
1273+
let mut response = ok_resp!(middle.call(req.with_method(Method::Delete).with_body(
1274+
body.as_bytes(),
1275+
)));
1276+
::json::<::Bad>(&mut response);
1277+
}
1278+
12281279
#[test]
12291280
fn owners() {
12301281
#[derive(Deserialize)]

0 commit comments

Comments
 (0)