init mydrive-3 commit

This commit is contained in:
kyle hoell
2020-11-23 21:51:08 -05:00
parent f384c93bdc
commit 938d5698a4
2026 changed files with 154094 additions and 2817 deletions
Vendored
BIN
View File
Binary file not shown.
Executable → Regular
+1
View File
@@ -1,3 +1,4 @@
{
"presets": ["@babel/env", "@babel/react"],
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread"]
+79 -48
View File
@@ -4,15 +4,31 @@ import MongoService from "../services/ChunkService/MongoService";
import FileSystemService from "../services/ChunkService/FileSystemService";
import S3Service from "../services/ChunkService/S3Service";
import {UserInterface} from "../models/user";
import uuid from "uuid";
import tempStorage from "../tempStorage/tempStorage";
import sendShareEmail from "../utils/sendShareEmail";
const fileService = new FileService()
interface RequestType extends Request {
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
auth?: boolean,
busboy: any,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
type ChunkServiceType = MongoService | FileSystemService | S3Service;
@@ -26,8 +42,7 @@ class FileController {
this.chunkService = chunkService;
}
getThumbnail = async(req: RequestType, res: Response) => {
getThumbnail = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
@@ -47,15 +62,14 @@ class FileController {
} catch (e) {
const code = e.code || 500;
console.log(e);
console.log("\nGet Thumbnail Error File Route:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
getFullThumbnail = async(req: RequestType, res: Response) => {
getFullThumbnail = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
@@ -69,13 +83,13 @@ class FileController {
await this.chunkService.getFullThumbnail(user, fileID, res);
} catch (e) {
const code = e.code || 500;
console.log(e.message, e.exception)
return res.status(code).send();
console.log("\nGet Thumbnail Full Error File Route:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
uploadFile = async(req: RequestType, res: Response) => {
uploadFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
@@ -93,12 +107,13 @@ class FileController {
res.send(file);
console.log("file uploaded");
} catch (e) {
console.log("sending error upload")
const code = e.code || 500;
console.log(e.message, e.exception)
return res.status(code).send();
res.writeHead(code, {'Connection': 'close'})
res.end();
//return res.status(code).send();
}
}
@@ -131,6 +146,8 @@ class FileController {
const id = req.params.id;
const userID = req.user._id;
console.log("remove link", id);
await fileService.removeLink(userID, id)
@@ -155,9 +172,9 @@ class FileController {
try {
const fileID = req.params.id;
const user = req.user;
const userID = req.user._id;
const token = await fileService.makePublic(user, fileID);
const token = await fileService.makePublic(userID, fileID);
res.send(token);
@@ -247,9 +264,9 @@ class FileController {
try {
const userID = req.user._id;
const user = req.user;
const quickList = await fileService.getQuickList(userID);
const quickList = await fileService.getQuickList(user);
res.send(quickList);
@@ -270,12 +287,16 @@ class FileController {
try {
console.log("Get file list")
const user = req.user;
const query = req.query;
const userID = req.user._id;
const fileList = await fileService.getList(userID, query);
const fileList = await fileService.getList(user, query);
res.send(fileList);
console.log("file list send", fileList.length)
} catch (e) {
@@ -286,7 +307,7 @@ class FileController {
}
}
getDownloadToken = async(req: RequestType, res: Response) => {
getDownloadToken = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return
@@ -309,7 +330,7 @@ class FileController {
}
}
getDownloadTokenVideo = async(req: RequestType, res: Response) => {
getDownloadTokenVideo = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return
@@ -333,7 +354,7 @@ class FileController {
}
}
removeTempToken = async(req: RequestType, res: Response) => {
removeTempToken = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return
@@ -358,9 +379,9 @@ class FileController {
}
}
streamVideo = async(req: RequestType, res: Response) => {
streamVideo = async(req: RequestTypeFullUser, res: Response) => {
if (!req.auth || !req.user) {
if (!req.user) {
return;
}
@@ -370,21 +391,7 @@ class FileController {
const fileID = req.params.id;
const headers = req.headers;
//tempStorage[req.params.uuid] = uuid.v4();
console.log("stream request 2", tempStorage);
// req.on("close", () => {
// console.log("req closed stream");
// })
// req.on("abort", () => {
// console.log("Aborted");
// })
await this.chunkService.streamVideo(user, fileID, headers, res, req);
//console.log("stream finished");
} catch (e) {
@@ -397,19 +404,19 @@ class FileController {
}
downloadFile = async(req: RequestType, res: Response) => {
downloadFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.auth || !req.user) {
if (!req.user) {
return;
}
try {
console.log("download request")
const user = req.user;
const fileID = req.params.id;
console.log("DOWNLOAD FILE USER ID", user._id);
await this.chunkService.downloadFile(user, fileID, res);
} catch (e) {
@@ -473,9 +480,33 @@ class FileController {
}
moveFile = async(req: RequestType, res: Response) => {
sendEmailShare = async(req: RequestType, res: Response) => {
console.log("move request");
if (!req.user) {
return;
}
try {
const user = req.user!;
const fileID = req.body.file._id;
const respient = req.body.file.resp;
const file = await fileService.getFileInfo(user._id, fileID);
await sendShareEmail(file, respient)
res.send()
} catch (e) {
console.log("Send Email Share Error", e);
const code = e.code || 500;
res.status(code).send();
}
}
moveFile = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
+73 -3
View File
@@ -7,8 +7,26 @@ import S3Service from "../services/ChunkService/S3Service";
const folderService = new FolderService();
interface RequestType extends Request {
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
type ChunkServiceType = MongoService | FileSystemService | S3Service;
@@ -72,6 +90,58 @@ class FolderController {
}
}
getSubfolderFullList = async(req: RequestType, res: Response) => {
if (!req.user) {
return
}
try {
const user = req.user;
const id: any = req.query.id;
const subfolderList = await folderService.getSubfolderFullList(user, id);
res.send(subfolderList);
} catch (e) {
const code = e.code || 500
console.log("Get Full Subfolder List Error", e);
res.status(code).send(e);
}
}
deletePersonalFolder = async(req: RequestType, res: Response) => {
if (!req.user) {
return
}
try {
const userID = req.user._id;
const folderID = req.body.id;
const parentList = req.body.parentList
const s3Service = new S3Service();
await s3Service.deleteFolder(userID, folderID, parentList);
res.send();
} catch (e) {
const code = e.code || 500
console.log(e);
res.status(code).send(e);
}
}
deleteAll = async(req: RequestType, res: Response) => {
if (!req.user) {
@@ -154,10 +224,10 @@ class FolderController {
try {
const userID = req.user._id;
const user = req.user;
const query = req.query;
const folderList = await folderService.getFolderList(userID, query);
const folderList = await folderService.getFolderList(user, query);
res.send(folderList);
+384
View File
@@ -0,0 +1,384 @@
import { Request, Response } from "express";
import {UserInterface} from "../models/user";
import GoogleFileService from "../services/GoogleFileService";
const googleFileService = new GoogleFileService();
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class GoogleFileController {
constructor() {
}
getList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const query = req.query;
const googleFiles = await googleFileService.getList(user, query);
res.send(googleFiles)
} catch (e) {
console.log("Get Google File List Error", e);
const code = 500;
res.status(code).send()
}
}
getMongoGoogleList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const query = req.query;
const mongoGoogleFiles = await googleFileService.getMongoGoogleList(user, query);
res.send(mongoGoogleFiles)
} catch (e) {
console.log("Get Mongo Google File List Error", e);
const code = 500;
res.status(code).send()
}
}
getFileInfo = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const id: any = req.params.id;
const user = req.user;
const fileInfo = await googleFileService.getFileInfo(user, id);
res.send(fileInfo);
} catch (e) {
console.log("Get Google File Info Error", e);
const code = 500;
res.status(code).send()
}
}
getGoogleMongoQuickList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const googleMongoQuickList = await googleFileService.getGoogleMongoQuickList(user);
res.send(googleMongoQuickList);
} catch (e) {
console.log("Get Google Mongo Quicklist error", e);
const code = 500;
res.status(code).send()
}
}
getGoogleMongoSuggestedList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const searchQuery: any = req.query.search || "";
const fileAndFolderList = await googleFileService.getGoogleMongoSuggestedList(user, searchQuery);
res.send(fileAndFolderList);
} catch (e) {
console.log("Get Google Mongo Suggested List error", e);
const code = 500;
res.status(code).send()
}
}
renameFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.body.id;
const title = req.body.title
await googleFileService.renameFile(user, fileID, title);
res.send();
} catch (e) {
console.log("Rename Google File Error", e);
const code = 500;
res.status(code).send()
}
}
removeFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const fileID = req.body.id;
const user = req.user!;
await googleFileService.removeFile(user, fileID);
res.send();
} catch (e) {
console.log("Remove Google File Error", e);
const code = 500;
res.status(code).send()
}
}
downloadFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user!;
const fileID = req.params.id;
await googleFileService.downloadFile(user, fileID, res);
} catch (e) {
console.log("Download Google File Error", e);
const code = 500;
res.status(code).send()
}
}
downloadDoc = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.params.id;
await googleFileService.downloadDoc(user, fileID, res);
} catch (e) {
console.log("Download Google Doc Error", e);
const code = 500;
res.status(code).send()
}
}
getThumbnail = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.params.id;
await googleFileService.getThumbnail(user, fileID, res);
} catch(e) {
console.log("Get Google Thumbnail Error", e);
const code = 500;
res.status(code).send()
}
}
getFulllThumbnail = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.params.id;
await googleFileService.getFullThumbnail(user, fileID, res);
} catch (e) {
console.log("Get Google Full Thumbnail Error", e);
const code = 500;
res.status(code).send()
}
}
streamVideo = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user!;
const fileID = req.params.id;
const tempUUID = req.params.uuid;
await googleFileService.streamVideo(user, fileID, tempUUID, req, res);
} catch (e) {
console.log("Stream Google Video Error", e);
const code = 500;
res.status(code).send()
}
}
uploadFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const busboy = req.busboy;
req.pipe(busboy);
await googleFileService.uploadFile(user, busboy, req, res);
} catch (e) {
console.log("Upload Google File Error", e);
const code = 500;
res.status(code).send()
}
}
moveFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user!;
const fileID = req.body.id;
const parentID = req.body.parent;
await googleFileService.moveFile(user, fileID, parentID);
res.send();
} catch (e) {
console.log("Move Google File Error", e);
const code = 500;
res.status(code).send()
}
}
makeFilePublic = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.params.id;
const publicURL = await googleFileService.makeFilePublic(user, fileID);
res.send(publicURL);
} catch (e) {
console.log("Make Google File Public Error", e);
const code = 500;
res.status(code).send()
}
}
removePublicLink = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user!;
const fileID = req.params.id;
await googleFileService.removePublicLink(user, fileID);
res.send();
} catch (e) {
console.log("Remove Google File Public Error", e);
const code = 500;
res.status(code).send()
}
}
}
export default GoogleFileController;
+237
View File
@@ -0,0 +1,237 @@
import { Request, Response } from "express";
import {UserInterface} from "../models/user";
import GoogleFolderService from "../services/GoogleFolderService";
const googleFolderService = new GoogleFolderService();
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class GoogleFolderController {
constructor() {
}
getList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const query = req.query;
const folderList = await googleFolderService.getList(user, query);
res.send(folderList);
} catch (e) {
console.log("Get Google Folder List Error", e);
const code = 500;
res.status(code).send()
}
}
getGoogleMongoList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const query = req.query;
const folderList = await googleFolderService.getGoogleMongoList(user, query);
res.send(folderList);
} catch (e) {
console.log("Get Google Mongo Folder List Error", e);
const code = 500;
res.status(code).send()
}
}
getInfo = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const id = req.params.id;
const folderInfo = await googleFolderService.getInfo(user, id);
res.send(folderInfo);
} catch (e) {
console.log("Get Google Info Error", e);
const code = 500;
res.status(code).send()
}
}
getSubFolderList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const id: any = req.query.id;
const nameAndIDList = await googleFolderService.getSubFolderList(user, id);
res.send(nameAndIDList);
} catch (e) {
console.log("Get Google Subfolder Error", e);
const code = 500;
res.status(code).send()
}
}
getSubfolderFullList = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const id: any = req.query.id;
const fullSubfolderList = await googleFolderService.getSubFolderFullList(user, id);
res.send(fullSubfolderList);
} catch (e) {
console.log("Get Google Full Subfolder Error", e);
const code = 500;
res.status(code).send()
}
}
renameFolder = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.body.id;
const title = req.body.title
await googleFolderService.renameFolder(user, fileID, title);
res.send();
} catch (e) {
console.log("Rename Google Folder Error", e);
const code = 500;
res.status(code).send()
}
}
removeFolder = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.body.id;
await googleFolderService.removeFolder(user, fileID)
res.send();
} catch (e) {
console.log("Remove Google Folder Error", e);
const code = 500;
res.status(code).send()
}
}
upload = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
let {name, parent} = req.body;
const createdFolder = await googleFolderService.upload(user, name, parent);
res.send(createdFolder);
} catch (e) {
console.log("Upload Google Folder Error", e);
const code = 500;
res.status(code).send()
}
}
moveFolder = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.body.id;
const parentID = req.body.parent;
await googleFolderService.moveFolder(user, fileID, parentID);
res.send();
} catch (e) {
console.log("Move Folder Google Error", e);
const code = 500;
res.status(code).send()
}
}
}
export default GoogleFolderController;
+213
View File
@@ -0,0 +1,213 @@
import S3Service from "../services/ChunkService/S3Service";
import { Request, Response } from "express";
import {UserInterface} from "../models/user";
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class PersonalFileController {
constructor() {
}
getPersonalThumbnail = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const s3Service = new S3Service();
const user = req.user;
const id = req.params.id;
const decryptedThumbnail = await s3Service.getThumbnail(user, id);
res.send(decryptedThumbnail);
} catch (e) {
const code = 500;
console.log(e);
res.status(code).send();
}
}
getFullPersonalThumbnail = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const s3Service = new S3Service();
const user = req.user;
const fileID = req.params.id;
await s3Service.getFullThumbnail(user, fileID, res);
} catch (e) {
const code = 500;
console.log(e.message, e.exception)
return res.status(code).send();
}
}
uploadPersonalFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return
}
try {
const s3Service = new S3Service();
const user = req.user;
const busboy = req.busboy;
req.pipe(busboy);
const file = await s3Service.uploadFile(user, busboy, req);
res.send(file);
} catch (e) {
const code = 500;
console.log("s3 personal upload err", e.message, e.exception, e)
return res.status(code).send();
}
}
getPublicPersonalDownload = async(req: RequestType, res: Response) => {
try {
const ID = req.params.id;
const tempToken = req.params.tempToken;
const s3Service = new S3Service();
await s3Service.getPublicDownload(ID, tempToken, res);
} catch (e) {
const code = 500;
const message = e.message || e;
console.log(message, e);
res.status(code).send();
}
}
streamPersonalVideo = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileID = req.params.id;
const headers = req.headers;
const s3Service = new S3Service();
await s3Service.streamVideo(user, fileID, headers, res, req);
} catch (e) {
const code = 500;
const message = e.message || e;
console.log(message, e);
res.status(code).send();
}
}
downloadPersonalFile = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const s3Service = new S3Service();
const user = req.user;
const fileID = req.params.id;
await s3Service.downloadFile(user, fileID, res);
} catch (e) {
const code = 500;
const message = e.message || e;
console.log(message, e);
res.status(code).send();
}
}
deletePersonalFile = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const s3Service = new S3Service();
const userID = req.user._id;
const fileID = req.body.id;
await s3Service.deleteFile(userID, fileID);
res.send()
} catch (e) {
const code = 500;
console.log(e);
res.status(code).send()
}
}
}
export default PersonalFileController;
+19 -1
View File
@@ -3,8 +3,26 @@ import env from "../enviroment/env";
import { Request, Response } from "express";
import { UserInterface } from "../models/user";
interface RequestType extends Request {
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class StorageController {
+236 -35
View File
@@ -3,13 +3,31 @@ import env from "../enviroment/env";
import UserService from "../services/UserService";
import { Request, Response } from "express";
import { UserInterface } from "../models/user";
import { createLoginCookie, createLogoutCookie } from "../cookies/createCookies";
import NotFoundError from "../utils/NotFoundError";
import InternalServerError from "../utils/InternalServerError";
const UserProvider = new UserService();
interface RequestType extends Request {
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
admin: boolean,
botChecked: boolean,
username: string,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class UserController {
constructor() {
@@ -21,17 +39,14 @@ class UserController {
try {
const user = req.user!;
user.tokens = [];
user.tempTokens = [];
user.password = '';
user.privateKey = undefined;
user.publicKey = undefined;
res.send(user)
} catch (e) {
res.status(500).send(e);
console.log("\nGet User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
@@ -40,23 +55,56 @@ class UserController {
try {
const body = req.body;
const ipAddress = req.clientIp;
const {user, token} = await UserProvider.login(body);
const {user, accessToken, refreshToken} = await UserProvider.login(body, ipAddress);
await user.save();
createLoginCookie(res, accessToken, refreshToken);
user.tokens = [];
user.tempTokens = [];
user.password = '';
user.tempTokens = []
user.privateKey = undefined;
user.publicKey = undefined;
res.status(200).send({user, token});
res.status(200).send({user});
} catch (e) {
const code = e.code || 500;
console.log("\nLogin User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
console.log(e);
res.status(code).send(e);
getToken = async(req: RequestTypeRefresh, res: Response) => {
try {
console.log("\nCreating New Refresh Token...")
const user = req.user;
if (!user) throw new NotFoundError("User Not Found");
console.log("tokens", user.tokens.length);
const {accessToken, refreshToken} = await user.generateAuthToken(req.clientIp);
if (!accessToken || !refreshToken) throw new InternalServerError("User/Access/Refresh Token Missing");
createLoginCookie(res, accessToken, refreshToken);
res.status(201).send();
console.log("New Refresh Token And Access Token Sent");
} catch (e) {
console.log("\nGet Refresh Token User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
@@ -69,32 +117,42 @@ class UserController {
try {
const user = req.user;
const token = req.encryptedToken;
const userID = req.user._id;
const refreshToken = req.cookies["refresh-token"];
await UserProvider.logout(user, token);
await UserProvider.logout(userID, refreshToken);
createLogoutCookie(res);
res.send();
} catch (e) {
res.status(500).send(e);
console.log("\nLogout User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
logoutAll = async(req: RequestType, res: Response) => {
if (!req.user) return;
try {
const user = req.user;
const userID = req.user._id;
await UserProvider.logoutAll(user!);
await UserProvider.logoutAll(userID);
createLogoutCookie(res);
res.send();
} catch (e) {
res.status(500).send(e);
console.log("\nLogout All User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
@@ -107,7 +165,11 @@ class UserController {
try {
const {user, token} = await UserProvider.create(req.body);
const ipAddress = req.clientIp;
const {user, accessToken, refreshToken} = await UserProvider.create(req.body, ipAddress);
createLoginCookie(res, accessToken, refreshToken);
user.tokens = [];
user.tempTokens = []
@@ -115,14 +177,13 @@ class UserController {
user.privateKey = undefined;
user.publicKey = undefined;
res.status(201).send({user, token})
res.status(201).send({user})
} catch (e) {
const code = e.code || 500;
console.log(e);
res.status(code).send(e);
console.log("\nCreate User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
@@ -134,21 +195,161 @@ class UserController {
}
try {
const user = req.user;
const userID = req.user._id;
const oldPassword = req.body.oldPassword;
const newPassword = req.body.newPassword;
const oldRefreshToken = req.cookies["refresh-token"];
const ipAddress = req.clientIp;
const newToken = await UserProvider.changePassword(user, oldPassword, newPassword);
const {accessToken, refreshToken} = await UserProvider.changePassword(userID, oldPassword, newPassword, oldRefreshToken, ipAddress);
res.send(newToken);
createLoginCookie(res, accessToken, refreshToken);
res.send();
} catch (e) {
const code = e.code || 500;
console.log("\nChange Password User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
console.log(e);
res.status(code).send(e);
refreshStorageSize = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const userID = req.user._id;
await UserProvider.refreshStorageSize(userID);
res.send();
} catch (e) {
console.log("\nRefresh Storage Size User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
getUserDetailed = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const userID = req.user._id;
const userDetailed = await UserProvider.getUserDetailed(userID);
res.send(userDetailed);
} catch (e) {
console.log("\nGet User Detailed User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
verifyEmail = async(req: RequestType, res: Response) => {
try {
const verifyToken = req.body.emailToken;
await UserProvider.verifyEmail(verifyToken);
res.send();
} catch (e) {
console.log("\nVerify Email User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
resendVerifyEmail = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const userID = req.user._id;
await UserProvider.resendVerifyEmail(userID);
res.send();
} catch (e) {
console.log("\nResend Email User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
sendPasswordReset = async(req: RequestType, res: Response) => {
try {
const email = req.body.email;
await UserProvider.sendPasswordReset(email);
res.send();
} catch (e) {
console.log("\nSend Password Reset Email User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
resetPassword = async(req: RequestType, res: Response) => {
try {
const verifyToken = req.body.passwordToken;
const newPassword = req.body.password;
await UserProvider.resetPassword(newPassword, verifyToken);
res.send();
} catch (e) {
console.log("\nReset Password User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
addName = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const userID = req.user._id;
const name = req.body.name;
await UserProvider.addName(userID, name);
res.send();
} catch (e) {
console.log("\nAdd Name User Route Error:", e.message);
const code = !e.code ? 500 : e.code >= 400 && e.code <= 599 ? e.code : 500;
res.status(code).send();
}
}
}
+101
View File
@@ -0,0 +1,101 @@
import { Request, Response } from "express";
import { UserInterface } from "../models/user";
import UserServiceGoogle from "../services/UserGoogle";
const UserProviderGoogle = new UserServiceGoogle();
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class UserGoogleController {
constructor() {
}
createGoogleStorageURL = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const googleData = req.body;
const url = await UserProviderGoogle.createGoogleStorageURL(user, googleData);
res.send(url);
} catch (e) {
const code = 500;
console.log("Create Google Storage URL Error", e);
res.status(code).send(e);
}
}
addGoogleStorage = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const code = req.body.code;
await UserProviderGoogle.addGoogleStorage(user, code);
res.send();
} catch (e) {
const code = 500;
console.log("Add Google Storage Error", e);
res.status(code).send(e);
}
}
removeGoogleStorage = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user
await UserProviderGoogle.removeGoogleStorage(user);
res.send();
} catch (e) {
const code = 500;
console.log("Remove Google Storage Error", e);
res.status(code).send(e);
}
}
}
export default UserGoogleController;
+150
View File
@@ -0,0 +1,150 @@
import { Request, Response } from "express";
import { UserInterface } from "../models/user";
import UserServicePersonal from "../services/UserPersonalService";
const UserProviderPersonal = new UserServicePersonal()
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
interface RequestTypeRefresh extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestTypeFullUser extends Request {
user?: UserInterface,
encryptedToken?: string
}
interface RequestType extends Request {
user?: userAccessType,
encryptedToken?: string
}
class UserPersonalController {
constructor() {
}
addS3Storage = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const s3Data = req.body;
await UserProviderPersonal.addS3Storage(user, s3Data);
res.send();
} catch (e) {
const code = 500;
console.log("Add S3 Storage Error", e);
res.status(code).send(e);
}
}
removeS3Storage = async(req: RequestTypeFullUser, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
await UserProviderPersonal.removeS3Storage(user);
res.send();
} catch (e) {
const code = 500;
console.log("Remove S3 Storage Error", e);
res.status(code).send(e);
}
}
removeS3Metadata = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
await UserProviderPersonal.removeS3Metadata(user);
res.send();
} catch (e) {
const code = 500;
console.log("Remove S3 Storage Error", e);
res.status(code).send(e);
}
}
downloadPersonalFileList = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
res.set('Content-Type', 'application/json');
res.setHeader('Content-disposition', 'attachment; filename= personal-data-list.json');
const personalFileList = await UserProviderPersonal.downloadPersonalFileList(user);
res.send(personalFileList);
} catch (e) {
const code = 500;
console.log("Download personal file list error", e);
res.status(code).send(e);
}
}
uploadPersonalFileList = async(req: RequestType, res: Response) => {
if (!req.user) {
return;
}
try {
const user = req.user;
const fileList = req.body;
await UserProviderPersonal.uploadPersonalFileList(user, fileList);
res.send();
} catch (e) {
const code = 500;
console.log("Upload personal file list error", e);
res.status(code).send(e);
}
}
}
export default UserPersonalController;
+38
View File
@@ -0,0 +1,38 @@
import {Response } from "express";
const maxAgeAccess = 1000 * 5;//60 * 1000 * 20;
const maxAgeRefresh = 60 * 1000 * 60 * 24 * 30;
export const createLoginCookie = (res: Response, accessToken: string, refreshToken: string) => {
res.cookie("access-token",accessToken, {
httpOnly: true,
maxAge: maxAgeAccess,
sameSite: "strict",
secure: process.env.NODE_ENV === "production"
})
res.cookie("refresh-token",refreshToken, {
httpOnly: true,
maxAge: maxAgeRefresh,
sameSite: "strict",
secure: process.env.NODE_ENV === "production"
})
}
export const createLogoutCookie = (res: Response) => {
res.cookie("access-token", {}, {
httpOnly: true,
maxAge: 0,
sameSite: "strict",
secure: process.env.NODE_ENV === "production"
})
res.cookie("refresh-token", {}, {
httpOnly: true,
maxAge: 0,
sameSite: "strict",
secure: process.env.NODE_ENV === "production"
})
}
+16
View File
@@ -0,0 +1,16 @@
import AWS from "aws-sdk";
const s3Auth = (id:string, key:string) => {
AWS.config.update({
accessKeyId: id,
secretAccessKey: key
});
const s3 = new AWS.S3();
return s3;
}
export default s3Auth;
+35
View File
@@ -0,0 +1,35 @@
import { UserInterface } from "../models/user";
import {google} from "googleapis";
import env from "../enviroment/env";
const getGoogleAuth = async (user: UserInterface) => {
const googleIDandToken = await user?.decryptDriveIDandKey();
const clientID = googleIDandToken?.clientID;
const clientKey = googleIDandToken?.clientKey;
const token = await user?.decryptDriveTokenData();
const refreshToken = token.refresh_token;
const date = new Date();
const time = date.getTime();
if (time >= token.expiry_date) {
// console.log("TOKEN EXPIRED!")
}
const redirectURL = env.remoteURL + "/add-google-account";
const oauth2Client = new google.auth.OAuth2(
clientID,
clientKey,
redirectURL,
);
oauth2Client.setCredentials(token);
return oauth2Client
}
export default getGoogleAuth;
+2 -1
View File
@@ -8,4 +8,5 @@ AWS.config.update({
const s3 = new AWS.S3();
export default s3;
export default s3;
module.exports = s3;
+23 -12
View File
@@ -32,7 +32,7 @@ class DbUtil {
const file = await conn.db.collection("fs.files")
.findOneAndUpdate({"_id": new ObjectID(fileID),
"metadata.owner": userID},
"metadata.owner": new ObjectID(userID)},
{"$unset": {"metadata.linkType": "", "metadata.link": ""}}) as FileInterface;
return file;
@@ -42,7 +42,7 @@ class DbUtil {
const file = await conn.db.collection("fs.files")
.findOneAndUpdate({"_id": new ObjectID(fileID),
"metadata.owner": userID},
"metadata.owner": new ObjectID(userID)},
{"$set": {"metadata.linkType": "public", "metadata.link": token}}) as FileInterface
return file;
@@ -60,7 +60,7 @@ class DbUtil {
const file = await conn.db.collection("fs.files")
.findOneAndUpdate({"_id": new ObjectID(fileID),
"metadata.owner": userID},
"metadata.owner": new ObjectID(userID)},
{"$set": {"metadata.linkType": "one", "metadata.link": token}}) as FileInterface;
return file;
@@ -69,15 +69,23 @@ class DbUtil {
getFileInfo = async(fileID: string, userID: string) => {
const file = await conn.db.collection("fs.files")
.findOne({"metadata.owner": userID, "_id": new ObjectID(fileID)}) as FileInterface;
.findOne({"metadata.owner": new ObjectID(userID), "_id": new ObjectID(fileID)}) as FileInterface;
return file;
}
getQuickList = async(userID: string) => {
getQuickList = async(userID: string, s3Enabled: boolean) => {
let query: any = {"metadata.owner": new ObjectID(userID)}
// if (s3Enabled) {
// query = {...query, "metadata.personalFile": true}
// } else if (!s3Enabled){
// query = {...query, "metadata.personalFile": null}
// }
const fileList = await conn.db.collection("fs.files")
.find({"metadata.owner": userID})
.find(query)
.sort({uploadDate: -1})
.limit(10)
.toArray() as FileInterface[];
@@ -109,8 +117,10 @@ class DbUtil {
getFileSearchList = async(userID: string, searchQuery: RegExp) => {
let query:any = {"metadata.owner": new ObjectID(userID), "filename": searchQuery};
const fileList = await conn.db.collection("fs.files")
.find({"metadata.owner": userID, "filename": searchQuery})
.find(query)
.limit(10)
.toArray() as FileInterface[];
@@ -121,7 +131,7 @@ class DbUtil {
const file = await conn.db.collection("fs.files")
.findOneAndUpdate({"_id": new ObjectID(fileID),
"metadata.owner": userID}, {"$set": {"filename": title}}) as FileInterface;
"metadata.owner": new ObjectID(userID)}, {"$set": {"filename": title}}) as FileInterface;
return file;
}
@@ -130,7 +140,7 @@ class DbUtil {
const file = await conn.db.collection("fs.files")
.findOneAndUpdate({"_id": new ObjectID(fileID),
"metadata.owner": userID}, {"$set": {"metadata.parent": parent, "metadata.parentList": parentList}})
"metadata.owner": new ObjectID(userID)}, {"$set": {"metadata.parent": parent, "metadata.parentList": parentList}})
return file;
}
@@ -138,7 +148,7 @@ class DbUtil {
getFileListByParent = async(userID: string, parentListString: string) => {
const fileList = await conn.db.collection("fs.files")
.find({"metadata.owner": userID,
.find({"metadata.owner": new ObjectID(userID),
"metadata.parentList": {$regex : `.*${parentListString}.*`}}).toArray() as FileInterface[];
return fileList;
@@ -147,7 +157,7 @@ class DbUtil {
getFileListByOwner = async(userID: string) => {
const fileList = await conn.db.collection("fs.files")
.find({"metadata.owner": userID}).toArray() as FileInterface[];
.find({"metadata.owner": new ObjectID(userID)}).toArray() as FileInterface[];
return fileList;
}
@@ -158,4 +168,5 @@ class DbUtil {
}
}
export default DbUtil;
export default DbUtil;
module.exports = DbUtil;
+46 -5
View File
@@ -9,7 +9,9 @@ class DbUtil {
getFolderSearchList = async(userID: string, searchQuery: RegExp) => {
const folderList = await Folder.find({"owner": userID, "name": searchQuery}).limit(10) as FolderInterface[];
let query:any = {"owner": userID, "name": searchQuery};
const folderList = await Folder.find(query).limit(10) as FolderInterface[];
return folderList;
}
@@ -21,17 +23,56 @@ class DbUtil {
return folder;
}
getFolderListByParent = async(userID: string, parent: string, sortBy: string) => {
getFolderListByParent = async(userID: string, parent: string, sortBy: string, s3Enabled: boolean, type: string, storageType: string) => {
const folderList = await Folder.find({"owner": userID, "parent": parent})
let query: any = {"owner": userID, "parent": parent};
// if (s3Enabled) {
// query = {...query, "personalFolder": true}
// } else if (!s3Enabled) {
// query = {...query, "personalFolder": null}
// }
// if (type) {
// if (type === "mongo") {
// query = {...query, "personalFolder": null}
// } else if (type === "s3") {
// query = {...query, "personalFolder": true}
// }
// }
// if (storageType === "s3") {
// query = {...query, "personalFolder": true}
// }
const folderList = await Folder.find(query)
.sort(sortBy) as FolderInterface[];
return folderList;
}
getFolderListBySearch = async(userID: string, searchQuery: string, sortBy: string) => {
getFolderListBySearch = async(userID: string, searchQuery: string, sortBy: string, type: string, parent: string, storageType: string, folderSearch: boolean) => {
const folderList = await Folder.find({"name": searchQuery,"owner": userID})
let query: any = {"name": searchQuery,"owner": userID};
if (type) {
if (type === "mongo") {
query = {...query, "personalFolder": null}
console.log("mongo query", query)
} else {
query = {...query, "personalFolder": true}
}
}
if (storageType === "s3") {
query = {...query, "personalFolder": true}
}
if (parent && (parent !== "/" || folderSearch)) {
query = {...query, parent}
}
const folderList = await Folder.find(query)
.sort(sortBy) as FolderInterface[];
return folderList;
+29 -2
View File
@@ -1,7 +1,9 @@
export default {
key: process.env.KEY,
newKey: process.env.NEW_KEY,
password: process.env.PASSWORD,
passwordAccess: process.env.PASSWORD_ACCESS,
passwordRefresh: process.env.PASSWORD_REFRESH,
passwordCookie: process.env.PASSWORD_COOKIE,
createAcctBlocked: process.env.BLOCK_CREATE_ACCOUNT,
root: process.env.ROOT,
url: process.env.URL,
@@ -12,5 +14,30 @@ export default {
s3Key: process.env.S3_KEY,
s3Bucket: process.env.S3_BUCKET,
useDocumentDB: process.env.USE_DOCUMENT_DB,
documentDBBundle: process.env.DOCUMENT_DB_BUNDLE
documentDBBundle: process.env.DOCUMENT_DB_BUNDLE,
sendgridKey: process.env.SENDGRID_KEY,
sendgridEmail: process.env.SENDGRID_EMAIL,
remoteURL: process.env.REMOTE_URL,
}
module.exports = {
key: process.env.KEY,
newKey: process.env.NEW_KEY,
passwordAccess: process.env.PASSWORD_ACCESS,
passwordRefresh: process.env.PASSWORD_REFRESH,
passwordCookie: process.env.PASSWORD_COOKIE,
createAcctBlocked: process.env.BLOCK_CREATE_ACCOUNT,
root: process.env.ROOT,
url: process.env.URL,
mongoURL: process.env.MONGODB_URL,
dbType: process.env.DB_TYPE,
fsDirectory: process.env.FS_DIRECTORY,
s3ID: process.env.S3_ID,
s3Key: process.env.S3_KEY,
s3Bucket: process.env.S3_BUCKET,
useDocumentDB: process.env.USE_DOCUMENT_DB,
documentDBBundle: process.env.DOCUMENT_DB_BUNDLE,
sendgridKey: process.env.SENDGRID_KEY,
sendgridEmail: process.env.SENDGRID_EMAIL,
remoteURL: process.env.REMOTE_URL,
}
+2 -1
View File
@@ -20,4 +20,5 @@ const getEnvVariables = () => {
}
}
export default getEnvVariables;
export default getEnvVariables;
module.exports = getEnvVariables
+32 -9
View File
@@ -1,38 +1,42 @@
import {Router} from "express";
import auth from "../middleware/auth";
import tempAuth from "../middleware/tempAuth";
import tempAuthVideo from "../middleware/tempAuthVideo";
import FileController from "../controllers/file";
import env from "../enviroment/env";
import MongoService from "../services/ChunkService/MongoService";
import FileSystemService from "../services/ChunkService/FileSystemService";
import S3Service from "../services/ChunkService/S3Service";
import ChunkInterface from "../services/ChunkService/utils/ChunkInterface";
import authFullUser from "../middleware/authFullUser";
let fileController: FileController;
let chunkService: ChunkInterface;
if (env.dbType === "mongo") {
const mongoService = new MongoService();
chunkService = mongoService;
fileController = new FileController(mongoService);
} else if (env.dbType === "fs") {
const fileSystemService = new FileSystemService();
chunkService = fileSystemService
fileController = new FileController(fileSystemService);
} else {
const s3Service = new S3Service();
chunkService = s3Service;
fileController = new FileController(s3Service);
}
const router = Router();
router.post("/file-service/upload", auth, fileController.uploadFile);
router.post("/file-service/upload", authFullUser, fileController.uploadFile);
router.get("/file-service/thumbnail/:id", auth, fileController.getThumbnail);
router.get("/file-service/thumbnail/:id", authFullUser, fileController.getThumbnail);
router.get("/file-service/full-thumbnail/:id", auth, fileController.getFullThumbnail);
router.get("/file-service/full-thumbnail/:id", authFullUser, fileController.getFullThumbnail);
router.get("/file-service/public/download/:id/:tempToken", fileController.getPublicDownload);
@@ -44,17 +48,17 @@ router.get("/file-service/quick-list", auth, fileController.getQuickList);
router.get("/file-service/list", auth, fileController.getList);
router.get("/file-service/download/get-token", auth, fileController.getDownloadToken);
router.get("/file-service/download/get-token", authFullUser, fileController.getDownloadToken);
router.get("/file-service/download/get-token-video", auth, fileController.getDownloadTokenVideo);
router.get("/file-service/stream-video/:id/:tempToken/:uuid", tempAuthVideo, fileController.streamVideo);
router.get("/file-service/stream-video/:id/:tempToken/:uuid", auth, fileController.streamVideo);
router.get("/file-service/download/:id/:tempToken", tempAuth, fileController.downloadFile);
router.get("/file-service/download/:id", authFullUser, fileController.downloadFile);
router.get("/file-service/suggested-list", auth, fileController.getSuggestedList);
router.patch("/file-service/make-public/:id", auth, fileController.makePublic);
router.patch("/file-service/make-public/:id", authFullUser, fileController.makePublic);
router.patch("/file-service/make-one/:id", auth, fileController.makeOneTimePublic);
@@ -68,4 +72,23 @@ router.delete("/file-service/remove/token-video/:tempToken/:uuid", auth, fileCon
router.delete("/file-service/remove", auth, fileController.deleteFile);
router.post("/file-service/send-share-email", auth, fileController.sendEmailShare);
// Moving File Accross Databases
// router.patch("/file-service/move-db", auth, async(req: RequestType, res) => {
// const user = req.user!
// const fileID = req.body.id;
// const parentFolderID = req.body.parentID;
// const readStream = chunkService.getFileReadStream(user, fileID);
// const parentFolder = await Folder.findById(parentFolderID);
// if (parentFolder?.personalFolder) {
// }
// })
export default router;
+6
View File
@@ -42,4 +42,10 @@ router.patch("/folder-service/rename", auth, folderController.renameFolder);
router.patch("/folder-service/move", auth, folderController.moveFolder);
router.get("/folder-service/subfolder-list-full", auth, folderController.getSubfolderFullList);
// Personal Files
router.delete("/folder-service-personal/remove", auth, folderController.deletePersonalFolder);
export default router;
+42
View File
@@ -0,0 +1,42 @@
import {Router} from "express";
import auth from "../middleware/auth";
import GoogleFileController from "../controllers/googleFile";
import authFullUser from "../middleware/authFullUser";
const googleController = new GoogleFileController();
const router = Router();
router.get("/file-service-google/list", authFullUser, googleController.getList);
router.get("/file-service-google-mongo/list", authFullUser, googleController.getMongoGoogleList);
router.get("/file-service-google/info/:id", authFullUser, googleController.getFileInfo);
router.get("/file-service-google-mongo/quick-list", authFullUser, googleController.getGoogleMongoQuickList);
router.get("/file-service-google-mongo/suggested-list", authFullUser, googleController.getGoogleMongoSuggestedList);
router.patch("/file-service-google/rename", authFullUser, googleController.renameFile);
router.delete("/file-service-google/remove", authFullUser, googleController.removeFile);
router.get("/file-service-google/download/:id/:tempToken", authFullUser, googleController.downloadFile);
router.get("/file-service-google-doc/download/:id/:tempToken", authFullUser, googleController.downloadDoc);
router.get("/file-service-google/thumbnail/:id", authFullUser, googleController.getThumbnail);
router.get("/file-service-google/full-thumbnail/:id", authFullUser, googleController.getFulllThumbnail);
router.get("/file-service-google/stream-video/:id/:tempToken/:uuid", authFullUser, googleController.streamVideo);
router.post("/file-service-google/upload", authFullUser, googleController.uploadFile);
router.patch("/file-service-google/move", authFullUser, googleController.moveFile);
router.patch("/file-service-google/make-public/:id", authFullUser, googleController.makeFilePublic);
router.delete("/file-service-google/remove-link/:id", authFullUser, googleController.removePublicLink);
export default router;
+28
View File
@@ -0,0 +1,28 @@
import {Router} from "express";
import auth from "../middleware/auth";
import GoogleFolderController from "../controllers/googleFolder";
import authFullUser from "../middleware/authFullUser";
const googleFolderController = new GoogleFolderController();
const router = Router();
router.get("/folder-service-google/list", authFullUser, googleFolderController.getList);
router.get("/folder-service-google-mongo/list", authFullUser, googleFolderController.getGoogleMongoList);
router.get("/folder-service-google/info/:id", authFullUser, googleFolderController.getInfo);
router.get("/folder-service-google/subfolder-list", authFullUser, googleFolderController.getSubFolderList);
router.get("/folder-service-google/subfolder-list-full", authFullUser, googleFolderController.getSubfolderFullList);
router.patch("/folder-service-google/rename", authFullUser, googleFolderController.renameFolder);
router.delete("/folder-service-google/remove", authFullUser,googleFolderController.removeFolder);
router.post("/folder-service-google/upload", authFullUser, googleFolderController.upload);
router.patch("/folder-service-google/move", authFullUser, googleFolderController.moveFolder);
export default router;
+25
View File
@@ -0,0 +1,25 @@
import {Router} from "express";
import auth from "../middleware/auth";
import PersonalFileController from "../controllers/personalFile";
import authFullUser from "../middleware/authFullUser";
const personalFileController = new PersonalFileController();
const router = Router();
router.post("/file-service-personal/upload", authFullUser, personalFileController.uploadPersonalFile);
router.get("/file-service-personal/download/:id/:tempToken", authFullUser, personalFileController.downloadPersonalFile);
router.get("/file-service-personal/thumbnail/:id", authFullUser, personalFileController.getPersonalThumbnail);
router.get("/file-service-personal/full-thumbnail/:id", authFullUser, personalFileController.getFullPersonalThumbnail);
router.get("/file-service-personal/stream-video/:id/:tempToken/:uuid", authFullUser, personalFileController.streamPersonalVideo);
router.get("/file-service-personal/public/download/:id/:tempToken", personalFileController.getPublicPersonalDownload);
router.delete("/file-service-personal/remove", auth, personalFileController.deletePersonalFile);
export default router;
+19 -1
View File
@@ -1,12 +1,18 @@
import { Router } from "express";
import auth from "../middleware/auth";
import authNoEmailVerification from "../middleware/authNoEmailVerificication"
import UserController from "../controllers/user";
import authRefresh from "../middleware/authRefresh";
const userController = new UserController();
const router = Router();
router.get("/user-service/user", auth, userController.getUser);
router.get("/user-service/user", authNoEmailVerification, userController.getUser);
router.patch("/user-service/refresh-storage-size", auth, userController.refreshStorageSize);
router.get("/user-service/user-detailed", auth, userController.getUserDetailed);
router.post("/user-service/login", userController.login);
@@ -18,4 +24,16 @@ router.post("/user-service/create", userController.createUser);
router.post("/user-service/change-password", auth, userController.changePassword);
router.post("/user-service/verify-email", userController.verifyEmail);
router.post("/user-service/resend-verify-email", authNoEmailVerification, userController.resendVerifyEmail);
router.post("/user-service/send-password-reset", userController.sendPasswordReset);
router.post("/user-service/reset-password", userController.resetPassword);
router.patch("/user-service/add-name", auth, userController.addName);
router.post("/user-service/get-token", authRefresh, userController.getToken);
export default router;
+16
View File
@@ -0,0 +1,16 @@
import { Router } from "express";
import auth from "../middleware/auth";
import UserGoogleController from "../controllers/userGoogle";
import authFullUser from "../middleware/authFullUser";
const userGoogleController = new UserGoogleController();
const router = Router();
router.post("/user-service/create-google-storage-url", authFullUser, userGoogleController.createGoogleStorageURL);
router.post("/user-service/add-google-storage", authFullUser, userGoogleController.addGoogleStorage);
router.delete("/user-service/remove-google-storage", authFullUser, userGoogleController.removeGoogleStorage);
export default router;
+20
View File
@@ -0,0 +1,20 @@
import { Router } from "express";
import auth from "../middleware/auth";
import UserPersonalController from "../controllers/userPersonal";
import authFullUser from "../middleware/authFullUser";
const userPersonalController = new UserPersonalController();
const router = Router();
router.get("/user-service/download-personal-file-list/:tempToken", auth, userPersonalController.downloadPersonalFileList);
router.post("/user-service/upload-personal-file-list", auth, userPersonalController.uploadPersonalFileList);
router.post("/user-service/add-s3-storage", authFullUser, userPersonalController.addS3Storage);
router.delete("/user-service/remove-s3-storage", authFullUser, userPersonalController.removeS3Storage);
router.delete("/user-service/remove-s3-metadata", auth, userPersonalController.removeS3Metadata);
export default router;
+1 -1
View File
@@ -40,7 +40,7 @@ const getWebUIKey = () => {
const server = http.createServer(app) as any;
server.listen(port, url, () => {
server.listen(port, () => {
console.log(`\nPlease navigate to http://localhost:${port} to enter encryption key\n`)
+171 -29
View File
@@ -4,58 +4,200 @@ import env from "../enviroment/env";
import {Request, Response, NextFunction} from "express";
interface RequestType extends Request {
user?: UserInterface,
user?: userAccessType,
token?: string,
encryptedToken?: string,
}
type jwtType = {
iv: Buffer,
user: userAccessType
}
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
admin: boolean,
botChecked: boolean,
username: string,
}
const auth = async(req: RequestType, res: Response, next: NextFunction) => {
try {
const token = req.header("Authorization")!.replace("Bearer ", "");
//console.log("\nAUTH RUOTE")
const decoded = jwt.verify(token, env.password!) as jwtType;
const accessToken = req.cookies["access-token"];
const iv = decoded.iv;
const user = await User.findOne({_id: decoded._id}) as UserInterface;
const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
if (!accessToken) throw new Error("No Access Token");
let tokenFound = false;
for (let i = 0; i < user.tokens.length; i++) {
const decoded = jwt.verify(accessToken, env.passwordAccess!) as jwtType;
const currentToken = user.tokens[i].token;
const user = decoded.user;
if (currentToken === encryptedToken) {
tokenFound = true;
break;
}
}
//console.log(user.email);
if (!user || !tokenFound) {
if (!user) throw new Error("No User");
if (!user.emailVerified) throw new Error("Email Not Verified")
throw new Error("User not found")
req.user = user;
} else {
req.token = token;
req.encryptedToken = encryptedToken
req.user = user;
next();
}
next();
} catch (e) {
console.log(e);
res.status(401).send({error: "Error Authenticating"})
console.log("\nAuthorization Middleware Error:", e.message);
res.status(401).send("Error Authenticating");
}
}
export default auth;
export default auth;
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
// interface RequestType extends Request {
// user?: UserInterface,
// token?: string,
// encryptedToken?: string,
// }
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
// const auth = async(req: RequestType, res: Response, next: NextFunction) => {
// try {
// const token = req.header("Authorization")!.replace("Bearer ", "");
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
// const iv = decoded.iv;
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// let tokenFound = false;
// for (let i = 0; i < user.tokens.length; i++) {
// const currentToken = user.tokens[i].token;
// //console.log("current token", currentToken === encryptedToken)
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
// if (!user || !tokenFound) {
// throw new Error("User not found")
// } else if (user.emailVerified && user.botChecked) {
// // TEMPORARY CHANGE THIS
// req.token = token;
// req.encryptedToken = encryptedToken
// req.user = user;
// next();
// } else {
// throw new Error("Email Not Verified, or Bot not checked")
// }
// } catch (e) {
// console.log(e);
// res.status(401).send({error: "Error Authenticating"})
// }
// }
// export default auth;
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
// interface RequestType extends Request {
// user?: UserInterface,
// token?: string,
// encryptedToken?: string,
// }
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
// const auth = async(req: RequestType, res: Response, next: NextFunction) => {
// try {
// const token = req.header("Authorization")!.replace("Bearer ", "");
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
// const iv = decoded.iv;
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// let tokenFound = false;
// for (let i = 0; i < user.tokens.length; i++) {
// const currentToken = user.tokens[i].token;
// //console.log("current token", currentToken === encryptedToken)
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
// if (!user || !tokenFound) {
// throw new Error("User not found")
// } else if (user.emailVerified) {
// req.token = token;
// req.encryptedToken = encryptedToken
// req.user = user;
// next();
// } else {
// throw new Error("Email Not Verified")
// }
// } catch (e) {
// console.log(e);
// res.status(401).send({error: "Error Authenticating"})
// }
// }
// export default auth;
+203
View File
@@ -0,0 +1,203 @@
import jwt from "jsonwebtoken";
import User, {UserInterface} from "../models/user";
import env from "../enviroment/env";
import {Request, Response, NextFunction} from "express";
interface RequestType extends Request {
user?: UserInterface,
token?: string,
encryptedToken?: string,
}
type jwtType = {
iv: Buffer,
user: userAccessType
}
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
admin: boolean,
botChecked: boolean,
username: string,
}
const authFullUser = async(req: RequestType, res: Response, next: NextFunction) => {
try {
const accessToken = req.cookies["access-token"];
if (!accessToken) throw new Error("No Access Token");
const decoded = jwt.verify(accessToken, env.passwordAccess!) as jwtType;
const user = decoded.user;
if (!user) throw new Error("No User");
if (!user.emailVerified) throw new Error("Email Not Verified")
const fullUser = await User.findById(user._id);
if (!fullUser) throw new Error("No User");
req.user = fullUser;
next();
} catch (e) {
console.log("\nAuthorization Middleware Error:", e.message);
res.status(401).send("Error Authenticating");
}
}
export default authFullUser;
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
// interface RequestType extends Request {
// user?: UserInterface,
// token?: string,
// encryptedToken?: string,
// }
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
// const auth = async(req: RequestType, res: Response, next: NextFunction) => {
// try {
// const token = req.header("Authorization")!.replace("Bearer ", "");
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
// const iv = decoded.iv;
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// let tokenFound = false;
// for (let i = 0; i < user.tokens.length; i++) {
// const currentToken = user.tokens[i].token;
// //console.log("current token", currentToken === encryptedToken)
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
// if (!user || !tokenFound) {
// throw new Error("User not found")
// } else if (user.emailVerified && user.botChecked) {
// // TEMPORARY CHANGE THIS
// req.token = token;
// req.encryptedToken = encryptedToken
// req.user = user;
// next();
// } else {
// throw new Error("Email Not Verified, or Bot not checked")
// }
// } catch (e) {
// console.log(e);
// res.status(401).send({error: "Error Authenticating"})
// }
// }
// export default auth;
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
// interface RequestType extends Request {
// user?: UserInterface,
// token?: string,
// encryptedToken?: string,
// }
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
// const auth = async(req: RequestType, res: Response, next: NextFunction) => {
// try {
// const token = req.header("Authorization")!.replace("Bearer ", "");
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
// const iv = decoded.iv;
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// let tokenFound = false;
// for (let i = 0; i < user.tokens.length; i++) {
// const currentToken = user.tokens[i].token;
// //console.log("current token", currentToken === encryptedToken)
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
// if (!user || !tokenFound) {
// throw new Error("User not found")
// } else if (user.emailVerified) {
// req.token = token;
// req.encryptedToken = encryptedToken
// req.user = user;
// next();
// } else {
// throw new Error("Email Not Verified")
// }
// } catch (e) {
// console.log(e);
// res.status(401).send({error: "Error Authenticating"})
// }
// }
// export default auth;
@@ -0,0 +1,178 @@
import jwt from "jsonwebtoken";
import User, {UserInterface} from "../models/user";
import env from "../enviroment/env";
import {Request, Response, NextFunction} from "express";
interface RequestType extends Request {
user?: userAccessType,
token?: string,
encryptedToken?: string,
}
type jwtType = {
iv: Buffer,
user: userAccessType
}
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
botChecked: boolean,
}
const auth = async(req: RequestType, res: Response, next: NextFunction) => {
try {
console.log("\nAUTH NO EMAIL");
const accessToken = req.cookies["access-token"];
if (!accessToken) throw new Error("No Access Token");
const decoded = jwt.verify(accessToken, env.passwordAccess!) as jwtType;
const user = decoded.user;
if (!user) throw new Error("No User");
req.user = user;
next();
} catch (e) {
console.log("\nAuthorization Middleware No Email Verifiaction Error:", e.message);
return res.status(401).send("Error Authenticating");
}
}
export default auth;
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
// interface RequestType extends Request {
// user?: UserInterface,
// token?: string,
// encryptedToken?: string,
// }
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
// const auth = async(req: RequestType, res: Response, next: NextFunction) => {
// try {
// const token = req.header("Authorization")!.replace("Bearer ", "");
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
// const iv = decoded.iv;
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// let tokenFound = false;
// for (let i = 0; i < user.tokens.length; i++) {
// const currentToken = user.tokens[i].token;
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
// if (!user || !tokenFound) {
// throw new Error("User not found")
// } else {
// req.token = token;
// req.encryptedToken = encryptedToken
// req.user = user;
// next();
// }
// } catch (e) {
// console.log(e);
// res.status(401).send({error: "Error Authenticating"})
// }
// }
// export default auth;
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
// interface RequestType extends Request {
// user?: UserInterface,
// token?: string,
// encryptedToken?: string,
// }
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
// const auth = async(req: RequestType, res: Response, next: NextFunction) => {
// try {
// const token = req.header("Authorization")!.replace("Bearer ", "");
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
// const iv = decoded.iv;
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// let tokenFound = false;
// for (let i = 0; i < user.tokens.length; i++) {
// const currentToken = user.tokens[i].token;
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
// if (!user || !tokenFound) {
// throw new Error("User not found")
// } else {
// req.token = token;
// req.encryptedToken = encryptedToken
// req.user = user;
// next();
// }
// } catch (e) {
// console.log(e);
// res.status(401).send({error: "Error Authenticating"})
// }
// }
// export default auth;
+90
View File
@@ -0,0 +1,90 @@
import jwt from "jsonwebtoken";
import User, {UserInterface} from "../models/user";
import env from "../enviroment/env";
import {Request, Response, NextFunction} from "express";
import { ObjectID } from "mongodb";
interface RequestType extends Request {
user?: UserInterface,
token?: string,
encryptedToken?: string,
}
type jwtType = {
iv: Buffer,
_id: string,
time: number
}
// type userAccessType = {
// _id: string,
// emailVerified: boolean,
// email: string,
// }
const removeOldTokens = async(userID: string, ipAddress: string | undefined, oldTime: number) => {
try {
const minusTime = oldTime - (1000 * 5 * 10);
ipAddress = ipAddress ? ipAddress : "";
if (ipAddress === "") return;
await User.updateOne({_id: userID}, {$pull: {tokens: {ipAddress, time: {$lt: minusTime}}}})
} catch (e) {
console.log("cannot remove old tokens", e);
}
}
const authRefresh = async(req: RequestType, res: Response, next: NextFunction) => {
try {
console.log("\nrefresh token auth")
//if (true === true) throw new Error("test");
const refreshToken = req.cookies["refresh-token"];
if (!refreshToken) throw new Error("No Refresh Token");
const decoded = jwt.verify(refreshToken, env.passwordRefresh!) as jwtType;
const time = decoded.time;
const user = await User.findById(new ObjectID(decoded._id));
if (!user) throw new Error("No User");
const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(refreshToken, encrpytionKey, decoded.iv);
let tokenFound = false;
for (let i = 0; i < user.tokens.length; i++) {
const currentEncryptedToken = user.tokens[i].token;
if (currentEncryptedToken === encryptedToken) {
tokenFound = true;
removeOldTokens(user._id, req.clientIp, time);
break;
}
}
if (!tokenFound) throw new Error("Refresh Token Not Found");
req.user = user;
next();
} catch (e) {
console.log("\nAuthorization Refresh Middleware Error:", e.message);
res.status(401).send("Error Refreshing Token");
}
}
export default authRefresh;
View File
+47 -47
View File
@@ -1,70 +1,70 @@
import jwt from "jsonwebtoken";
import User, {UserInterface} from "../models/user";
import env from "../enviroment/env";
import {Request, Response, NextFunction} from "express";
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
interface RequestType extends Request {
user?: UserInterface,
auth?: boolean,
encryptedTempToken?: string,
}
// interface RequestType extends Request {
// user?: UserInterface,
// auth?: boolean,
// encryptedTempToken?: string,
// }
type jwtType = {
iv: Buffer,
_id: string,
}
// type jwtType = {
// iv: Buffer,
// _id: string,
// }
const tempAuth = async(req: RequestType, res: Response, next: NextFunction) => {
// const tempAuth = async(req: RequestType, res: Response, next: NextFunction) => {
try {
// try {
const token = req.params.tempToken;
// const token = req.params.tempToken;
const decoded = jwt.verify(token, env.password!) as jwtType;
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
const iv = decoded.iv;
// const iv = decoded.iv;
const user = await User.findOne({_id: decoded._id}) as UserInterface;
const encrpytionKey = user.getEncryptionKey();
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
let tokenFound = false;
for (let i = 0; i < user.tempTokens.length; i++) {
// let tokenFound = false;
// for (let i = 0; i < user.tempTokens.length; i++) {
const currentToken = user.tempTokens[i].token;
// const currentToken = user.tempTokens[i].token;
if (currentToken === encryptedToken) {
tokenFound = true;
break;
}
}
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
if (!user || !tokenFound) {
// if (!user || !tokenFound) {
throw new Error("User Not Found")
// throw new Error("User Not Found")
} else {
// } else {
user.tempTokens = user.tempTokens.filter((filterToken) => {
// user.tempTokens = user.tempTokens.filter((filterToken) => {
return filterToken.token !== encryptedToken
})
// return filterToken.token !== encryptedToken
// })
await user.save();
// await user.save();
req.user = user;
req.auth = true;
req.encryptedTempToken = encryptedToken;
// req.user = user;
// req.auth = true;
// req.encryptedTempToken = encryptedToken;
next();
}
// next();
// }
} catch (e) {
console.log(e);
res.status(401).send();
}
}
// } catch (e) {
// console.log(e);
// res.status(401).send();
// }
// }
export default tempAuth;
// export default tempAuth;
+48 -48
View File
@@ -1,70 +1,70 @@
import jwt from "jsonwebtoken";
import User, {UserInterface} from "../models/user";
import env from "../enviroment/env";
import {Request, Response, NextFunction} from "express";
// import jwt from "jsonwebtoken";
// import User, {UserInterface} from "../models/user";
// import env from "../enviroment/env";
// import {Request, Response, NextFunction} from "express";
interface RequestType extends Request {
user?: UserInterface,
auth?: boolean,
encryptedTempToken?: string,
}
// interface RequestType extends Request {
// user?: UserInterface,
// auth?: boolean,
// encryptedTempToken?: string,
// }
type jwtType = {
iv: Buffer,
_id: string,
cookie: string
}
// type jwtType = {
// iv: Buffer,
// _id: string,
// cookie: string
// }
const tempAuthVideo = async(req: RequestType, res: Response, next: NextFunction) => {
// const tempAuthVideo = async(req: RequestType, res: Response, next: NextFunction) => {
try {
// try {
const token = req.params.tempToken;
// const token = req.params.tempToken;
const decoded = jwt.verify(token, env.password!) as jwtType;
// const decoded = jwt.verify(token, env.passwordAccess!) as jwtType;
const iv = decoded.iv;
// const iv = decoded.iv;
if (req.params.uuid !== decoded.cookie) {
// if (req.params.uuid !== decoded.cookie) {
throw new Error("Cookie mismatch")
}
// throw new Error("Cookie mismatch")
// }
const user = await User.findOne({_id: decoded._id}) as UserInterface;
const encrpytionKey = user.getEncryptionKey();
// const user = await User.findOne({_id: decoded._id}) as UserInterface;
// const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
// const encryptedToken = user.encryptToken(token, encrpytionKey, iv);
let tokenFound = false;
for (let i = 0; i < user.tempTokens.length; i++) {
// let tokenFound = false;
// for (let i = 0; i < user.tempTokens.length; i++) {
const currentToken = user.tempTokens[i].token;
// const currentToken = user.tempTokens[i].token;
if (currentToken === encryptedToken) {
tokenFound = true;
break;
}
}
// if (currentToken === encryptedToken) {
// tokenFound = true;
// break;
// }
// }
if (!user || !tokenFound) {
// if (!user || !tokenFound) {
throw new Error("User not found");
// throw new Error("User not found");
} else {
// } else {
await user.save();
// await user.save();
req.user = user;
req.auth = true;
req.encryptedTempToken = encryptedToken;
next();
}
// req.user = user;
// req.auth = true;
// req.encryptedTempToken = encryptedToken;
// next();
// }
} catch (e) {
console.log(e);
res.status(401).send();
}
}
// } catch (e) {
// console.log(e);
// res.status(401).send();
// }
// }
export default tempAuthVideo;
// export default tempAuthVideo;
+4 -1
View File
@@ -53,6 +53,7 @@ const fileSchema = new mongoose.Schema({
link: String,
filePath: String,
s3ID: String,
personalFile: Boolean,
},
required: true
@@ -79,9 +80,11 @@ export interface FileInterface extends Document {
link?: string,
filePath?: string,
s3ID?: string,
personalFile? : boolean
}
}
const File = mongoose.model<FileInterface>("fs.files", fileSchema);
export default File;
export default File;
module.exports = File;
+6 -3
View File
@@ -20,8 +20,8 @@ const folderSchema = new mongoose.Schema({
parentList: {
type: Array,
required:true
}
},
personalFolder: Boolean
}, {
timestamps: true
@@ -31,8 +31,11 @@ export interface FolderInterface extends Document {
name: string,
parent: string,
owner: string,
createdAt: Date,
updatedAt: Date,
parentList: string[],
_doc?: any
_doc?: any,
personalFolder?: boolean
}
const Folder = mongoose.model<FolderInterface>("Folder", folderSchema);
+8 -3
View File
@@ -21,21 +21,26 @@ const thumbnailSchema = new mongoose.Schema({
IV: {
type: Buffer,
},
s3ID: String
s3ID: String,
personalFile: String,
}, {
timestamps: true
})
export interface ThumbnailInterface extends Document {
_id: string,
_id: any,
name: string,
owner: string,
data?: any,
path?: string,
IV?: Buffer,
s3ID? : string,
personalFile?: boolean,
createdAt: Date,
updatedAt: Date
}
const Thumbnail = mongoose.model<ThumbnailInterface>("Thumbnail", thumbnailSchema);
export default Thumbnail;
export default Thumbnail;
module.exports = Thumbnail;
+330 -13
View File
@@ -10,7 +10,6 @@ const userSchema = new mongoose.Schema({
name:
{
type:String,
trim: true
},
email: {
type: String,
@@ -38,6 +37,14 @@ const userSchema = new mongoose.Schema({
token: {
type: String,
required: true
},
ipAddress: {
type: String,
required: true,
},
time: {
type: Number,
required: true
}
}],
tempTokens: [{
@@ -51,8 +58,80 @@ const userSchema = new mongoose.Schema({
},
publicKey: {
type: String,
}
},
emailVerified: {
type: Boolean
},
emailToken: {
type: String,
},
passwordResetToken: {
type: String
},
googleDriveEnabled: {
type: Boolean
},
googleDriveData: {
id: {
type: String
},
key: {
type: String
},
iv: {
type: Buffer
},
token: {
type: String
}
// accessToken: {
// type: String
// },
// refreshToken: {
// type: String
// },
// tokenType: {
// type: String
// },
// expiryDate: {
// type: String
// }
},
s3Enabled: {
type: Boolean
},
s3Data: {
id: {
type: String
},
key: {
type: String
},
bucket: {
type: String
},
iv: {
type: Buffer
}
},
personalStorageCanceledDate: Number,
storageData: {
storageSize: Number,
storageLimit: Number
},
storageDataPersonal: {
storageSize: Number,
},
storageDataGoogle: {
storageSize: Number,
storageLimit: Number
},
activeSubscription: Boolean,
planID: String,
passwordLastModified: Number,
lastSubscriptionCheckTime: Number,
lastSubscriptionStatus: Boolean
}, {
timestamps: true
})
@@ -67,17 +146,71 @@ export interface UserInterface extends Document {
privateKey?: string,
publicKey?: string,
token?: string,
emailVerified?: boolean,
emailToken?: string,
passwordResetToken?: string,
googleDriveEnabled?: boolean,
googleDriveData?: {
id?: string,
key?: string,
iv?: Buffer,
// accessToken?: string,
// refreshToken?: string,
// tokenType?: string,
// expiryDate?: string,
token?: string,
},
s3Enabled?: boolean,
s3Data?: {
id?: string,
key?: string,
bucket?: string,
iv?: Buffer,
},
storageData?: {
storageSize?: number,
storageLimit?: number
},
storageDataPersonal?: {
storageSize?: number
},
storageDataGoogle?: {
storageSize?: number,
storageLimit?: number
},
activeSubscription?: boolean,
passwordLastModified?: number,
personalStorageCanceledDate?: number,
planID?: string,
lastSubscriptionCheckTime?: number,
lastSubscriptionStatus?: boolean,
getEncryptionKey: () => Buffer | undefined;
generateTempAuthToken: () => any;
generateTempAuthTokenVideo: (cookie: string) => any;
encryptToken: (tempToken: any, key: any, publicKey: any) => any;
decryptToken: (encryptedToken: any, key: any, publicKey: any) => any;
findByCreds: (email: string, password: string) => UserInterface;
generateAuthToken: () => any;
generateAuthToken: (ipAddress: string | undefined) => Promise<{accessToken: string, refreshToken: string}>
generateEncryptionKeys: () => Promise<void>;
changeEncryptionKey: (randomKey: Buffer) => void;
generateEmailVerifyToken: () => string;
generatePasswordResetToken: () => string;
encryptDriveIDandKey: (ID:string, key: string) => void;
decryptDriveIDandKey: () => {clientID: string, clientKey: string};
encryptDriveTokenData: (token: Object) => void;
decryptDriveTokenData: () => any;
encryptS3Data: (id: string, key: string, bucket: string) => void;
decryptS3Data: () => {
id: string,
key: string,
bucket: string
}
}
const maxAgeAccess = 1000 * 5 * 10; //60 * 1000 * 20 + (1000 * 60);
const maxAgeRefresh = 60 * 1000 * 60 * 24 * 30 + (1000 * 60);
userSchema.pre("save", async function(this: any, next: any) {
const user = this;
@@ -121,21 +254,47 @@ userSchema.methods.toJSON = function() {
return userObject;
}
userSchema.methods.generateAuthToken = async function() {
userSchema.methods.generateAuthToken = async function(ipAddress: string | undefined) {
const iv = crypto.randomBytes(16);
const user = this;
let token = jwt.sign({_id:user._id.toString(), iv}, env.password!);
const user = this;
const date = new Date();
const time = date.getTime();
const userObj = {_id: user._id, emailVerified: user.emailVerified, email: user.email, s3Enabled: user.s3Enabled}
let accessToken = jwt.sign({user: userObj, iv}, env.passwordAccess!, {expiresIn: maxAgeAccess.toString()});
let refreshToken = jwt.sign({_id:user._id.toString(), iv, time}, env.passwordRefresh!, {expiresIn: maxAgeRefresh.toString()});
const encryptionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encryptionKey, iv);
const encryptedToken = user.encryptToken(refreshToken, encryptionKey, iv);
user.tokens = user.tokens.concat({token: encryptedToken});
//user.tokens = user.tokens.concat({token: encryptedToken});
await user.save();
return token;
ipAddress = ipAddress ? ipAddress : "";
await User.updateOne({_id: user._id}, {$push: {"tokens": {token: encryptedToken, ipAddress, time}}})
// console.log("saving user")
// console.log("user saved")
return {accessToken, refreshToken};
// const iv = crypto.randomBytes(16);
// const user = this;
// let token = jwt.sign({_id:user._id.toString(), iv}, env.passwordAccess!);
// const encryptionKey = user.getEncryptionKey();
// const encryptedToken = user.encryptToken(token, encryptionKey, iv);
// user.tokens = user.tokens.concat({token: encryptedToken});
// await user.save();
// return token;
}
userSchema.methods.encryptToken = function(token: string, key: string, iv: any) {
@@ -243,7 +402,7 @@ userSchema.methods.generateTempAuthToken = async function() {
const iv = crypto.randomBytes(16);
const user = this as UserInterface;
const token = jwt.sign({_id:user._id.toString(), iv}, env.password!, {expiresIn: "3000ms"});
const token = jwt.sign({_id:user._id.toString(), iv}, env.passwordAccess!, {expiresIn: "3000ms"});
const encryptionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encryptionKey, iv);
@@ -254,12 +413,169 @@ userSchema.methods.generateTempAuthToken = async function() {
return token;
}
userSchema.methods.generateEmailVerifyToken = async function() {
const iv = crypto.randomBytes(16);
const user = this as UserInterface;
const token = jwt.sign({_id:user._id.toString(), iv}, env.passwordAccess!, {expiresIn: "1d"});
const encryptionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encryptionKey, iv);
user.emailToken = encryptedToken;
await user.save();
return token;
}
userSchema.methods.encryptDriveIDandKey = async function(ID: string, key: string) {
const iv = crypto.randomBytes(16);
const user = this as UserInterface;
const encryptedKey = user.getEncryptionKey();
const encryptedDriveID = user.encryptToken(ID, encryptedKey, iv);
const encryptedDriveKey = user.encryptToken(key, encryptedKey, iv);
if (!user.googleDriveData) user.googleDriveData = {};
user.googleDriveData!.id = encryptedDriveID;
user.googleDriveData!.key = encryptedDriveKey;
user.googleDriveData!.iv = iv;
await user.save();
}
userSchema.methods.decryptDriveIDandKey = async function() {
const user = this as UserInterface;
const iv = user.googleDriveData!.iv;
const encryptedKey = user.getEncryptionKey();
const encryptedDriveID = user.googleDriveData?.id;
const encryptedDriveKey = user.googleDriveData?.key;
const decryptedDriveID = user.decryptToken(encryptedDriveID, encryptedKey, iv)
const decryptedDriveKey = user.decryptToken(encryptedDriveKey, encryptedKey, iv);
return {
clientID: decryptedDriveID,
clientKey: decryptedDriveKey
}
}
userSchema.methods.encryptDriveTokenData = async function(token: Object) {
const user = this as UserInterface;
const iv = user.googleDriveData?.iv;
const tokenToString = JSON.stringify(token);
const encryptedKey = user.getEncryptionKey();
const encryptedDriveToken = user.encryptToken(tokenToString, encryptedKey, iv);;
if (!user.googleDriveData) user.googleDriveData = {};
user.googleDriveData.token = encryptedDriveToken;
user.googleDriveEnabled = true;
await user.save();
}
userSchema.methods.decryptDriveTokenData = async function() {
const user = this as UserInterface;
const iv = user.googleDriveData!.iv;
const encryptedKey = user.getEncryptionKey();
const encryptedToken = user.googleDriveData?.token;
const decryptedToken = user.decryptToken(encryptedToken, encryptedKey, iv);
const tokenToObj = JSON.parse(decryptedToken);
return tokenToObj;
}
userSchema.methods.encryptS3Data = async function(ID: string, key: string, bucket: string) {
const iv = crypto.randomBytes(16);
const user = this as UserInterface;
const encryptedKey = user.getEncryptionKey();
const encryptedS3ID = user.encryptToken(ID, encryptedKey, iv);
const encryptedS3Key = user.encryptToken(key, encryptedKey, iv);
const encryptedS3Bucket = user.encryptToken(bucket, encryptedKey, iv);
if (!user.s3Data) user.s3Data = {};
user.s3Data!.id = encryptedS3ID;
user.s3Data!.key = encryptedS3Key;
user.s3Data!.bucket = encryptedS3Bucket;
user.s3Data!.iv = iv;
user.s3Enabled = true;
await user.save();
}
userSchema.methods.decryptS3Data = async function() {
const user = this as UserInterface;
const iv = user.s3Data?.iv;
const encryptedKey = user.getEncryptionKey();
const encrytpedS3ID = user.s3Data?.id;
const encryptedS3Key = user.s3Data?.key;
const encryptedS3Bucket = user.s3Data?.bucket;
const decrytpedS3ID = user.decryptToken(encrytpedS3ID, encryptedKey, iv);
const decryptedS3Key = user.decryptToken(encryptedS3Key, encryptedKey, iv);
const decryptedS3Bucket = user.decryptToken(encryptedS3Bucket, encryptedKey, iv);
//console.log("decrypted keys", decrytpedS3ID, decryptedS3Key, decryptedS3Bucket);
return {
id: decrytpedS3ID,
key: decryptedS3Key,
bucket: decryptedS3Bucket,
}
}
userSchema.methods.generatePasswordResetToken = async function() {
console.log("generating reset password token")
const iv = crypto.randomBytes(16);
const user = this as UserInterface;
const token = jwt.sign({_id:user._id.toString(), iv}, env.passwordAccess!, {expiresIn: "1h"});
const encryptionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encryptionKey, iv);
user.passwordResetToken = encryptedToken;
await user.save();
return token;
}
userSchema.methods.generateTempAuthTokenVideo = async function(cookie: string) {
const iv = crypto.randomBytes(16);
const user = this;
const token = jwt.sign({_id:user._id.toString(), cookie, iv}, env.password!, {expiresIn:"5h"});
const token = jwt.sign({_id:user._id.toString(), cookie, iv}, env.passwordAccess!, {expiresIn:"5h"});
const encryptionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(token, encryptionKey, iv);
@@ -272,4 +588,5 @@ userSchema.methods.generateTempAuthTokenVideo = async function(cookie: string) {
const User = mongoose.model<UserInterface>("User", userSchema);
export default User;
export default User;
module.exports = User;
+16 -7
View File
@@ -4,6 +4,11 @@ import userRouter from "../express-routers/user";
import fileRouter from "../express-routers/file";
import folderRouter from "../express-routers/folder";
import storageRouter from "../express-routers/storage";
import googleFileRouter from "../express-routers/googleFile";
import personalFileRouter from "../express-routers/personalFile";
import googleFolderRouter from "../express-routers/googleFolder";
import userGoogleRouter from "../express-routers/userGoogle";
import userPersonalRouter from "../express-routers/userPersonal";
import bodyParser from "body-parser";
import https from "https";
import fs from "fs";
@@ -11,8 +16,9 @@ import helmet from "helmet";
import busboy from "connect-busboy";
import compression from "compression";
import http from "http";
import cookieParser from "cookie-parser";
import env from "../enviroment/env";
import requestIp from "request-ip";
const app = express();
const publicPath = path.join(__dirname, "..", "..", "public");
@@ -21,7 +27,7 @@ let server: any;
let serverHttps: any;
if (process.env.SSL === 'true') {
const cert = fs.readFileSync("certificate.crt")
const ca = fs.readFileSync("certificate.ca-bundle");
const key = fs.readFileSync("certificate.key");
@@ -40,23 +46,25 @@ server = http.createServer(app);
require("../db/mongoose");
app.use(cookieParser(env.passwordCookie));
app.use(helmet())
app.use(compression());
app.use(express.json());
app.use(express.static(publicPath));
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit: "50mb", extended: true, parameterLimit:50000}))
app.use(requestIp.mw());
app.use(busboy({
highWaterMark: 2 * 1024 * 1024,
}));
app.use(userRouter, fileRouter, folderRouter, storageRouter);
app.use(userRouter, fileRouter, folderRouter, storageRouter, googleFileRouter, personalFileRouter, googleFolderRouter, userPersonalRouter, userGoogleRouter);
const nodeMode = process.env.NODE_ENV ? "Production" : "Development/Testing";
//const nodeMode = process.env.NODE_ENV ? "Production" : "Development/Testing";
console.log("Node Enviroment Mode:", nodeMode);
//console.log("Node Enviroment Mode:", nodeMode);
app.get("*", (_: Request, res: Response) => {
@@ -64,4 +72,5 @@ app.get("*", (_: Request, res: Response) => {
res.sendFile(path.join(publicPath, "index.html"))
})
export default {server, serverHttps};
export default {server, serverHttps};
@@ -13,6 +13,7 @@ import File, { FileInterface } from "../../models/file";
import getFileSize from "./utils/getFileSize";
import DbUtilFile from "../../db/utils/fileUtils/index";
import awaitStream from "./utils/awaitStream";
import createThumbnailAny from "./utils/createThumbailAny";
import createThumbnailFS from "./utils/createThumbnailFS";
import imageChecker from "../../utils/imageChecker";
import Thumbnail, {ThumbnailInterface} from "../../models/thumbnail";
@@ -23,7 +24,9 @@ import removeChunksFS from "./utils/removeChunksFS";
import getPrevIVFS from "./utils/getPrevIVFS";
import awaitStreamVideo from "./utils/awaitStreamVideo";
import fixStartChunkLength from "./utils/fixStartChunkLength";
import Folder from "../../models/folder";
import Folder, { FolderInterface } from "../../models/folder";
import addToStoageSize from "./utils/addToStorageSize";
import subtractFromStorageSize from "./utils/subtractFromStorageSize";
const dbUtilsFile = new DbUtilFile();
@@ -40,7 +43,6 @@ class FileSystemService implements ChunkInterface {
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const initVect = crypto.randomBytes(16);
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
@@ -52,10 +54,11 @@ class FileSystemService implements ChunkInterface {
const parent = formData.get("parent") || "/"
const parentList = formData.get("parentList") || "/";
const size = formData.get("size") || ""
const personalFile = formData.get("personal-file") ? true : false;
let hasThumbnail = false;
let thumbnailID = ""
const isVideo = videoChecker(filename)
const systemFileName = uuid.v4();
const metadata = {
@@ -88,13 +91,13 @@ class FileSystemService implements ChunkInterface {
await currentFile.save();
console.log(currentFile);
await addToStoageSize(user, size, personalFile);
const imageCheck = imageChecker(currentFile.filename);
if (currentFile.length < 15728640 && imageCheck) {
const updatedFile = await createThumbnailFS(currentFile, filename, user);
const updatedFile = await createThumbnailAny(currentFile, filename, user);
return updatedFile;
@@ -105,6 +108,47 @@ class FileSystemService implements ChunkInterface {
}
getFileWriteStream = async(user: UserInterface, file: FileInterface, parentFolder: FolderInterface) => {
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const initVect = crypto.randomBytes(16);
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const cipher = crypto.createCipheriv('aes256', CIPHER_KEY, initVect);
const filename = file.filename
const parent = parentFolder._id
const parentList = [...parentFolder.parentList, parentFolder._id]
const size = file.metadata.size
const personalFile = file.metadata.personalFile ? true : false
let hasThumbnail = file.metadata.hasThumbnail;
let thumbnailID = file.metadata.thumbnailID
const isVideo = file.metadata.isVideo
const systemFileName = uuid.v4();
const metadata = {
owner: user._id,
parent,
parentList,
hasThumbnail,
thumbnailID,
isVideo,
size,
IV: file.metadata.IV,
filePath: env.fsDirectory + systemFileName
}
const fileWriteStream = fs.createWriteStream(metadata.filePath);
return fileWriteStream;
}
downloadFile = async(user: UserInterface, fileID: string, res: Response) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(fileID, user._id);
@@ -134,6 +178,29 @@ class FileSystemService implements ChunkInterface {
await awaitStream(readStream.pipe(decipher), res, allStreamsToErrorCatch);
}
getFileReadStream = async(user: UserInterface, fileID: string) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(fileID, user._id);
if (!currentFile) throw new NotFoundError("Download File Not Found");
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const filePath = currentFile.metadata.filePath!;
const IV = currentFile.metadata.IV.buffer as Buffer;
const readStream = fs.createReadStream(filePath);
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, IV);
return readStream
}
getThumbnail = async(user: UserInterface, id: string) => {
const password = user.getEncryptionKey();
@@ -188,9 +255,7 @@ class FileSystemService implements ChunkInterface {
const allStreamsToErrorCatch = [readStream, decipher];
console.log("Sending Full Thumbnail...")
await awaitStream(readStream.pipe(decipher), res, allStreamsToErrorCatch);
console.log("Full thumbnail sent");
}
streamVideo = async(user: UserInterface, fileID: string, headers: any, res: Response, req: Request) => {
@@ -264,7 +329,6 @@ class FileSystemService implements ChunkInterface {
const tempUUID = req.params.uuid;
await awaitStreamVideo(start, end, differenceStart, decipher, res, req, tempUUID, allStreamsToErrorCatch);
console.log("Video Stream Finished");
readStream.destroy();
}
@@ -321,6 +385,7 @@ class FileSystemService implements ChunkInterface {
await removeChunksFS(file.metadata.filePath!);
await File.deleteOne({_id: file._id});
await subtractFromStorageSize(userID, file.length, file.metadata.personalFile!)
}
deleteFolder = async(userID: string, folderID: string, parentList: string[]) => {
+73 -10
View File
@@ -1,12 +1,11 @@
import mongoose from "../../db/mongoose";
import { Response, Request } from "express";
import DbUtilFolder from "../../db/utils/folderUtils";
import { Response, Request } from "express";;
import DbUtilFile from "../../db/utils/fileUtils";
import crypto from "crypto";
import videoChecker from "../../utils/videoChecker"
import imageChecker from "../../utils/imageChecker"
import { ObjectID } from "mongodb";
import createThumbnail from "./utils/createThumbnail";
import createThumbnailAny from "./utils/createThumbailAny";
import Thumbnail, {ThumbnailInterface} from "../../models/thumbnail";
import NotAuthorizedError from "../../utils/NotAuthorizedError";
import NotFoundError from "../../utils/NotFoundError";
@@ -14,13 +13,15 @@ import {GridFSBucketWriteStream} from "mongodb";
import awaitStream from "./utils/awaitStream";
import awaitUploadStream from "./utils/awaitUploadStream";
import User, { UserInterface } from "../../models/user";
import Folder from "../../models/folder";
import Folder, { FolderInterface } from "../../models/folder";
import { FileInterface } from "../../models/file";
import getBusboyData from "./utils/getBusboyData";
import ChunkInterface from "./utils/ChunkInterface";
import fixStartChunkLength from "./utils/fixStartChunkLength";
import getPrevIVMongo from "./utils/getPrevIVMongo";
import awaitStreamVideo from "./utils/awaitStreamVideo";
import addToStoageSize from "./utils/addToStorageSize";
import subtractFromStorageSize from "./utils/subtractFromStorageSize";
const conn = mongoose.connection;
@@ -51,10 +52,11 @@ class MongoService implements ChunkInterface {
const parent = formData.get("parent") || "/"
const parentList = formData.get("parentList") || "/";
const size = formData.get("size") || ""
const personalFile = formData.get("personal-file") ? true : false;
let hasThumbnail = false;
let thumbnailID = ""
const isVideo = videoChecker(filename)
const metadata = {
owner: user._id,
parent,
@@ -66,7 +68,6 @@ class MongoService implements ChunkInterface {
IV: initVect
}
let bucket = new mongoose.mongo.GridFSBucket(conn.db);
bucketStream = bucket.openUploadStream(filename, {metadata});
@@ -75,11 +76,13 @@ class MongoService implements ChunkInterface {
const finishedFile = await awaitUploadStream(file.pipe(cipher), bucketStream, req, allStreamsToErrorCatch) as FileInterface;
await addToStoageSize(user, size, personalFile);
const imageCheck = imageChecker(filename);
if (finishedFile.length < 15728640 && imageCheck) {
const updatedFile = await createThumbnail(finishedFile, filename, user);
const updatedFile = await createThumbnailAny(finishedFile, filename, user);
return updatedFile;
@@ -89,6 +92,46 @@ class MongoService implements ChunkInterface {
}
}
getFileWriteStream = async(user: UserInterface, file: FileInterface, parentFolder: FolderInterface) => {
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const initVect = crypto.randomBytes(16);
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const cipher = crypto.createCipheriv('aes256', CIPHER_KEY, initVect);
const filename = file.filename
const parent = parentFolder._id
const parentList = [...parentFolder.parentList, parentFolder._id]
const size = file.metadata.size
const personalFile = file.metadata.personalFile ? true : false
let hasThumbnail = file.metadata.hasThumbnail;
let thumbnailID = file.metadata.thumbnailID
const isVideo = file.metadata.isVideo;
const metadata = {
owner: user._id,
parent,
parentList,
hasThumbnail,
thumbnailID,
isVideo,
size,
IV: file.metadata.IV
}
let bucket = new mongoose.mongo.GridFSBucket(conn.db);
const bucketStream = bucket.openUploadStream(filename, {metadata});
return bucketStream;
}
downloadFile = async(user: UserInterface, fileID: string, res: Response) => {
const currentFile = await dbUtilsFile.getFileInfo(fileID, user._id);
@@ -117,6 +160,28 @@ class MongoService implements ChunkInterface {
await awaitStream(readStream.pipe(decipher), res, allStreamsToErrorCatch);
}
getFileReadStream = async(user: UserInterface, fileID: string) => {
const currentFile = await dbUtilsFile.getFileInfo(fileID, user._id);
if (!currentFile) throw new NotFoundError("Download File Not Found");
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const bucket = new mongoose.mongo.GridFSBucket(conn.db);
const IV = currentFile.metadata.IV.buffer as Buffer;
const readStream = bucket.openDownloadStream(new ObjectID(fileID));
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, IV);
return readStream
}
getThumbnail = async(user: UserInterface, id: string) => {
const password = user.getEncryptionKey();
@@ -167,12 +232,9 @@ class MongoService implements ChunkInterface {
res.set('Content-Disposition', 'attachment; filename="' + file.filename + '"');
res.set('Content-Length', file.metadata.size.toString());
console.log("Sending Full Thumbnail...")
const allStreamsToErrorCatch = [readStream, decipher];
await awaitStream(readStream.pipe(decipher), res, allStreamsToErrorCatch);
console.log("Full thumbnail sent");
}
getPublicDownload = async(fileID: string, tempToken: any, res: Response) => {
@@ -307,6 +369,7 @@ class MongoService implements ChunkInterface {
}
await bucket.delete(new ObjectID(fileID));
await subtractFromStorageSize(userID, file.length, file.metadata.personalFile!);
}
deleteFolder = async(userID: string, folderID: string, parentList: string[]) => {
+166 -75
View File
@@ -12,7 +12,7 @@ import videoChecker from "../../utils/videoChecker";
import uuid from "uuid";
import awaitUploadStreamS3 from "./utils/awaitUploadStreamS3";
import awaitStream from "./utils/awaitStream";
import createThumbnailS3 from "./utils/createThumbnailS3";
import createThumbnailAny from "./utils/createThumbailAny";
import imageChecker from "../../utils/imageChecker";
import Thumbnail, {ThumbnailInterface} from "../../models/thumbnail";
import streamToBuffer from "../../utils/streamToBuffer";
@@ -21,9 +21,12 @@ import fixStartChunkLength from "./utils/fixStartChunkLength";
import fixEndChunkLength from "./utils/fixEndChunkLength";
import getPrevIVS3 from "./utils/getPrevIVS3";
import awaitStreamVideo from "./utils/awaitStreamVideo";
import Folder from "../../models/folder";
import Folder, { FolderInterface } from "../../models/folder";
import DbUtilFile from "../../db/utils/fileUtils/index";
import s3Auth from "../../db/S3Personal";
import addToStoageSize from "./utils/addToStorageSize";
import subtractFromStorageSize from "./utils/subtractFromStorageSize";
const dbUtilsFile = new DbUtilFile();
class S3Service implements ChunkInterface {
@@ -49,13 +52,17 @@ class S3Service implements ChunkInterface {
const parent = formData.get("parent") || "/"
const parentList = formData.get("parentList") || "/";
const size = formData.get("size") || ""
const personalFile = formData.get("personal-file") ? true : false;
let hasThumbnail = false;
let thumbnailID = ""
const isVideo = videoChecker(filename)
const randomS3ID = uuid.v4();
const metadata = {
const s3Data: any = personalFile ? await user.decryptS3Data() : {};
const bucketName = personalFile ? s3Data.bucket : env.s3Bucket;
let metadata: any = {
owner: user._id,
parent,
parentList,
@@ -64,16 +71,18 @@ class S3Service implements ChunkInterface {
isVideo,
size,
IV: initVect,
s3ID: randomS3ID
s3ID: randomS3ID,
}
if (personalFile) metadata = {...metadata, personalFile: true}
const params = {
Bucket: env.s3Bucket,
Bucket: bucketName,
Body : file.pipe(cipher),
Key : randomS3ID
};
await awaitUploadStreamS3(params);
await awaitUploadStreamS3(params, personalFile, s3Data);
const date = new Date();
const encryptedFileSize = size;
@@ -87,12 +96,13 @@ class S3Service implements ChunkInterface {
await currentFile.save();
await addToStoageSize(user, size, personalFile);
const imageCheck = imageChecker(currentFile.filename);
if (currentFile.length < 15728640 && imageCheck) {
console.log("Creating thumbnail...")
const updatedFile = await createThumbnailS3(currentFile, filename, user);
const updatedFile = await createThumbnailAny(currentFile, filename, user);
return updatedFile;
@@ -102,6 +112,77 @@ class S3Service implements ChunkInterface {
}
}
getFileWriteStream = async(user: UserInterface, file: FileInterface, parentFolder: FolderInterface, readStream: any) => {
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const initVect = crypto.randomBytes(16);
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const cipher = crypto.createCipheriv('aes256', CIPHER_KEY, initVect);
const filename = file.filename
const parent = parentFolder._id
const parentList = [...parentFolder.parentList, parentFolder._id]
const size = file.metadata.size
const personalFile = file.metadata.personalFile ? true : false
let hasThumbnail = file.metadata.hasThumbnail;
let thumbnailID = file.metadata.thumbnailID
const isVideo = file.metadata.isVideo
const metadata = {
owner: user._id,
parent,
parentList,
hasThumbnail,
thumbnailID,
isVideo,
size,
IV: file.metadata.IV,
s3ID: file.metadata.s3ID,
personalFile
}
const s3Data: any = personalFile ? await user.decryptS3Data() : {};
const bucketName = personalFile ? s3Data.bucket : env.s3Bucket;
const params = {
Bucket: bucketName,
Body : readStream,
Key : file.metadata.s3ID
};
}
getS3AuthThumbnail = async (thumbnail: ThumbnailInterface, user: UserInterface) => {
if (thumbnail.personalFile) {
const s3Data = await user.decryptS3Data();
//console.log("s3 data", s3Data)
return {s3Storage: s3Auth(s3Data.id, s3Data.key), bucket: s3Data.bucket};
} else {
return {s3Storage: s3, bucket: env.s3Bucket};
}
}
getS3Auth = async (file: FileInterface, user: UserInterface) => {
if (file.metadata.personalFile) {
const s3Data = await user.decryptS3Data();
//console.log("s3 data", s3Data)
return {s3Storage: s3Auth(s3Data.id, s3Data.key), bucket: s3Data.bucket};
} else {
return {s3Storage: s3, bucket: env.s3Bucket};
}
}
downloadFile = async(user: UserInterface, fileID: string, res: Response) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(fileID, user._id);
@@ -110,7 +191,9 @@ class S3Service implements ChunkInterface {
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
if (!password) throw new NotAuthorizedError("Invalid Encryption Key");
const {s3Storage, bucket} = await this.getS3Auth(currentFile, user);
const IV = currentFile.metadata.IV.buffer as Buffer;
@@ -122,14 +205,38 @@ class S3Service implements ChunkInterface {
res.set('Content-Disposition', 'attachment; filename="' + currentFile.filename + '"');
res.set('Content-Length', currentFile.metadata.size.toString());
const params: any = {Bucket: env.s3Bucket, Key: currentFile.metadata.s3ID!};
const params: any = {Bucket: bucket, Key: currentFile.metadata.s3ID!};
const s3ReadStream = s3.getObject(params).createReadStream();
const s3ReadStream = s3Storage.getObject(params).createReadStream();
const allStreamsToErrorCatch = [s3ReadStream, decipher];
await awaitStream(s3ReadStream.pipe(decipher), res, allStreamsToErrorCatch);
}
getFileReadStream = async(user: UserInterface, fileID: string) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(fileID, user._id);
if (!currentFile) throw new NotFoundError("Download File Not Found");
const password = user.getEncryptionKey();
if (!password) throw new NotAuthorizedError("Invalid Encryption Key");
const {s3Storage, bucket} = await this.getS3Auth(currentFile, user);
const IV = currentFile.metadata.IV.buffer as Buffer;
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, IV);
const params: any = {Bucket: bucket, Key: currentFile.metadata.s3ID!};
const s3ReadStream = s3Storage.getObject(params).createReadStream();
return s3ReadStream
}
streamVideo = async(user: UserInterface, fileID: string, headers: any, res: Response, req: Request) => {
@@ -144,6 +251,8 @@ class S3Service implements ChunkInterface {
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const fileSize = currentFile.metadata.size;
const isPersonal = currentFile.metadata.personalFile!;
const range = headers.range
const parts = range.replace(/bytes=/, "").split("-")
@@ -175,12 +284,14 @@ class S3Service implements ChunkInterface {
if (fixedStart !== 0 && start !== 0) {
currentIV = await getPrevIVS3(fixedStart - 16, currentFile.metadata.s3ID!) as Buffer;
currentIV = await getPrevIVS3(fixedStart - 16, currentFile.metadata.s3ID!, isPersonal, user) as Buffer;
}
const params: any = {Bucket: env.s3Bucket, Key: currentFile.metadata.s3ID!, Range: `bytes=${fixedStart}-${fixedEnd}`};
const {s3Storage, bucket} = await this.getS3Auth(currentFile, user);
const s3ReadStream = s3.getObject(params).createReadStream();
const params: any = {Bucket: bucket, Key: currentFile.metadata.s3ID!, Range: `bytes=${fixedStart}-${fixedEnd}`};
const s3ReadStream = s3Storage.getObject(params).createReadStream();
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
@@ -194,44 +305,7 @@ class S3Service implements ChunkInterface {
const tempUUID = req.params.uuid;
// s3ReadStream.on("data", () => {
// console.log("data", tempUUID);
// })
// req.on("close", () => {
// // console.log("Destoying read stream");
// // s3ReadStream.destroy();
// // console.log("Read Stream Destroyed");
// })
// req.on("end", () => {
// console.log("ending stream");
// s3ReadStream.destroy();
// console.log("ended stream")
// })
// req.on("error", () => {
// console.log("req error");
// })
// req.on("pause", () => {
// console.log("req pause")
// })
// req.on("close", () => {
// // console.log("req closed");
// s3ReadStream.destroy();
// })
//req.on("")
// req.on("end", () => {
// console.log("req end");
// })
await awaitStreamVideo(start, end, differenceStart, decipher, res, req, tempUUID, allStreamsToErrorCatch);
console.log("Video stream finished");
s3ReadStream.destroy();
}
@@ -249,14 +323,16 @@ class S3Service implements ChunkInterface {
}
const iv = thumbnail.IV!;
const {s3Storage, bucket} = await this.getS3AuthThumbnail(thumbnail, user);
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
const decipher = crypto.createDecipheriv("aes256", CIPHER_KEY, iv);
const params: any = {Bucket: env.s3Bucket, Key: thumbnail.s3ID!};
const params: any = {Bucket: bucket, Key: thumbnail.s3ID!};
const readStream = s3.getObject(params).createReadStream();
const readStream = s3Storage.getObject(params).createReadStream();
const allStreamsToErrorCatch = [readStream, decipher];
@@ -278,9 +354,11 @@ class S3Service implements ChunkInterface {
if (!password) throw new NotAuthorizedError("Invalid Encryption Key")
const params: any = {Bucket: env.s3Bucket, Key: file.metadata.s3ID!};
const {s3Storage, bucket} = await this.getS3Auth(file, user);
const readStream = s3.getObject(params).createReadStream();
const params: any = {Bucket: bucket, Key: file.metadata.s3ID!};
const readStream = s3Storage.getObject(params).createReadStream();
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
@@ -292,9 +370,7 @@ class S3Service implements ChunkInterface {
const allStreamsToErrorCatch = [readStream, decipher];
console.log("Sending Full Thumbnail...")
await awaitStream(readStream.pipe(decipher), res, allStreamsToErrorCatch);
console.log("Full thumbnail sent");
}
getPublicDownload = async(fileID: string, tempToken: any, res: Response) => {
@@ -312,10 +388,12 @@ class S3Service implements ChunkInterface {
if (!password) throw new NotAuthorizedError("Invalid Encryption Key");
const IV = file.metadata.IV.buffer as Buffer;
const params: any = {Bucket: env.s3Bucket, Key: file.metadata.s3ID!};
const readStream = s3.getObject(params).createReadStream();
const {s3Storage, bucket} = await this.getS3Auth(file, user);
const params: any = {Bucket: bucket, Key: file.metadata.s3ID!};
const readStream = s3Storage.getObject(params).createReadStream();
const CIPHER_KEY = crypto.createHash('sha256').update(password).digest()
@@ -340,18 +418,23 @@ class S3Service implements ChunkInterface {
const file: FileInterface = await dbUtilsFile.getFileInfo(fileID, userID);
if (!file) throw new NotFoundError("Delete File Not Found Error");
const user = await User.findById(userID) as UserInterface;
const {s3Storage, bucket} = await this.getS3Auth(file, user);
if (file.metadata.thumbnailID) {
const thumbnail = await Thumbnail.findById(file.metadata.thumbnailID) as ThumbnailInterface;
const paramsThumbnail: any = {Bucket: env.s3Bucket, Key: thumbnail.s3ID!};
await removeChunksS3(paramsThumbnail);
const paramsThumbnail: any = {Bucket: bucket, Key: thumbnail.s3ID!};
await removeChunksS3(s3Storage, paramsThumbnail);
await Thumbnail.deleteOne({_id: file.metadata.thumbnailID});
}
const params: any = {Bucket: env.s3Bucket, Key: file.metadata.s3ID!};
await removeChunksS3(params);
const params: any = {Bucket: bucket, Key: file.metadata.s3ID!};
await removeChunksS3(s3Storage, params);
await File.deleteOne({_id: file._id});
await subtractFromStorageSize(userID, file.length, file.metadata.personalFile!);
}
deleteFolder = async(userID: string, folderID: string, parentList: string[]) => {
@@ -364,23 +447,27 @@ class S3Service implements ChunkInterface {
const fileList = await dbUtilsFile.getFileListByParent(userID, parentListString);
if (!fileList) throw new NotFoundError("Delete File List Not Found");
const user = await User.findById(userID) as UserInterface;
for (let i = 0; i < fileList.length; i++) {
const currentFile = fileList[i];
const {s3Storage, bucket} = await this.getS3Auth(currentFile, user);
try {
if (currentFile.metadata.thumbnailID) {
const thumbnail = await Thumbnail.findById(currentFile.metadata.thumbnailID) as ThumbnailInterface;
const paramsThumbnail: any = {Bucket: env.s3Bucket, Key: thumbnail.s3ID!};
await removeChunksS3(paramsThumbnail);
const paramsThumbnail: any = {Bucket: bucket, Key: thumbnail.s3ID!};
await removeChunksS3(s3Storage, paramsThumbnail);
await Thumbnail.deleteOne({_id: currentFile.metadata.thumbnailID});
}
const params: any = {Bucket: env.s3Bucket, Key: currentFile.metadata.s3ID!};
await removeChunksS3(params);
const params: any = {Bucket: bucket, Key: currentFile.metadata.s3ID!};
await removeChunksS3(s3Storage, params);
await File.deleteOne({_id: currentFile._id});
} catch (e) {
@@ -401,21 +488,25 @@ class S3Service implements ChunkInterface {
if (!fileList) throw new NotFoundError("Delete All File List Not Found Error");
const user = await User.findById(userID) as UserInterface;
for (let i = 0; i < fileList.length; i++) {
const currentFile = fileList[i];
const {s3Storage, bucket} = await this.getS3Auth(currentFile, user);
try {
if (currentFile.metadata.thumbnailID) {
const thumbnail = await Thumbnail.findById(currentFile.metadata.thumbnailID) as ThumbnailInterface;
const paramsThumbnail: any = {Bucket: env.s3Bucket, Key: thumbnail.s3ID!};
await removeChunksS3(paramsThumbnail);
const paramsThumbnail: any = {Bucket: bucket, Key: thumbnail.s3ID!};
await removeChunksS3(s3Storage, paramsThumbnail);
await Thumbnail.deleteOne({_id: currentFile.metadata.thumbnailID});
}
const params: any = {Bucket: env.s3Bucket, Key: currentFile.metadata.s3ID!};
await removeChunksS3(params);
const params: any = {Bucket: bucket, Key: currentFile.metadata.s3ID!};
await removeChunksS3(s3Storage, params);
await File.deleteOne({_id: currentFile._id});
} catch (e) {
@@ -9,6 +9,7 @@ interface ChunkInterface {
getFullThumbnail: (user: UserInterface, fileID: string, res: Response) => void;
getPublicDownload: (fileID: string, tempToken: any, res: Response) => void;
streamVideo: (user: UserInterface, fileID: string, headers: any, res: Response, req: Request) => void;
getFileReadStream: (user: UserInterface, fileID: string) => any
}
export default ChunkInterface;
@@ -0,0 +1,20 @@
import {UserInterface} from "../../../models/user";
import env from "../../../enviroment/env";
const addToStoageSize = async(user: UserInterface, size: number, isPersonalFile: boolean) => {
if (isPersonalFile) {
//console.log("user storage")
user.storageDataPersonal!.storageSize = +user.storageDataPersonal!.storageSize! + +size;
await user.save()
return;
}
if (!user.storageData || (!user.storageData.storageSize && !user.storageData.storageLimit)) user.storageData = {storageSize: 0, storageLimit: 0};
user.storageData!.storageSize = +user.storageData!.storageSize! + +size;
await user.save();
}
export default addToStoageSize;
@@ -15,7 +15,6 @@ const awaitStream = <T>(inputSteam: any, outputStream: any, allStreamsToErrorCat
})
inputSteam.pipe(outputStream).on("finish", (data: T) => {
console.log("await stream finished")
resolve(data);
})
})
@@ -0,0 +1,66 @@
import request from "request";
import axios from "axios";
import { Response, Request } from "express";
import { UserInterface } from "../../../models/user";
import convertDriveToMongo from "../../../utils/convertDriveToMongo";
interface RequestType extends Request {
user?: UserInterface,
auth?: boolean,
busboy: any,
}
const awaitUploadGoogle = (file: any, size: number, axiosBody: any, axiosConfigObj: any, drive: any, req: RequestType, res: Response, allStreamsToErrorCatch: any[]) => {
return new Promise((resolve, reject) => {
allStreamsToErrorCatch.forEach((currentStream: any) => {
currentStream.on("error", (err: Error) => {
console.log("req errror", err)
reject({
message: "Await Stream Input Error",
code: 500,
error: err
})
})
})
axios.post("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable", axiosBody, axiosConfigObj).then((result) => {
const URI: any = result.headers.location
request.post({
url: URI,
headers: {
"Content-Length": size,
},
body: file
}, async function (e, results, b) {
if (e) {
console.log(e)
return;
}
const jsonResults = JSON.parse(results.body)
const retrievedFile = await drive.files.get({
fileId: jsonResults.id,
fields: "*"
})
const reqAny: any = req;
const uploadedFile = convertDriveToMongo(retrievedFile.data, reqAny.user._id);
res.send(uploadedFile)
resolve()
})
}).catch((err) => {
console.log("axios err", err)
})
})
}
export default awaitUploadGoogle;
@@ -21,8 +21,6 @@ const awaitUploadStream = <T>(inputSteam: any, outputStream: any, req: Request,
req.on("aborted", () => {
console.log("Upload Request Cancelling...");
removeChunks(outputStream);
})
@@ -21,8 +21,6 @@ const awaitUploadStream = <T>(inputSteam: any, outputStream: any, req: Request,
req.on("aborted", () => {
console.log("Upload Request Cancelling...");
removeChunksFS(path);
})
@@ -1,18 +1,36 @@
import s3 from "../../../db/s3";
import s3Personal from "../../../db/S3Personal";
const awaitUploadStreamS3 = (params: any) => {
const awaitUploadStreamS3 = (params: any, personalFile: boolean, s3Data: {id: string, key: string, bucket: string}) => {
return new Promise((resolve, reject) => {
s3.upload(params, (err: any, data: any) => {
if (personalFile) {
if (err) {
reject("Amazon upload error");
}
const s3PersonalAuth = s3Personal(s3Data.id, s3Data.key);
resolve();
})
s3PersonalAuth.upload(params, (err: any, data: any) => {
if (err) {
console.log("Amazon upload personal err", err)
reject("Amazon upload error");
}
resolve();
})
} else {
s3.upload(params, (err: any, data: any) => {
if (err) {
console.log("Amazon upload err", err)
reject("Amazon upload error");
}
resolve();
})
}
})
}
@@ -0,0 +1,57 @@
// class CachedSubsriptions {
// cachedSubscriptionStatuses: any;
// constructor() {
// this.cachedSubscriptionStatuses = {}
// }
// addToCachedSubscriptionStatus = (userID: string) => {
// this.cachedSubscriptionStatuses[userID] = true;
// console.log("new cached", this.cachedSubscriptionStatuses)
// }
// checkCachedSubscriptionStatus = (userID: string) => {
// console.log("cache check", this.cachedSubscriptionStatuses)
// return this.cachedSubscriptionStatuses[userID];
// }
// }
// export default CachedSubsriptions;
// const cachedSubscriptionStatuses: any = {};
// export default cachedSubscriptionStatuses;
// import redis from "redis";
// const client = redis.createClient();
// export const setCachedValue = (userID: string) => {
// const date = new Date();
// return new Promise((resolve, reject) => {
// client.set(userID, date.getTime().toString(), (err, res) => {
// if (err) {
// console.log("Redis key err", err);
// reject()
// }
// resolve();
// });
// })
// }
// export const checkCachedValue = (userID: string) => {
// return new Promise((resolve, reject) => {
// client.get(userID, (err) => {
// if (err) {
// console.log("Redis key err", err);
// reject()
// } else {
// resolve();
// }
// })
// })
// }
@@ -0,0 +1,27 @@
import s3Auth from "../../../db/S3Personal";
const calculateS3Size = async(id:string, key:string, bucket:string) => {
const s3Storage = s3Auth(id, key);
const params = {
Bucket: bucket
}
const objectList = await s3Storage.listObjects(params).promise();
if (!objectList.Contents) return 0;
let size = 0
for (let i = 0; i < objectList.Contents!.length; i++) {
const currentObject = objectList.Contents[i];
if (!currentObject.Size) continue;
size += +currentObject.Size!;
}
return size;
}
export default calculateS3Size;
@@ -0,0 +1,25 @@
import {FileInterface} from "../../../models/file";
import {UserInterface} from "../../../models/user";
import createThumbnailS3 from "./createThumbnailS3";
import createThumbnailMongo from "./createThumbnail";
import createThumbnailFilesystem from "./createThumbnailFS";
import env from "../../../enviroment/env";
const createThumnailAny = async(currentFile: FileInterface, filename: string, user: UserInterface) => {
if (currentFile.metadata.personalFile || env.dbType === "s3") {
return await createThumbnailS3(currentFile, filename, user);
} else if (env.dbType === "mongo") {
return await createThumbnailMongo(currentFile, filename, user);
} else {
return await createThumbnailFilesystem(currentFile, filename, user);
}
}
export default createThumnailAny;
@@ -7,22 +7,40 @@ import { UserInterface } from "../../../models/user";
import uuid from "uuid";
import env from "../../../enviroment/env";
import s3 from "../../../db/s3";
import s3Auth from "../../../db/S3Personal"
const conn = mongoose.connection;
const getS3Auth = async (file: FileInterface, user: UserInterface) => {
if (file.metadata.personalFile) {
const s3Data = await user.decryptS3Data();
//console.log("s3 data", s3Data)
return {s3Storage: s3Auth(s3Data.id, s3Data.key), bucket: s3Data.bucket};
} else {
return {s3Storage: s3, bucket: env.s3Bucket};
}
}
const createThumbnailS3 = (file: FileInterface, filename: string, user: UserInterface) => {
return new Promise<FileInterface>((resolve, reject) => {
return new Promise<FileInterface>( async(resolve, reject) => {
const password = user.getEncryptionKey();
let CIPHER_KEY = crypto.createHash('sha256').update(password!).digest()
const thumbnailFilename = uuid.v4();
const params: any = {Bucket: env.s3Bucket, Key: file.metadata.s3ID!};
const readStream = s3.getObject(params).createReadStream();
const {s3Storage, bucket} = await getS3Auth(file, user);
const isPersonalFile = file.metadata.personalFile;
const params: any = {Bucket: bucket, Key: file.metadata.s3ID!};
const readStream = s3Storage.getObject(params).createReadStream();
const decipher = crypto.createDecipheriv('aes256', CIPHER_KEY, file.metadata.IV);
@@ -48,19 +66,19 @@ const createThumbnailS3 = (file: FileInterface, filename: string, user: UserInte
})
const paramsWrite: any = {
Bucket: env.s3Bucket,
Bucket: bucket,
Body : readStream.pipe(decipher).pipe(imageResize).pipe(thumbnailCipher),
Key : thumbnailFilename
};
s3.upload(paramsWrite, async(err: any, data: any) => {
s3Storage.upload(paramsWrite, async(err: any, data: any) => {
if (err) {
console.log("Amazon Upload Error", err);
reject("Amazon upload error");
}
const thumbnailModel = new Thumbnail({name: thumbnailFilename, owner: user._id, IV: thumbnailIV, s3ID: thumbnailFilename});
const thumbnailModel = new Thumbnail({name: thumbnailFilename, owner: user._id, IV: thumbnailIV, s3ID: thumbnailFilename, personalFile: isPersonalFile});
await thumbnailModel.save();
@@ -1,18 +1,38 @@
import s3 from "../../../db/s3";
import s3Auth from "../../../db/S3Personal";
import env from "../../../enviroment/env";
import {UserInterface} from "../../../models/user"
const getPrevIV = (start: number, key: string) => {
const getPrevIV = (start: number, key: string, isPersonal: boolean, user: UserInterface) => {
return new Promise<Buffer | string>((resolve, reject) => {
return new Promise<Buffer | string>(async(resolve, reject) => {
const params: any = {Bucket: env.s3Bucket, Key: key, Range: `bytes=${start}-${start + 15}`};
if (isPersonal) {
const stream = s3.getObject(params).createReadStream();
const s3Data = await user.decryptS3Data();
stream.on("data", (data) => {
const params: any = {Bucket: s3Data.bucket, Key: key, Range: `bytes=${start}-${start + 15}`};
resolve(data);
})
const s3Storage = s3Auth(s3Data.id, s3Data.key);
const stream = s3Storage.getObject(params).createReadStream();
stream.on("data", (data) => {
resolve(data);
})
} else {
const params: any = {Bucket: env.s3Bucket, Key: key, Range: `bytes=${start}-${start + 15}`};
const stream = s3.getObject(params).createReadStream();
stream.on("data", (data) => {
resolve(data);
})
}
})
}
@@ -16,7 +16,6 @@ const removeChunks = async(bucketStream: GridFSBucketWriteStream) => {
}
await dbUtilsFile.removeChunksByID(uploadID);
console.log("Upload Request Cancelled, Chunks Removed");
} catch(e) {
@@ -11,10 +11,10 @@ const removeChunksFS = (path: string) => {
resolve();
}
console.log("File Removed");
resolve();
})
})
}
export default removeChunksFS;
export default removeChunksFS;
module.exports = removeChunksFS;
@@ -1,21 +1,21 @@
import s3 from "../../../db/s3";
//import s3 from "../../../db/s3";
const removeChunksS3 = (parmas: any) => {
const removeChunksS3 = (s3: any, parmas: any) => {
return new Promise((resolve, reject) => {
s3.deleteObject(parmas, (err, data) => {
s3.deleteObject(parmas, (err: any, data: any) => {
if (err) {
console.log("Could not remove S3 file");
reject("Could Not Remove S3 File");
}
console.log("Delete S3 file");
resolve();
})
})
}
export default removeChunksS3;
export default removeChunksS3;
module.exports = removeChunksS3;
@@ -0,0 +1,24 @@
import User, {UserInterface} from "../../../models/user";
import env from "../../../enviroment/env";
const subtractFromStorageSize = async(userID: string, size: number, isPersonalFile: boolean) => {
const user = await User.findById(userID) as UserInterface;
if (isPersonalFile) {
user.storageDataPersonal!.storageSize = +user.storageDataPersonal!.storageSize! - +size;
if (user.storageDataPersonal!.storageSize < 0) user.storageDataPersonal!.storageSize = 0;
await user.save();
return
}
if (!user.storageData || (!user.storageData.storageSize && !user.storageData.storageLimit)) user.storageData = {storageSize: 0, storageLimit: 0}
user.storageData!.storageSize = +user.storageData!.storageSize! - +size;
if (user.storageData?.storageSize! < 0) user.storageData!.storageSize! = 0;
await user.save();
}
export default subtractFromStorageSize;
+26 -11
View File
@@ -10,10 +10,17 @@ import DbUtilFolder from "../../db/utils/folderUtils";
import { UserInterface } from "../../models/user";
import { FileInterface } from "../../models/file";
import tempStorage from "../../tempStorage/tempStorage";
import uuid from "uuid";
const dbUtilsFile = new DbUtilFile();
const dbUtilsFolder = new DbUtilFolder();
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
class MongoFileService {
@@ -38,10 +45,9 @@ class MongoFileService {
if (!file.lastErrorObject.updatedExisting) throw new NotFoundError("Remove Link File Not Found Error")
}
makePublic = async(user: UserInterface, fileID: string) => {
makePublic = async(userID: string, fileID: string) => {
const userID = user._id;
const token = await jwt.sign({_id: userID.toString()}, env.password!);
const token = await jwt.sign({_id: userID.toString()}, env.passwordAccess!);
const file = await dbUtilsFile.makePublic(fileID, userID, token);
@@ -66,7 +72,7 @@ class MongoFileService {
makeOneTimePublic = async(userID: string, fileID: string) => {
const token = await jwt.sign({_id: userID.toString()}, env.password!);
const token = await jwt.sign({_id: userID.toString()}, env.passwordAccess!);
const file = await dbUtilsFile.makeOneTimePublic(fileID, userID, token);
@@ -107,16 +113,21 @@ class MongoFileService {
return {...currentFile, parentName}
}
getQuickList = async(userID: string) => {
getQuickList = async(user: userAccessType | UserInterface) => {
const quickList = await dbUtilsFile.getQuickList(userID);
const userID = user._id;
const s3Enabled = user.s3Enabled ? true : false;
const quickList = await dbUtilsFile.getQuickList(userID, s3Enabled);
if (!quickList) throw new NotFoundError("Quick List Not Found Error");
return quickList;
}
getList = async(userID: string, query: any) => {
getList = async(user: userAccessType | UserInterface, query: any) => {
const userID = user._id;
let searchQuery = query.search || "";
const parent = query.parent || "/";
@@ -125,11 +136,15 @@ class MongoFileService {
const startAt = query.startAt || undefined
const startAtDate = query.startAtDate || "0"
const startAtName = query.startAtName || ""
const storageType = query.storageType || undefined;
const folderSearch = query.folder_search || undefined;
sortBy = sortBySwitch(sortBy)
limit = parseInt(limit)
const s3Enabled = user.s3Enabled ? true : false;
const queryObj = createQuery(userID, parent, query.sortby,startAt, startAtDate, searchQuery, startAtName)
const queryObj = createQuery(userID, parent, query.sortby,startAt, startAtDate, searchQuery, s3Enabled ,startAtName, storageType, folderSearch);
const fileList = await dbUtilsFile.getList(queryObj, sortBy, limit);
if (!fileList) throw new NotFoundError("File List Not Found");
@@ -161,7 +176,7 @@ class MongoFileService {
const key = user.getEncryptionKey();
const decoded = await jwt.verify(tempToken, env.password!) as any;
const decoded = await jwt.verify(tempToken, env.passwordAccess!) as any;
const publicKey = decoded.iv;
+64 -4
View File
@@ -4,6 +4,14 @@ import NotFoundError from "../../utils/NotFoundError";
import UtilsFile from "../../db/utils/fileUtils";
import UtilsFolder from "../../db/utils/folderUtils";
import sortBySwitch from "../../utils/sortBySwitchFolder";
import { UserInterface } from "../../models/user";
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
const utilsFile = new UtilsFile();
const utilsFolder = new UtilsFolder();
@@ -97,16 +105,23 @@ class FolderService {
}
}
getFolderList = async(userID: string, query: any) => {
getFolderList = async(user: userAccessType | UserInterface, query: any) => {
const userID = user._id;
let searchQuery = query.search || "";
const parent = query.parent || "/";
let sortBy = query.sortby || "DEFAULT"
sortBy = sortBySwitch(sortBy)
const type = query.type;
const storageType = query.storageType || undefined;
const folderSearch = query.folder_search || undefined;
sortBy = sortBySwitch(sortBy);
const s3Enabled = user.s3Enabled ? true : false;
if (searchQuery.length === 0) {
const folderList = await utilsFolder.getFolderListByParent(userID, parent, sortBy);
const folderList = await utilsFolder.getFolderListByParent(userID, parent, sortBy, s3Enabled, type, storageType);
if (!folderList) throw new NotFoundError("Folder List Not Found Error");
@@ -115,7 +130,7 @@ class FolderService {
} else {
searchQuery = new RegExp(searchQuery, 'i')
const folderList = await utilsFolder.getFolderListBySearch(userID, searchQuery, sortBy);
const folderList = await utilsFolder.getFolderListBySearch(userID, searchQuery, sortBy, type, parent, storageType, folderSearch);
if (!folderList) throw new NotFoundError("Folder List Not Found Error");
@@ -130,6 +145,51 @@ class FolderService {
if (!folder) throw new NotFoundError("Rename Folder Not Found");
}
getSubfolderFullList = async(user: userAccessType, id: string) => {
const userID = user._id;
const folder = await utilsFolder.getFolderInfo(id, userID)
const subFolders = await this.getFolderList(user, {parent: id}) //folderService.getFolderList(user._id, {parent: id})
let folderList: any[] = [];
const rootID = "/"
let currentID = folder.parent;
folderList.push({
_id: folder._id,
parent: folder._id,
name: folder.name,
subFolders: subFolders
})
while (true) {
if (rootID === currentID) break;
console.log("finding ID", currentID)
const currentFolder = await this.getFolderInfo(userID, currentID);
const currentSubFolders = await this.getFolderList(user, {parent: currentFolder._id});
folderList.splice(0, 0, {
_id: currentFolder._id,
parent: currentFolder._id,
name: currentFolder.name,
subFolders: currentSubFolders
})
currentID = currentFolder.parent;
}
// console.log("SENDING FOLDER LIST FULL MONGO", folderList)
return folderList;
}
moveFolder = async(userID: string, folderID: string, parentID: string) => {
let parentList = ["/"];
+485
View File
@@ -0,0 +1,485 @@
import { UserInterface } from "../../models/user";
import getGoogleAuth from "../../db/googleAuth";
import {google} from "googleapis";
import convertDriveListToMongoList from "../../utils/convertDriveListToMongoList";
import createQueryGoogle from "../../utils/createQueryGoogle";
import FileService from "../FileService";
import sortGoogleMongoList from "../../utils/sortGoogleMongoList";
import convertDriveToMongo from "../../utils/convertDriveToMongo";
import convertDriveFoldersToMongoFolders from "../../utils/convertDriveFoldersToMongoFolders";
import { Response, Request } from "express";
import tempStorage from "../../tempStorage/tempStorage";
import uuid from "uuid";
import getBusboyData from "../ChunkService/utils/getBusboyData";
import axios from "axios";
import awaitUploadGoogle from "../ChunkService/utils/awaitUploadGoogle";
interface RequestType extends Request {
user?: UserInterface,
auth?: boolean,
busboy: any,
}
const fileService = new FileService();
const fields = 'id, name, size, modifiedTime, hasThumbnail, parents, mimeType, thumbnailLink, webViewLink, shared';
class GoogleFileService {
constructor() {
}
getList = async(user: UserInterface, query: any) => {
const oauth2Client = await getGoogleAuth(user);
const limit: any = query.limit as any;
let parent = query.parent === "/" ? "root" : query.parent;
const {queryBuilder, orderBy} = createQueryGoogle(query, parent)
const previosPageToken: any = query.pageToken;
const drive = google.drive({version:"v3", auth: oauth2Client});
const files = await drive.files.list({pageSize: limit, fields: `nextPageToken, files(${fields})`, q: queryBuilder, orderBy, pageToken: previosPageToken});
const nextPageToken: any = files.data.nextPageToken;
const userID = user._id;
const convertedFiles = convertDriveListToMongoList(files.data.files, userID, nextPageToken);
return convertedFiles;
}
getMongoGoogleList = async(user: UserInterface, query: any) => {
const oauth2Client = await getGoogleAuth(user);
const limit: any = query.limit as any;
let parent = query.parent === "/" ? "root" : query.parent;
const {queryBuilder, orderBy} = createQueryGoogle(query, parent)
const previosPageToken: any = query.pageToken;
const drive = google.drive({version:"v3", auth: oauth2Client});
const files = await drive.files.list({pageSize: limit, fields: `nextPageToken, files(${fields})`, q: queryBuilder, orderBy, pageToken: previosPageToken});
const nextPageToken: any = files.data.nextPageToken;
const userID = user._id;
const convertedFiles = convertDriveListToMongoList(files.data.files, userID, nextPageToken);
const fileList = await fileService.getList(user, query);
const sortedList = sortGoogleMongoList([...convertedFiles, ...fileList], query)
return sortedList;
}
getFileInfo = async(user: UserInterface, id: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const file = await drive.files.get({fileId: id, fields: fields});
const userID = user._id;
const convertedFile = convertDriveToMongo(file.data, userID);
return convertedFile;
}
getGoogleMongoQuickList = async(user: UserInterface) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
let query = 'mimeType != "application/vnd.google-apps.folder" and trashed=false';
const files = await drive.files.list({pageSize: 10, fields: `nextPageToken, files(${fields})`, q: query});
const userID = user._id
const convertedFiles = convertDriveListToMongoList(files.data.files, userID);
const quickList = await fileService.getQuickList(user);
let combinedData = [...convertedFiles, ...quickList]
combinedData = combinedData.sort((a, b) => {
const convertedDateA = new Date(a.uploadDate).getTime();
const convertedDateB = new Date(b.uploadDate).getTime();
return convertedDateB - convertedDateA;
})
if (combinedData.length >= 10) {
combinedData = combinedData.slice(0, 10);
}
return combinedData;
}
getGoogleMongoSuggestedList = async(user: UserInterface, searchQuery: string) => {
const driveQuery = `name contains "${searchQuery}" and mimeType != "application/vnd.google-apps.folder" and trashed=false`
const driveQueryFolder = `name contains "${searchQuery}" and mimeType = "application/vnd.google-apps.folder" and trashed=false`
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const files = await drive.files.list({pageSize: 10, fields: `nextPageToken, files(${fields})`, q: driveQuery});
const folders = await drive.files.list({pageSize: 10, fields: `nextPageToken, files(${fields})`, q: driveQueryFolder});
const userID = user._id;
const convertedFiles = convertDriveListToMongoList(files.data.files, userID);
const convertedFolders = convertDriveFoldersToMongoFolders(folders.data.files, userID);
const {fileList: mongoFileList, folderList: mongoFolderList} = await fileService.getSuggestedList(user._id, searchQuery);
return {
folderList: [...mongoFolderList, ...convertedFolders],
fileList: [...mongoFileList, ...convertedFiles]
}
}
renameFile = async(user: UserInterface, fileID: string, title: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
await drive.files.update({fileId: fileID, requestBody: {name:title}})
}
removeFile = async(user: UserInterface, fileID: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
await drive.files.delete({fileId:fileID});
}
downloadFile = async(user: UserInterface, fileID: string, res: Response) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const fileMetadata = await drive.files.get({fileId: fileID, fields: "*"})
res.set('Content-Type', 'binary/octet-stream');
res.set('Content-Disposition', 'attachment; filename="' + fileMetadata.data.name! + '"');
res.set('Content-Length', fileMetadata.data.size!);
return new Promise((resolve, reject) => {
drive.files.get(
{fileId: fileID, alt: "media"},
{responseType: "stream"},
(err, resp) => {
if (err) {
console.log(err);
return;
}
resp?.data
.on("end", () => {resolve()})
.on("error", (err: any) => {
console.log(err);
reject();
})
.pipe(res);
})
})
}
downloadDoc = async(user: UserInterface, fileID: string, res: Response) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const fileMetadata = await drive.files.get({fileId: fileID, fields: "*"})
res.set('Content-Type', 'binary/octet-stream');
res.set('Content-Disposition', 'attachment; filename="' + fileMetadata.data.name! + ".pdf" + '"');
res.set('Content-Length', fileMetadata.data.size!);
drive.files.export({
fileId: fileID,
mimeType: 'application/pdf'
}, {
responseType: "stream"
}, (err, resp) => {
if (err) {
console.log("export err", err);
res.end();
return;
}
resp?.data.pipe(res)
})
}
getThumbnail = async(user: UserInterface, fileID: string, res: Response) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const fileMetadata = await drive.files.get({fileId: fileID, fields: "*"})
res.set('Content-Type', 'binary/octet-stream');
res.set('Content-Disposition', 'attachment; filename="' + fileMetadata.data.name! + '"');
res.set('Content-Length', fileMetadata.data.size!);
return new Promise((resolve, reject) => {
drive.files.get(
{fileId: fileID, alt: "media"},
{responseType: "stream"},
(err, resp) => {
if (err) {
console.log(err);
return;
}
resp?.data
.on("end", () => {resolve()})
.on("error", (err: any) => {
console.log(err);
reject();
})
.pipe(res);
})
})
}
getFullThumbnail = async(user: UserInterface, fileID: string, res: Response) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const fileMetadata = await drive.files.get({fileId: fileID, fields: "*"})
res.set('Content-Type', 'binary/octet-stream');
res.set('Content-Disposition', 'attachment; filename="' + fileMetadata.data.name! + '"');
res.set('Content-Length', fileMetadata.data.size!);
return new Promise((resolve, reject) => {
drive.files.get(
{fileId: fileID, alt: "media"},
{responseType: "stream"},
(err, resp) => {
if (err) {
console.log(err);
reject()
return;
}
resp?.data
.on("end", () => {resolve()})
.on("error", (err: any) => {
console.log(err);
reject();
})
.pipe(res);
})
})
}
streamVideo = async(user: UserInterface, fileID: string, tempUUID: string, req: RequestType, res: Response) => {
const currentUUID = uuid.v4();
tempStorage[tempUUID] = currentUUID;
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const fileMetadata = await drive.files.get({fileId: fileID, fields: "*"})
const fileSize = +fileMetadata.data.size!
const headers = req.headers;
const range = headers.range!
const parts = range.replace(/bytes=/, "").split("-")
let start = parseInt(parts[0], 10)
let end = parts[1]
? parseInt(parts[1], 10)
: fileSize-1
const chunksize = (end-start)+1
let head = {
'Content-Range': 'bytes ' + start + '-' + end + '/' + fileSize,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'}
res.writeHead(206, head);
return new Promise((resolve, reject) => {
drive.files.get(
{fileId: fileID, alt: "media"},
{responseType: "stream", headers: {
Range: `bytes=${start}-${end}`
}},
(err, resp) => {
if (err) {
console.log(err);
return;
}
resp?.data
.on("end", () => {resolve()})
.on("error", (err: any) => {
console.log(err);
reject();
})
.on("data", () => {
if (tempStorage[tempUUID] !== currentUUID) {
resp?.data.destroy();
resolve();
}
})
.pipe(res);
})
})
}
uploadFile = async(user: UserInterface, busboy: any, req: RequestType, res: Response) => {
const streamsToErrorCatch = [req, busboy];
const {file, filename, formData} = await getBusboyData(busboy);
let parent = formData.get("parent") || "/"
const size = formData.get("size") || ""
parent = parent === "/" ? "root" : parent;
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
type fileMetadataType = {
name?: string,
parents?: string[]
}
let fileMetadata: fileMetadataType = {}
fileMetadata.name = filename;
if (parent !== "/") {
fileMetadata.parents = [parent]
}
const googleIDandKey = await user.decryptDriveIDandKey();
const clientID = googleIDandKey.clientID;
const clientKey = googleIDandKey.clientKey;
const googleToken = await user.decryptDriveTokenData();
const refreshToken = googleToken.refresh_token;
const data = {
client_id: clientID,
client_secret: clientKey,
refresh_token: refreshToken,
grant_type: 'refresh_token'
}
const tokenResp = await axios.post("https://www.googleapis.com/oauth2/v4/token", data);
const accessToken = tokenResp.data.access_token
const config = {
'Authorization': `Bearer ${accessToken}`,
'Content-Length': size,
'Content-Type': 'application/json'
}
const axiosConfigObj = {
headers: config,
}
const axiosBody = {
name: filename,
parents: [parent],
fields: "*"
}
await awaitUploadGoogle(file, size, axiosBody, axiosConfigObj, drive, req, res, streamsToErrorCatch);
}
moveFile = async(user: UserInterface, fileID: string, parentID: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const previousFile = await drive.files.get({
fileId: fileID,
fields: "*"
})
const previousParent = previousFile.data.parents![0];
await drive.files.update({
fileId: fileID,
addParents: parentID,
removeParents: previousParent,
fields: fields
})
}
makeFilePublic = async(user: UserInterface, fileID: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const publicFile = await drive.permissions.create({
requestBody: {
type: "anyone",
role: "reader"
},
fileId: fileID,
fields: "*"
})
const fileDetails = await drive.files.get({
fileId: fileID,
fields: fields
})
const publicURL = fileDetails.data.webViewLink!;
return publicURL;
}
removePublicLink = async(user: UserInterface, fileID: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const fileMetadata = await drive.files.get({
fileId: fileID,
fields: "*",
})
const permissions = await drive.permissions.get({
fileId: fileID,
permissionId: fileMetadata.data.permissionIds![0]
})
console.log(permissions.data)
await drive.permissions.delete({
fileId: fileID,
permissionId: fileMetadata.data.permissionIds![0]
})
}
}
export default GoogleFileService;
@@ -0,0 +1,239 @@
import { UserInterface } from "../../models/user";
import getGoogleAuth from "../../db/googleAuth";
import {google} from "googleapis";
import convertDriveFoldersToMongoFolders from "../../utils/convertDriveFoldersToMongoFolders";
import createQueryGoogleFolder from "../../utils/createQueryGoogleFolder";
import FolderService from "../FolderService";
import sortGoogleMongoFolderList from "../../utils/sortGoogleMongoFolderList";
import convertDriveFolderToMongoFolder from "../../utils/convertDriveFolderToMongoFolder";
const folderService = new FolderService();
const fields = 'id, name, createdTime, parents, mimeType'
class GoogleFolderService {
constructor() {
}
getList = async(user: UserInterface, query: any) => {
const oauth2Client = await getGoogleAuth(user);
const limit: any = query.limit as any;
let parent = query.parent === "/" ? "root" : query.parent;
const {orderBy, queryBuilder} = createQueryGoogleFolder(query, parent);
const drive = google.drive({version:"v3", auth: oauth2Client});
const files = await drive.files.list({pageSize: limit, fields: `files(${fields})`, q: queryBuilder, orderBy});
const userID = user._id;
const convertedFiles = convertDriveFoldersToMongoFolders(files.data.files, userID);
return convertedFiles;
}
getGoogleMongoList = async(user: UserInterface, query: any) => {
const oauth2Client = await getGoogleAuth(user);
const limit: any = query.limit as any;
let parent = query.parent === "/" ? "root" : query.parent;
const {orderBy, queryBuilder} = createQueryGoogleFolder(query, parent)
const drive = google.drive({version:"v3", auth: oauth2Client});
const files = await drive.files.list({pageSize: limit, fields: `files(${fields})`, q: queryBuilder, orderBy});
const userID = user._id;
const convertedFiles = convertDriveFoldersToMongoFolders(files.data.files, userID);
const folderList = await folderService.getFolderList(user, query);
const mongoGoogleList = sortGoogleMongoFolderList([...convertedFiles, ...folderList], query);
return mongoGoogleList;
}
getInfo = async(user: UserInterface, id: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const file = await drive.files.get({fileId: id, fields: fields});
const userID = user._id;
const convertedFile = convertDriveFolderToMongoFolder(file.data, userID);
return convertedFile;
}
getSubFolderList = async(user: UserInterface, id: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const file = await drive.files.get({fileId: id, fields: fields});
let folderIDList = []
let folderNameList = []
folderIDList.push("/");
folderNameList.push("Home")
const rootGet = await drive.files.get({fileId: "root"});
const rootID = rootGet.data.id!;
let currentID = file.data.parents![0]
while (true) {
if (rootID === currentID) break;
const currentFile = await drive.files.get({fileId: currentID, fields: fields});
folderIDList.splice(1, 0, currentFile.data.id!)
folderNameList.splice(1,0, currentFile.data.name!)
currentID = currentFile.data.parents![0];
}
folderIDList.push(id);
folderNameList.push(file.data.name)
return {
folderIDList,
folderNameList
}
}
getSubFolderFullList = async(user: UserInterface, id: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const file = await drive.files.get({fileId: id, fields: fields});
const parent = file.data.parents![0];
let queryBuilder = `mimeType = "application/vnd.google-apps.folder"`
queryBuilder += ` and "${file.data.id!}" in parents`
const subFolders = await drive.files.list({fields: `files(${fields})`, q: queryBuilder})
const convertedFile = convertDriveFolderToMongoFolder(file.data, user._id);
const convertedSubFolders = convertDriveFoldersToMongoFolders(subFolders.data.files, user._id)
let folderList: any[] = [];
const rootGet = await drive.files.get({fileId: 'root', fields: fields});
const rootID = rootGet.data.id!;
let currentID = file.data.parents![0]
folderList.push({
_id: convertedFile._id,
parent: convertedFile._id,
name: convertedFile.name,
subFolders: convertedSubFolders
})
while (true) {
if (rootID === currentID) break;
const currentFile = await drive.files.get({fileId: currentID, fields: fields});
const currentConvertedFile = convertDriveFolderToMongoFolder(currentFile.data, user._id)
queryBuilder = `mimeType = "application/vnd.google-apps.folder"`
queryBuilder += ` and "${currentConvertedFile._id}" in parents`
const currentSubFolders = await drive.files.list({fields: `files(${fields})`, q: queryBuilder})
const currentConvertedSubFolders = convertDriveFoldersToMongoFolders(currentSubFolders.data.files, user._id)
folderList.splice(0, 0, {
_id: currentConvertedFile._id,
parent: currentConvertedFile._id,
name: currentConvertedFile.name,
subFolders: currentConvertedSubFolders
})
currentID = currentFile.data.parents![0];
}
return folderList;
}
renameFolder = async(user: UserInterface, fileID: string, title: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
await drive.files.update({fileId: fileID, requestBody: {name:title}})
}
removeFolder = async(user: UserInterface, fileID: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
await drive.files.delete({fileId:fileID});
}
upload = async(user: UserInterface, name: string, parent: string, ) => {
parent = parent === "/" ? "root" : parent;
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const folderMetadata = {
name,
mimeType: 'application/vnd.google-apps.folder',
parents: [parent]
}
const createdFolder = await drive.files.create({
requestBody: folderMetadata,
fields: fields
})
const userID = user._id;
const convertedFolder = convertDriveFolderToMongoFolder(createdFolder.data, userID)
return convertedFolder;
}
moveFolder = async(user: UserInterface, fileID: string, parentID: string) => {
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const previousFile = await drive.files.get({
fileId: fileID,
fields: fields
})
const previousParent = previousFile.data.parents![0];
await drive.files.update({
fileId: fileID,
addParents: parentID,
removeParents: previousParent,
fields: fields
})
}
}
export default GoogleFolderService;
+72
View File
@@ -0,0 +1,72 @@
import {UserInterface} from "../../models/user";
import env from "../../enviroment/env";
import { google } from "googleapis";
class UserGoogleService {
constructor() {
}
createGoogleStorageURL = async(user: UserInterface, googleData: any) => {
const {clientID, clientKey, clientRedirect} = googleData;
const oauth2Client = new google.auth.OAuth2(
clientID, clientKey, env.remoteURL + "/add-google-account"
);
const url = oauth2Client.generateAuthUrl({
access_type: 'offline',
prompt: "consent",
scope: ["https://www.googleapis.com/auth/drive"],
});
await user.encryptDriveIDandKey(clientID, clientKey);
user.decryptDriveIDandKey();
return url;
}
addGoogleStorage = async(user: UserInterface, code: string) => {
const redirectURL = env.remoteURL + "/add-google-account";
const decrypyedIdandKey = await user.decryptDriveIDandKey();
const clientID = decrypyedIdandKey.clientID;
const clientKey = decrypyedIdandKey.clientKey
const oauth2Client = new google.auth.OAuth2(
clientID,
clientKey,
redirectURL,
);
return new Promise((resolve, reject) => {
oauth2Client.getToken(code, async(err, tokens) => {
if (!err) {
const token: any = tokens;
user.encryptDriveTokenData(token);
resolve();
} else {
reject("Get Google Token Error")
}
})
})
}
removeGoogleStorage = async(user: UserInterface) => {
user.googleDriveEnabled = undefined;
user.googleDriveData = undefined;
await user.save();
}
}
export default UserGoogleService;
@@ -0,0 +1,147 @@
import {UserInterface} from "../../models/user";
import File, { FileInterface } from "../../models/file";
import Folder, { FolderInterface } from "../../models/folder";
import Thumbnail, { ThumbnailInterface } from "../../models/thumbnail";
import { ObjectID } from "mongodb";;
import calculateS3Size from "../ChunkService/utils/calculateS3Size";
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
s3Enabled: boolean,
}
class UserPeronsalService {
constructor() {
}
addS3Storage = async(user: UserInterface, s3Data: any) => {
const {id, key, bucket} = s3Data;
user.storageDataPersonal!.storageSize = await calculateS3Size(id, key, bucket);
user.personalStorageCanceledDate = undefined;
await user.encryptS3Data(id, key, bucket);
await user.save();
}
removeS3Storage = async(user: UserInterface) => {
const date = new Date();
user.s3Enabled = undefined;
user.s3Data = undefined;
user.storageDataPersonal = undefined;
user.personalStorageCanceledDate = date.getTime();
await user.save();
}
downloadPersonalFileList = async(user: userAccessType) => {
const fileList = await File.find({"metadata.owner": user._id, "metadata.personalFile": true});
const folderList = await Folder.find({"owner": user._id.toString(), 'personalFolder': true});
const thumbnailList: ThumbnailInterface[] = [];
for (const currentFile of fileList) {
if (currentFile.metadata.hasThumbnail) {
const currentThumbnail = await Thumbnail.findById(new ObjectID(currentFile.metadata.thumbnailID)) as ThumbnailInterface;
thumbnailList.push(currentThumbnail);
}
}
const combined = {fileList, folderList, thumbnailList}
const data = JSON.stringify(combined);
return data;
}
uploadPersonalFileList = async(user: userAccessType, data: any) => {
const personalFileList: FileInterface[] = data.fileList;
const personalFolderList: FolderInterface[] = data.folderList;
const personalThumbnailList: ThumbnailInterface[] = data.thumbnailList;
const fixedFileList: FileInterface[] = []
for (let currentObj of personalFileList) {
await File.deleteMany({_id: currentObj._id, 'metadata.owner': user._id});
currentObj.metadata.owner = user._id;
currentObj._id = new ObjectID(currentObj._id)
const oldIV: any = currentObj.metadata.IV;
const IV: any = Buffer.from(oldIV, 'base64');
currentObj.metadata.IV = IV;
const newDate: any = new Date(currentObj.uploadDate);
currentObj.uploadDate = newDate;
currentObj.metadata.parent = currentObj.metadata.parent.toString();
fixedFileList.push(currentObj);
}
const fixedFolderList: FolderInterface[] = []
for (let currentObj of personalFolderList) {
await Folder.deleteMany({_id: currentObj._id, owner: user._id.toString()});
currentObj._id = new ObjectID(currentObj._id)
currentObj.owner = user._id.toString();
currentObj.createdAt = new Date(currentObj.createdAt);
currentObj.updatedAt = new Date(currentObj.updatedAt);
fixedFolderList.push(currentObj);
}
const fixedThumbnailList: ThumbnailInterface[] = [];
for (let currentObj of personalThumbnailList) {
await Thumbnail.deleteMany({_id: currentObj._id, owner: user._id.toString()});
currentObj._id = new ObjectID(currentObj._id);
currentObj.owner = user._id.toString();
currentObj.createdAt = new Date(currentObj.createdAt);
currentObj.updatedAt = new Date(currentObj.updatedAt);
const oldIV: any = currentObj.IV;
const IV: any = Buffer.from(oldIV, 'base64');
currentObj.IV = IV;
fixedThumbnailList.push(currentObj);
}
await File.insertMany(fixedFileList);
await Folder.insertMany(fixedFolderList);
await Thumbnail.insertMany(fixedThumbnailList);
}
removeS3Metadata = async(user: userAccessType) => {
const fileList = await File.find({"metadata.owner": user._id,
"metadata.personalFile": true})
for (let currentFile of fileList) {
await File.deleteOne({_id: currentFile._id});
if (currentFile.metadata.hasThumbnail) {
await Thumbnail.deleteOne({_id: currentFile.metadata.thumbnailID})
}
}
await Folder.deleteMany({'owner': user._id.toString(), 'personalFolder': true});
}
}
export default UserPeronsalService;
+261 -21
View File
@@ -3,73 +3,132 @@ import bcrypt from "bcrypt";
import NotFoundError from "../../utils/NotFoundError";
import InternalServerError from "../../utils/InternalServerError";
import NotAuthorizedError from "../../utils/NotAuthorizedError";
import sendEmailVerification from "../../utils/sendVerificationEmail";
import File from "../../models/file";
import env from "../../enviroment/env";
import getGoogleAuth from "../../db/googleAuth";
import { google } from "googleapis";
import jwt from "jsonwebtoken"
import sendVerificationEmail from "../../utils/sendVerificationEmail";
import sendPasswordResetEmail from "../../utils/sendPasswordResetEmail";
type UserDataType = {
email: string,
password: string,
}
type jwtType = {
iv: Buffer,
_id: string,
}
const uknownUserType = User as unknown;
const UserStaticType = uknownUserType as {
findByCreds: (email: string, password: string) => Promise<UserInterface>;
};
class UserService {
constructor() {
}
login = async(userData: UserDataType) => {
login = async(userData: UserDataType, ipAddress: string | undefined) => {
const email = userData.email;
const password = userData.password;
const user = await UserStaticType.findByCreds(email, password);
const token = await user.generateAuthToken();
if (!user) throw new NotFoundError("Cannot Find User");
if (!user || !token) throw new NotFoundError("Login User Not Found Error");
const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress);
return {user, token}
if (!accessToken || !refreshToken) throw new NotFoundError("Login User Not Found Error");
//if (!user.emailVerified) throw new NotEmailVertifiedError("Email Address Not Verified")
return {user, accessToken, refreshToken}
}
logout = async(user: UserInterface, userToken: any) => {
logout = async(userID: string, refreshToken: string) => {
user.tokens = user.tokens.filter((token) => {
return token.token !== userToken;
})
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Could Not Find User");
if (refreshToken) {
const decoded = jwt.verify(refreshToken, env.passwordRefresh!) as jwtType;
const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(refreshToken, encrpytionKey, decoded.iv);
for (let i = 0; i < user.tokens.length; i++) {
const currentEncryptedToken = user.tokens[i].token;
if (currentEncryptedToken === encryptedToken) {
console.log("Refresh Token Found Logout!");
user.tokens.splice(i, 1);
await user.save();
break;
}
}
}
await user.save();
// user.tokens = user.tokens.filter((token) => {
// return token.token !== userToken;
// })
// await user.save();
}
logoutAll = async(user: UserInterface) => {
logoutAll = async(userID: string) => {
user.tokens = []
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Could Not Find User");
user.tokens = [];
user.tempTokens = [];
await user.save();
// user.tokens = []
// user.tempTokens = [];
// await user.save();
}
create = async(userData: any) => {
create = async(userData: any, ipAddress: string | undefined) => {
console.log("Create");
const user = new User(userData);
const user = new User({email: userData.email, password: userData.password});
await user.save();
if (!user) throw new NotFoundError("User Not Found");
await user.generateEncryptionKeys();
const token = await user.generateAuthToken();
const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress);
const emailToken = await user.generateEmailVerifyToken();
if (!user || !token) throw new InternalServerError("Could Not Create New User Error");
await sendEmailVerification(user, emailToken);
return {user, token}
if (!accessToken || !refreshToken) throw new InternalServerError("Could Not Create New User Error");
return {user, accessToken, refreshToken}
}
changePassword = async(user: UserInterface, oldPassword: string, newPassword: string) => {
changePassword = async(userID: string, oldPassword: string, newPassword: string, oldRefreshToken: string, ipAddress: string | undefined) => {
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Could Not Find User");
const date = new Date();
const isMatch = await bcrypt.compare(oldPassword, user.password);
@@ -81,15 +140,196 @@ class UserService {
user.tokens = [];
user.tempTokens = [];
user.passwordLastModified = date.getTime();
if (oldRefreshToken) {
const decoded = jwt.verify(oldRefreshToken, env.passwordRefresh!) as jwtType;
const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(oldRefreshToken, encrpytionKey, decoded.iv);
for (let i = 0; i < user.tokens.length; i++) {
const currentEncryptedToken = user.tokens[i].token;
if (currentEncryptedToken === encryptedToken) {
console.log("Refresh Token Found Logout!");
user.tokens.splice(i, 1);
await user.save();
break;
}
}
}
await user.save();
await user.changeEncryptionKey(encryptionKey!);
const newToken = await user.generateAuthToken();
const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress);
return newToken;
return {accessToken, refreshToken};
// const date = new Date();
// const isMatch = await bcrypt.compare(oldPassword, user.password);
// if (!isMatch) throw new NotAuthorizedError("Change Passwords Do Not Match Error");
// const encryptionKey = user.getEncryptionKey();
// user.password = newPassword;
// user.tokens = [];
// user.tempTokens = [];
// user.passwordLastModified = date.getTime();
// await user.save();
// await user.changeEncryptionKey(encryptionKey!);
// const newToken = await user.generateAuthToken();
// return newToken;
}
refreshStorageSize = async(userID: string) => {
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Cannot find user");
const fileList = await File.find({"metadata.owner": user._id, "metadata.personalFile": null});
let size = 0;
for (let currentFile of fileList) {
size += currentFile.length;
}
user.storageData = {storageSize: size, storageLimit: 0};
await user.save();
}
getUserDetailed = async(userID: string) => {
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Cannot find user");
if (user.s3Enabled) {
const {bucket} = await user.decryptS3Data()
user.s3Data!.bucket = bucket;
}
if (user.googleDriveEnabled) {
const {clientID} = await user.decryptDriveIDandKey()
const oauth2Client = await getGoogleAuth(user);
const drive = google.drive({version:"v3", auth: oauth2Client});
const googleData = await drive.about.get({
fields: "storageQuota"
})
user.storageDataGoogle = {storageLimit: +googleData.data.storageQuota!.limit!, storageSize: +googleData.data.storageQuota!.usage!}
user.googleDriveData!.id = clientID;
}
if (!user.storageData || (!user.storageData.storageSize && !user.storageData.storageLimit)) user.storageData = {storageLimit: 0, storageSize: 0}
if (!user.storageDataPersonal || (!user.storageDataPersonal.storageSize)) user.storageDataPersonal = {storageSize: 0}
if (!user.storageDataGoogle || (!user.storageDataGoogle.storageLimit && !user.storageDataGoogle.storageSize)) user.storageDataGoogle = {storageLimit: 0, storageSize: 0}
delete user.privateKey;
delete user.publicKey;
return user;
}
verifyEmail = async(verifyToken: any) => {
const decoded: any = jwt.verify(verifyToken!, env.passwordAccess!);
const iv = decoded.iv;
const user = await User.findOne({_id: decoded._id}) as UserInterface;
const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(verifyToken, encrpytionKey, iv);
if (encryptedToken === user.emailToken) {
user.emailVerified = true;
await user.save();
} else {
throw new NotAuthorizedError('Email Token Verification Failed')
}
}
resendVerifyEmail = async(userID: string) => {
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Cannot find user")
const verifiedEmail = user.emailVerified;
if (!verifiedEmail) {
const emailToken = await user.generateEmailVerifyToken();
await sendVerificationEmail(user, emailToken);
} else {
throw new NotAuthorizedError("Email Already Authorized")
}
}
sendPasswordReset = async(email: string) => {
const user = await User.findOne({email});
if (!user) throw new NotFoundError("User Not Found Password Reset Email")
const passwordResetToken = await user.generatePasswordResetToken();
await sendPasswordResetEmail(user, passwordResetToken!);
}
resetPassword = async(newPassword: string, verifyToken: any) => {
const decoded: any = jwt.verify(verifyToken!, env.passwordAccess!);
const iv = decoded.iv;
const user = await User.findOne({_id: decoded._id}) as UserInterface;
const encrpytionKey = user.getEncryptionKey();
const encryptedToken = user.encryptToken(verifyToken, encrpytionKey, iv);
if (encryptedToken === user.passwordResetToken) {
const encryptionKey = user.getEncryptionKey();
user.password = newPassword;
user.tokens = [];
user.tempTokens = [];
user.passwordResetToken = undefined;
await user.save();
await user.changeEncryptionKey(encryptionKey!);
} else {
throw new NotAuthorizedError("Reset Password Token Do Not Match")
}
}
addName = async(userID: string, name: string) => {
const user = await User.findById(userID);
if (!user) throw new NotFoundError("Cannot find user")
user.name = name;
await user.save();
}
}
export default UserService;
+12
View File
@@ -0,0 +1,12 @@
class ForbiddenError extends Error {
code: number;
constructor(args: any) {
super(args);
this.code = 403;
}
}
export default ForbiddenError;
+12
View File
@@ -0,0 +1,12 @@
class NotEmailVerifiedError extends Error {
code: number;
constructor(args: any) {
super(args);
this.code = 404;
}
}
export default NotEmailVerifiedError;
+12
View File
@@ -0,0 +1,12 @@
class NotValidDataError extends Error {
code: number;
constructor(args: any) {
super(args);
this.code = 403;
}
}
export default NotValidDataError;
@@ -0,0 +1,17 @@
const convertDriveFolderToMongoFolder = (driveObj: any, ownerID: string) => {
let convertedObj:any = {};
convertedObj._id = driveObj.id;
convertedObj.name = driveObj.name;
convertedObj.createdAt = driveObj.createdTime;
convertedObj.owner = ownerID;
convertedObj.parent = driveObj.parents[driveObj.parents.length - 1];
convertedObj.parentList = driveObj.parents;
convertedObj.updatedAt = driveObj.createdTime;
convertedObj.drive = true;
convertedObj.googleDoc = driveObj.mimeType === "application/vnd.google-apps.document";
return convertedObj;
}
export default convertDriveFolderToMongoFolder;
@@ -0,0 +1,14 @@
import convertDriveFolderToMongoFolder from "./convertDriveFolderToMongoFolder";
const convertDriveFoldersToMongoFolders = (driveObjs: any, ownerID: string) => {
let convertedFolders = [];
for (let currentFolder of driveObjs) {
convertedFolders.push(convertDriveFolderToMongoFolder(currentFolder, ownerID))
}
return convertedFolders;
}
export default convertDriveFoldersToMongoFolders;
@@ -0,0 +1,14 @@
import convertDriveToMongo from "./convertDriveToMongo";
const convertDriveListToMongoList = (driveObjs: any, ownerID:string, pageToken?: string) => {
let convertedObjs = [];
for (let currentObj of driveObjs) {
convertedObjs.push(convertDriveToMongo(currentObj, ownerID, pageToken));
}
return convertedObjs;
}
export default convertDriveListToMongoList;
+29
View File
@@ -0,0 +1,29 @@
import videoChecker from "./videoChecker";
const convertDriveToMongo = (driveObj: any, ownerID: string, pageToken?: string) => {
let convertedObj: any = {};
convertedObj._id = driveObj.id;
convertedObj.filename = driveObj.name;
convertedObj.length = driveObj.size;
convertedObj.uploadDate = driveObj.modifiedTime;
convertedObj.pageToken = pageToken
convertedObj.metadata = {
IV: "",
hasThumbnail: driveObj.hasThumbnail,
isVideo: videoChecker(driveObj.name),
owner: ownerID,
parent: driveObj.parents[driveObj.parents.length - 1] === "root" ? "/" : driveObj.parents[driveObj.parents.length - 1],
parentList: driveObj.parents,
size: driveObj.size,
drive: true,
googleDoc: driveObj.mimeType === "application/vnd.google-apps.document",
thumbnailID: driveObj.thumbnailLink,
link: driveObj.shared ? driveObj.webViewLink : undefined,
linkType: driveObj.shared ? "public" : undefined
}
return convertedObj;
}
export default convertDriveToMongo;
+22 -3
View File
@@ -1,5 +1,8 @@
import s3 from "../db/s3"
import { ObjectID } from "mongodb"
export interface QueryInterface {
"metadata.owner": string,
"metadata.owner": ObjectID,
"metadata.parent"?: string,
filename?: string | RegExp | {
$lt?: string,
@@ -9,11 +12,12 @@ export interface QueryInterface {
$lt?: Date,
$gt?: Date,
},
"metadata.personalFile"?: boolean | null
}
const createQuery = (owner: string, parent: string, sortBy: string, startAt: number, startAtDate: number, searchQuery: string | RegExp, startAtName: string) => {
const createQuery = (owner: string, parent: string, sortBy: string, startAt: number, startAtDate: number, searchQuery: string | RegExp, s3Enabled: boolean,startAtName: string, storageType: string, folderSearch: boolean) => {
let query: QueryInterface = {"metadata.owner": owner}
let query: QueryInterface = {"metadata.owner": new ObjectID(owner)}
if (searchQuery !== "") {
@@ -21,6 +25,9 @@ const createQuery = (owner: string, parent: string, sortBy: string, startAt: num
query = {...query, filename: searchQuery}
if (parent !== "/" || folderSearch) query = {...query, "metadata.parent": parent}
//if (parent === "home") query = {...query, "metadata.parent": "/"};
} else {
query = {...query, "metadata.parent": parent}
@@ -46,6 +53,18 @@ const createQuery = (owner: string, parent: string, sortBy: string, startAt: num
}
}
// if (s3Enabled) {
// query = {...query, "metadata.personalFile": true}
// } else if (!s3Enabled) {
// query = {...query, "metadata.personalFile": null}
// }
// if (storageType === "s3") {
// query = {...query, "metadata.personalFile": true}
// }
console.log("storage type", storageType)
console.log("query", query);
return query;
+28
View File
@@ -0,0 +1,28 @@
const createQueryGoogle = (query: any, parent: any) => {
let queryBuilder = `mimeType != "application/vnd.google-apps.folder"`
let orderBy = ""
if (query.sortby === "date_desc" || query.sortby === "DEFAULT") {
orderBy = "modifiedTime desc"
} else if (query.sortby === "date_asc") {
orderBy = "modifiedTime asc"
} else if (query.sortby === "alp_desc") {
orderBy = "name desc"
} else {
orderBy = "name asc"
}
if (query.search && query.search.length !== 0) {
queryBuilder += ` and name contains "${query.search}"`
} else {
queryBuilder += ` and "${parent}" in parents`
}
queryBuilder += ` and trashed=false`;
return {queryBuilder, orderBy}
}
export default createQueryGoogle;
+28
View File
@@ -0,0 +1,28 @@
const createQueryGoogleFolder = (query: any, parent: string) => {
let orderBy = ""
if (query.sortby === "date_desc") {
orderBy = "modifiedTime desc"
} else if (query.sortby === "date_asc") {
orderBy = "modifiedTime asc"
} else if (query.sortby === "alp_desc") {
orderBy = "name desc"
} else {
orderBy = "name asc"
}
let queryBuilder = `mimeType = "application/vnd.google-apps.folder"`
if (query.search && query.search.length !== 0) {
queryBuilder += ` and name contains "${query.search}"`
} else {
queryBuilder += ` and "${parent}" in parents`;
}
queryBuilder += ` and trashed=false`;
return {orderBy, queryBuilder}
}
export default createQueryGoogleFolder;
+27
View File
@@ -0,0 +1,27 @@
import env from "../enviroment/env";
import {UserInterface} from "../models/user"
import sgMail from "@sendgrid/mail";
const sendPasswordResetEmail = async (user: UserInterface, passwordResetToken: string) => {
const apiKey: any = env.sendgridKey;
const sendgridEmail:any = env.sendgridEmail;
const url = env.remoteURL + `/reset-password/${passwordResetToken}`
// console.log("send grid api key", apiKey)
// console.log("send grid email", sendgridEmail);
// console.log("send grid reset url", url)
sgMail.setApiKey(apiKey);
const msg = {
to: user.email,
from: sendgridEmail,
subject: "myDrive Password Reset",
text: `Please navigate to the following link to reset your password: ${url}`
}
await sgMail.send(msg);
//console.log("Send grid email sent reset");
}
export default sendPasswordResetEmail;
+26
View File
@@ -0,0 +1,26 @@
import env from "../enviroment/env";
import sgMail from "@sendgrid/mail";
const currentURL = env.remoteURL;
const sendShareEmail = async (file: any, respient: string) => {
const apiKey: any = env.sendgridKey;
const sendgridEmail:any = env.sendgridEmail;
sgMail.setApiKey(apiKey);
const fileLink = `${currentURL}/download-page/${file._id}/${file.metadata.link}`
const msg = {
to: respient,
from: sendgridEmail,
subject: "A File Was Shared With You Through myDrive",
text: `Please navigate to the following link to view the file ${fileLink}`
}
await sgMail.send(msg);
console.log("Share email sent");
}
export default sendShareEmail
+27
View File
@@ -0,0 +1,27 @@
import env from "../enviroment/env";
import {UserInterface} from "../models/user"
import sgMail from "@sendgrid/mail";
const sendVerificationEmail = async (user: UserInterface, emailToken: string) => {
const apiKey: any = env.sendgridKey;
const sendgridEmail:any = env.sendgridEmail;
const url = env.remoteURL + `/verify-email/${emailToken}`
// console.log("send grid api key", apiKey)
// console.log("send grid email", sendgridEmail);
// console.log("send grid verify url", url)
sgMail.setApiKey(apiKey);
const msg = {
to: user.email,
from: sendgridEmail,
subject: "myDrive Email Verification",
text: `Please navigate to the following link to verify your email address: ${url}`
}
await sgMail.send(msg);
//console.log("Send grid email sent");
}
export default sendVerificationEmail;
@@ -0,0 +1,58 @@
import { FolderInterface } from "../models/folder";
const sortGoogleMongoFolderList = (combinedList: FolderInterface[], query: any) => {
if (query.sortby === "date_desc" || query.sortby === "DEFAULT") {
combinedList = combinedList.sort((a, b) => {
const convertedDateA = new Date(a.createdAt).getTime();
const convertedDateB = new Date(b.createdAt).getTime();
return convertedDateB - convertedDateA;
})
} else if (query.sortby === "date_asc") {
combinedList = combinedList.sort((a, b) => {
const convertedDateA = new Date(a.createdAt).getTime();
const convertedDateB = new Date(b.createdAt).getTime();
return convertedDateA - convertedDateB;
})
} else if (query.sortby === "alp_desc") {
combinedList = combinedList.sort((a, b) => {
const name1 = a.name.toLowerCase();
const name2 = b.name.toLowerCase();
if (name1 > name2) {
return -1;
}
if (name2 > name1) {
return 1
}
return 0;
})
} else if (query.sortby === "alp_asc") {
combinedList = combinedList.sort((a, b) => {
const name1 = a.name.toLowerCase();
const name2 = b.name.toLowerCase();
if (name1 > name2) {
return 1;
}
if (name2 > name1) {
return -1
}
return 0;
})
}
return combinedList;
}
export default sortGoogleMongoFolderList;
+62
View File
@@ -0,0 +1,62 @@
import { FileInterface } from "../models/file";
const sortGoogleMongoList = (fileList: FileInterface[], query: any) => {
let combinedList = fileList;
if (query.sortby === "date_desc" || query.sortby === "DEFAULT") {
combinedList = combinedList.sort((a, b) => {
const convertedDateA = new Date(a.uploadDate).getTime();
const convertedDateB = new Date(b.uploadDate).getTime();
//onsole.log("data", b.uploadDate, convertedDate)
return convertedDateB - convertedDateA;
})
} else if (query.sortby === "date_asc") {
combinedList = combinedList.sort((a, b) => {
const convertedDateA = new Date(a.uploadDate).getTime();
const convertedDateB = new Date(b.uploadDate).getTime();
//onsole.log("data", b.uploadDate, convertedDate)
return convertedDateA - convertedDateB;
})
} else if (query.sortby === "alp_desc") {
combinedList = combinedList.sort((a, b) => {
const name1 = a.filename.toLowerCase();
const name2 = b.filename.toLowerCase();
if (name1 > name2) {
return -1;
}
if (name2 > name1) {
return 1
}
return 0;
})
} else if (query.sortby === "alp_asc") {
combinedList = combinedList.sort((a, b) => {
const name1 = a.filename.toLowerCase();
const name2 = b.filename.toLowerCase();
if (name1 > name2) {
return 1;
}
if (name2 > name1) {
return -1
}
return 0;
})
}
return combinedList;
}
export default sortGoogleMongoList;
+102
View File
@@ -0,0 +1,102 @@
import express, {Request, Response} from "express";
import http from "http";
import path from "path";
import bodyParser from "body-parser";
import fs from "fs";
const app = express();
const getWebUIKey = () => {
console.log("Starting Server...\n")
const publicPath = path.join(__dirname, "..", "..", "webUISetup");
return new Promise<string>((resolve, reject) => {
app.use(express.static(publicPath));
app.use(express.json());
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit: "50mb", extended: true, parameterLimit:50000}))
app.post("/submit", async(req: Request, res: Response) => {
console.log("Response")
await createConfigFiles(req.body.clientObj, req.body.serverObj);
res.send();
})
app.get("*", (req: Request, res: Response) => {
res.sendFile(path.join(publicPath, "index.html"));
})
const port = process.env.HTTP_PORT || process.env.PORT || "3000";
const url = process.env.DOCKER ? undefined : "localhost";
const server = http.createServer(app) as any;
server.listen(port, () => {
console.log(`\nPlease navigate to http://localhost:${port} to enter setup details\n`)
});
})
}
const awaitcreateDir = (path: any) => {
return new Promise((resolve, reject) => {
fs.mkdir(path, () => {
resolve();
})
})
}
const awaitWriteFile = (path:string, data:string) => {
return new Promise((resolve, reject) => {
fs.writeFile(path, data, async(err:any) => {
if (err) {
console.log("file write error", err);
reject();
}
resolve();
})
})
}
const createConfigFiles = async(clientObj: any, serverObj: any) => {
await awaitcreateDir("./config")
let totalClientString = "";
let totalServerString = "";
for (let currentKey in clientObj) {
totalClientString += `${currentKey}=${clientObj[currentKey]}\n`
}
for (let currentKey in serverObj) {
totalServerString += `${currentKey}=${serverObj[currentKey]}\n`
}
if (serverObj.DOCKER) {
const combinedStrings = totalClientString + totalServerString;
await awaitWriteFile("./docker-variables.env", combinedStrings);
} else {
await awaitWriteFile("./.env.production", totalClientString);
await awaitWriteFile("./config/prod.env", totalServerString);
}
console.log("File(s) Created");
}
getWebUIKey();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Some files were not shown because too many files have changed in this diff Show More