-
-
Notifications
You must be signed in to change notification settings - Fork 749
Cargo owner username disambiguation #14213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
31b1dc3
b92a3ba
98025c3
99a2726
82f2941
c3b7f02
ebb148e
11657db
51f3045
6836aea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,10 @@ pub struct User { | |
| pub name: Option<String>, | ||
| pub gh_id: i32, | ||
| pub gh_login: String, | ||
| // This is the same as gh_login, but reads from oauth_github instead. | ||
| // Can rename to `gh_login` or something more appropriate when gh_login is removed from this struct. | ||
| #[diesel(select_expression = oauth_github::login.nullable())] | ||
| pub gh_username: Option<String>, | ||
|
Turbo87 marked this conversation as resolved.
|
||
| #[diesel(select_expression = oauth_github::avatar.nullable())] | ||
| pub gh_avatar: Option<String>, | ||
| #[diesel(select_expression = oauth_github::encrypted_token.nullable())] | ||
|
|
@@ -216,6 +220,20 @@ pub struct OauthGithub { | |
| pub user_id: i32, | ||
| } | ||
|
|
||
| impl OauthGithub { | ||
| pub async fn find_by_login( | ||
| mut conn: &AsyncPgConnection, | ||
| login: &str, | ||
| ) -> QueryResult<OauthGithub> { | ||
| oauth_github::table | ||
| .filter(canon_username(oauth_github::login).eq(canon_username(login))) | ||
| .filter(oauth_github::account_id.ne(-1)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| .order(oauth_github::account_id.desc()) | ||
| .first(&mut conn) | ||
| .await | ||
| } | ||
| } | ||
|
|
||
| /// Represents a new crates.io user to GitHub user OAuth link to be inserted into the | ||
| /// `oauth_github` table. | ||
| #[derive(Insertable, Debug, Builder)] | ||
|
|
@@ -245,3 +263,53 @@ impl NewOauthGithub<'_> { | |
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| use crates_io_test_db::TestDatabase; | ||
|
|
||
| async fn insert_user( | ||
| conn: &AsyncPgConnection, | ||
| username: &str, | ||
| gh_login: &str, | ||
| gh_id: i32, | ||
| ) -> QueryResult<i32> { | ||
| let user_id = NewUser::builder() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you able to use |
||
| .gh_id(gh_id) | ||
| .gh_login(gh_login) | ||
| .username(username) | ||
| .build() | ||
| .insert(conn) | ||
| .await?; | ||
|
|
||
| NewOauthGithub::builder() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... These test builders might not have existed when you started this PR, but they should make other changes smaller, like the |
||
| .account_id(gh_id as i64) | ||
| .encrypted_token(&[]) | ||
| .login(gh_login) | ||
| .user_id(user_id) | ||
| .build() | ||
| .insert(conn) | ||
| .await?; | ||
|
|
||
| Ok(user_id) | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn test_find_by_login_returns_highest_account_id_account() { | ||
| let test_db = TestDatabase::new(); | ||
| let conn = test_db.async_connect().await; | ||
|
|
||
| insert_user(&conn, "alice", "alice", 100).await.unwrap(); | ||
| let user_id = insert_user(&conn, "alice", "Alice", 200).await.unwrap(); | ||
|
|
||
| // case-insensitive checks | ||
| for login in ["alice", "Alice", "ALICE"] { | ||
| let user = OauthGithub::find_by_login(&conn, login).await.unwrap(); | ||
|
|
||
| assert_eq!(user.account_id, 200); | ||
| assert_eq!(user.user_id, user_id); | ||
| assert_eq!(user.login, "Alice"); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DROP INDEX CONCURRENTLY IF EXISTS index_oauth_github_login; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| run_in_transaction = false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| CREATE INDEX CONCURRENTLY IF NOT EXISTS index_oauth_github_login ON oauth_github (lower(login)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on a resolved comment thread on this PR that I'm having trouble linking to and the current state of the query in
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, I wasn't done with refactorings in this branch yet 🙈 I think we should actually do the opposite and keep GitHub account comparisons as only lower(), since hyphen and underscore are not equivalent on the GitHub side, even if we plan on treating them that way for the crates.io usernames.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh whoops! sorry-- i'll hold off with the rest of my review til you say you're done :) sounds good with the github normalization! |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3293,9 +3293,14 @@ export interface operations { | |
| * | ||
| * For users, use just the username (e.g., `"octocat"`). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tiny nit that I think will make this documentation clearer: The note this PR adds about disambiguation of usernames should be added up here with users rather than after the note about teams, and the "just" in "use just the username" should be removed because that's not necessarily true now. |
||
| * For GitHub teams, use the format `github:org:team` (e.g., `"github:rust-lang:owners"`). | ||
| * | ||
| * To disambiguate between crates.io and GitHub usernames, use | ||
| * the `crates.io:username` or `github:username` prefix. | ||
| * @example [ | ||
| * "octocat", | ||
| * "github:rust-lang:owners" | ||
| * "github:rust-lang:owners", | ||
| * "crates.io:some_user", | ||
| * "github:other_user" | ||
| * ] | ||
| */ | ||
| owners: string[]; | ||
|
|
@@ -3358,9 +3363,14 @@ export interface operations { | |
| * | ||
| * For users, use just the username (e.g., `"octocat"`). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here with moving the disambiguation note up here and removing "just" |
||
| * For GitHub teams, use the format `github:org:team` (e.g., `"github:rust-lang:owners"`). | ||
| * | ||
| * To disambiguate between crates.io and GitHub usernames, use | ||
| * the `crates.io:username` or `github:username` prefix. | ||
| * @example [ | ||
| * "octocat", | ||
| * "github:rust-lang:owners" | ||
| * "github:rust-lang:owners", | ||
| * "crates.io:some_user", | ||
| * "github:other_user" | ||
| * ] | ||
| */ | ||
| owners: string[]; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just noticed that the change to this query, because
crate_owners_with_loginis selecting bothteams.loginandusers.usernameascrate_owners_with_login.login, makes it so that we're comparing team names using thecanon_usernamefunction (which also normalizes hyphen to underscore), whereas before we were only comparing team names usinglower.I don't think we want to change anything about how we handle team names right now. That's under GitHub's control (and we don't have plans to change the way teams work yet).
Looking at the production database, I don't see any team names that differ only by hyphen/underscore today, but I do see some team names with hyphens and some with underscores, so GitHub does allow it. While I don't think it would be a good idea for anyone to do this, I just confirmed that it's possible to create two teams in GitHub, one named
crates-ioand one namedcrates_io. I think the change to this query would mean you couldn't manage them independently. If they both existed in crates.io, then you rancargo owner --add github:rust-lang:crates-io, both thecrates-ioand thecrates_ioteam would get added, if my reasoning is correct.Given that we now have this query in
owner_remove_with_usernameand a slightly different query inowner_remove_with_gh_login, maybe we should splitowner_remove_with_usernameintoowner_remove_with_usernameandowner_remove_with_team_name?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, thanks for catching this! i did a partial extraction from this pr and did the split in #14596. I'll rebase when #14596 is merged.