Skip to content

Commit aa0b84e

Browse files
committed
1 parent 43922b1 commit aa0b84e

3 files changed

Lines changed: 79 additions & 10 deletions

File tree

datasette_auth_github/utils.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,8 @@ async def load_orgs_and_teams(config, profile, access_token):
3939
else:
4040
continue
4141
# Now check if user is an active member of the team:
42-
team_membership_url = (
43-
"https://api.{}/teams/{}/memberships/{}".format(
44-
config["host"], team_id, profile["login"]
45-
)
42+
team_membership_url = "https://api.{}/teams/{}/memberships/{}".format(
43+
config["host"], team_id, profile["login"]
4644
)
4745
async with httpx.AsyncClient() as client:
4846
response = await client.get(

datasette_auth_github/views.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def verify_config(config):
1111
config = config or {}
1212
for key in DEPRECATED_KEYS:
1313
assert key not in config, "{} is no longer a supported option".format(key)
14-
config.setdefault('host', "github.com")
14+
config.setdefault("host", "github.com")
1515

1616

1717
async def github_auth_start(datasette):
@@ -21,10 +21,8 @@ async def github_auth_start(datasette):
2121
scope = "read:org"
2222
else:
2323
scope = "user:email"
24-
github_login_url = (
25-
"https://{}/login/oauth/authorize?scope={}&client_id={}".format(
26-
config["host"], scope, config["client_id"]
27-
)
24+
github_login_url = "https://{}/login/oauth/authorize?scope={}&client_id={}".format(
25+
config["host"], scope, config["client_id"]
2826
)
2927
return Response.redirect(github_login_url)
3028

@@ -87,7 +85,7 @@ async def github_auth_callback(datasette, request, scope, receive, send):
8785
extras = await load_orgs_and_teams(config, profile, access_token)
8886
actor.update(extras)
8987

90-
# Set a signed cookie and redirect to homepage (respecting 'base_url' setting)
88+
# Set a signed cookie and redirect to homepage (respecting 'base_url' setting)
9189
response = Response.redirect(datasette.urls.path("/"))
9290
response.set_cookie("ds_actor", datasette.sign({"a": actor}, "actor"))
9391
return response

tests/test_datasette_auth_github.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,76 @@ async def test_database_access_permissions(
198198
cookies = {"ds_actor": auth_response.cookies["ds_actor"]}
199199
databases = await ds.client.get("/.json", cookies=cookies)
200200
assert set(databases.json()["databases"].keys()) == expected_databases
201+
202+
203+
@pytest.mark.asyncio
204+
async def test_github_enterprise_host(tmpdir, httpx_mock):
205+
"""Test that GitHub Enterprise host configuration works correctly"""
206+
# Mock GitHub Enterprise endpoints
207+
enterprise_host = "github.example.com"
208+
209+
httpx_mock.add_response(
210+
url=f"https://{enterprise_host}/login/oauth/access_token",
211+
method="POST",
212+
content=b"access_token=enterprise_access_token",
213+
)
214+
215+
httpx_mock.add_response(
216+
url=f"https://api.{enterprise_host}/user",
217+
json={
218+
"id": 456,
219+
"name": "Enterprise User",
220+
"login": "enterpriseuser",
221+
"email": "enterprise@example.com",
222+
},
223+
)
224+
225+
httpx_mock.add_response(
226+
url=re.compile(
227+
rf"^https://api\.{re.escape(enterprise_host)}/orgs/enterprise-org/memberships/.*"
228+
),
229+
json={"state": "active", "role": "member"},
230+
)
231+
232+
# Create Datasette instance with GitHub Enterprise configuration
233+
filepath = str(tmpdir / "test.db")
234+
ds = Datasette(
235+
[filepath],
236+
metadata={
237+
"plugins": {
238+
"datasette-auth-github": {
239+
"client_id": "enterprise_client_id",
240+
"client_secret": "enterprise_client_secret",
241+
"host": enterprise_host,
242+
"load_orgs": ["enterprise-org"],
243+
}
244+
}
245+
},
246+
)
247+
248+
def create_tables(conn):
249+
sqlite_utils.Database(conn)["example"].insert({"name": "example"})
250+
251+
await ds.get_database().execute_write_fn(create_tables, block=True)
252+
253+
# Test that the auth start URL uses the enterprise host
254+
response = await ds.client.get("/-/github-auth-start", follow_redirects=False)
255+
expected_url = f"https://{enterprise_host}/login/oauth/authorize?scope=read:org&client_id=enterprise_client_id"
256+
assert expected_url == response.headers["location"]
257+
258+
# Test that the auth callback uses the enterprise host for API calls
259+
response = await ds.client.get(
260+
"/-/github-auth-callback?code=enterprise-code",
261+
follow_redirects=False,
262+
)
263+
264+
actor = ds.unsign(response.cookies["ds_actor"], "actor")["a"]
265+
assert {
266+
"id": "github:456",
267+
"display": "enterpriseuser",
268+
"gh_id": "456",
269+
"gh_name": "Enterprise User",
270+
"gh_login": "enterpriseuser",
271+
"gh_email": "enterprise@example.com",
272+
"gh_orgs": ["enterprise-org"],
273+
}.items() <= actor.items()

0 commit comments

Comments
 (0)