fix: support gists through GitHub App login (#875)

* fix: prompt OAuth reconnection when gist credentials are rejected

* fix: support gist reads through GitHub App user grants

* test: adapt truncated gist regression to provider selection

* fix: address gist reconnect visibility and token renewal review

* fix: verify App authorization before revoking OAuth
This commit is contained in:
Thomas Durieux authored and GitHub committed 2026-10-08 10:26:13 +01:00
1 parent 4fd31a59c8
commit db966356ec
14 files changed
+283 -54

No files matched your search

+29 -4
View File
@@ -469,17 +469,23 @@ describe("Vue 3 UI", function () {
expect(ui.window.document.querySelector('a[href="/github/app/login"]')).to.equal(null);
});
it("offers OAuth for an App-only gist and saves the draft before connecting", async function () {
for (const provider of ["OAuth", "App"]) {
it(`offers ${provider} recovery when gist credentials are rejected`, async function () {
ui = await browser("/gist-anonymize", {
"/api/user": { username: "owner" },
"/github/connections": { appEnabled: true, appConnected: true, oauthEnabled: true, oauthConnected: false },
"/github/connections": { appEnabled: true, appConnected: provider === "App", oauthEnabled: true, oauthConnected: provider === "OAuth" },
"/api/gist/source/311fc9": { __status: 403, body: { error: provider === "App" ? "github_app_reconnect_required" : "github_oauth_required" } },
});
const input = await ui.input("#sourceUrl", "https://gist.github.com/311fc9");
input.dispatchEvent(new ui.window.Event("blur"));
await delay(60);
const button = [...ui.window.document.querySelectorAll("button")].find(node => node.textContent.includes("Connect GitHub OAuth to access gists"));
const button = [...ui.window.document.querySelectorAll("button")].find(node => node.textContent.includes(`Connect GitHub ${provider} to access gists`));
expect(button).not.to.equal(undefined);
expect(ui.requests.some(r => r.url.pathname === "/api/gist/source/311fc9")).to.equal(false);
expect(button.closest(".anonymize-workspace")).not.to.equal(null);
for (let node = button; node; node = node.parentElement) {
expect(ui.window.getComputedStyle(node).display, node.className).not.to.equal("none");
}
expect(ui.requests.some(r => r.url.pathname === "/api/gist/source/311fc9")).to.equal(true);
button.click();
const saved = JSON.parse(ui.window.sessionStorage.getItem("github-access-draft"));
expect(saved.path).to.equal("/gist-anonymize");
@@ -487,6 +493,25 @@ describe("Vue 3 UI", function () {
expect(ui.errors).to.deep.equal([]);
});
}
it("previews a gist with only an App login", async function () {
ui = await browser("/gist-anonymize", {
"/api/user": { username: "owner" },
"/github/connections": { appEnabled: true, appConnected: true, gistConnection: "github-app", oauthEnabled: true, oauthConnected: false },
"/api/user/default": { terms: [], options: { content: true } },
"/api/anonymize-preview": request => ({ contents: request.payload.contents }),
"/api/gist/source/311fc9": { gist: { description: "App gist", files: [{ filename: "example.txt", content: "example" }], comments: [] } },
});
const input = await ui.input("#sourceUrl", "https://gist.github.com/311fc9");
input.dispatchEvent(new ui.window.Event("blur"));
await delay(300);
expect(ui.requests.some(r => r.url.pathname === "/api/gist/source/311fc9")).to.equal(true);
expect(ui.window.document.body.textContent).to.include("example.txt");
expect(ui.window.document.body.textContent).not.to.include("Connect GitHub OAuth to access gists");
expect(ui.errors).to.deep.equal([]);
});
for (const status of ["archived", "preparing", "queue", "download", "removing", "expiring"]) {
it(`hides connection changes on ${status} resources`, async function () {
ui = await browser("/connections", {