Merge pull request #27 from Heartune/gitLab_support

增强 GitLab 仓库集成,支持多种 Token 认证方式,解决自建 GitLab 使用 Project Access Token 无法克隆的问题
This commit is contained in:
lintsinghua 2025-10-30 20:13:48 +08:00 committed by GitHub
commit f0a5c3237e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 39 additions and 3 deletions

View File

@ -31,7 +31,12 @@ async function githubApi<T>(url: string, token?: string): Promise<T> {
async function gitlabApi<T>(url: string, token?: string): Promise<T> { async function gitlabApi<T>(url: string, token?: string): Promise<T> {
const headers: Record<string, string> = { "Content-Type": "application/json" }; const headers: Record<string, string> = { "Content-Type": "application/json" };
const t = token || (import.meta.env.VITE_GITLAB_TOKEN as string | undefined); const t = token || (import.meta.env.VITE_GITLAB_TOKEN as string | undefined);
if (t) headers["PRIVATE-TOKEN"] = t; if (t) {
// 支持两种 token 格式:
// 1. 标准 Personal Access Token (glpat-xxx)
// 2. OAuth2 token (从 URL 中提取的纯 token)
headers["PRIVATE-TOKEN"] = t;
}
const res = await fetch(url, { headers }); const res = await fetch(url, { headers });
if (!res.ok) { if (!res.ok) {
if (res.status === 401) throw new Error("GitLab API 401请配置 VITE_GITLAB_TOKEN 或确认仓库权限"); if (res.status === 401) throw new Error("GitLab API 401请配置 VITE_GITLAB_TOKEN 或确认仓库权限");
@ -112,6 +117,21 @@ export async function runRepositoryAudit(params: {
} else if (isGitLab) { } else if (isGitLab) {
// GitLab 仓库处理(支持自定义域名/IP基于仓库 URL 动态构建 API 基地址 // GitLab 仓库处理(支持自定义域名/IP基于仓库 URL 动态构建 API 基地址
const u = new URL(repoUrl); const u = new URL(repoUrl);
// 从 URL 中提取 OAuth2 token如果存在
// 格式https://oauth2:TOKEN@host/path 或 https://TOKEN@host/path
let extractedToken = params.gitlabToken;
if (u.username) {
// 如果 username 是 oauth2token 在 password 中
if (u.username === 'oauth2' && u.password) {
extractedToken = u.password;
}
// 如果直接使用 token 作为 username
else if (u.username && !u.password) {
extractedToken = u.username;
}
}
const base = `${u.protocol}//${u.host}`; // 例如 https://git.dev-rs.com 或 http://192.168.1.10 const base = `${u.protocol}//${u.host}`; // 例如 https://git.dev-rs.com 或 http://192.168.1.10
// 解析项目路径,支持多级 group/subgroup去除开头/结尾斜杠与 .git 后缀 // 解析项目路径,支持多级 group/subgroup去除开头/结尾斜杠与 .git 后缀
const path = u.pathname.replace(/^\/+|\/+$/g, '').replace(/\.git$/i, ''); const path = u.pathname.replace(/^\/+|\/+$/g, '').replace(/\.git$/i, '');
@ -122,7 +142,7 @@ export async function runRepositoryAudit(params: {
const treeUrl = `${base}/api/v4/projects/${projectPath}/repository/tree?ref=${encodeURIComponent(branch)}&recursive=true&per_page=100`; const treeUrl = `${base}/api/v4/projects/${projectPath}/repository/tree?ref=${encodeURIComponent(branch)}&recursive=true&per_page=100`;
console.log(`📡 GitLab API: 获取仓库文件树 - ${treeUrl}`); console.log(`📡 GitLab API: 获取仓库文件树 - ${treeUrl}`);
const tree = await gitlabApi<Array<{ path: string; type: string }>>(treeUrl, params.gitlabToken); const tree = await gitlabApi<Array<{ path: string; type: string }>>(treeUrl, extractedToken);
console.log(`✅ GitLab API: 获取到 ${tree.length} 个项目`); console.log(`✅ GitLab API: 获取到 ${tree.length} 个项目`);
files = tree files = tree
@ -194,7 +214,23 @@ export async function runRepositoryAudit(params: {
const headers: Record<string, string> = {}; const headers: Record<string, string> = {};
// 为 GitLab 添加认证 Token // 为 GitLab 添加认证 Token
if (isGitLab) { if (isGitLab) {
const token = params.gitlabToken || (import.meta.env.VITE_GITLAB_TOKEN as string | undefined); // 优先使用从 URL 提取的 token否则使用配置的 token
let token = params.gitlabToken || (import.meta.env.VITE_GITLAB_TOKEN as string | undefined);
// 如果 URL 中包含 OAuth2 token提取它
if (repoUrl.includes('@')) {
try {
const urlObj = new URL(repoUrl);
if (urlObj.username === 'oauth2' && urlObj.password) {
token = urlObj.password;
} else if (urlObj.username && !urlObj.password) {
token = urlObj.username;
}
} catch (e) {
// URL 解析失败,使用原有 token
}
}
if (token) { if (token) {
headers["PRIVATE-TOKEN"] = token; headers["PRIVATE-TOKEN"] = token;
} }