Files
myDrive/backend/services/chunk-service/utils/getPublicFileData.ts
T
2024-12-22 16:39:59 -05:00

106 lines
2.9 KiB
TypeScript

import { EventEmitter } from "stream";
import { UserInterface } from "../../../models/user-model";
import { Response } from "express";
import ForbiddenError from "../../../utils/ForbiddenError";
import NotFoundError from "../../../utils/NotFoundError";
import crypto from "crypto";
import { createGenericParams } from "./storageHelper";
import { getStorageActions } from "../actions/helper-actions";
import FileDB from "../../../db/mongoDB/fileDB";
import NotAuthorizedError from "../../../utils/NotAuthorizedError";
import UserDB from "../../../db/mongoDB/userDB";
const fileDB = new FileDB();
const userDB = new UserDB();
const storageActions = getStorageActions();
const proccessData = (res: Response, fileID: string, tempToken: string) => {
const eventEmitter = new EventEmitter();
const processFile = async () => {
try {
const file = await fileDB.getPublicFile(fileID);
if (!file || !file.metadata.link || file.metadata.link !== tempToken) {
throw new NotAuthorizedError("File Not Public");
}
if (file.metadata.linkType === "one") {
await fileDB.removeOneTimePublicLink(fileID);
}
const user = await userDB.getUserInfo(file.metadata.owner);
if (!user) throw new NotFoundError("User Not Found");
const password = user.getEncryptionKey();
if (!password) throw new ForbiddenError("Invalid Encryption Key");
const IV = file.metadata.IV;
const readStreamParams = createGenericParams({
filePath: file.metadata.filePath,
Key: file.metadata.s3ID,
});
const readStream = storageActions.createReadStream(readStreamParams);
const CIPHER_KEY = crypto.createHash("sha256").update(password).digest();
const decipher = crypto.createDecipheriv("aes256", CIPHER_KEY, IV);
decipher.on("error", (e: Error) => {
eventEmitter.emit("error", e);
});
readStream.on("error", (e: Error) => {
eventEmitter.emit("error", e);
});
res.on("error", (e: Error) => {
eventEmitter.emit("error", e);
});
res.set("Content-Type", "binary/octet-stream");
res.set(
"Content-Disposition",
'attachment; filename="' + file.filename + '"'
);
res.set("Content-Length", file.metadata.size.toString());
readStream
.pipe(decipher)
.pipe(res)
.on("finish", () => {
eventEmitter.emit("finish");
});
} catch (e) {
eventEmitter.emit("error", e);
}
};
processFile();
return eventEmitter;
};
const getPublicFileData = (
res: Response,
fileID: string,
tempToken: string
) => {
return new Promise((resolve, reject) => {
const eventEmitter = proccessData(res, fileID, tempToken);
eventEmitter.on("finish", (data) => {
resolve(data);
});
eventEmitter.on("error", (e) => {
reject(e);
});
});
};
export default getPublicFileData;