Scope files jobs and plugins to request profile

This commit is contained in:
ekko
2026-05-24 10:11:03 +08:00
committed by ekko
parent 289a958684
commit 9708a6a521
23 changed files with 353 additions and 117 deletions
@@ -7,6 +7,7 @@ import {
validatePath,
resolveHermesPath,
} from '../../services/hermes/file-provider'
import { getActiveProfileName } from '../../services/hermes/hermes-profile'
export const downloadRoutes = new Router()
@@ -62,6 +63,10 @@ function getMimeType(fileName: string): string {
return MIME_MAP[ext] || 'application/octet-stream'
}
function requestedProfile(ctx: any): string {
return ctx.state?.profile?.name || getActiveProfileName() || 'default'
}
downloadRoutes.get('/api/hermes/download', async (ctx) => {
const filePath = ctx.query.path as string | undefined
const fileName = ctx.query.name as string | undefined
@@ -73,16 +78,17 @@ downloadRoutes.get('/api/hermes/download', async (ctx) => {
}
try {
const profile = requestedProfile(ctx)
// Validate the path first
// Support both absolute and relative paths
const validPath = isAbsolute(filePath) ? validatePath(filePath) : resolveHermesPath(filePath)
const validPath = isAbsolute(filePath) ? validatePath(filePath) : resolveHermesPath(filePath, profile)
// Choose provider: always use local for upload directory files
let data: Buffer
if (isInUploadDir(validPath)) {
data = await localProvider.readFile(validPath)
} else {
const provider = await createFileProvider()
const provider = await createFileProvider(profile)
data = await provider.readFile(validPath)
}
+36 -24
View File
@@ -6,8 +6,20 @@ import {
MAX_EDIT_SIZE,
} from '../../services/hermes/file-provider'
function withAbsolutePath<T extends { path: string }>(entry: T): T & { absolutePath: string } {
return { ...entry, absolutePath: resolveHermesPath(entry.path) }
function requestedProfile(ctx: any): string | undefined {
return ctx.state?.profile?.name
}
function resolveRequestPath(ctx: any, relativePath: string): string {
return resolveHermesPath(relativePath, requestedProfile(ctx))
}
async function createRequestFileProvider(ctx: any) {
return createFileProvider(requestedProfile(ctx))
}
function withAbsolutePath<T extends { path: string }>(ctx: any, entry: T): T & { absolutePath: string } {
return { ...entry, absolutePath: resolveRequestPath(ctx, entry.path) }
}
export const fileRoutes = new Router()
@@ -36,14 +48,14 @@ function handleError(ctx: any, err: any) {
fileRoutes.get('/api/hermes/files/list', async (ctx) => {
const relativePath = (ctx.query.path as string) || ''
try {
const absPath = resolveHermesPath(relativePath)
const provider = await createFileProvider()
const absPath = resolveRequestPath(ctx, relativePath)
const provider = await createRequestFileProvider(ctx)
const entries = await provider.listDir(absPath)
entries.sort((a, b) => {
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1
return a.name.localeCompare(b.name)
})
ctx.body = { entries: entries.map(withAbsolutePath), path: relativePath, absolutePath: absPath }
ctx.body = { entries: entries.map(entry => withAbsolutePath(ctx, entry)), path: relativePath, absolutePath: absPath }
} catch (err: any) {
handleError(ctx, err)
}
@@ -58,10 +70,10 @@ fileRoutes.get('/api/hermes/files/stat', async (ctx) => {
return
}
try {
const absPath = resolveHermesPath(relativePath)
const provider = await createFileProvider()
const absPath = resolveRequestPath(ctx, relativePath)
const provider = await createRequestFileProvider(ctx)
const info = await provider.stat(absPath)
ctx.body = withAbsolutePath(info)
ctx.body = withAbsolutePath(ctx, info)
} catch (err: any) {
handleError(ctx, err)
}
@@ -76,8 +88,8 @@ fileRoutes.get('/api/hermes/files/read', async (ctx) => {
return
}
try {
const absPath = resolveHermesPath(relativePath)
const provider = await createFileProvider()
const absPath = resolveRequestPath(ctx, relativePath)
const provider = await createRequestFileProvider(ctx)
const data = await provider.readFile(absPath)
if (data.length > MAX_EDIT_SIZE) {
ctx.status = 413
@@ -110,8 +122,8 @@ fileRoutes.put('/api/hermes/files/write', async (ctx) => {
ctx.body = { error: 'Content too large', code: 'file_too_large' }
return
}
const absPath = resolveHermesPath(relativePath)
const provider = await createFileProvider()
const absPath = resolveRequestPath(ctx, relativePath)
const provider = await createRequestFileProvider(ctx)
await provider.writeFile(absPath, buf)
ctx.body = { ok: true, path: relativePath }
} catch (err: any) {
@@ -133,8 +145,8 @@ fileRoutes.delete('/api/hermes/files/delete', async (ctx) => {
return
}
try {
const absPath = resolveHermesPath(relativePath)
const provider = await createFileProvider()
const absPath = resolveRequestPath(ctx, relativePath)
const provider = await createRequestFileProvider(ctx)
if (recursive) {
await provider.deleteDir(absPath)
} else {
@@ -160,9 +172,9 @@ fileRoutes.post('/api/hermes/files/rename', async (ctx) => {
return
}
try {
const absOld = resolveHermesPath(oldPath)
const absNew = resolveHermesPath(newPath)
const provider = await createFileProvider()
const absOld = resolveRequestPath(ctx, oldPath)
const absNew = resolveRequestPath(ctx, newPath)
const provider = await createRequestFileProvider(ctx)
await provider.renameFile(absOld, absNew)
ctx.body = { ok: true }
} catch (err: any) {
@@ -179,8 +191,8 @@ fileRoutes.post('/api/hermes/files/mkdir', async (ctx) => {
return
}
try {
const absPath = resolveHermesPath(relativePath)
const provider = await createFileProvider()
const absPath = resolveRequestPath(ctx, relativePath)
const provider = await createRequestFileProvider(ctx)
await provider.mkDir(absPath)
ctx.body = { ok: true }
} catch (err: any) {
@@ -197,9 +209,9 @@ fileRoutes.post('/api/hermes/files/copy', async (ctx) => {
return
}
try {
const absSrc = resolveHermesPath(srcPath)
const absDest = resolveHermesPath(destPath)
const provider = await createFileProvider()
const absSrc = resolveRequestPath(ctx, srcPath)
const absDest = resolveRequestPath(ctx, destPath)
const provider = await createRequestFileProvider(ctx)
await provider.copyFile(absSrc, absDest)
ctx.body = { ok: true }
} catch (err: any) {
@@ -230,7 +242,7 @@ fileRoutes.post('/api/hermes/files/upload', async (ctx) => {
const boundaryBuf = Buffer.from(boundary)
const parts = splitMultipart(raw, boundaryBuf)
const provider = await createFileProvider()
const provider = await createRequestFileProvider(ctx)
const results: { name: string; path: string }[] = []
for (const part of parts) {
@@ -263,7 +275,7 @@ fileRoutes.post('/api/hermes/files/upload', async (ctx) => {
return
}
const absPath = resolveHermesPath(filePath)
const absPath = resolveRequestPath(ctx, filePath)
await provider.writeFile(absPath, data)
results.push({ name: filename, path: filePath })
}