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 }