|
| 1 | +use crate::models::{CrateOwner, OwnerKind}; |
| 2 | +use crate::tests::builders::CrateBuilder; |
| 3 | +use crate::tests::util::{RequestHelper, TestApp}; |
| 4 | +use crates_io_database::schema::{crate_owners, users}; |
| 5 | +use diesel::prelude::*; |
| 6 | +use http::StatusCode; |
| 7 | +use insta::assert_snapshot; |
| 8 | + |
| 9 | +/// See <https://github.com/rust-lang/crates.io/issues/2736>. |
| 10 | +#[tokio::test(flavor = "multi_thread")] |
| 11 | +async fn test_issue_2736() -> anyhow::Result<()> { |
| 12 | + let (app, _) = TestApp::full().empty(); |
| 13 | + let mut conn = app.db_conn(); |
| 14 | + |
| 15 | + // - A user had a GitHub account named, let's say, `foo` |
| 16 | + let foo1 = app.db_new_user("foo"); |
| 17 | + |
| 18 | + // - Another user `someone_else` added them as an owner of a crate |
| 19 | + let someone_else = app.db_new_user("someone_else"); |
| 20 | + |
| 21 | + let krate = CrateBuilder::new("crate1", someone_else.as_model().id).expect_build(&mut conn); |
| 22 | + |
| 23 | + diesel::insert_into(crate_owners::table) |
| 24 | + .values(CrateOwner { |
| 25 | + crate_id: krate.id, |
| 26 | + owner_id: foo1.as_model().id, |
| 27 | + created_by: someone_else.as_model().id, |
| 28 | + owner_kind: OwnerKind::User, |
| 29 | + email_notifications: true, |
| 30 | + }) |
| 31 | + .execute(&mut conn)?; |
| 32 | + |
| 33 | + // - `foo` deleted their GitHub account (but crates.io has no real knowledge of this) |
| 34 | + // - `foo` recreated their GitHub account with the same username (because it was still available), but in this situation GitHub assigns them a new ID |
| 35 | + // - 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) |
| 36 | + let foo2 = app.db_new_user("foo"); |
| 37 | + |
| 38 | + let github_ids = users::table |
| 39 | + .filter(users::gh_login.eq("foo")) |
| 40 | + .select(users::gh_id) |
| 41 | + .load::<i32>(&mut conn)?; |
| 42 | + |
| 43 | + assert_eq!(github_ids.len(), 2); |
| 44 | + assert_ne!(github_ids[0], github_ids[1]); |
| 45 | + |
| 46 | + // - The new `foo` account is NOT an owner of the crate |
| 47 | + let owners = krate.owners(&mut conn)?; |
| 48 | + assert_eq!(owners.len(), 2); |
| 49 | + assert_none!(owners.iter().find(|o| o.id() == foo2.as_model().id)); |
| 50 | + |
| 51 | + // Removing an owner, whether it's valid/current or not, should always work (if performed by another valid owner, etc) |
| 52 | + let response = someone_else.remove_named_owner("crate1", "foo").await; |
| 53 | + assert_eq!(response.status(), StatusCode::OK); |
| 54 | + assert_snapshot!(response.text(), @r#"{"msg":"owners successfully removed","ok":true}"#); |
| 55 | + |
| 56 | + let owners = krate.owners(&mut conn)?; |
| 57 | + assert_eq!(owners.len(), 1); |
| 58 | + assert_eq!(owners[0].id(), someone_else.as_model().id); |
| 59 | + |
| 60 | + // Once that removal works, it should be possible to add the new account as an owner |
| 61 | + let response = someone_else.add_named_owner("crate1", "foo").await; |
| 62 | + assert_eq!(response.status(), StatusCode::OK); |
| 63 | + assert_snapshot!(response.text(), @r#"{"msg":"user foo has been invited to be an owner of crate crate1","ok":true}"#); |
| 64 | + |
| 65 | + Ok(()) |
| 66 | +} |
0 commit comments