Skip to content
28 changes: 17 additions & 11 deletions apps/server/src/assets/AssetAccess.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import * as ServerSecretStore from "../auth/ServerSecretStore.ts";
import * as ServerConfig from "../config.ts";
import * as Orchestrator from "../orchestration-v2/Orchestrator.ts";
import * as ProjectFaviconResolver from "../project/ProjectFaviconResolver.ts";
import * as RepositoryIdentityResolver from "../project/RepositoryIdentityResolver.ts";
import * as T3ProjectFileLoader from "../project/T3ProjectFileLoader.ts";
import * as WorkspacePaths from "../workspace/WorkspacePaths.ts";
import { assetFileResponse } from "../http.ts";
Expand Down Expand Up @@ -195,17 +196,22 @@ describe("AssetAccess", () => {
expect(authorizations).toEqual([undefined, "Bearer signed-in", "Bearer signed-in"]);
}).pipe(
Effect.provide(
Layer.mock(GitHubCredentials.GitHubCredentials)({
get: (host) =>
++lookups === 1
? Effect.fail(new GitHubCredentials.GitHubNotSignedInError({ host }))
: Effect.succeed({
host,
token: Redacted.make("signed-in"),
source: "gh" as const,
fingerprint: "fingerprint",
}),
}),
Layer.mergeAll(
Layer.mock(RepositoryIdentityResolver.RepositoryIdentityResolver)({
resolve: () => Effect.succeed(null),
}),
Layer.mock(GitHubCredentials.GitHubCredentials)({
get: (host) =>
++lookups === 1
? Effect.fail(new GitHubCredentials.GitHubNotSignedInError({ host }))
: Effect.succeed({
host,
token: Redacted.make("signed-in"),
source: "gh" as const,
fingerprint: "fingerprint",
}),
}),
),
),
Effect.provideService(
HttpClient.HttpClient,
Expand Down
22 changes: 16 additions & 6 deletions apps/server/src/assets/GitHubMediaFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {

import * as GitHubCredentials from "@t3tools/source-control-github/server/GitHubCredentials";

import { workspaceGitHubCredential } from "../sourceControl/GitHubWorkspaceAccount.ts";

/**
* Everything a redirect leads to — the presigned object stores GitHub hands assets off to —
* authorizes with its own signature, and some of them reject a request that also carries a
Expand Down Expand Up @@ -50,11 +52,19 @@ const SVG_CONTENT_TYPE = "image/svg+xml";
// body cannot run script against this origin.
const SVG_CONTENT_SECURITY_POLICY = "default-src 'none'; style-src 'unsafe-inline'; sandbox";

const githubToken = GitHubCredentials.GitHubCredentials.pipe(
Effect.flatMap((credentials) => credentials.get("github.com")),
Effect.map((credential) => credential.token),
Effect.orElseSucceed(() => null),
);
/** The github.com credential the workspace's repository is read with; null still loads public media. */
const githubToken = (cwd: string) =>
workspaceGitHubCredential(cwd).pipe(
Effect.flatMap((credential) =>
credential?.host === "github.com"
? Effect.succeed(credential)
: GitHubCredentials.GitHubCredentials.pipe(
Effect.flatMap((credentials) => credentials.get("github.com")),
),
),
Effect.map((credential) => credential.token),
Effect.orElseSucceed(() => null),
);

const fetchFollowingRedirects = Effect.fn("GitHubMediaFetch.fetchFollowingRedirects")(function* (
url: string,
Expand Down Expand Up @@ -92,7 +102,7 @@ export const githubMediaResponse = Effect.fn("GitHubMediaFetch.githubMediaRespon
requestHeaders: Record<string, string | undefined>,
) {
// Both media hosts are served by github.com's account, which is the host `gh` stores it under.
const token = yield* githubToken;
const token = yield* githubToken(asset.cwd);
const forwarded: Record<string, string> = {};
for (const name of FORWARDED_REQUEST_HEADERS) {
const value = requestHeaders[name];
Expand Down
Loading
Loading