Skip to content

Commit 54d4b18

Browse files
committed
Add regression test for rust-lang#2736
1 parent 1765dd1 commit 54d4b18

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/tests/routes/crates/owners/remove.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use crate::models::{CrateOwner, OwnerKind};
12
use crate::tests::builders::CrateBuilder;
23
use crate::tests::util::{RequestHelper, TestApp};
4+
use crate::util::diesel::prelude::*;
5+
use crates_io_database::schema::{crate_owners, users};
36
use http::StatusCode;
47
use insta::assert_snapshot;
58

@@ -80,3 +83,71 @@ async fn test_unknown_team() {
8083
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
8184
assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"could not find team with login `github:unknown:unknown`"}]}"#);
8285
}
86+
87+
/// See <https://github.com/rust-lang/crates.io/issues/2736>.
88+
#[tokio::test(flavor = "multi_thread")]
89+
async fn test_issue_2736() -> anyhow::Result<()> {
90+
use diesel::RunQueryDsl;
91+
92+
let (app, _) = TestApp::full().empty();
93+
let mut conn = app.db_conn();
94+
95+
// - A user had a GitHub account named, let's say, `foo`
96+
let foo1 = app.db_new_user("foo");
97+
98+
// - Another user `someone_else` added them as an owner of a crate
99+
let someone_else = app.db_new_user("someone_else");
100+
101+
let krate = CrateBuilder::new("crate1", someone_else.as_model().id).expect_build(&mut conn);
102+
103+
diesel::insert_into(crate_owners::table)
104+
.values(CrateOwner {
105+
crate_id: krate.id,
106+
owner_id: foo1.as_model().id,
107+
created_by: someone_else.as_model().id,
108+
owner_kind: OwnerKind::User,
109+
email_notifications: true,
110+
})
111+
.execute(&mut conn)?;
112+
113+
// - `foo` deleted their GitHub account (but crates.io has no real knowledge of this)
114+
// - `foo` recreated their GitHub account with the same username (because it was still available), but in this situation GitHub assigns them a new ID
115+
// - When `foo` now logs in to crates.io, it's a different account than their old `foo` crates.io account because of the new GitHub ID (and if it wasn't, this would be a security problem)
116+
let foo2 = app.db_new_user("foo");
117+
118+
let github_ids = users::table
119+
.filter(users::gh_login.eq("foo"))
120+
.select(users::gh_id)
121+
.load::<i32>(&mut conn)?;
122+
123+
assert_eq!(github_ids.len(), 2);
124+
assert_ne!(github_ids[0], github_ids[1]);
125+
126+
// - The new `foo` account is NOT an owner of the crate
127+
let owner_ids = crate_owners::table
128+
.filter(crate_owners::crate_id.eq(krate.id))
129+
.filter(crate_owners::deleted.eq(false))
130+
.select(crate_owners::owner_id)
131+
.load::<i32>(&mut conn)?;
132+
133+
assert_eq!(owner_ids.len(), 2);
134+
assert!(!owner_ids.contains(&foo2.as_model().id));
135+
136+
// - `someone_else` can't add the new `foo` account as an owner, nor can they remove the old `foo` as an owner :(
137+
let url = "/api/v1/crates/crate1/owners";
138+
let payload = json!({ "owners": ["foo"] }).to_string();
139+
let response = someone_else.delete_with_body::<()>(url, payload).await;
140+
assert_eq!(response.status(), StatusCode::OK);
141+
assert_snapshot!(response.text(), @r#"{"msg":"owners successfully removed","ok":true}"#);
142+
143+
let owner_ids = crate_owners::table
144+
.filter(crate_owners::crate_id.eq(krate.id))
145+
.filter(crate_owners::deleted.eq(false))
146+
.select(crate_owners::owner_id)
147+
.load::<i32>(&mut conn)?;
148+
149+
assert_eq!(owner_ids.len(), 1);
150+
assert_eq!(owner_ids[0], someone_else.as_model().id);
151+
152+
Ok(())
153+
}

0 commit comments

Comments
 (0)