-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SONAR-24336 Make GitHub login ready to scale with # of organizations
- Loading branch information
1 parent
2540165
commit e5466c0
Showing
6 changed files
with
176 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
server/sonar-auth-github/src/main/java/org/sonar/auth/github/GsonOrganization.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* SonarQube | ||
* Copyright (C) 2009-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
package org.sonar.auth.github; | ||
|
||
import com.google.gson.Gson; | ||
import com.google.gson.annotations.SerializedName; | ||
import com.google.gson.reflect.TypeToken; | ||
import java.util.List; | ||
|
||
public record GsonOrganization (@SerializedName("login") String organization) { | ||
public static List<GsonOrganization> parse(String json) { | ||
Gson gson = new Gson(); | ||
return gson.fromJson(json, new TypeToken<>() { | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GsonOrganizationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* SonarQube | ||
* Copyright (C) 2009-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
package org.sonar.auth.github; | ||
|
||
import java.util.List; | ||
import org.junit.Test; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public class GsonOrganizationTest { | ||
|
||
@Test | ||
public void parse() { | ||
List<GsonOrganization> underTest = GsonOrganization.parse(""" | ||
[ | ||
{ | ||
"login": "github", | ||
"id": 1, | ||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE=", | ||
"url": "https://api.github.com/orgs/github", | ||
"repos_url": "https://api.github.com/orgs/github/repos", | ||
"events_url": "https://api.github.com/orgs/github/events", | ||
"hooks_url": "https://api.github.com/orgs/github/hooks", | ||
"issues_url": "https://api.github.com/orgs/github/issues", | ||
"members_url": "https://api.github.com/orgs/github/members{/member}", | ||
"public_members_url": "https://api.github.com/orgs/github/public_members{/member}", | ||
"avatar_url": "https://github.com/images/error/octocat_happy.gif", | ||
"description": "A great organization" | ||
}, | ||
{ | ||
"login": "github-org2", | ||
"id": 1, | ||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjE=", | ||
"url": "https://api.github.com/orgs/github", | ||
"repos_url": "https://api.github.com/orgs/github/repos", | ||
"events_url": "https://api.github.com/orgs/github/events", | ||
"hooks_url": "https://api.github.com/orgs/github/hooks", | ||
"issues_url": "https://api.github.com/orgs/github/issues", | ||
"members_url": "https://api.github.com/orgs/github/members{/member}", | ||
"public_members_url": "https://api.github.com/orgs/github/public_members{/member}", | ||
"avatar_url": "https://github.com/images/error/octocat_happy.gif", | ||
"description": "An even greater organization" | ||
} | ||
]"""); | ||
assertThat(underTest).hasSize(2); | ||
assertThat(underTest).extracting(GsonOrganization::organization).containsExactly("github", "github-org2"); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,10 +124,13 @@ public void callback_on_successful_authentication() throws IOException, Interrup | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"[email protected]\"}")); | ||
// response of api.github.com/orgs/first_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(404)); | ||
// response of api.github.com/orgs/second_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(204)); | ||
// response of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
{ | ||
"login": "second_org" | ||
} | ||
]""")); | ||
|
||
HttpServletRequest request = newRequest("the-verifier-code"); | ||
DumbCallbackContext callbackContext = new DumbCallbackContext(request); | ||
|
@@ -161,8 +164,13 @@ public void should_retrieve_private_primary_verified_email_address() { | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":null}")); | ||
// response of api.github.com/orgs/first_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(204)); | ||
// response of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
{ | ||
"login": "second_org" | ||
} | ||
]""")); | ||
// response of api.github.com/user/emails | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
|
@@ -198,7 +206,12 @@ public void should_not_fail_if_no_email() { | |
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":null}")); | ||
// response of api.github.com/orgs/first_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(204)); | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
{ | ||
"login": "second_org" | ||
} | ||
]""")); | ||
// response of api.github.com/user/emails | ||
github.enqueue(new MockResponse().setBody("[]")); | ||
|
||
|
@@ -238,8 +251,13 @@ public void callback_on_successful_authentication_with_group_sync() { | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"[email protected]\"}")); | ||
// response of api.github.com/orgs/first_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(204)); | ||
// response of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
{ | ||
"login": "second_org" | ||
} | ||
]""")); | ||
// response of api.github.com/user/teams | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
|
@@ -267,8 +285,13 @@ public void callback_on_successful_authentication_with_group_sync_on_many_pages( | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"[email protected]\"}")); | ||
// response of api.github.com/orgs/first_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(204)); | ||
// response of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
{ | ||
"login": "second_org" | ||
} | ||
]""")); | ||
// responses of api.github.com/user/teams | ||
github.enqueue(new MockResponse() | ||
.setHeader("Link", "<" + gitHubUrl + "/user/teams?per_page=100&page=2>; rel=\"next\", <" + gitHubUrl + "/user/teams?per_page=100&page=2>; rel=\"last\"") | ||
|
@@ -324,8 +347,13 @@ public void callback_on_successful_authentication_with_organizations_with_member | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"[email protected]\"}")); | ||
// response of api.github.com/orgs/example0/members/user | ||
github.enqueue(new MockResponse().setResponseCode(204)); | ||
// response of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setBody(""" | ||
[ | ||
{ | ||
"login": "example1" | ||
} | ||
]""")); | ||
|
||
HttpServletRequest request = newRequest("the-verifier-code"); | ||
DumbCallbackContext callbackContext = new DumbCallbackContext(request); | ||
|
@@ -343,10 +371,8 @@ public void callback_on_successful_authentication_with_organizations_without_mem | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"[email protected]\"}")); | ||
// response of api.github.com/orgs/first_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(404).setBody("{}")); | ||
// response of api.github.com/orgs/second_org/members/user | ||
github.enqueue(new MockResponse().setResponseCode(404).setBody("{}")); | ||
// response of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setBody("[]")); | ||
|
||
HttpServletRequest request = newRequest("the-verifier-code"); | ||
DumbCallbackContext callbackContext = new DumbCallbackContext(request); | ||
|
@@ -381,7 +407,7 @@ public void callback_throws_ISE_if_error_when_checking_membership() { | |
github.enqueue(newSuccessfulAccessTokenResponse()); | ||
// response of api.github.com/user | ||
github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"[email protected]\"}")); | ||
// crash of api.github.com/orgs/example/members/user | ||
// crash of api.github.com/user/orgs | ||
github.enqueue(new MockResponse().setResponseCode(500).setBody("{error}")); | ||
|
||
HttpServletRequest request = newRequest("the-verifier-code"); | ||
|
@@ -390,7 +416,7 @@ public void callback_throws_ISE_if_error_when_checking_membership() { | |
underTest.callback(callbackContext); | ||
fail("exception expected"); | ||
} catch (IllegalStateException e) { | ||
assertThat(e.getMessage()).isEqualTo("Fail to execute request '" + gitHubSettings.apiURL() + "orgs/example/members/octocat'. HTTP code: 500, response: {error}"); | ||
assertThat(e.getMessage()).isEqualTo("Fail to execute request '" + gitHubSettings.apiURL() + "user/orgs'. HTTP code: 500, response: {error}"); | ||
} | ||
} | ||
|
||
|