From ef191fb27575a0b63a922c103acfcc4ee76ae080 Mon Sep 17 00:00:00 2001 From: subnub Date: Mon, 13 Apr 2020 15:55:27 -0400 Subject: [PATCH] Added more typescript files --- backend/controllers/file.ts | 88 +++--- backend/express-routers/file.ts | 6 +- backend/middleware/auth.js | 4 +- backend/middleware/tempAuth.js | 2 +- backend/middleware/tempAuthVideo.js | 2 +- backend/models/user.ts | 2 +- backend/services/ChunkService/MongoService.ts | 262 +++++++++++++++++- backend/services/FileService/index.js | 2 +- backend/services/FileService/indexnew.ts | 24 -- ...{createThumbnail.js => createThumbnail.ts} | 26 +- backend/services/UserService/index.js | 2 +- dist/controllers/file.js | 97 ++++--- dist/express-routers/file.js | 6 +- dist/middleware/auth.js | 8 +- dist/middleware/tempAuth.js | 8 +- dist/middleware/tempAuthVideo.js | 8 +- dist/models/user.js | 2 +- dist/services/ChunkService/MongoService.js | 194 +++++++++++++ dist/services/FileService/index.js | 2 +- dist/services/FileService/indexnew.js | 14 - .../FileService/utils/createThumbnail.js | 17 +- dist/services/UserService/index.js | 10 +- 22 files changed, 613 insertions(+), 173 deletions(-) rename backend/services/FileService/utils/{createThumbnail.js => createThumbnail.ts} (77%) diff --git a/backend/controllers/file.ts b/backend/controllers/file.ts index f55db61..0be8d10 100644 --- a/backend/controllers/file.ts +++ b/backend/controllers/file.ts @@ -39,7 +39,7 @@ class FileController { const user = req.user; const id = req.params.id; - const decryptedThumbnail = await fileService.getThumbnail(user, id); + const decryptedThumbnail = await mongoService.getThumbnail(user, id); res.send(decryptedThumbnail); @@ -53,71 +53,71 @@ class FileController { } - // async getFullThumbnail(req: RequestType, res: Response) { + async getFullThumbnail(req: RequestType, res: Response) { - // if (!req.user) { - // return; - // } + if (!req.user) { + return; + } - // try { + try { - // const user = req.user; - // const fileID = req.params.id; + const user = req.user; + const fileID = req.params.id; - // await fileService.getFullThumbnail(user, fileID, res); + await mongoService.getFullThumbnail(user, fileID, res); - // } catch (e) { - // const code = e.code || 500; - // console.log(e.message, e.exception) - // return res.status(code).send(); - // } - // } + } catch (e) { + const code = e.code || 500; + console.log(e.message, e.exception) + return res.status(code).send(); + } + } - // async uploadFile(req: RequestType, res: Response) { + async uploadFile(req: RequestType, res: Response) { - // if (!req.user) { + if (!req.user) { - // return - // } + return + } - // try { + try { - // const user = req.user; - // const busboy = req.busboy; + const user = req.user; + const busboy = req.busboy; - // req.pipe(busboy); + req.pipe(busboy); - // const file = await fileService.upload(user, busboy, req); + const file = await mongoService.uploadFile(user, busboy, req); - // res.send(file); + res.send(file); - // console.log("file uploaded"); + console.log("file uploaded"); - // } catch (e) { - // const code = e.code || 500; - // console.log(e.message, e.exception) - // return res.status(code).send(); - // } - // } + } catch (e) { + const code = e.code || 500; + console.log(e.message, e.exception) + return res.status(code).send(); + } + } - // async getPublicDownload(req: RequestType, res: Response) { + async getPublicDownload(req: RequestType, res: Response) { - // try { + try { - // const ID = req.params.id; - // const tempToken = req.params.tempToken; + const ID = req.params.id; + const tempToken = req.params.tempToken; - // await fileService.publicDownload(ID, tempToken, res); + await mongoService.getPublicDownload(ID, tempToken, res); - // } catch (e) { + } catch (e) { - // const code = e.code || 500; - // const message = e.message || e; + const code = e.code || 500; + const message = e.message || e; - // console.log(message, e); - // res.status(code).send(); - // } - // } + console.log(message, e); + res.status(code).send(); + } + } async removeLink(req: RequestType, res: Response) { diff --git a/backend/express-routers/file.ts b/backend/express-routers/file.ts index 35d46e4..d745ef4 100644 --- a/backend/express-routers/file.ts +++ b/backend/express-routers/file.ts @@ -10,15 +10,15 @@ import FileController from "../controllers/file"; const fileController = new FileController() -//router.post("/file-service/upload", auth, fileController.uploadFile); +router.post("/file-service/upload", auth, fileController.uploadFile); //router.post("/file-service/transcode-video", auth, fileController.transcodeVideo); router.get("/file-service/thumbnail/:id", auth, fileController.getThumbnail); -//router.get("/file-service/full-thumbnail/:id", auth, fileController.getFullThumbnail); +router.get("/file-service/full-thumbnail/:id", auth, fileController.getFullThumbnail); -//router.get("/file-service/public/download/:id/:tempToken", fileController.getPublicDownload); +router.get("/file-service/public/download/:id/:tempToken", fileController.getPublicDownload); router.get("/file-service/public/info/:id/:tempToken", fileController.getPublicInfo); diff --git a/backend/middleware/auth.js b/backend/middleware/auth.js index 35085f2..8c70bb3 100644 --- a/backend/middleware/auth.js +++ b/backend/middleware/auth.js @@ -1,5 +1,5 @@ const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +import User from "../models/user"; const env = require("../enviroment/env"); const auth = async(req, res, next) => { @@ -11,7 +11,7 @@ const auth = async(req, res, next) => { const decoded = await jwt.verify(token, env.password); const iv = decoded.iv; - + const user = await User.findOne({_id: decoded._id}); const encrpytionKey = user.getEncryptionKey(); diff --git a/backend/middleware/tempAuth.js b/backend/middleware/tempAuth.js index 06dec37..8638520 100644 --- a/backend/middleware/tempAuth.js +++ b/backend/middleware/tempAuth.js @@ -1,5 +1,5 @@ const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +import User from "../models/user"; const env = require("../enviroment/env"); const tempAuth = async(req, res, next) => { diff --git a/backend/middleware/tempAuthVideo.js b/backend/middleware/tempAuthVideo.js index 3f62d06..1ae1861 100644 --- a/backend/middleware/tempAuthVideo.js +++ b/backend/middleware/tempAuthVideo.js @@ -1,5 +1,5 @@ const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +import User from "../models/user"; const env = require("../enviroment/env"); const tempAuthVideo = async(req, res, next) => { diff --git a/backend/models/user.ts b/backend/models/user.ts index 0ee9243..fe64aea 100644 --- a/backend/models/user.ts +++ b/backend/models/user.ts @@ -290,4 +290,4 @@ userSchema.methods.generateTempAuthTokenVideo = async function(cookie: string) { const User = mongoose.model("User", userSchema); -module.exports = User; \ No newline at end of file +export default User; \ No newline at end of file diff --git a/backend/services/ChunkService/MongoService.ts b/backend/services/ChunkService/MongoService.ts index ecd9830..ecf2449 100644 --- a/backend/services/ChunkService/MongoService.ts +++ b/backend/services/ChunkService/MongoService.ts @@ -1,15 +1,20 @@ import mongoose from "../../db/mongoose"; -import {Response} from "express"; +import {Response, Request} from "express"; const conn = mongoose.connection; const env = require("../../enviroment/env"); const DbUtilFolder = require("../../db/utils/folderUtils"); import DbUtilFile from "../../db/utils/fileUtils/index"; import crypto from "crypto"; - +const videoChecker = require("../../utils/videoChecker"); +const imageChecker = require("../../utils/imageChecker"); const ObjectID = require('mongodb').ObjectID +import createThumbnail from "../FileService/utils/createThumbnail"; +import Thumbnail, {ThumbnailInterface} from "../../models/thumbnail"; +import NotAuthorizedError from "../../utils/NotAuthorizedError"; -import { UserInterface } from "../../models/user"; +import User, { UserInterface } from "../../models/user"; import { FileInterface } from "../../models/file"; +const removeChunks = require("../FileService/utils/removeChunks"); const dbUtilsFile = new DbUtilFile(); const dbUtilsFolder = new DbUtilFolder(); @@ -20,6 +25,112 @@ class MongoService { } + uploadFile = (user: UserInterface, busboy: any, req: Request) => { + + return new Promise((resolve, reject) => { + + const password = user.getEncryptionKey(); + + let bucketStream: any; + + const initVect = crypto.randomBytes(16); + + const CIPHER_KEY = crypto.createHash('sha256').update(password).digest() + + const cipher = crypto.createCipheriv('aes256', CIPHER_KEY, initVect); + + cipher.on("error", async(e) => { + await removeChunks(bucketStream); + reject({ + message: "File service upload cipher error", + exception: e, + code: 500 + }) + }) + + const formData = new Map(); + + busboy.on("error", async(e: Error) => { + await removeChunks(bucketStream); + reject({ + message: "File service upload busboy error", + exception: e, + code: 500 + }) + }) + + busboy.on("file", async(_: string, file: any, filename: string) => { + + const parent = formData.get("parent") || "/" + const parentList = formData.get("parentList") || "/"; + const size = formData.get("size") || "" + let hasThumbnail = false; + let thumbnailID = "" + const isVideo = videoChecker(filename) + + const metadata = { + owner: user._id, + parent, + parentList, + hasThumbnail, + thumbnailID, + isVideo, + size, + IV: initVect + } + + + let bucket = new mongoose.mongo.GridFSBucket(conn.db, { + chunkSizeBytes: 1024 * 255 + }); + + + bucketStream = bucket.openUploadStream(filename, {metadata}) + + bucketStream.on("error", async(e: Error) => { + await removeChunks(bucketStream); + reject({ + message: "Cannot upload file to database", + exception: e, + code: 500 + }) + }) + + req.on("aborted", async() => { + + console.log("Upload Request Cancelling..."); + + await removeChunks(bucketStream); + }) + + file.pipe(cipher).pipe(bucketStream); + + bucketStream.on("finish", (file: FileInterface) => { + + const imageCheck = imageChecker(filename); + + if (file.length < 15728640 && imageCheck) { + + createThumbnail(file, filename, user).then((updatedFile: FileInterface) => { + resolve(updatedFile); + }) + + } else { + + resolve(file); + } + + }) + + }).on("field", (field: any, val: any) => { + + formData.set(field, val) + + }) + + }) + } + downloadFile = (user: UserInterface, fileID: string, res: Response) => { return new Promise((resolve, reject) => { @@ -76,6 +187,151 @@ class MongoService { }) } + getThumbnail = async(user: UserInterface, id: string) => { + + const password: Buffer = user.getEncryptionKey(); + + const thumbnail = await Thumbnail.findById(id) as ThumbnailInterface; + + if (thumbnail.owner !== user._id.toString()) { + + throw new NotAuthorizedError('Thumbnail Unauthorized Error'); + } + + const iv = thumbnail.data.slice(0, 16); + + const chunk = thumbnail.data.slice(16); + + const CIPHER_KEY = crypto.createHash('sha256').update(password).digest() + + const decipher = crypto.createDecipheriv("aes256", CIPHER_KEY, iv); + + const decryptedThumbnail = Buffer.concat([decipher.update(chunk), decipher.final()]); + + return decryptedThumbnail; + } + + getFullThumbnail = (user: UserInterface, fileID: string, res: Response) => { + + return new Promise((resolve, reject) => { + + const userID = user._id; + + dbUtilsFile.getFileInfo(fileID, userID).then((file) => { + + if (!file) { + reject({ + code: 401, + message: "File For Full Thumbnail Not Found", + exception: undefined + }) + } + + const bucket = new mongoose.mongo.GridFSBucket(conn.db, { + chunkSizeBytes: 1024 * 255, + }) + const password = user.getEncryptionKey(); + const IV = file.metadata.IV.buffer + + const readStream = bucket.openDownloadStream(ObjectID(fileID)) + + readStream.on("error", (e) => { + reject({ + code: 500, + message: "File service Full Thumbnail stream error", + exception: e + }) + }) + + const CIPHER_KEY = crypto.createHash('sha256').update(password).digest() + + const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, IV); + + decipher.on("error", (e) => { + reject({ + code: 500, + message: "File service Full Thumbnail decipher error", + exception: e + }) + }) + + res.set('Content-Type', 'binary/octet-stream'); + res.set('Content-Disposition', 'attachment; filename="' + file.filename + '"'); + res.set('Content-Length', file.metadata.size); + + readStream.pipe(decipher).pipe(res).on("finish", async() => { + console.log("Sent Full Thumbnail"); + resolve(); + }); + }); + }) + + } + + getPublicDownload = (fileID: string, tempToken: any, res: Response) => { + + return new Promise((resolve, reject) => { + + dbUtilsFile.getPublicFile(fileID).then(async(file: FileInterface) => { + + if (!file || !file.metadata.link || file.metadata.link !== tempToken) { + reject({ + code: 401, + message: "File not public/Not found", + exception: undefined + }) + } else { + + const user = await User.findById(file.metadata.owner) as UserInterface; + + const bucket = new mongoose.mongo.GridFSBucket(conn.db, { + chunkSizeBytes: 1024 * 255, + }) + + const password = user.getEncryptionKey(); + const IV = file.metadata.IV.buffer + + const readStream = bucket.openDownloadStream(ObjectID(fileID)) + + readStream.on("error", (e) => { + reject({ + code: 500, + message: "File service public download decipher error", + exception: e + }) + }) + + const CIPHER_KEY = crypto.createHash('sha256').update(password).digest() + + const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, IV); + + decipher.on("error", (e) => { + reject({ + code: 500, + message: "File service public download decipher error", + exception: 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", async() => { + + if (file.metadata.linkType === "one") { + console.log("removing public link"); + await dbUtilsFile.removeOneTimePublicLink(fileID); + } + resolve(); + }); + + } + + }) + }) + } + } export default MongoService; \ No newline at end of file diff --git a/backend/services/FileService/index.js b/backend/services/FileService/index.js index abe4686..7fc7860 100644 --- a/backend/services/FileService/index.js +++ b/backend/services/FileService/index.js @@ -3,7 +3,7 @@ import crypto from "crypto"; const videoChecker = require("../../utils/videoChecker"); const mongoose = require("../../db/mongoose") const conn = mongoose.connection; -const createThumbnail = require("./utils/createThumbnail"); +const createThumbnail = require("./utils/createThumbnail.ss"); const Thumbnail = require("../../models/thumbnail"); const ObjectID = require('mongodb').ObjectID const NotAuthorizedError = require("../../utils/NotAuthorizedError"); diff --git a/backend/services/FileService/indexnew.ts b/backend/services/FileService/indexnew.ts index 7092fdc..90338ed 100644 --- a/backend/services/FileService/indexnew.ts +++ b/backend/services/FileService/indexnew.ts @@ -36,30 +36,6 @@ class MongoFileService { } - getThumbnail = async(user: UserInterface, id: string) => { - - const password: Buffer = user.getEncryptionKey(); - - const thumbnail = await Thumbnail.findById(id) as ThumbnailInterface; - - if (thumbnail.owner !== user._id.toString()) { - - throw new NotAuthorizedError('Thumbnail Unauthorized Error'); - } - - const iv = thumbnail.data.slice(0, 16); - - const chunk = thumbnail.data.slice(16); - - const CIPHER_KEY = crypto.createHash('sha256').update(password).digest() - - const decipher = crypto.createDecipheriv("aes256", CIPHER_KEY, iv); - - const decryptedThumbnail = Buffer.concat([decipher.update(chunk), decipher.final()]); - - return decryptedThumbnail; - } - removePublicOneTimeLink = async(currentFile: FileInterface) => { const fileID = currentFile._id; diff --git a/backend/services/FileService/utils/createThumbnail.js b/backend/services/FileService/utils/createThumbnail.ts similarity index 77% rename from backend/services/FileService/utils/createThumbnail.js rename to backend/services/FileService/utils/createThumbnail.ts index 8a43a3f..d7aa0e2 100644 --- a/backend/services/FileService/utils/createThumbnail.js +++ b/backend/services/FileService/utils/createThumbnail.ts @@ -2,14 +2,16 @@ const mongoose = require("../../../db/mongoose") const conn = mongoose.connection; const crypto= require("crypto"); const env = require("../../../enviroment/env"); -const Thumbnail = require("../../../models/thumbnail"); +import Thumbnail from "../../../models/thumbnail"; const ObjectID = require('mongodb').ObjectID const sharp = require("sharp"); const concat = require("concat-stream") +import {FileInterface} from "../../../models/file"; +import {UserInterface} from "../../../models/user"; -const createThumbnail = async(file, filename, user) => { +const createThumbnail = (file: FileInterface, filename: string, user: UserInterface) => { - return new Promise((resolve) => { + return new Promise((resolve) => { const password = user.getEncryptionKey(); @@ -21,29 +23,27 @@ const createThumbnail = async(file, filename, user) => { const readStream = bucket.openDownloadStream(ObjectID(file._id)) - readStream.on("error", (e) => { + readStream.on("error", (e: Error) => { console.log("File service upload thumbnail error", e); resolve(file); }) const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, file.metadata.IV); - decipher.on("error", (e) => { + decipher.on("error", (e: Error) => { console.log("File service upload thumbnail decipher error", e); resolve(file) }) try { - const concatStream = concat(async(bufferData) => { + const concatStream = concat(async(bufferData: Buffer) => { - const thumbnailIV = crypto.randomBytes(16); - - //CIPHER_KEY = crypto.createHash('sha256').update(process.env.newPassword).digest() + const thumbnailIV = crypto.randomBytes(16); const thumbnailCipher = crypto.createCipheriv("aes256", CIPHER_KEY, thumbnailIV); - bufferData = Buffer.concat([thumbnailIV, thumbnailCipher.update(bufferData), thumbnailCipher.final()]); //thumbnailCipher.update(bufferData) + bufferData = Buffer.concat([thumbnailIV, thumbnailCipher.update(bufferData), thumbnailCipher.final()]); const thumbnailModel = new Thumbnail({name: filename, owner: user._id, data: bufferData}); @@ -58,12 +58,12 @@ const createThumbnail = async(file, filename, user) => { resolve(updatedFile); - }).on("error", (e) => { + }).on("error", (e: Error) => { console.log("File service upload concat stream error", e); resolve(file); }) - const imageResize = sharp().resize(300).on("error", (e) => { + const imageResize = sharp().resize(300).on("error", (e: Error) => { console.log("resize error", e); resolve(file); @@ -81,4 +81,4 @@ const createThumbnail = async(file, filename, user) => { }) } -module.exports = createThumbnail; \ No newline at end of file +export default createThumbnail; \ No newline at end of file diff --git a/backend/services/UserService/index.js b/backend/services/UserService/index.js index b18ed44..48c376d 100644 --- a/backend/services/UserService/index.js +++ b/backend/services/UserService/index.js @@ -1,4 +1,4 @@ -const User = require("../../models/user"); +import User from "../../models/user"; const bcrypt = require("bcrypt"); const crypto = require("crypto"); const NotFoundError = require("../../utils/NotFoundError"); diff --git a/dist/controllers/file.js b/dist/controllers/file.js index e8b5ae4..5128b84 100644 --- a/dist/controllers/file.js +++ b/dist/controllers/file.js @@ -27,7 +27,7 @@ class FileController { try { const user = req.user; const id = req.params.id; - const decryptedThumbnail = yield fileService.getThumbnail(user, id); + const decryptedThumbnail = yield mongoService.getThumbnail(user, id); res.send(decryptedThumbnail); } catch (e) { @@ -37,49 +37,58 @@ class FileController { } }); } - // async getFullThumbnail(req: RequestType, res: Response) { - // if (!req.user) { - // return; - // } - // try { - // const user = req.user; - // const fileID = req.params.id; - // await fileService.getFullThumbnail(user, fileID, res); - // } catch (e) { - // const code = e.code || 500; - // console.log(e.message, e.exception) - // return res.status(code).send(); - // } - // } - // async uploadFile(req: RequestType, res: Response) { - // if (!req.user) { - // return - // } - // try { - // const user = req.user; - // const busboy = req.busboy; - // req.pipe(busboy); - // const file = await fileService.upload(user, busboy, req); - // res.send(file); - // console.log("file uploaded"); - // } catch (e) { - // const code = e.code || 500; - // console.log(e.message, e.exception) - // return res.status(code).send(); - // } - // } - // async getPublicDownload(req: RequestType, res: Response) { - // try { - // const ID = req.params.id; - // const tempToken = req.params.tempToken; - // await fileService.publicDownload(ID, tempToken, res); - // } catch (e) { - // const code = e.code || 500; - // const message = e.message || e; - // console.log(message, e); - // res.status(code).send(); - // } - // } + getFullThumbnail(req, res) { + return __awaiter(this, void 0, void 0, function* () { + if (!req.user) { + return; + } + try { + const user = req.user; + const fileID = req.params.id; + yield mongoService.getFullThumbnail(user, fileID, res); + } + catch (e) { + const code = e.code || 500; + console.log(e.message, e.exception); + return res.status(code).send(); + } + }); + } + uploadFile(req, res) { + return __awaiter(this, void 0, void 0, function* () { + if (!req.user) { + return; + } + try { + const user = req.user; + const busboy = req.busboy; + req.pipe(busboy); + const file = yield mongoService.uploadFile(user, busboy, req); + res.send(file); + console.log("file uploaded"); + } + catch (e) { + const code = e.code || 500; + console.log(e.message, e.exception); + return res.status(code).send(); + } + }); + } + getPublicDownload(req, res) { + return __awaiter(this, void 0, void 0, function* () { + try { + const ID = req.params.id; + const tempToken = req.params.tempToken; + yield mongoService.getPublicDownload(ID, tempToken, res); + } + catch (e) { + const code = e.code || 500; + const message = e.message || e; + console.log(message, e); + res.status(code).send(); + } + }); + } removeLink(req, res) { return __awaiter(this, void 0, void 0, function* () { if (!req.user) { diff --git a/dist/express-routers/file.js b/dist/express-routers/file.js index 89692aa..3bc151e 100644 --- a/dist/express-routers/file.js +++ b/dist/express-routers/file.js @@ -10,11 +10,11 @@ const tempAuth = require("../middleware/tempAuth"); const tempAuthVideo = require("../middleware/tempAuthVideo"); const file_1 = __importDefault(require("../controllers/file")); const fileController = new file_1.default(); -//router.post("/file-service/upload", auth, fileController.uploadFile); +router.post("/file-service/upload", auth, fileController.uploadFile); //router.post("/file-service/transcode-video", auth, fileController.transcodeVideo); router.get("/file-service/thumbnail/:id", auth, fileController.getThumbnail); -//router.get("/file-service/full-thumbnail/:id", auth, fileController.getFullThumbnail); -//router.get("/file-service/public/download/:id/:tempToken", fileController.getPublicDownload); +router.get("/file-service/full-thumbnail/:id", auth, fileController.getFullThumbnail); +router.get("/file-service/public/download/:id/:tempToken", fileController.getPublicDownload); router.get("/file-service/public/info/:id/:tempToken", fileController.getPublicInfo); router.get("/file-service/info/:id", auth, fileController.getFileInfo); router.get("/file-service/quick-list", auth, fileController.getQuickList); diff --git a/dist/middleware/auth.js b/dist/middleware/auth.js index e00bb45..0af0b65 100644 --- a/dist/middleware/auth.js +++ b/dist/middleware/auth.js @@ -8,15 +8,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +const user_1 = __importDefault(require("../models/user")); const env = require("../enviroment/env"); const auth = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () { try { const token = req.header("Authorization").replace("Bearer ", ""); const decoded = yield jwt.verify(token, env.password); const iv = decoded.iv; - const user = yield User.findOne({ _id: decoded._id }); + const user = yield user_1.default.findOne({ _id: decoded._id }); const encrpytionKey = user.getEncryptionKey(); const encryptedToken = user.encryptToken(token, encrpytionKey, iv); let tokenFound = false; diff --git a/dist/middleware/tempAuth.js b/dist/middleware/tempAuth.js index 206a31b..6cf4982 100644 --- a/dist/middleware/tempAuth.js +++ b/dist/middleware/tempAuth.js @@ -8,15 +8,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +const user_1 = __importDefault(require("../models/user")); const env = require("../enviroment/env"); const tempAuth = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () { try { const token = req.params.tempToken; const decoded = yield jwt.verify(token, env.password); const iv = decoded.iv; - const user = yield User.findOne({ _id: decoded._id }); + const user = yield user_1.default.findOne({ _id: decoded._id }); const encrpytionKey = user.getEncryptionKey(); const encryptedToken = user.encryptToken(token, encrpytionKey, iv); let tokenFound = false; diff --git a/dist/middleware/tempAuthVideo.js b/dist/middleware/tempAuthVideo.js index 5cb9f1f..3f8931c 100644 --- a/dist/middleware/tempAuthVideo.js +++ b/dist/middleware/tempAuthVideo.js @@ -8,8 +8,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const jwt = require("jsonwebtoken"); -const User = require("../models/user"); +const user_1 = __importDefault(require("../models/user")); const env = require("../enviroment/env"); const tempAuthVideo = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () { try { @@ -19,7 +23,7 @@ const tempAuthVideo = (req, res, next) => __awaiter(void 0, void 0, void 0, func if (req.params.uuid !== decoded.cookie) { throw new Error("Cookie mismatch"); } - const user = yield User.findOne({ _id: decoded._id }); + const user = yield user_1.default.findOne({ _id: decoded._id }); const encrpytionKey = user.getEncryptionKey(); const encryptedToken = user.encryptToken(token, encrpytionKey, iv); let tokenFound = false; diff --git a/dist/models/user.js b/dist/models/user.js index c7344e2..e0ec58b 100644 --- a/dist/models/user.js +++ b/dist/models/user.js @@ -221,4 +221,4 @@ userSchema.methods.generateTempAuthTokenVideo = function (cookie) { }); }; const User = mongoose_1.default.model("User", userSchema); -module.exports = User; +exports.default = User; diff --git a/dist/services/ChunkService/MongoService.js b/dist/services/ChunkService/MongoService.js index 8b84ff7..47cd435 100644 --- a/dist/services/ChunkService/MongoService.js +++ b/dist/services/ChunkService/MongoService.js @@ -1,4 +1,13 @@ "use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -9,11 +18,92 @@ const env = require("../../enviroment/env"); const DbUtilFolder = require("../../db/utils/folderUtils"); const index_1 = __importDefault(require("../../db/utils/fileUtils/index")); const crypto_1 = __importDefault(require("crypto")); +const videoChecker = require("../../utils/videoChecker"); +const imageChecker = require("../../utils/imageChecker"); const ObjectID = require('mongodb').ObjectID; +const createThumbnail_1 = __importDefault(require("../FileService/utils/createThumbnail")); +const thumbnail_1 = __importDefault(require("../../models/thumbnail")); +const NotAuthorizedError_1 = __importDefault(require("../../utils/NotAuthorizedError")); +const user_1 = __importDefault(require("../../models/user")); +const removeChunks = require("../FileService/utils/removeChunks"); const dbUtilsFile = new index_1.default(); const dbUtilsFolder = new DbUtilFolder(); class MongoService { constructor() { + this.uploadFile = (user, busboy, req) => { + return new Promise((resolve, reject) => { + const password = user.getEncryptionKey(); + let bucketStream; + const initVect = crypto_1.default.randomBytes(16); + const CIPHER_KEY = crypto_1.default.createHash('sha256').update(password).digest(); + const cipher = crypto_1.default.createCipheriv('aes256', CIPHER_KEY, initVect); + cipher.on("error", (e) => __awaiter(this, void 0, void 0, function* () { + yield removeChunks(bucketStream); + reject({ + message: "File service upload cipher error", + exception: e, + code: 500 + }); + })); + const formData = new Map(); + busboy.on("error", (e) => __awaiter(this, void 0, void 0, function* () { + yield removeChunks(bucketStream); + reject({ + message: "File service upload busboy error", + exception: e, + code: 500 + }); + })); + busboy.on("file", (_, file, filename) => __awaiter(this, void 0, void 0, function* () { + const parent = formData.get("parent") || "/"; + const parentList = formData.get("parentList") || "/"; + const size = formData.get("size") || ""; + let hasThumbnail = false; + let thumbnailID = ""; + const isVideo = videoChecker(filename); + const metadata = { + owner: user._id, + parent, + parentList, + hasThumbnail, + thumbnailID, + isVideo, + size, + IV: initVect + }; + let bucket = new mongoose_1.default.mongo.GridFSBucket(conn.db, { + chunkSizeBytes: 1024 * 255 + }); + bucketStream = bucket.openUploadStream(filename, { metadata }); + bucketStream.on("error", (e) => __awaiter(this, void 0, void 0, function* () { + yield removeChunks(bucketStream); + reject({ + message: "Cannot upload file to database", + exception: e, + code: 500 + }); + })); + req.on("aborted", () => __awaiter(this, void 0, void 0, function* () { + console.log("Upload Request Cancelling..."); + yield removeChunks(bucketStream); + })); + file.pipe(cipher).pipe(bucketStream); + bucketStream.on("finish", (file) => { + const imageCheck = imageChecker(filename); + if (file.length < 15728640 && imageCheck) { + createThumbnail_1.default(file, filename, user).then((updatedFile) => { + resolve(updatedFile); + }); + } + else { + resolve(file); + } + }); + })).on("field", (field, val) => { + formData.set(field, val); + }); + }); + }; this.downloadFile = (user, fileID, res) => { return new Promise((resolve, reject) => { dbUtilsFile.getFileInfo(fileID, user._id).then((currentFile) => { @@ -55,6 +145,110 @@ class MongoService { }); }); }; + this.getThumbnail = (user, id) => __awaiter(this, void 0, void 0, function* () { + const password = user.getEncryptionKey(); + const thumbnail = yield thumbnail_1.default.findById(id); + if (thumbnail.owner !== user._id.toString()) { + throw new NotAuthorizedError_1.default('Thumbnail Unauthorized Error'); + } + const iv = thumbnail.data.slice(0, 16); + const chunk = thumbnail.data.slice(16); + const CIPHER_KEY = crypto_1.default.createHash('sha256').update(password).digest(); + const decipher = crypto_1.default.createDecipheriv("aes256", CIPHER_KEY, iv); + const decryptedThumbnail = Buffer.concat([decipher.update(chunk), decipher.final()]); + return decryptedThumbnail; + }); + this.getFullThumbnail = (user, fileID, res) => { + return new Promise((resolve, reject) => { + const userID = user._id; + dbUtilsFile.getFileInfo(fileID, userID).then((file) => { + if (!file) { + reject({ + code: 401, + message: "File For Full Thumbnail Not Found", + exception: undefined + }); + } + const bucket = new mongoose_1.default.mongo.GridFSBucket(conn.db, { + chunkSizeBytes: 1024 * 255, + }); + const password = user.getEncryptionKey(); + const IV = file.metadata.IV.buffer; + const readStream = bucket.openDownloadStream(ObjectID(fileID)); + readStream.on("error", (e) => { + reject({ + code: 500, + message: "File service Full Thumbnail stream error", + exception: e + }); + }); + const CIPHER_KEY = crypto_1.default.createHash('sha256').update(password).digest(); + const decipher = crypto_1.default.createDecipheriv('aes256', CIPHER_KEY, IV); + decipher.on("error", (e) => { + reject({ + code: 500, + message: "File service Full Thumbnail decipher error", + exception: e + }); + }); + res.set('Content-Type', 'binary/octet-stream'); + res.set('Content-Disposition', 'attachment; filename="' + file.filename + '"'); + res.set('Content-Length', file.metadata.size); + readStream.pipe(decipher).pipe(res).on("finish", () => __awaiter(this, void 0, void 0, function* () { + console.log("Sent Full Thumbnail"); + resolve(); + })); + }); + }); + }; + this.getPublicDownload = (fileID, tempToken, res) => { + return new Promise((resolve, reject) => { + dbUtilsFile.getPublicFile(fileID).then((file) => __awaiter(this, void 0, void 0, function* () { + if (!file || !file.metadata.link || file.metadata.link !== tempToken) { + reject({ + code: 401, + message: "File not public/Not found", + exception: undefined + }); + } + else { + const user = yield user_1.default.findById(file.metadata.owner); + const bucket = new mongoose_1.default.mongo.GridFSBucket(conn.db, { + chunkSizeBytes: 1024 * 255, + }); + const password = user.getEncryptionKey(); + const IV = file.metadata.IV.buffer; + const readStream = bucket.openDownloadStream(ObjectID(fileID)); + readStream.on("error", (e) => { + reject({ + code: 500, + message: "File service public download decipher error", + exception: e + }); + }); + const CIPHER_KEY = crypto_1.default.createHash('sha256').update(password).digest(); + const decipher = crypto_1.default.createDecipheriv('aes256', CIPHER_KEY, IV); + decipher.on("error", (e) => { + reject({ + code: 500, + message: "File service public download decipher error", + exception: 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", () => __awaiter(this, void 0, void 0, function* () { + if (file.metadata.linkType === "one") { + console.log("removing public link"); + yield dbUtilsFile.removeOneTimePublicLink(fileID); + } + resolve(); + })); + } + })); + }); + }; } } exports.default = MongoService; diff --git a/dist/services/FileService/index.js b/dist/services/FileService/index.js index 12da623..a20bd95 100644 --- a/dist/services/FileService/index.js +++ b/dist/services/FileService/index.js @@ -17,7 +17,7 @@ const crypto_1 = __importDefault(require("crypto")); const videoChecker = require("../../utils/videoChecker"); const mongoose = require("../../db/mongoose"); const conn = mongoose.connection; -const createThumbnail = require("./utils/createThumbnail"); +const createThumbnail = require("./utils/createThumbnail.ss"); const Thumbnail = require("../../models/thumbnail"); const ObjectID = require('mongodb').ObjectID; const NotAuthorizedError = require("../../utils/NotAuthorizedError"); diff --git a/dist/services/FileService/indexnew.js b/dist/services/FileService/indexnew.js index cc49a43..8a06593 100644 --- a/dist/services/FileService/indexnew.js +++ b/dist/services/FileService/indexnew.js @@ -13,7 +13,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const imageChecker = require("../../utils/imageChecker"); -const crypto_1 = __importDefault(require("crypto")); const videoChecker = require("../../utils/videoChecker"); const mongoose = require("../../db/mongoose"); const conn = mongoose.connection; @@ -39,19 +38,6 @@ const dbUtilsFile = new index_1.default(); const dbUtilsFolder = new DbUtilFolder(); class MongoFileService { constructor() { - this.getThumbnail = (user, id) => __awaiter(this, void 0, void 0, function* () { - const password = user.getEncryptionKey(); - const thumbnail = yield thumbnail_1.default.findById(id); - if (thumbnail.owner !== user._id.toString()) { - throw new NotAuthorizedError_1.default('Thumbnail Unauthorized Error'); - } - const iv = thumbnail.data.slice(0, 16); - const chunk = thumbnail.data.slice(16); - const CIPHER_KEY = crypto_1.default.createHash('sha256').update(password).digest(); - const decipher = crypto_1.default.createDecipheriv("aes256", CIPHER_KEY, iv); - const decryptedThumbnail = Buffer.concat([decipher.update(chunk), decipher.final()]); - return decryptedThumbnail; - }); this.removePublicOneTimeLink = (currentFile) => __awaiter(this, void 0, void 0, function* () { const fileID = currentFile._id; if (currentFile.metadata.linkType === "one") { diff --git a/dist/services/FileService/utils/createThumbnail.js b/dist/services/FileService/utils/createThumbnail.js index 0ccf56f..bef3ef3 100644 --- a/dist/services/FileService/utils/createThumbnail.js +++ b/dist/services/FileService/utils/createThumbnail.js @@ -8,15 +8,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const mongoose = require("../../../db/mongoose"); const conn = mongoose.connection; const crypto = require("crypto"); const env = require("../../../enviroment/env"); -const Thumbnail = require("../../../models/thumbnail"); +const thumbnail_1 = __importDefault(require("../../../models/thumbnail")); const ObjectID = require('mongodb').ObjectID; const sharp = require("sharp"); const concat = require("concat-stream"); -const createThumbnail = (file, filename, user) => __awaiter(void 0, void 0, void 0, function* () { +const createThumbnail = (file, filename, user) => { return new Promise((resolve) => { const password = user.getEncryptionKey(); let CIPHER_KEY = crypto.createHash('sha256').update(password).digest(); @@ -36,10 +40,9 @@ const createThumbnail = (file, filename, user) => __awaiter(void 0, void 0, void try { const concatStream = concat((bufferData) => __awaiter(void 0, void 0, void 0, function* () { const thumbnailIV = crypto.randomBytes(16); - //CIPHER_KEY = crypto.createHash('sha256').update(process.env.newPassword).digest() const thumbnailCipher = crypto.createCipheriv("aes256", CIPHER_KEY, thumbnailIV); - bufferData = Buffer.concat([thumbnailIV, thumbnailCipher.update(bufferData), thumbnailCipher.final()]); //thumbnailCipher.update(bufferData) - const thumbnailModel = new Thumbnail({ name: filename, owner: user._id, data: bufferData }); + bufferData = Buffer.concat([thumbnailIV, thumbnailCipher.update(bufferData), thumbnailCipher.final()]); + const thumbnailModel = new thumbnail_1.default({ name: filename, owner: user._id, data: bufferData }); yield thumbnailModel.save(); let updatedFile = yield conn.db.collection("fs.files") .findOneAndUpdate({ "_id": file._id }, { "$set": { "metadata.hasThumbnail": true, "metadata.thumbnailID": thumbnailModel._id } }); @@ -61,5 +64,5 @@ const createThumbnail = (file, filename, user) => __awaiter(void 0, void 0, void resolve(file); } }); -}); -module.exports = createThumbnail; +}; +exports.default = createThumbnail; diff --git a/dist/services/UserService/index.js b/dist/services/UserService/index.js index 2984442..89b6d61 100644 --- a/dist/services/UserService/index.js +++ b/dist/services/UserService/index.js @@ -8,7 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; -const User = require("../../models/user"); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const user_1 = __importDefault(require("../../models/user")); const bcrypt = require("bcrypt"); const crypto = require("crypto"); const NotFoundError = require("../../utils/NotFoundError"); @@ -18,7 +22,7 @@ const UserService = function () { this.login = (userData) => __awaiter(this, void 0, void 0, function* () { const email = userData.email; const password = userData.password; - const user = yield User.findByCreds(email, password); + const user = yield user_1.default.findByCreds(email, password); const token = yield user.generateAuthToken(); if (!user || !token) throw new NotFoundError("Login User Not Found Error"); @@ -37,7 +41,7 @@ const UserService = function () { }); this.create = (userData) => __awaiter(this, void 0, void 0, function* () { console.log("Create"); - const user = new User(userData); + const user = new user_1.default(userData); yield user.save(); yield user.generateEncryptionKeys(); const token = yield user.generateAuthToken();