feat: overhaul server automation, files editor, and CS2 setup workflows
This commit is contained in:
@@ -19,6 +19,17 @@ const FileParamSchema = {
|
||||
}),
|
||||
};
|
||||
|
||||
function decodeBase64Payload(data: string): Buffer {
|
||||
const normalized = data.trim();
|
||||
if (!normalized) return Buffer.alloc(0);
|
||||
|
||||
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(normalized) || normalized.length % 4 !== 0) {
|
||||
throw AppError.badRequest('Invalid base64 payload');
|
||||
}
|
||||
|
||||
return Buffer.from(normalized, 'base64');
|
||||
}
|
||||
|
||||
export default async function fileRoutes(app: FastifyInstance) {
|
||||
app.addHook('onRequest', app.authenticate);
|
||||
|
||||
@@ -56,40 +67,61 @@ export default async function fileRoutes(app: FastifyInstance) {
|
||||
...FileParamSchema,
|
||||
querystring: Type.Object({
|
||||
path: Type.String({ minLength: 1 }),
|
||||
encoding: Type.Optional(Type.Union([Type.Literal('utf8'), Type.Literal('base64')])),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (request) => {
|
||||
const { orgId, serverId } = request.params as { orgId: string; serverId: string };
|
||||
const { path } = request.query as { path: string };
|
||||
const { path, encoding } = request.query as {
|
||||
path: string;
|
||||
encoding?: 'utf8' | 'base64';
|
||||
};
|
||||
|
||||
await requirePermission(request, orgId, 'files.read');
|
||||
const serverContext = await getServerContext(app, orgId, serverId);
|
||||
|
||||
const content = await daemonReadFile(serverContext.node, serverContext.serverUuid, path);
|
||||
return { data: content.data.toString('utf8') };
|
||||
const requestedEncoding = encoding === 'base64' ? 'base64' : 'utf8';
|
||||
|
||||
return {
|
||||
data:
|
||||
requestedEncoding === 'base64'
|
||||
? content.data.toString('base64')
|
||||
: content.data.toString('utf8'),
|
||||
encoding: requestedEncoding,
|
||||
mimeType: content.mimeType,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
app.post(
|
||||
'/write',
|
||||
{
|
||||
bodyLimit: 128 * 1024 * 1024,
|
||||
schema: {
|
||||
...FileParamSchema,
|
||||
body: Type.Object({
|
||||
path: Type.String({ minLength: 1 }),
|
||||
data: Type.String(),
|
||||
encoding: Type.Optional(Type.Union([Type.Literal('utf8'), Type.Literal('base64')])),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (request) => {
|
||||
const { orgId, serverId } = request.params as { orgId: string; serverId: string };
|
||||
const { path, data } = request.body as { path: string; data: string };
|
||||
const { path, data, encoding } = request.body as {
|
||||
path: string;
|
||||
data: string;
|
||||
encoding?: 'utf8' | 'base64';
|
||||
};
|
||||
|
||||
await requirePermission(request, orgId, 'files.write');
|
||||
const serverContext = await getServerContext(app, orgId, serverId);
|
||||
|
||||
await daemonWriteFile(serverContext.node, serverContext.serverUuid, path, data);
|
||||
const payload = encoding === 'base64' ? decodeBase64Payload(data) : data;
|
||||
|
||||
await daemonWriteFile(serverContext.node, serverContext.serverUuid, path, payload);
|
||||
return { success: true, path };
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user