fix(git-providers): resolve legacy GitHub owners for repository loading
This commit is contained in:
1 parent
14ae4c5e0e
commit
04173f1f83
3 files changed
+66
-6
No files matched your search
@@ -5,7 +5,6 @@ import {
|
||||
} from "@/app/settings/components/SettingsPrimitives";
|
||||
import {
|
||||
type GithubProviderModalProps,
|
||||
ProviderBadge,
|
||||
getProviderMeta,
|
||||
launchGithubManifestFlow,
|
||||
} from "./git-provider-shared";
|
||||
@@ -117,7 +116,19 @@ export default function GithubProviderModal({
|
||||
placeholder="Organization name"
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
) : (
|
||||
<div>
|
||||
<FieldLabel>GitHub Username</FieldLabel>
|
||||
<input
|
||||
className="input"
|
||||
value={draft.accountUsername}
|
||||
onChange={(event) =>
|
||||
updateDraft("accountUsername", event.target.value)
|
||||
}
|
||||
placeholder="Your GitHub username"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
style={{
|
||||
@@ -191,7 +202,7 @@ export default function GithubProviderModal({
|
||||
className="input"
|
||||
value={draft.appName}
|
||||
onChange={(event) => updateDraft("appName", event.target.value)}
|
||||
placeholder={`Doktainer-${new Date().toISOString().split("T")[0].replace(/-/g, "")}-${Math.random().toString(36).slice(2, 10)}`}
|
||||
placeholder="Doktainer-20260718-ab12cd34"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { ExternalLink } from "lucide-react";
|
||||
import { FieldLabel } from "@/app/settings/components/SettingsPrimitives";
|
||||
import {
|
||||
type GitProviderModalBaseProps,
|
||||
ProviderBadge,
|
||||
getProviderMeta,
|
||||
} from "./git-provider-shared";
|
||||
import { markGitProviderCallbackIntent } from "@/lib/git-provider-callback-intent";
|
||||
@@ -193,6 +192,18 @@ export default function GitlabProviderModal({
|
||||
placeholder="my-org"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ gridColumn: "1 / -1" }}>
|
||||
<FieldLabel>GitLab Username (Required Without Group)</FieldLabel>
|
||||
<input
|
||||
className="input"
|
||||
value={draft.accountUsername}
|
||||
onChange={(event) =>
|
||||
updateDraft("accountUsername", event.target.value)
|
||||
}
|
||||
placeholder="Your GitLab username"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FastifyInstance } from "fastify";
|
||||
import { z } from "zod";
|
||||
import prisma from "../lib/prisma";
|
||||
import { decrypt, encrypt } from "../lib/crypto";
|
||||
import { encrypt } from "../lib/crypto";
|
||||
import { authenticate, requireRole } from "../middleware/auth";
|
||||
import { auditLog } from "../services/audit.service";
|
||||
import { verifyGitProviderConfiguration } from "../services/integration-verification.service";
|
||||
@@ -170,6 +170,18 @@ function getProviderOwner(provider: GitProviderRecord) {
|
||||
);
|
||||
}
|
||||
|
||||
function getGithubInstallationTargetId(installationUrl?: string | null) {
|
||||
const rawUrl = toTrimmedValue(installationUrl);
|
||||
if (!rawUrl) return "";
|
||||
|
||||
try {
|
||||
const targetId = new URL(rawUrl).searchParams.get("target_id")?.trim();
|
||||
return targetId && /^\d+$/.test(targetId) ? targetId : "";
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function buildProviderFetchErrorMessage(args: {
|
||||
provider: GitProviderRecord["provider"];
|
||||
resource: string;
|
||||
@@ -247,6 +259,32 @@ async function fetchJson(
|
||||
return json;
|
||||
}
|
||||
|
||||
async function resolveProviderOwner(provider: GitProviderRecord) {
|
||||
const configuredOwner = getProviderOwner(provider);
|
||||
if (configuredOwner || provider.provider !== "GITHUB") {
|
||||
return configuredOwner;
|
||||
}
|
||||
|
||||
// GitHub's manifest flow stores the installation target account ID in the
|
||||
// installation URL. Older personal-account records did not persist a
|
||||
// username, so resolve the public login from that stable account ID.
|
||||
const targetId = getGithubInstallationTargetId(provider.installationUrl);
|
||||
if (!targetId) return "";
|
||||
|
||||
const baseUrl = normalizeBaseUrl(provider.providerUrl, "https://github.com");
|
||||
const apiBase =
|
||||
baseUrl.toLowerCase() === "https://github.com"
|
||||
? "https://api.github.com"
|
||||
: `${baseUrl}/api/v3`;
|
||||
const payload = await fetchJson(`${apiBase}/user/${targetId}`, {
|
||||
provider: provider.provider,
|
||||
resource: "GitHub account",
|
||||
});
|
||||
|
||||
if (!payload || typeof payload !== "object") return "";
|
||||
return toTrimmedValue((payload as { login?: string }).login);
|
||||
}
|
||||
|
||||
function mapGithubRepositories(payload: unknown): GitProviderRepository[] {
|
||||
if (!Array.isArray(payload)) return [];
|
||||
|
||||
@@ -468,7 +506,7 @@ function mapGiteaBranches(
|
||||
async function listRepositoriesForProvider(
|
||||
provider: GitProviderRecord,
|
||||
): Promise<GitProviderRepository[]> {
|
||||
const owner = getProviderOwner(provider);
|
||||
const owner = await resolveProviderOwner(provider);
|
||||
if (!owner) {
|
||||
throw new Error(
|
||||
"Configure namespace, organization name, or account username on the Git provider before loading repositories",
|
||||
|
||||
Reference in new issue
Block a user