@restroom-mw/files
Advanced tools
Comparing version 0.13.1-4c8a52e.19 to 0.13.1-4f7fd4a.73
export declare const DOWNLOAD = "download the {} and extract it into {}"; | ||
export declare const STORE_RESULT = "store {} in the file {}"; | ||
export declare const READ = "read the content of {}"; | ||
export declare const LS = "list the content of directory {} as {}"; | ||
//# sourceMappingURL=actions.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.READ = exports.STORE_RESULT = exports.DOWNLOAD = void 0; | ||
exports.LS = exports.READ = exports.STORE_RESULT = exports.DOWNLOAD = void 0; | ||
exports.DOWNLOAD = "download the {} and extract it into {}"; | ||
exports.STORE_RESULT = "store {} in the file {}"; | ||
exports.READ = "read the content of {}"; | ||
exports.LS = "list the content of directory {} as {}"; |
@@ -19,5 +19,7 @@ "use strict"; | ||
const fs_1 = __importDefault(require("fs")); | ||
const promises_1 = require("node:fs/promises"); | ||
const os_1 = __importDefault(require("os")); | ||
const extract_zip_1 = __importDefault(require("extract-zip")); | ||
const path_1 = __importDefault(require("path")); | ||
const utils_1 = require("@restroom-mw/utils"); | ||
require("dotenv").config(); | ||
@@ -47,13 +49,3 @@ /** | ||
// save path must be subdirs of FILES_DIR | ||
const validatePath = (p) => { | ||
if (!exports.FILES_DIR) | ||
throw new Error(`FILES_DIR is not defined`); | ||
if (exports.FILES_DIR != "/") { | ||
const relative = path_1.default.relative(exports.FILES_DIR, p); | ||
const isSubdir = relative && !relative.startsWith('..') && !path_1.default.isAbsolute(relative); | ||
if (!isSubdir) { | ||
throw new Error(`Result path outside ${exports.FILES_DIR}`); | ||
} | ||
} | ||
}; | ||
const validatePath = (0, utils_1.validateSubdir)(exports.FILES_DIR); | ||
exports.default = (req, res, next) => { | ||
@@ -63,5 +55,7 @@ const rr = new core_1.Restroom(req, res); | ||
const { zencode, keys, data } = params; | ||
input = rr.combineDataKeys(data, keys); | ||
if (zencode.match(actions_3.READ)) { | ||
const params = zencode.paramsOf(actions_3.READ); | ||
for (const file of params) { | ||
for (const f of params) { | ||
const file = input[f] || f; | ||
validatePath(file); | ||
@@ -78,2 +72,45 @@ const absoluteFile = path_1.default.join(exports.FILES_DIR, file); | ||
} | ||
if (zencode.match(actions_3.LS)) { | ||
const params = zencode.chunkedParamsOf(actions_3.LS, 2); | ||
const fileStats = {}; | ||
const allLs = (yield Promise.all(params.map(([p, name]) => __awaiter(void 0, void 0, void 0, function* () { | ||
const f = input[p] || p; | ||
validatePath(f); | ||
try { | ||
const content = yield (0, promises_1.readdir)(f); | ||
// I am not checking if `name` is used multiple times | ||
fileStats[name] = []; | ||
return content.map((current) => [name, f, current]); | ||
} | ||
catch (e) { | ||
throw new Error(`[FILES] error while reading the file ${f}`); | ||
} | ||
})))).flat(); | ||
// list with all files I want to see the stats of | ||
const allStats = yield Promise.all(allLs.map(([name, p, current]) => __awaiter(void 0, void 0, void 0, function* () { | ||
const currentFile = path_1.default.join(p, current); | ||
const fileStat = yield (0, promises_1.stat)(currentFile); | ||
return [name, current, fileStat]; | ||
}))); | ||
for (const [name, current, currentStat] of allStats) { | ||
// see https://unix.stackexchange.com/questions/317855/file-mode-on-macosx#317907 | ||
// for the meaning of the mode field | ||
fileStats[name].push({ | ||
'name': current, | ||
'mode': currentStat.mode.toString(8), | ||
'dev': currentStat.dev, | ||
'nlink': currentStat.nlink, | ||
'uid': currentStat.uid, | ||
'gid': currentStat.gid, | ||
'size': currentStat.size, | ||
'blksize': currentStat.blksize, | ||
'blocks': currentStat.blocks, | ||
'atime': currentStat.atime.toISOString(), | ||
'mtime': currentStat.mtime.toISOString(), | ||
'ctime': currentStat.ctime.toISOString(), | ||
'birthtime': currentStat.birthtime.toISOString(), | ||
}); | ||
} | ||
Object.assign(data, fileStats); | ||
} | ||
input = rr.combineDataKeys(data, keys); | ||
@@ -86,4 +123,6 @@ })); | ||
for (let i = 0; i < allPassOutputs.length; i += 2) { | ||
const file = result[allPassOutputs[i]]; | ||
const folder = input[allPassOutputs[i + 1]]; | ||
const file = result[allPassOutputs[i]] || | ||
input[allPassOutputs[i]]; | ||
const folder = result[allPassOutputs[i + 1]] || | ||
input[allPassOutputs[i + 1]]; | ||
if (!file) { | ||
@@ -117,4 +156,6 @@ throw new Error(`[FILES] url not defined`); | ||
for (let i = 0; i < allPassOutputs.length; i += 2) { | ||
const variable = result[allPassOutputs[i]]; | ||
const file = input[allPassOutputs[i + 1]]; | ||
const variable = result[allPassOutputs[i]] || | ||
input[allPassOutputs[i]]; | ||
const file = result[allPassOutputs[i + 1]] || | ||
input[allPassOutputs[i + 1]]; | ||
if (!variable) { | ||
@@ -121,0 +162,0 @@ throw new Error(`[FILES] variable not defined`); |
{ | ||
"name": "@restroom-mw/files", | ||
"version": "0.13.1-4c8a52e.19+4c8a52e", | ||
"version": "0.13.1-4f7fd4a.73+4f7fd4a", | ||
"description": "Utilities middleware to work with files for Restroom", | ||
@@ -35,3 +35,3 @@ "author": "Alberto Lerda <alberto@dyne.org>", | ||
}, | ||
"gitHead": "4c8a52eb3b411f3f545da13b9e9ad708d75e3608" | ||
"gitHead": "4f7fd4ac366156d253e0b10525dd308a445acbf4" | ||
} |
export const DOWNLOAD = "download the {} and extract it into {}"; | ||
export const STORE_RESULT = "store {} in the file {}"; | ||
export const READ = "read the content of {}"; | ||
export const LS = "list the content of directory {} as {}"; |
@@ -5,2 +5,3 @@ import {Restroom} from "@restroom-mw/core"; | ||
import fs from 'fs' | ||
import { readdir, stat } from 'node:fs/promises'; | ||
import os from 'os' | ||
@@ -10,2 +11,3 @@ import extract from 'extract-zip'; | ||
import {ObjectLiteral} from "@restroom-mw/types"; | ||
import {validateSubdir} from "@restroom-mw/utils" | ||
@@ -26,6 +28,5 @@ require("dotenv").config(); | ||
*/ | ||
import {STORE_RESULT} from "./actions"; | ||
import {READ} from "./actions"; | ||
import {READ, LS} from "./actions"; | ||
@@ -43,25 +44,15 @@ | ||
// save path must be subdirs of FILES_DIR | ||
const validatePath = (p: string) => { | ||
if (!FILES_DIR) | ||
throw new Error(`FILES_DIR is not defined`); | ||
const validatePath = validateSubdir(FILES_DIR); | ||
if (FILES_DIR != "/") { | ||
const relative = path.relative(FILES_DIR, p); | ||
const isSubdir = relative && !relative.startsWith('..') && !path.isAbsolute(relative); | ||
if (!isSubdir) { | ||
throw new Error(`Result path outside ${FILES_DIR}`) | ||
} | ||
} | ||
} | ||
export default (req: Request, res: Response, next: NextFunction) => { | ||
const rr = new Restroom(req, res); | ||
rr.onBefore(async (params) => { | ||
const { zencode, keys, data } = params; | ||
input = rr.combineDataKeys(data, keys); | ||
if (zencode.match(READ)) { | ||
const params = zencode.paramsOf(READ); | ||
for(const file of params) { | ||
for(const f of params) { | ||
const file = input[f] || f; | ||
validatePath(file); | ||
@@ -77,2 +68,46 @@ const absoluteFile = path.join(FILES_DIR, file) | ||
} | ||
if (zencode.match(LS)) { | ||
const params = zencode.chunkedParamsOf(LS, 2); | ||
const fileStats: Record<string, any> = {} | ||
const allLs = (await Promise.all(params.map( | ||
async ([p, name]: string[]) => { | ||
const f = input[p] || p; | ||
validatePath(f); | ||
try { | ||
const content = await readdir(f) | ||
// I am not checking if `name` is used multiple times | ||
fileStats[name] = [] | ||
return content.map((current) => [name, f, current]); | ||
} catch(e) { | ||
throw new Error(`[FILES] error while reading the file ${f}`); | ||
} | ||
}))).flat() | ||
// list with all files I want to see the stats of | ||
const allStats = await Promise.all(allLs.map(async ([name, p, current]) => { | ||
const currentFile = path.join(p, current) | ||
const fileStat = await stat(currentFile) | ||
return [name, current, fileStat] | ||
})) | ||
for(const [name, current, currentStat] of allStats) { | ||
// see https://unix.stackexchange.com/questions/317855/file-mode-on-macosx#317907 | ||
// for the meaning of the mode field | ||
fileStats[name].push({ | ||
'name': current, | ||
'mode': currentStat.mode.toString(8), | ||
'dev': currentStat.dev, | ||
'nlink': currentStat.nlink, | ||
'uid': currentStat.uid, | ||
'gid': currentStat.gid, | ||
'size': currentStat.size, | ||
'blksize': currentStat.blksize, | ||
'blocks': currentStat.blocks, | ||
'atime': currentStat.atime.toISOString(), | ||
'mtime': currentStat.mtime.toISOString(), | ||
'ctime': currentStat.ctime.toISOString(), | ||
'birthtime': currentStat.birthtime.toISOString(), | ||
}) | ||
} | ||
Object.assign(data, fileStats) | ||
} | ||
input = rr.combineDataKeys(data, keys); | ||
@@ -86,4 +121,6 @@ }); | ||
for (let i = 0; i < allPassOutputs.length; i += 2) { | ||
const file = result[allPassOutputs[i]] | ||
const folder = input[allPassOutputs[i + 1]]; | ||
const file = result[allPassOutputs[i]] || | ||
input[allPassOutputs[i]]; | ||
const folder = result[allPassOutputs[i + 1]] || | ||
input[allPassOutputs[i + 1]]; | ||
@@ -119,4 +156,6 @@ if(!file) { | ||
for (let i = 0; i < allPassOutputs.length; i += 2) { | ||
const variable = result[allPassOutputs[i]] | ||
const file = input[allPassOutputs[i + 1]] | ||
const variable = result[allPassOutputs[i]] || | ||
input[allPassOutputs[i]]; | ||
const file = result[allPassOutputs[i + 1]] || | ||
input[allPassOutputs[i + 1]]; | ||
@@ -123,0 +162,0 @@ if(!variable) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
51717
362