WebService/services/productsFileService.js
2026-01-27 22:43:59 +01:00

106 lines
3.4 KiB
JavaScript

const fs = require("node:fs")
const path = require("node:path")
const crypto = require("node:crypto")
const { DefaultError } = require("../errors/errors")
const { pipeline } = require("node:stream/promises")
const productsDataPath = path.join(process.cwd(), "data", "products")
fs.promises.exists = async function exists(path) {
try {
await fs.promises.access(path)
return true
} catch {
return false
}
};
function normalizePath($path) {
return $path.split(path.win32.sep).join(path.posix.sep)
}
async function getFileSha1(filePath) {
const hash = crypto.createHash("sha1")
const readStream = fs.createReadStream(filePath)
try {
await pipeline(readStream, hash)
return hash.digest("hex")
} catch (error) {
throw new Error(`Error when calculating SHA-1 hash: ${error.message}`);
}
}
async function getProductFiles(productName, platform) {
const finalPath = path.join(productsDataPath, productName, platform)
const files = await fs.promises.readdir(finalPath, { recursive: true })
const productFilesIndex = { root: [] }
for (const file of files) {
const filePath = path.join(finalPath, file)
const fileMetadata = await fs.promises.stat(filePath)
if (!fileMetadata.isDirectory() && !filePath.endsWith(".brikcfg")) {
const normalizedFilePath = normalizePath(file)
const artifact = {
path: normalizedFilePath,
sha1: await getFileSha1(filePath),
size: fileMetadata.size,
url: (process.env.BASE_POINT || "") + normalizedFilePath
}
const downloadObject = {
downloads: {
artifact,
},
name: path.parse(normalizedFilePath).base
}
productFilesIndex.root.push(downloadObject)
}
}
return productFilesIndex
}
async function getFile(basePath, productName, productPlatform) {
try {
const fixedPath = path.join(productsDataPath, productName, productPlatform, decodeURI(basePath))
const fileMetadata = await fs.promises.stat(fixedPath)
if (fileMetadata.isDirectory()) {
throw new DefaultError(409, "Can't download a directory", "", "NotDownloadableException")
}
return { code: 200, path: fixedPath }
} catch (error) {
if (error.code == "ENOENT") {
throw new DefaultError(404, "File not found", "", "NotFoundException")
} else {
throw error
}
}
}
async function canAccess(productName, productPlatform) {
const fixedPath = path.join(productsDataPath, productName, productPlatform, ".brikcfg")
const fileState = await fs.promises.exists(fixedPath, fs.constants.F_OK)
if (!fileState) {
return { code: 200 }
}
try {
const brikConfig = JSON.parse(await fs.promises.readFile(fixedPath))
if (!brikConfig.canAccess) {
throw new DefaultError(403, "Forbidden", "Locked resource.", "InsuffisentPrivilegeException")
}
return { code: 200 }
} catch (error) {
if (!error instanceof DefaultError) {
throw new DefaultError(500, "Please contact the maintener", "CONFIGURATION", "0x00")
}
throw error
}
}
module.exports = {
getFile,
canAccess,
getFileSha1,
getProductFiles
}