Show SVN repository auth hints

This commit is contained in:
lwt
2026-06-18 14:41:15 +08:00
parent 4ab3332f34
commit 11b2504ce5
2 changed files with 68 additions and 5 deletions
+58
View File
@@ -54,6 +54,11 @@ function limitText(value, maxLength = 4000) {
return String(value || "").trim().slice(0, maxLength);
}
function limitStringArray(value, maxItems = 30, maxLength = 120) {
if (!Array.isArray(value)) return [];
return value.map((item) => limitText(item, maxLength)).filter(Boolean).slice(0, maxItems);
}
function isRemoteTarget(value) {
return REMOTE_TARGET_PATTERN.test(String(value || "").trim());
}
@@ -138,6 +143,41 @@ async function readTextIfExists(filePath) {
}
}
function parseSimpleConfig(text) {
const result = {};
for (const line of String(text || "").split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith(";") || trimmed.startsWith("[")) continue;
const index = trimmed.indexOf("=");
if (index === -1) continue;
result[trimmed.slice(0, index).trim()] = trimmed.slice(index + 1).trim();
}
return result;
}
function parsePasswdUsers(text) {
const users = [];
let inUsers = false;
for (const line of String(text || "").split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith(";")) continue;
if (/^\[users\]$/i.test(trimmed)) {
inUsers = true;
continue;
}
if (/^\[.+\]$/.test(trimmed)) {
inUsers = false;
continue;
}
if (!inUsers) continue;
const index = trimmed.indexOf("=");
if (index === -1) continue;
const username = trimmed.slice(0, index).trim();
if (username) users.push(username);
}
return users;
}
function addAuthArgs(args, repo) {
const next = [...args, "--non-interactive"];
if (repo.trustServerCert !== false) {
@@ -250,6 +290,9 @@ async function discoveredRepoInfo(options, req, rootPath, repoPath) {
const name = relativePath || path.basename(repoPath);
const current = await readTextIfExists(path.join(repoPath, "db", "current"));
const revision = current.split(/\s+/)[0] || "";
const svnserveConfig = parseSimpleConfig(await readTextIfExists(path.join(repoPath, "conf", "svnserve.conf")));
const authUsers = parsePasswdUsers(await readTextIfExists(path.join(repoPath, "conf", svnserveConfig["password-db"] || "passwd")));
const anonAccess = svnserveConfig["anon-access"] || "";
return {
id: slugify(name),
name,
@@ -261,6 +304,11 @@ async function discoveredRepoInfo(options, req, rootPath, repoPath) {
uuid: await readTextIfExists(path.join(repoPath, "db", "uuid")),
fsType: await readTextIfExists(path.join(repoPath, "db", "fs-type")),
format: await readTextIfExists(path.join(repoPath, "format")),
anonAccess,
authAccess: svnserveConfig["auth-access"] || "",
realm: svnserveConfig.realm || "",
authRequired: anonAccess.toLowerCase() === "none",
authUsers: authUsers.slice(0, 30),
};
}
@@ -323,6 +371,11 @@ function repoFromDiscovered(discovered, existing = {}) {
serverRelativePath: discovered.relativePath,
serverRevision: discovered.revision,
serverUuid: discovered.uuid,
serverAnonAccess: discovered.anonAccess,
serverAuthAccess: discovered.authAccess,
serverRealm: discovered.realm,
serverAuthRequired: discovered.authRequired,
serverAuthUsers: discovered.authUsers,
description: existing.description || `从服务器 SVN 服务接入:${discovered.repositoryPath}`,
}, existing);
}
@@ -398,6 +451,11 @@ function normalizeRepoPatch(body, existing = {}) {
serverRelativePath: limitText(body.serverRelativePath || existing.serverRelativePath, 1000),
serverRevision: limitText(body.serverRevision || existing.serverRevision, 80),
serverUuid: limitText(body.serverUuid || existing.serverUuid, 120),
serverAnonAccess: limitText(body.serverAnonAccess || existing.serverAnonAccess, 80),
serverAuthAccess: limitText(body.serverAuthAccess || existing.serverAuthAccess, 80),
serverRealm: limitText(body.serverRealm || existing.serverRealm, 200),
serverAuthRequired: parseBoolean(body.serverAuthRequired, existing.serverAuthRequired === true),
serverAuthUsers: limitStringArray(body.serverAuthUsers || existing.serverAuthUsers),
updatedAt: new Date().toISOString(),
createdAt: existing.createdAt || new Date().toISOString(),
};