Skip to content

Commit 4ad168f

Browse files
Merge #1171
1171: GitHub org/team names should be treated case insensitively (fixes #1167) r=sgrif I believe this fixes the issue. If there are areas that I missed, I will be sure to update them as well! Example usage output: ``` # cargo owner -a github:test-cratesio:dev --index file:///development/crates.io/tmp/index-co Updating registry `file:///development/crates.io/tmp/index-co` Owner team github:test-cratesio:dev has been added as an owner of crate test-crate # cargo owner -a github:Test-Cratesio:Dev --index file:///development/crates.io/tmp/index-co Updating registry `file:///development/crates.io/tmp/index-co` error: failed to invite owners to crate test-crate: api errors: `github:Test-Cratesio:Dev` is already an owner # cargo owner -r github:Test-Cratesio:Dev --index file:///development/crates.io/tmp/index-co Updating registry `file:///development/crates.io/tmp/index-co` Owner removing ["github:Test-Cratesio:Dev"] from crate test-crate # cargo owner -a github:Test-Cratesio:Dev --index file:///development/crates.io/tmp/index-co Updating registry `file:///development/crates.io/tmp/index-co` Owner team github:test-cratesio:dev has been added as an owner of crate test-crate ```
2 parents 44d01f0 + 43549a8 commit 4ad168f

File tree

6 files changed

+62
-4
lines changed

6 files changed

+62
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE teams
2+
DROP CONSTRAINT teams_login_lowercase_ck;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
UPDATE teams SET login=lower(login);
2+
ALTER TABLE teams
3+
ADD CONSTRAINT teams_login_lowercase_ck
4+
CHECK (login = lower(login));

src/controllers/krate/owners.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ fn modify_owners(req: &mut Request, add: bool) -> CargoResult<Response> {
106106

107107
for login in &logins {
108108
if add {
109-
if owners.iter().any(|owner| owner.login() == *login) {
109+
let login_test = |owner: &Owner| owner.login().to_lowercase() == *login.to_lowercase();
110+
if owners.iter().any(login_test) {
110111
return Err(human(&format_args!("`{}` is already an owner", login)));
111112
}
112113
let msg = krate.owner_add(req.app(), &conn, user, login)?;

src/models/team.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,14 @@ impl Team {
8585
format is github:org:team",
8686
)
8787
})?;
88-
Team::create_or_update_github_team(app, conn, login, org, team, req_user)
88+
Team::create_or_update_github_team(
89+
app,
90+
conn,
91+
&login.to_lowercase(),
92+
org,
93+
team,
94+
req_user,
95+
)
8996
}
9097
_ => Err(human(
9198
"unknown organization handler, \
@@ -140,7 +147,7 @@ impl Team {
140147

141148
let team = teams
142149
.into_iter()
143-
.find(|team| team.slug == team_name)
150+
.find(|team| team.slug.to_lowercase() == team_name.to_lowercase())
144151
.ok_or_else(|| {
145152
human(&format_args!(
146153
"could not find the github team {}/{}",
@@ -161,7 +168,7 @@ impl Team {
161168
let (handle, resp) = github::github(app, &url, &token)?;
162169
let org: Org = github::parse_github_response(handle, &resp)?;
163170

164-
NewTeam::new(login, team.id, team.name, org.avatar_url)
171+
NewTeam::new(&login.to_lowercase(), team.id, team.name, org.avatar_url)
165172
.create_or_update(conn)
166173
.map_err(Into::into)
167174
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"request":{"uri":"http://api.github.com/orgs/Crates-Test-Org/teams?per_page=100","method":"GET","headers":[["Proxy-Connection","Keep-Alive"],["User-Agent","hello!"],["Host","api.github.com"],["Authorization","token 7534f8b996e3a3f800f0a324f619adba12a74532"],["Accept","application/vnd.github.v3+json"]],"body":[]},"response":{"status":200,"headers":[["X-RateLimit-Remaining","4995"],["X-Content-Type-Options","nosniff"],["X-XSS-Protection","1; mode=block"],["X-Runtime-rack","0.035631"],["X-RateLimit-Limit","5000"],["Server","GitHub.com"],["X-Frame-Options","deny"],["X-Accepted-OAuth-Scopes","admin:org, read:org, repo, user, write:org"],["Vary","Accept, Authorization, Cookie, X-GitHub-OTP"],["X-GitHub-Media-Type","github.v3; format=json"],["Content-Length","905"],["ETag","\"168464471f229c2bec917d1c95ad86ff\""],["Access-Control-Allow-Origin","*"],["Content-Type","application/json; charset=utf-8"],["X-GitHub-Request-Id","CA9C:6F2F:8060D6:FB015A:59D4F5CA"],["X-OAuth-Client-Id","89b6afdeaa6c6c7506ec"],["Access-Control-Expose-Headers","ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"],["X-RateLimit-Reset","1507132377"],["X-OAuth-Scopes","read:org"],["Status","200 OK"],["Date","Wed, 04 Oct 2017 14:52:58 GMT"],["Cache-Control","private, max-age=60, s-maxage=60"],["Strict-Transport-Security","max-age=31536000; includeSubdomains; preload"],["Content-Security-Policy","default-src 'none'"]],"body":[91,123,34,110,97,109,101,34,58,34,99,111,114,101,34,44,34,105,100,34,58,49,54,57,57,51,55,55,44,34,115,108,117,103,34,58,34,99,111,114,101,34,44,34,100,101,115,99,114,105,112,116,105,111,110,34,58,110,117,108,108,44,34,112,114,105,118,97,99,121,34,58,34,115,101,99,114,101,116,34,44,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,55,34,44,34,109,101,109,98,101,114,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,55,47,109,101,109,98,101,114,115,123,47,109,101,109,98,101,114,125,34,44,34,114,101,112,111,115,105,116,111,114,105,101,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,55,47,114,101,112,111,115,34,44,34,112,101,114,109,105,115,115,105,111,110,34,58,34,97,100,109,105,110,34,125,44,123,34,110,97,109,101,34,58,34,106,117,115,116,45,102,111,114,45,99,114,97,116,101,115,45,50,34,44,34,105,100,34,58,49,54,57,57,51,55,57,44,34,115,108,117,103,34,58,34,106,117,115,116,45,102,111,114,45,99,114,97,116,101,115,45,50,34,44,34,100,101,115,99,114,105,112,116,105,111,110,34,58,34,74,117,115,116,32,102,111,114,32,67,114,97,116,101,115,32,50,34,44,34,112,114,105,118,97,99,121,34,58,34,115,101,99,114,101,116,34,44,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,57,34,44,34,109,101,109,98,101,114,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,57,47,109,101,109,98,101,114,115,123,47,109,101,109,98,101,114,125,34,44,34,114,101,112,111,115,105,116,111,114,105,101,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,57,47,114,101,112,111,115,34,44,34,112,101,114,109,105,115,115,105,111,110,34,58,34,112,117,108,108,34,125,44,123,34,110,97,109,101,34,58,34,106,117,115,116,45,102,111,114,45,99,114,97,116,101,115,49,34,44,34,105,100,34,58,49,54,57,57,51,55,56,44,34,115,108,117,103,34,58,34,106,117,115,116,45,102,111,114,45,99,114,97,116,101,115,49,34,44,34,100,101,115,99,114,105,112,116,105,111,110,34,58,34,34,44,34,112,114,105,118,97,99,121,34,58,34,115,101,99,114,101,116,34,44,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,56,34,44,34,109,101,109,98,101,114,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,56,47,109,101,109,98,101,114,115,123,47,109,101,109,98,101,114,125,34,44,34,114,101,112,111,115,105,116,111,114,105,101,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,56,47,114,101,112,111,115,34,44,34,112,101,114,109,105,115,115,105,111,110,34,58,34,112,117,108,108,34,125,93]}},{"request":{"uri":"http://api.github.com/teams/1699377/memberships/crates-tester-2","method":"GET","headers":[["Host","api.github.com"],["User-Agent","hello!"],["Accept","application/vnd.github.v3+json"],["Authorization","token 7534f8b996e3a3f800f0a324f619adba12a74532"],["Proxy-Connection","Keep-Alive"]],"body":[]},"response":{"status":200,"headers":[["X-XSS-Protection","1; mode=block"],["X-RateLimit-Limit","5000"],["Access-Control-Expose-Headers","ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"],["X-Runtime-rack","0.030002"],["X-OAuth-Scopes","read:org"],["X-GitHub-Request-Id","CA9C:6F2F:8060E2:FB016C:59D4F5CA"],["Access-Control-Allow-Origin","*"],["X-Content-Type-Options","nosniff"],["X-RateLimit-Reset","1507132377"],["X-RateLimit-Remaining","4994"],["Content-Length","111"],["Server","GitHub.com"],["X-Accepted-OAuth-Scopes","admin:org, read:org, repo, write:org"],["X-GitHub-Media-Type","github.v3; format=json"],["Content-Type","application/json; charset=utf-8"],["X-OAuth-Client-Id","89b6afdeaa6c6c7506ec"],["Content-Security-Policy","default-src 'none'"],["Status","200 OK"],["Vary","Accept, Authorization, Cookie, X-GitHub-OTP"],["ETag","\"a004da562b1c421613f0ca38f7a9bf2f\""],["Date","Wed, 04 Oct 2017 14:52:58 GMT"],["X-Frame-Options","deny"],["Strict-Transport-Security","max-age=31536000; includeSubdomains; preload"],["Cache-Control","private, max-age=60, s-maxage=60"]],"body":[123,34,115,116,97,116,101,34,58,34,97,99,116,105,118,101,34,44,34,114,111,108,101,34,58,34,109,97,105,110,116,97,105,110,101,114,34,44,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,116,101,97,109,115,47,49,54,57,57,51,55,55,47,109,101,109,98,101,114,115,104,105,112,115,47,99,114,97,116,101,115,45,116,101,115,116,101,114,45,50,34,125]}},{"request":{"uri":"http://api.github.com/orgs/Crates-Test-Org","method":"GET","headers":[["Host","api.github.com"],["Proxy-Connection","Keep-Alive"],["User-Agent","hello!"],["Authorization","token 7534f8b996e3a3f800f0a324f619adba12a74532"],["Accept","application/vnd.github.v3+json"]],"body":[]},"response":{"status":200,"headers":[["Server","GitHub.com"],["Status","200 OK"],["X-RateLimit-Remaining","4993"],["X-Runtime-rack","0.052093"],["Cache-Control","private, max-age=60, s-maxage=60"],["Access-Control-Allow-Origin","*"],["Access-Control-Expose-Headers","ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"],["Content-Length","1168"],["X-OAuth-Scopes","read:org"],["X-OAuth-Client-Id","89b6afdeaa6c6c7506ec"],["X-Accepted-OAuth-Scopes","admin:org, read:org, repo, user, write:org"],["Content-Security-Policy","default-src 'none'"],["X-RateLimit-Limit","5000"],["X-GitHub-Request-Id","CA9C:6F2F:8060E5:FB0178:59D4F5CA"],["X-Frame-Options","deny"],["X-XSS-Protection","1; mode=block"],["Last-Modified","Tue, 18 Aug 2015 17:37:08 GMT"],["Content-Type","application/json; charset=utf-8"],["Strict-Transport-Security","max-age=31536000; includeSubdomains; preload"],["X-RateLimit-Reset","1507132377"],["X-Content-Type-Options","nosniff"],["Vary","Accept, Authorization, Cookie, X-GitHub-OTP"],["ETag","\"164b3fa13f1e681dc06cab6811749c2f\""],["Date","Wed, 04 Oct 2017 14:52:58 GMT"],["X-GitHub-Media-Type","github.v3; format=json"]],"body":[123,34,108,111,103,105,110,34,58,34,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,34,44,34,105,100,34,58,49,51,56,48,52,50,50,50,44,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,34,44,34,114,101,112,111,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,47,114,101,112,111,115,34,44,34,101,118,101,110,116,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,47,101,118,101,110,116,115,34,44,34,104,111,111,107,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,47,104,111,111,107,115,34,44,34,105,115,115,117,101,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,47,105,115,115,117,101,115,34,44,34,109,101,109,98,101,114,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,47,109,101,109,98,101,114,115,123,47,109,101,109,98,101,114,125,34,44,34,112,117,98,108,105,99,95,109,101,109,98,101,114,115,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,112,105,46,103,105,116,104,117,98,46,99,111,109,47,111,114,103,115,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,47,112,117,98,108,105,99,95,109,101,109,98,101,114,115,123,47,109,101,109,98,101,114,125,34,44,34,97,118,97,116,97,114,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,97,118,97,116,97,114,115,50,46,103,105,116,104,117,98,117,115,101,114,99,111,110,116,101,110,116,46,99,111,109,47,117,47,49,51,56,48,52,50,50,50,63,118,61,52,34,44,34,100,101,115,99,114,105,112,116,105,111,110,34,58,110,117,108,108,44,34,104,97,115,95,111,114,103,97,110,105,122,97,116,105,111,110,95,112,114,111,106,101,99,116,115,34,58,116,114,117,101,44,34,104,97,115,95,114,101,112,111,115,105,116,111,114,121,95,112,114,111,106,101,99,116,115,34,58,116,114,117,101,44,34,112,117,98,108,105,99,95,114,101,112,111,115,34,58,48,44,34,112,117,98,108,105,99,95,103,105,115,116,115,34,58,48,44,34,102,111,108,108,111,119,101,114,115,34,58,48,44,34,102,111,108,108,111,119,105,110,103,34,58,48,44,34,104,116,109,108,95,117,114,108,34,58,34,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,99,114,97,116,101,115,45,116,101,115,116,45,111,114,103,34,44,34,99,114,101,97,116,101,100,95,97,116,34,58,34,50,48,49,53,45,48,56,45,49,53,84,48,48,58,48,55,58,51,48,90,34,44,34,117,112,100,97,116,101,100,95,97,116,34,58,34,50,48,49,53,45,48,56,45,49,56,84,49,55,58,51,55,58,48,56,90,34,44,34,116,121,112,101,34,58,34,79,114,103,97,110,105,122,97,116,105,111,110,34,44,34,116,111,116,97,108,95,112,114,105,118,97,116,101,95,114,101,112,111,115,34,58,48,44,34,111,119,110,101,100,95,112,114,105,118,97,116,101,95,114,101,112,111,115,34,58,48,44,34,112,114,105,118,97,116,101,95,103,105,115,116,115,34,58,110,117,108,108,44,34,100,105,115,107,95,117,115,97,103,101,34,58,110,117,108,108,44,34,99,111,108,108,97,98,111,114,97,116,111,114,115,34,58,110,117,108,108,44,34,98,105,108,108,105,110,103,95,101,109,97,105,108,34,58,110,117,108,108,44,34,112,108,97,110,34,58,123,34,110,97,109,101,34,58,34,102,114,101,101,34,44,34,115,112,97,99,101,34,58,57,55,54,53,54,50,52,57,57,44,34,112,114,105,118,97,116,101,95,114,101,112,111,115,34,58,48,44,34,102,105,108,108,101,100,95,115,101,97,116,115,34,58,50,44,34,115,101,97,116,115,34,58,48,125,44,34,100,101,102,97,117,108,116,95,114,101,112,111,115,105,116,111,114,121,95,112,101,114,109,105,115,115,105,111,110,34,58,110,117,108,108,44,34,109,101,109,98,101,114,115,95,99,97,110,95,99,114,101,97,116,101,95,114,101,112,111,115,105,116,111,114,105,101,115,34,58,110,117,108,108,125]}}]

src/tests/team.rs

+43
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,49 @@ fn nonexistent_team() {
125125
);
126126
}
127127

128+
// Test adding team names with mixed case
129+
#[test]
130+
fn add_team_mixed_case() {
131+
let (_b, app, middle) = ::app();
132+
let mut req =
133+
::request_with_user_and_mock_crate(&app, &mock_user_on_x_and_y(), "foo_mixed_case");
134+
135+
let body = r#"{"users":["github:Crates-Test-Org:Core"]}"#;
136+
137+
ok_resp!(
138+
middle.call(
139+
req.with_path("/api/v1/crates/foo_mixed_case/owners")
140+
.with_method(Method::Put)
141+
.with_body(body.as_bytes()),
142+
)
143+
);
144+
145+
{
146+
let conn = app.diesel_database.get().unwrap();
147+
let krate = Crate::by_name("foo_mixed_case")
148+
.first::<Crate>(&*conn)
149+
.unwrap();
150+
assert_eq!(krate.owners(&*conn).unwrap().len(), 2);
151+
}
152+
153+
ok_resp!(
154+
middle.call(
155+
req.with_path("/api/v1/crates/foo_mixed_case/owners")
156+
.with_method(Method::Get)
157+
.with_body(body.as_bytes()),
158+
)
159+
);
160+
161+
{
162+
let conn = app.diesel_database.get().unwrap();
163+
let krate = Crate::by_name("foo_mixed_case")
164+
.first::<Crate>(&*conn)
165+
.unwrap();
166+
let owner = &krate.owners(&*conn).unwrap()[1];
167+
assert_eq!(owner.login(), owner.login().to_lowercase());
168+
}
169+
}
170+
128171
// Test adding team as owner when on it
129172
#[test]
130173
fn add_team_as_member() {

0 commit comments

Comments
 (0)