fixed hotloading, fixed _id types, fixed some links, downloading, and started imrpoving db code

This commit is contained in:
subnub
2024-06-09 00:28:42 -04:00
parent 3462701394
commit c088076140
29 changed files with 3893 additions and 3128 deletions
+19 -20
View File
@@ -1,6 +1,6 @@
import mongoose from "../../mongoose";
import { ObjectId } from "mongodb";
import { FileInterface } from "../../../models/file";
import File, { FileInterface } from "../../../models/file";
import { UserInterface } from "../../../models/user";
import { QueryInterface } from "../../../utils/createQuery";
const conn = mongoose.connection;
@@ -19,6 +19,7 @@ class DbUtil {
removeOneTimePublicLink = async (
fileID: string | mongoose.Types.ObjectId
) => {
mongoose;
const file = (await conn.db.collection("fs.files").findOneAndUpdate(
{ _id: new ObjectId(fileID) },
{
@@ -33,7 +34,7 @@ class DbUtil {
const file = (await conn.db
.collection("fs.files")
.findOneAndUpdate(
{ _id: new ObjectId(fileID), "metadata.owner": new ObjectId(userID) },
{ _id: new ObjectId(fileID), "metadata.owner": userID },
{ $unset: { "metadata.linkType": "", "metadata.link": "" } }
)) as FileInterface;
@@ -44,7 +45,7 @@ class DbUtil {
const file = (await conn.db
.collection("fs.files")
.findOneAndUpdate(
{ _id: new ObjectId(fileID), "metadata.owner": new ObjectId(userID) },
{ _id: new ObjectId(fileID), "metadata.owner": userID },
{ $set: { "metadata.linkType": "public", "metadata.link": token } }
)) as FileInterface;
@@ -64,7 +65,7 @@ class DbUtil {
const file = (await conn.db
.collection("fs.files")
.findOneAndUpdate(
{ _id: new ObjectId(fileID), "metadata.owner": new ObjectId(userID) },
{ _id: new ObjectId(fileID), "metadata.owner": userID },
{ $set: { "metadata.linkType": "one", "metadata.link": token } }
)) as FileInterface;
@@ -72,16 +73,17 @@ class DbUtil {
};
getFileInfo = async (fileID: string, userID: string) => {
const file = (await conn.db.collection("fs.files").findOne({
"metadata.owner": new ObjectId(userID),
console.log("info diff", userID.toString());
const file = await File.findOne({
"metadata.owner": userID,
_id: new ObjectId(fileID),
})) as FileInterface;
});
return file;
};
getQuickList = async (userID: string, s3Enabled: boolean) => {
let query: any = { "metadata.owner": new ObjectId(userID) };
let query: any = { "metadata.owner": userID };
if (!s3Enabled) {
query = { ...query, "metadata.personalFile": null };
@@ -118,7 +120,7 @@ class DbUtil {
getFileSearchList = async (userID: string, searchQuery: RegExp) => {
let query: any = {
"metadata.owner": new ObjectId(userID),
"metadata.owner": userID,
filename: searchQuery,
};
@@ -132,14 +134,11 @@ class DbUtil {
};
renameFile = async (fileID: string, userID: string, title: string) => {
const file = (await conn.db
.collection("fs.files")
.findOneAndUpdate(
{ _id: new ObjectId(fileID), "metadata.owner": new ObjectId(userID) },
{ $set: { filename: title } }
)) as FileInterface;
return file;
const updateFileResponse = await File.findOneAndUpdate(
{ _id: new ObjectId(fileID), "metadata.owner": userID },
{ $set: { filename: title } }
);
return updateFileResponse;
};
moveFile = async (
@@ -149,7 +148,7 @@ class DbUtil {
parentList: string
) => {
const file = await conn.db.collection("fs.files").findOneAndUpdate(
{ _id: new ObjectId(fileID), "metadata.owner": new ObjectId(userID) },
{ _id: new ObjectId(fileID), "metadata.owner": userID },
{
$set: {
"metadata.parent": parent,
@@ -168,7 +167,7 @@ class DbUtil {
const fileList = (await conn.db
.collection("fs.files")
.find({
"metadata.owner": new ObjectId(userID),
"metadata.owner": userID,
"metadata.parentList": { $regex: `.*${parentListString}.*` },
})
.toArray()) as FileInterface[];
@@ -179,7 +178,7 @@ class DbUtil {
getFileListByOwner = async (userID: string) => {
const fileList = (await conn.db
.collection("fs.files")
.find({ "metadata.owner": new ObjectId(userID) })
.find({ "metadata.owner": userID })
.toArray()) as FileInterface[];
return fileList;
@@ -3,6 +3,7 @@ import User, { UserInterface } from "../models/user";
import env from "../enviroment/env";
import { Request, Response, NextFunction } from "express";
import userUpdateCheck from "../utils/userUpdateCheck";
import mongoose from "mongoose";
interface RequestType extends Request {
user?: userAccessType;
@@ -16,7 +17,7 @@ type jwtType = {
};
type userAccessType = {
_id: string;
_id: mongoose.Types.ObjectId;
emailVerified: boolean;
email: string;
botChecked: boolean;
+2 -1
View File
@@ -3,6 +3,7 @@ import User, { UserInterface } from "../models/user";
import env from "../enviroment/env";
import { Request, Response, NextFunction } from "express";
import { ObjectId } from "mongodb";
import mongoose from "mongoose";
interface RequestType extends Request {
user?: UserInterface;
@@ -17,7 +18,7 @@ type jwtType = {
};
const removeOldTokens = async (
userID: string,
userID: mongoose.Types.ObjectId,
uuid: string | undefined,
oldTime: number
) => {
+2 -1
View File
@@ -3,6 +3,7 @@ import User, { UserInterface } from "../models/user";
import env from "../enviroment/env";
import { Request, Response, NextFunction } from "express";
import { ObjectId } from "mongodb";
import mongoose from "mongoose";
interface RequestType extends Request {
user?: UserInterface;
@@ -18,7 +19,7 @@ type jwtType = {
};
const removeOldTokens = async (
userID: string,
userID: mongoose.Types.ObjectId,
uuid: string | undefined,
oldTime: number
) => {
+2 -2
View File
@@ -59,14 +59,14 @@ const fileSchema = new mongoose.Schema({
});
export interface FileInterface
extends mongoose.Document<string | mongoose.Types.ObjectId> {
extends mongoose.Document<mongoose.Types.ObjectId> {
length: number;
chunkSize: number;
uploadDate: string;
filename: string;
lastErrorObject: { updatedExisting: any };
metadata: {
owner: string | ObjectId;
owner: string;
parent: string;
parentList: string;
hasThumbnail: boolean;
+545 -447
View File
File diff suppressed because it is too large Load Diff
@@ -35,6 +35,7 @@ class FileSystemService implements ChunkInterface {
constructor() {}
uploadFile = async (user: UserInterface, busboy: any, req: Request) => {
console.log("upeload file");
const password = user.getEncryptionKey();
if (!password) throw new ForbiddenError("Invalid Encryption Key");
@@ -45,7 +46,11 @@ class FileSystemService implements ChunkInterface {
const cipher = crypto.createCipheriv("aes256", CIPHER_KEY, initVect);
const { file, filename, formData } = await getBusboyData(busboy);
const { file, filename: fileInfo, formData } = await getBusboyData(busboy);
const filename = fileInfo.filename;
console.log("1filename", filename);
const parent = formData.get("parent") || "/";
const parentList = formData.get("parentList") || "/";
@@ -84,6 +89,8 @@ class FileSystemService implements ChunkInterface {
const date = new Date();
const encryptedFileSize = await getFileSize(metadata.filePath);
console.log("filtnamed", filename);
const currentFile = new File({
filename,
uploadDate: date.toISOString(),
@@ -95,6 +102,8 @@ class FileSystemService implements ChunkInterface {
await addToStoageSize(user, size, personalFile);
console.log("current file", currentFile);
const imageCheck = imageChecker(currentFile.filename);
if (currentFile.length < 15728640 && imageCheck) {
@@ -150,11 +159,11 @@ class FileSystemService implements ChunkInterface {
};
downloadFile = async (user: UserInterface, fileID: string, res: Response) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(
const currentFile = await dbUtilsFile.getFileInfo(
fileID,
user._id
user._id.toString()
);
console.log(fileID, user._id);
if (!currentFile) throw new NotFoundError("Download File Not Found");
const password = user.getEncryptionKey();
@@ -184,9 +193,9 @@ class FileSystemService implements ChunkInterface {
};
getFileReadStream = async (user: UserInterface, fileID: string) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(
const currentFile = await dbUtilsFile.getFileInfo(
fileID,
user._id
user._id.toString()
);
if (!currentFile) throw new NotFoundError("Download File Not Found");
@@ -246,7 +255,7 @@ class FileSystemService implements ChunkInterface {
) => {
const userID = user._id;
const file: FileInterface = await dbUtilsFile.getFileInfo(fileID, userID);
const file = await dbUtilsFile.getFileInfo(fileID, userID.toString());
if (!file) throw new NotFoundError("File Thumbnail Not Found");
@@ -291,9 +300,9 @@ class FileSystemService implements ChunkInterface {
// Is safari going to be the next internet explorer?
const userID = user._id;
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(
const currentFile = await dbUtilsFile.getFileInfo(
fileID,
userID
userID.toString()
);
if (!currentFile) throw new NotFoundError("Video File Not Found");
@@ -435,7 +444,7 @@ class FileSystemService implements ChunkInterface {
};
deleteFile = async (userID: string, fileID: string) => {
const file: FileInterface = await dbUtilsFile.getFileInfo(fileID, userID);
const file = await dbUtilsFile.getFileInfo(fileID, userID);
if (!file) throw new NotFoundError("Delete File Not Found Error");
+10 -9
View File
@@ -44,7 +44,8 @@ class S3Service implements ChunkInterface {
const cipher = crypto.createCipheriv("aes256", CIPHER_KEY, initVect);
const { file, filename, formData } = await getBusboyData(busboy);
const { file, filename: fileInfo, formData } = await getBusboyData(busboy);
const filename = fileInfo.filename;
const parent = formData.get("parent") || "/";
const parentList = formData.get("parentList") || "/";
@@ -166,9 +167,9 @@ class S3Service implements ChunkInterface {
};
downloadFile = async (user: UserInterface, fileID: string, res: Response) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(
const currentFile = await dbUtilsFile.getFileInfo(
fileID,
user._id
user._id.toString()
);
if (!currentFile) throw new NotFoundError("Download File Not Found");
@@ -202,9 +203,9 @@ class S3Service implements ChunkInterface {
};
getFileReadStream = async (user: UserInterface, fileID: string) => {
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(
const currentFile = await dbUtilsFile.getFileInfo(
fileID,
user._id
user._id.toString()
);
if (!currentFile) throw new NotFoundError("Download File Not Found");
@@ -246,9 +247,9 @@ class S3Service implements ChunkInterface {
// Is safari going to be the next internet explorer?
const userID = user._id;
const currentFile: FileInterface = await dbUtilsFile.getFileInfo(
const currentFile = await dbUtilsFile.getFileInfo(
fileID,
userID
userID.toString()
);
if (!currentFile) throw new NotFoundError("Video File Not Found");
@@ -416,7 +417,7 @@ class S3Service implements ChunkInterface {
) => {
const userID = user._id;
const file: FileInterface = await dbUtilsFile.getFileInfo(fileID, userID);
const file = await dbUtilsFile.getFileInfo(fileID, userID.toString());
if (!file) throw new NotFoundError("File Thumbnail Not Found");
@@ -489,7 +490,7 @@ class S3Service implements ChunkInterface {
};
deleteFile = async (userID: string, fileID: string) => {
const file: FileInterface = await dbUtilsFile.getFileInfo(fileID, userID);
const file = await dbUtilsFile.getFileInfo(fileID, userID);
if (!file) throw new NotFoundError("Delete File Not Found Error");
@@ -1,33 +1,40 @@
import { Stream } from "stream";
const getBusboyData = (busboy: any) => {
type dataType = {
file: Stream;
filename: {
filename: string;
};
formData: Map<any, any>;
};
type dataType = {
return new Promise<dataType>((resolve, reject) => {
const formData = new Map();
busboy.on("field", (field: any, val: any) => {
console.log("field", field, val);
formData.set(field, val);
});
busboy.on(
"file",
async (
_: string,
file: Stream,
filename: string,
formData: Map<any, any>
}
return new Promise<dataType>((resolve, reject) => {
const formData = new Map();
busboy.on("field", (field: any, val: any) => {
formData.set(field, val)
filename: {
filename: string;
}
) => {
resolve({
file,
filename,
formData,
});
}
);
});
};
busboy.on("file", async(_: string, file: Stream, filename: string) => {
resolve({
file,
filename,
formData
})
})
})
}
export default getBusboyData;
export default getBusboyData;
+6 -4
View File
@@ -106,7 +106,10 @@ class MongoFileService {
const userID = user._id;
const s3Enabled = user.s3Enabled ? true : false;
const quickList = await dbUtilsFile.getQuickList(userID, s3Enabled);
const quickList = await dbUtilsFile.getQuickList(
userID.toString(),
s3Enabled
);
if (!quickList) throw new NotFoundError("Quick List Not Found Error");
@@ -131,7 +134,7 @@ class MongoFileService {
const s3Enabled = user.s3Enabled ? true : false;
const queryObj = createQuery(
userID,
userID.toString(),
parent,
query.sortby,
startAt,
@@ -219,8 +222,7 @@ class MongoFileService {
renameFile = async (userID: string, fileID: string, title: string) => {
const file = await dbUtilsFile.renameFile(fileID, userID, title);
if (!file.lastErrorObject.updatedExisting)
throw new NotFoundError("Rename File Not Found Error");
if (!file) throw new NotFoundError("Rename File Not Found Error");
return file;
};
+2 -2
View File
@@ -109,7 +109,7 @@ class FolderService {
if (searchQuery.length === 0) {
const folderList = await utilsFolder.getFolderListByParent(
userID,
userID.toString(),
parent,
sortBy,
s3Enabled,
@@ -124,7 +124,7 @@ class FolderService {
} else {
searchQuery = new RegExp(searchQuery, "i");
const folderList = await utilsFolder.getFolderListBySearch(
userID,
userID.toString(),
searchQuery,
sortBy,
type,
+2 -2
View File
@@ -2,7 +2,7 @@ import s3 from "../db/s3";
import { ObjectId } from "mongodb";
export interface QueryInterface {
"metadata.owner": ObjectId;
"metadata.owner": ObjectId | string;
"metadata.parent"?: string;
filename?:
| string
@@ -30,7 +30,7 @@ const createQuery = (
storageType: string,
folderSearch: boolean
) => {
let query: QueryInterface = { "metadata.owner": new ObjectId(owner) };
let query: QueryInterface = { "metadata.owner": owner };
if (searchQuery !== "") {
searchQuery = new RegExp(searchQuery, "i");
+30 -21
View File
@@ -1,6 +1,6 @@
import User, {UserInterface} from "../models/user";
import {Request, Response, NextFunction} from "express";
import User, { UserInterface } from "../models/user";
import mongoose from "mongoose";
import { Request, Response, NextFunction } from "express";
import NotFoundError from "./NotFoundError";
import { createLoginCookie } from "../cookies/createCookies";
@@ -11,27 +11,36 @@ import { createLoginCookie } from "../cookies/createCookies";
// }
type userAccessType = {
_id: string,
emailVerified: boolean,
email: string,
botChecked: boolean,
}
_id: mongoose.Types.ObjectId;
emailVerified: boolean;
email: string;
botChecked: boolean;
};
const userUpdateCheck = async(res: Response, id: string, uuid: string | undefined) => {
const userUpdateCheck = async (
res: Response,
id: mongoose.Types.ObjectId,
uuid: string | undefined
) => {
const updatedUser = await User.findById(id);
const updatedUser = await User.findById(id);
if (!updatedUser) throw new NotFoundError("Cannot find updated user auth");
if (!updatedUser) throw new NotFoundError("Cannot find updated user auth");
if (updatedUser.emailVerified) {
const { accessToken, refreshToken } = await updatedUser.generateAuthToken(
uuid
);
createLoginCookie(res, accessToken, refreshToken);
}
if (updatedUser.emailVerified) {
let strippedUser: userAccessType = {
_id: updatedUser._id,
emailVerified: updatedUser.emailVerified!,
email: updatedUser.email,
botChecked: false,
};
const {accessToken, refreshToken} = await updatedUser.generateAuthToken(uuid);
createLoginCookie(res, accessToken, refreshToken);
}
return strippedUser;
};
let strippedUser: userAccessType = {_id: updatedUser._id, emailVerified: updatedUser.emailVerified!, email: updatedUser.email, botChecked: false}
return strippedUser;
}
export default userUpdateCheck;
export default userUpdateCheck;
+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>myDrive</title>
<link rel="icon" href="/images/icon.png" />
<link rel="shortcut icon" type="image/png" href="/images/icon.png" />
<link rel="shortcut icon" sizes="192x192" href="/images/icon.png" />
<link rel="apple-touch-icon" href="/images/icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- <script src="https://kit.fontawesome.com/f982e94d70.js" crossorigin="anonymous"></script> -->
<!-- <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700&display=swap" rel="stylesheet"> -->
<script defer src="/fontawesome/js/all.js"></script>
<link rel="stylesheet" href="/dist/fonts.css" />
<link rel="stylesheet" type="text/css" href="/dist/styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
<!-- <script src="/socket.io/socket.io.js"></script> -->
<script type="module" src="/src/app.js"></script>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
{
"watch": ["dist/"],
"ignore": ["src", "node_modules"],
"ext": "js,json",
"exec": "node dist/server/serverStart.js"
}
+9 -3
View File
@@ -30,7 +30,12 @@
"remove-old-subscription-data": "node serverUtils/removeOldSubscriptionData.js",
"remove-old-personal-data": "node serverUtils/removeOldPersonalData.js",
"remove-tokens": "node serverUtils/removeTokens.js --env production",
"remove-tokens:dev": "NODE_ENV=development node serverUtils/removeTokens.js"
"remove-tokens:dev": "NODE_ENV=development node serverUtils/removeTokens.js",
"vite-test": "vite",
"dev-test": "concurrently \"vite\" \"nodemon server.js\"",
"watch:backend": "tsc -w",
"dev-hot": "concurrently \"vite\" \"tsc -w\" \"npm run dev:backend\"",
"dev:backend": "nodemon dist/server/serverStart.js"
},
"dependencies": {
"@babel/core": "^7.8.4",
@@ -66,7 +71,7 @@
"cli-progress": "^3.6.0",
"compression": "^1.7.4",
"concat-stream": "^2.0.0",
"connect-busboy": "0.0.2",
"connect-busboy": "^1.0.0",
"cookie-parser": "^1.4.6",
"copy-text-to-clipboard": "^2.1.1",
"core-js": "^3.6.4",
@@ -100,7 +105,7 @@
"sharp": "^0.33.4",
"stream-skip": "^1.0.3",
"supertest-session": "^4.1.0",
"sweetalert2": "^9.17.4",
"sweetalert2": "^11.11.1",
"temp": "^0.9.1",
"typescript": "^5.4.5",
"uuid": "^3.4.0",
@@ -129,6 +134,7 @@
"live-server": "^1.2.1",
"nodemon": "^3.1.3",
"react-test-renderer": "^16.12.0",
"sass": "^1.77.4",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3",
"superagent-binary-parser": "^1.0.1",
+143 -154
View File
@@ -1,189 +1,178 @@
import {setLoginFailed} from "./main";
import {history} from "../routers/AppRouter"
import {resetUpload} from "./uploads"
import { setLoginFailed } from "./main";
import { history } from "../routers/AppRouter";
import { resetUpload } from "./uploads";
import axios from "../axiosInterceptor";
import env from "../enviroment/envFrontEnd";
import {setCreateNewAccount} from "./main";
import { setCreateNewAccount } from "./main";
export const login = (id) => ({
type: "LOGIN",
id
})
type: "LOGIN",
id,
});
export const logout = () => ({
type: "LOGOUT"
})
type: "LOGOUT",
});
export const startLogin = (email, password, currentRoute) => {
return (dispatch) => {
const dt = { email, password };
return (dispatch) => {
axios
.post("/user-service/login", dt)
.then((response) => {
// console.log("USER SERVICE LOGIN RESPONSE")
const dt = {email, password};
const id = response.data.user._id;
const emailVerified = response.data.user.emailVerified;
axios.post("/user-service/login", dt).then((response) => {
env.googleDriveEnabled = response.data.user.googleDriveEnabled;
env.s3Enabled = response.data.user.s3Enabled;
env.activeSubscription = response.data.user.activeSubscription;
env.emailAddress = response.data.user.email;
env.name = response.data.user.name || "";
// console.log("USER SERVICE LOGIN RESPONSE")
//window.localStorage.setItem("token", token);
const id = response.data.user._id;
const emailVerified = response.data.user.emailVerified;
env.googleDriveEnabled = response.data.user.googleDriveEnabled;
env.s3Enabled = response.data.user.s3Enabled;
env.activeSubscription = response.data.user.activeSubscription;
env.emailAddress = response.data.user.email;
env.name = response.data.user.name || ""
//window.localStorage.setItem("token", token);
if (emailVerified) {
dispatch(setLoginFailed(false))
dispatch(login(id));
history.push(currentRoute);
} else {
console.log("Email Not Verified")
dispatch(setLoginFailed("Unverified Email", 404))
}
}).catch((err) => {
console.log("USER SERVICE LOGIN ERROR")
const code = err.response.status;
dispatch(setLoginFailed("Incorrect Email or Password", code))
console.log(err);
})
}
}
if (emailVerified) {
dispatch(setLoginFailed(false));
dispatch(login(id));
history.push(currentRoute);
} else {
console.log("Email Not Verified");
dispatch(setLoginFailed("Unverified Email", 404));
}
})
.catch((err) => {
console.log("USER SERVICE LOGIN ERROR", err);
const code = err.response?.status;
dispatch(setLoginFailed("Incorrect Email or Password", code));
console.log(err);
});
};
};
export const startCreateAccount = (email, password) => {
return (dispatch) => {
const dt = { email, password };
axios
.post("/user-service/create", dt)
.then((response) => {
const token = response.data.token;
const id = response.data.user._id;
const emailVerified = response.data.user.emailVerified;
return (dispatch) => {
// window.localStorage.setItem("token", token);
const dt = {email, password};
axios.post("/user-service/create", dt).then((response) => {
const token = response.data.token;
const id = response.data.user._id;
const emailVerified = response.data.user.emailVerified;
if (emailVerified) {
dispatch(setLoginFailed(false));
dispatch(login(id));
history.push("/home");
} else {
console.log("Email Not Verified");
dispatch(setLoginFailed("Unverified Email", 404));
dispatch(setCreateNewAccount(true));
}
})
.catch((err) => {
console.log(err);
// window.localStorage.setItem("token", token);
if (emailVerified) {
dispatch(setLoginFailed(false))
dispatch(login(id));
history.push("/home");
} else {
console.log("Email Not Verified")
dispatch(setLoginFailed("Unverified Email", 404))
dispatch(setCreateNewAccount(true))
}
if (err.response) {
const errStatus = err.response.status;
}).catch((err) => {
console.log(err);
if (err.response) {
const errStatus = err.response.status;
if (errStatus === 401) {
dispatch(setLoginFailed("Create Blocked By Admin"))
} else {
dispatch(setLoginFailed("Duplicate Email, or Invalid Password"))
}
} else {
dispatch(setLoginFailed("Duplicate Email, or Invalid Password"))
}
})
}
}
if (errStatus === 401) {
dispatch(setLoginFailed("Create Blocked By Admin"));
} else {
dispatch(setLoginFailed("Duplicate Email, or Invalid Password"));
}
} else {
dispatch(setLoginFailed("Duplicate Email, or Invalid Password"));
}
});
};
};
const reload = () => {
setTimeout(() => {
window.location.reload(true);
}, 3000);
}
setTimeout(() => {
window.location.reload(true);
}, 3000);
};
export const startLoginCheck = (currentRoute) => {
return (dispatch) => {
axios
.get("/user-service/user")
.then((response) => {
const emailVerified = response.data.emailVerified;
return (dispatch) => {
const id = response.data._id;
axios.get("/user-service/user").then((response) => {
const emailVerified = response.data.emailVerified;
env.googleDriveEnabled = response.data.googleDriveEnabled;
env.s3Enabled = response.data.s3Enabled;
env.activeSubscription = response.data.activeSubscription;
env.emailAddress = response.data.email;
env.name = response.data.name || "";
const id = response.data._id;
if (emailVerified) {
dispatch(setLoginFailed(false));
dispatch(login(id));
history.push(currentRoute);
} else {
console.log("Email Not Verified");
dispatch(setLoginFailed("Unverified Email", 404));
}
env.googleDriveEnabled = response.data.googleDriveEnabled;
env.s3Enabled = response.data.s3Enabled;
env.activeSubscription = response.data.activeSubscription;
env.emailAddress = response.data.email;
env.name = response.data.name || ""
if (emailVerified) {
dispatch(setLoginFailed(false))
dispatch(login(id))
history.push(currentRoute);
} else {
console.log("Email Not Verified")
dispatch(setLoginFailed("Unverified Email", 404))
}
//reload();
}).catch((err) => {
console.log("login check error", err, err.response.data, err.data, err.response);
// window.localStorage.removeItem("token")
dispatch(setLoginFailed("Login Expired"))
// history.push("/login")
})
}
}
//reload();
})
.catch((err) => {
console.log(
"login check error",
err,
err.response?.data,
err.data,
err.response
);
// window.localStorage.removeItem("token")
dispatch(setLoginFailed("Login Expired"));
// history.push("/login")
});
};
};
export const startLogoutAll = () => {
return (dispatch) => {
axios
.post("/user-service/logout-all")
.then(() => {
window.localStorage.removeItem("token");
return (dispatch) => {
dispatch(resetUpload());
dispatch(setLoginFailed(false));
dispatch(logout());
axios.post("/user-service/logout-all").then(() => {
window.localStorage.removeItem("token")
dispatch(resetUpload())
dispatch(setLoginFailed(false))
dispatch(logout())
history.push("/")
}).catch((err) => {
console.log(err);
})
}
}
history.push("/");
})
.catch((err) => {
console.log(err);
});
};
};
export const startLogout = () => {
return (dispatch) => {
axios
.post("/user-service/logout")
.then(() => {
window.localStorage.removeItem("token");
return (dispatch) => {
dispatch(resetUpload());
dispatch(setLoginFailed(false));
dispatch(logout());
axios.post("/user-service/logout").then(() => {
window.localStorage.removeItem("token")
dispatch(resetUpload())
dispatch(setLoginFailed(false))
dispatch(logout())
history.push("/")
}).catch((err) => {
console.log(err);
})
}
}
history.push("/");
})
.catch((err) => {
console.log(err);
});
};
};
+499 -465
View File
File diff suppressed because it is too large Load Diff
+73 -71
View File
@@ -1,4 +1,4 @@
import axios from 'axios';
import axios from "axios";
import uuid from "uuid";
let browserIDCheck = localStorage.getItem("browser-id");
@@ -8,88 +8,90 @@ const sleep = () => {
setTimeout(() => {
resolve();
}, 150);
})
}
});
};
const axiosRetry = axios.create();
const axiosNoRetry = axios.create();
const axios3 = axios.create();
axiosRetry.interceptors.request.use((config) => {
if (!browserIDCheck) {
browserIDCheck = uuid.v4();
localStorage.setItem("browser-id", browserIDCheck);
};
config.headers.uuid = browserIDCheck;
return config;
}, (error) => {
return Promise.reject(error);
})
axiosRetry.interceptors.response.use((response) => {
//console.log("axios interceptor successful")
return response;
}, (error) => {
return new Promise((resolve, reject) => {
//console.log("request interceptor failed", error.config.url);
let originalRequest = error.config;
if (error.response.status !== 401) {
//console.log("error does not equal 401");
return reject(error);
}
if (originalRequest.ran === true) {
//console.log("original request ran", error.config.url);
return reject(error);
}
if (error.config.url === "/user-service/get-token") {
//console.log("error url equal to refresh token route")
return reject();
}
const axiosRetry = axios.create({ baseURL: "http://localhost:5173/api" });
const axiosNoRetry = axios.create({ baseURL: "http://localhost:5173/api" });
const axios3 = axios.create({ baseURL: "http://localhost:5173/api" });
axiosRetry.interceptors.request.use(
(config) => {
if (!browserIDCheck) {
browserIDCheck = uuid.v4();
localStorage.setItem("browser-id", browserIDCheck);
};
axiosNoRetry.post("/user-service/get-token", {}, {headers: {
"uuid" : browserIDCheck
}}).then((cookieResponse) => {
// We need to sleep before requesting again, if not I believe
// The old request will still be open and it will not make a
// Brand new request sometimes, so it will log users out
// But adding a sleep function seems to fix this.
return sleep("sleepy boi");
}
}).then((sleepres) => {
config.headers.uuid = browserIDCheck;
return axios3(originalRequest);
return config;
},
(error) => {
return Promise.reject(error);
}
);
}).then((response) => {
axiosRetry.interceptors.response.use(
(response) => {
//console.log("axios interceptor successful")
return response;
},
(error) => {
return new Promise((resolve, reject) => {
//console.log("request interceptor failed", error.config.url);
resolve(response)
let originalRequest = error.config;
}).catch((e) => {
if (error.response.status !== 401) {
//console.log("error does not equal 401");
return reject(error);
}
//console.log("error");
return reject(error);
if (originalRequest.ran === true) {
//console.log("original request ran", error.config.url);
return reject(error);
}
})
})
if (error.config.url === "/user-service/get-token") {
//console.log("error url equal to refresh token route")
return reject();
}
})
if (!browserIDCheck) {
browserIDCheck = uuid.v4();
localStorage.setItem("browser-id", browserIDCheck);
}
axiosNoRetry
.post(
"/user-service/get-token",
{},
{
headers: {
uuid: browserIDCheck,
},
}
)
.then((cookieResponse) => {
// We need to sleep before requesting again, if not I believe
// The old request will still be open and it will not make a
// Brand new request sometimes, so it will log users out
// But adding a sleep function seems to fix this.
return sleep("sleepy boi");
})
.then((sleepres) => {
return axios3(originalRequest);
})
.then((response) => {
resolve(response);
})
.catch((e) => {
//console.log("error");
return reject(error);
});
});
}
);
// axios.interceptors.response.use( (response) => {
@@ -148,7 +150,7 @@ axiosRetry.interceptors.response.use((response) => {
// // console.log("cookieError", cookieError);
// // return Promise.reject(error);
// // })
// });
export default axiosRetry;
+68 -49
View File
@@ -1,53 +1,72 @@
import React from "react";
const Header = (props) => (
<header>
<div class="container">
<div class="outer__header">
<div class="left__header">
<div class="logo__wrapper">
<a onClick={props.goHome}>
<img
className="header__icon"
src="/images/mydrive-logo.png"
alt="logo"
/>
</a>
</div>
<div class="search__wrapper">
<a href="#">
<img src="/assets/searchicon.svg" alt="search" />
</a>
<input
type="text"
onChange={props.searchOnChange}
value={props.search}
placeholder="Search"
onFocus={props.showSuggested}
onBlur={props.hideSuggested}
/>
<div
class="search__files--dropdown"
style={
props.state.focused && props.searchValue.length !== 0
? { display: "block" }
: { display: "none" }
}
>
<div
onMouseDown={props.selectSuggestedByParent}
class="elem__search--files search__filter--local"
>
<a>
Search for <span class="file__name">{props.searchValue}</span>
<span class="spacer">
<img src="/assets/spacer.svg" alt="spacer" />
</span>
</a>
</div>
</div>
</div>
</div>
<div class="right__header">
<div class="profile__info">
<div class="settings__button">
<a onClick={props.goToSettings}>
<img src="/assets/settings.svg" alt="settings" />
</a>
</div>
<div class="profile__wrapper">
<div class="profile__button">
<a style={{ backgroundColor: "#3c85ee" }}>
<span style={{ color: "#fff" }}>{props.getProfilePic()}</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
);
<header>
<div class="container">
<div class="outer__header">
<div class="left__header">
<div class="logo__wrapper">
<a onClick={props.goHome}>
<img className="header__icon" src="/images/mydrive-logo.png" alt="logo"/>
</a>
</div>
<div class="search__wrapper">
<a href="#">
<img src="/assets/searchicon.svg" alt="search"/>
</a>
<input type="text"
placeholder="Search your files"
onChange={props.searchOnChange}
value={props.search}
placeholder="Search" type="text"
onFocus={props.showSuggested}
onBlur={props.hideSuggested}/>
<div class="search__files--dropdown" style={(props.state.focused && props.searchValue.length !== 0)? {display:"block"} : {display:"none"}}>
<div onMouseDown={props.selectSuggestedByParent} class="elem__search--files search__filter--local">
<a>Search for <span class="file__name">{props.searchValue}</span><span class="spacer"><img src="/assets/spacer.svg" alt="spacer"/></span></a>
</div>
</div>
</div>
</div>
<div class="right__header">
<div class="profile__info">
<div class="settings__button">
<a onClick={props.goToSettings}>
<img src="/assets/settings.svg" alt="settings"/>
</a>
</div>
<div class="profile__wrapper">
<div class="profile__button">
<a style={{backgroundColor:"#3c85ee"}}>
<span style={{color:"#fff"}}>{props.getProfilePic()}</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
)
export default Header
export default Header;
+196 -207
View File
@@ -1,224 +1,213 @@
import Header from "./Header";
import {startLogout} from "../../actions/auth"
import {showSettings} from "../../actions/settings";
import {setSearch} from "../../actions/filter"
import {loadMoreItems} from "../../actions/main";
import {setParent, resetParentList} from "../../actions/parent";
import {startSetFiles} from "../../actions/files";
import {startSetFolders} from "../../actions/folders";
import { startLogout } from "../../actions/auth";
import { showSettings } from "../../actions/settings";
import { setSearch } from "../../actions/filter";
import { loadMoreItems } from "../../actions/main";
import { setParent, resetParentList } from "../../actions/parent";
import { startSetFiles } from "../../actions/files";
import { startSetFolders } from "../../actions/folders";
import env from "../../enviroment/envFrontEnd";
import {history} from "../../routers/AppRouter";
import { history } from "../../routers/AppRouter";
import axios from "../../axiosInterceptor";
import {connect} from "react-redux";
import { connect } from "react-redux";
import React from "react";
const currentURL = env.url;
class HeaderContainer extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.searchValue = "";
this.searchValue = "";
this.state = {
focused: false,
suggestedList: {
fileList: [],
folderList: [],
},
};
}
this.state = {
focused: false,
suggestedList: {
fileList: [],
folderList: []
}
}
searchEvent = (e) => {
e.preventDefault();
const value = this.props.search;
// console.log("Search value". value)
const parent = "/";
this.props.dispatch(setParent(parent));
this.props.dispatch(loadMoreItems(true));
this.props.dispatch(startSetFiles(undefined, undefined, value));
this.props.dispatch(startSetFolders(undefined, undefined, value));
this.props.dispatch(resetParentList());
};
searchOnChange = (e) => {
const value = e.target.value;
this.searchValue = value;
this.props.dispatch(setSearch(value));
this.searchSuggested();
};
showSuggested = () => {
this.setState(() => {
return {
...this.state,
focused: true,
};
});
};
hideSuggested = () => {
this.setState(() => {
return {
...this.state,
focused: false,
};
});
};
selectSuggested = () => {
history.push(`/search/${this.searchValue}`);
this.searchValue = "";
this.setState(() => {
return {
...this.state,
suggestedList: {
fileList: [],
folderList: [],
},
};
});
};
searchSuggested = () => {
return;
// if (this.searchValue === "") {
// return this.setState(() => {
// return {
// ...this.state,
// suggestedList: {
// fileList: [],
// folderList: []
// }
// }
// })
// }
// const url = !env.googleDriveEnabled ? currentURL +`/file-service/suggested-list?search=${this.searchValue}` : currentURL +`/file-service-google-mongo/suggested-list?search=${this.searchValue}`
// axios.get(url).then((results) => {
// this.setState(() => {
// return {
// ...this.state,
// suggestedList: results.data
// }
// })
// }).catch((err) => {
// console.log(err)
// })
};
showSettings = () => {
this.props.dispatch(showSettings());
};
logoutUser = () => {
this.props.dispatch(startLogout());
};
itemClick = () => {
console.log("item click");
};
selectSuggestedByParent = () => {
// const parent = this.props.parent === "/" ? "home" : this.props.parent;
const parent = this.props.parent;
history.push(
`/search/${this.searchValue}?parent=${parent}&folder_search=true`
);
this.searchValue = "";
this.setState(() => {
return {
...this.state,
suggestedList: {
fileList: [],
folderList: [],
},
};
});
};
selectSuggestedByStorageType = () => {
history.push(`/search/${this.searchValue}?storageType=stripe`);
this.searchValue = "";
this.setState(() => {
return {
...this.state,
suggestedList: {
fileList: [],
folderList: [],
},
};
});
};
goToSettings = () => {
history.push("/settings");
};
getProfilePic = () => {
if (env.name && env.name.length !== 0) {
return env.name.substring(0, 1).toUpperCase();
} else if (env.emailAddress && env.emailAddress.length !== 0) {
return env.emailAddress.substring(0, 1).toUpperCase();
} else {
return "?";
}
searchEvent = (e) => {
e.preventDefault();
};
const value = this.props.search;
// console.log("Search value". value)
const parent = "/"
this.props.dispatch(setParent(parent))
this.props.dispatch(loadMoreItems(true))
this.props.dispatch(startSetFiles(undefined, undefined, value));
this.props.dispatch(startSetFolders(undefined, undefined, value));
this.props.dispatch(resetParentList())
}
searchOnChange = (e) => {
const value = e.target.value;
this.searchValue = value;
this.props.dispatch(setSearch(value))
this.searchSuggested()
}
showSuggested = () => {
this.setState(() => {
return {
...this.state,
focused: true
}
})
}
hideSuggested = () => {
this.setState(() => {
return {
...this.state,
focused: false
}
})
}
selectSuggested = () => {
history.push(`/search/${this.searchValue}`)
this.searchValue = ''
this.setState(() => {
return {
...this.state,
suggestedList: {
fileList: [],
folderList: []
}
}
})
}
searchSuggested = () => {
return;
// if (this.searchValue === "") {
// return this.setState(() => {
// return {
// ...this.state,
// suggestedList: {
// fileList: [],
// folderList: []
// }
// }
// })
// }
// const url = !env.googleDriveEnabled ? currentURL +`/file-service/suggested-list?search=${this.searchValue}` : currentURL +`/file-service-google-mongo/suggested-list?search=${this.searchValue}`
// axios.get(url).then((results) => {
// this.setState(() => {
// return {
// ...this.state,
// suggestedList: results.data
// }
// })
// }).catch((err) => {
// console.log(err)
// })
}
showSettings = () => {
this.props.dispatch(showSettings())
}
logoutUser = () => {
this.props.dispatch(startLogout())
}
itemClick = () => {
console.log("item click")
}
selectSuggestedByParent = () => {
// const parent = this.props.parent === "/" ? "home" : this.props.parent;
const parent = this.props.parent;
history.push(`/search/${this.searchValue}?parent=${parent}&folder_search=true`)
this.searchValue = ''
this.setState(() => {
return {
...this.state,
suggestedList: {
fileList: [],
folderList: []
}
}
})
}
selectSuggestedByStorageType = () => {
history.push(`/search/${this.searchValue}?storageType=stripe`)
this.searchValue = ''
this.setState(() => {
return {
...this.state,
suggestedList: {
fileList: [],
folderList: []
}
}
})
}
goToSettings = () => {
window.location.assign(env.url+"/settings")
}
getProfilePic = () => {
if (env.name && env.name.length !== 0) {
return env.name.substring(0, 1).toUpperCase();
} else if (env.emailAddress && env.emailAddress.length !== 0) {
return env.emailAddress.substring(0,1).toUpperCase();
} else {
return "?"
}
}
render() {
return <Header
searchEvent={this.searchEvent}
searchOnChange={this.searchOnChange}
selectSuggested={this.selectSuggested}
showSuggested={this.showSuggested}
hideSuggested={this.hideSuggested}
showSettings={this.showSettings}
searchValue={this.searchValue}
selectSuggestedByParent={this.selectSuggestedByParent}
selectSuggestedByStorageType={this.selectSuggestedByStorageType}
itemClick={this.itemClick}
goToSettings={this.goToSettings}
getProfilePic={this.getProfilePic}
state={this.state}
{...this.props}
/>
}
render() {
return (
<Header
searchEvent={this.searchEvent}
searchOnChange={this.searchOnChange}
selectSuggested={this.selectSuggested}
showSuggested={this.showSuggested}
hideSuggested={this.hideSuggested}
showSettings={this.showSettings}
searchValue={this.searchValue}
selectSuggestedByParent={this.selectSuggestedByParent}
selectSuggestedByStorageType={this.selectSuggestedByStorageType}
itemClick={this.itemClick}
goToSettings={this.goToSettings}
getProfilePic={this.getProfilePic}
state={this.state}
{...this.props}
/>
);
}
}
const connectPropToStore = (state) => ({
search: state.filter.search,
parentNameList: state.parent.parentNameList,
parent: state.parent.parent,
})
search: state.filter.search,
parentNameList: state.parent.parentNameList,
parent: state.parent.parent,
});
export default connect(connectPropToStore)(HeaderContainer);
export default connect(connectPropToStore)(HeaderContainer);
+226 -168
View File
@@ -3,181 +3,239 @@ import React from "react";
import env from "../../enviroment/envFrontEnd";
const LoginPage = (props) => {
return (
return (
<div>
{!props.loginFailed ? (
<div>
{(!props.loginFailed) ?
<div>
<div className="box-layout">
<div>
<SpinnerLogin />
</div>
</div>
</div>
:
<div className="sign__back">
{(props.loginFailed && props.loginFailedCode === 404) ?
<div class="sign__block">
<div class="sign__inner">
<div class="confirm__email">
<h2>Confirm your email address</h2>
<p>We've sent a confirmation email to <span>{env.emailAddress ? env.emailAddress.length !== 0 ? env.emailAddress : props.state.email : props.state.email}</span>.</p>
<p>Refresh this page after confirming email.</p>
<form action="">
{/* <div class="group__input">
<div className="box-layout">
<div>
<SpinnerLogin />
</div>
</div>
</div>
) : (
<div className="sign__back">
{props.loginFailed && props.loginFailedCode === 404 ? (
<div className="sign__block">
<div className="sign__inner">
<div className="confirm__email">
<h2>Confirm your email address</h2>
<p>
We've sent a confirmation email to{" "}
<span>
{env.emailAddress
? env.emailAddress.length !== 0
? env.emailAddress
: props.state.email
: props.state.email}
</span>
.
</p>
<p>Refresh this page after confirming email.</p>
<form action="">
{/* <div className="group__input">
<input type="text" placeholder="Enter one-time PIN"/>
</div>
<div class="group__submit">
<div className="group__submit">
<input type="submit" value="Continue"/>
</div> */}
<div class="resend__email">
<p style={props.state.verifyEmailResent ? {display:"block"} : {display:"none"}}><span><img src="/assets/checkbox.svg" alt="checkbox"/></span> Weve resent the email. You can resend again in <span class="full__timer">0:<span class="seconds__span">{props.state.verifyEmailResentTimer}</span></span></p>
<a class="resend__button" onClick={props.resendEmail}>Resend confirmation email</a>
<a class="resend__button" onClick={props.logout}>Logout</a>
</div>
</form>
</div>
</div>
</div>
:
<div className="login__block">
<div className="login__inner">
<div class="login__logo">
<img src="/images/icon.png" alt="logo"/>
</div>
{/* <!-- Login form block --> */}
<div class="login__form" style={(props.loginFailed && props.loginFailedCode === 404) ? {display:"none"} : {display:"block"}}>
<h2>{props.state.loginMode ? "Login to your account" : "Create an account"}</h2>
<form onSubmit={props.login}>
<div class="group__input">
<input type="text" placeholder="Email address" onChange={props.emailOnChange} value={props.state.email} ref={(ref) => { props.emailInput = ref }}/>
</div>
{!props.state.resetPasswordMode ? <div class="group__input forgot__pass">
<input type="password" placeholder="Password" onChange={props.passwordOnChange} value={props.state.password} ref={(ref) => { props.passwordInput = ref }}/>
{props.state.loginMode ? <a onClick={props.switchResetPasswordMode}>Forgot?</a> : undefined}
</div> : undefined}
{props.state.loginMode ? undefined :
<div class="group__input">
<input type="password" placeholder="Verify Password" onChange={props.verifyPasswordOnChange} value={props.state.verifyPassword} ref={(ref) => { props.passwordInput = ref }}/>
</div>
}
<div class="group__submit">
<input type="submit" value={props.state.resetPasswordMode ? "Reset" : props.state.loginMode ? "Login" : "Create"}/>
</div>
{!props.state.resetPasswordMode ?
<div class="create__account">
{props.state.loginMode ?
<p>Don't have an account? <a onClick={props.switchLoginMode}>Create account</a></p>
:
<p>Back to <a onClick={props.switchLoginMode}>Login</a></p>
}
</div>
:
<div class="create__account">
<p>Back to <a onClick={props.switchResetPasswordMode}>Login</a></p>
</div>
}
{props.loginFailed ?
props.loginFailedCode === 404 ?
<div>
<div className="login__image__wrapper">
<img className="login__image" src="/images/error-red.png" />
<p className="login__title">Email Not Verified</p>
</div>
<div className="login-resend-email__wrapper">
<p className="login-resend-email" onClick={props.resendEmail}>Resend Email Verification</p>
<p className="login-resend-email" onClick={props.logout}>Logout</p>
</div>
</div>
:
<div className="login__image__wrapper">
<img className="login__image" src="/images/error-red.png" />
<p className="login__title">{props.loginFailed}</p>
</div>
:
undefined}
</form>
</div>
{/* <!-- Forgot password block --> */}
<div class="forgotpass__form" style={{display:"none"}}>
<h2>Forgot your password?</h2>
<p>Type in your email address and well send you instructions to reset your password.</p>
<form action="">
<div class="group__input">
<input type="text" placeholder="Email address"/>
</div>
<div class="group__submit">
<input type="submit" value="Submit"/>
</div>
</form>
</div>
<div class="checkemail__pass" style={{display:"none"}}>
<h2>Check your email</h2>
<p>If the email address matches any in our database, well send you an email with instructions on how to reset your password</p>
</div>
</div>
</div>
}
{/* <!-- Bottom copyright --> */}
{/* <div class="bottom__float">
<p>Copyright © 2020 myDrive. All Rights Reserved.</p>
</div> */}
<div className="resend__email">
<p
style={
props.state.verifyEmailResent
? { display: "block" }
: { display: "none" }
}
>
<span>
<img src="/assets/checkbox.svg" alt="checkbox" />
</span>{" "}
Weve resent the email. You can resend again in{" "}
<span className="full__timer">
0:
<span className="seconds__span">
{props.state.verifyEmailResentTimer}
</span>
</span>
</p>
<a className="resend__button" onClick={props.resendEmail}>
Resend confirmation email
</a>
<a className="resend__button" onClick={props.logout}>
Logout
</a>
</div>
</form>
</div>
</div>
</div>
) : (
<div className="login__block">
<div className="login__inner">
<div className="login__logo">
<img src="/images/icon.png" alt="logo" />
</div>
}
{/* <!-- Login form block --> */}
<div
className="login__form"
style={
props.loginFailed && props.loginFailedCode === 404
? { display: "none" }
: { display: "block" }
}
>
<h2>
{props.state.loginMode
? "Login to your account"
: "Create an account"}
</h2>
<form onSubmit={props.login}>
<div className="group__input">
<input
type="text"
placeholder="Email address"
onChange={props.emailOnChange}
value={props.state.email}
/>
</div>
{!props.state.resetPasswordMode ? (
<div className="group__input forgot__pass">
<input
type="password"
placeholder="Password"
onChange={props.passwordOnChange}
value={props.state.password}
/>
{props.state.loginMode ? (
<a onClick={props.switchResetPasswordMode}>Forgot?</a>
) : undefined}
</div>
) : undefined}
{props.state.loginMode ? undefined : (
<div className="group__input">
<input
type="password"
placeholder="Verify Password"
onChange={props.verifyPasswordOnChange}
value={props.state.verifyPassword}
ref={(ref) => {
props.passwordInput = ref;
}}
/>
</div>
)}
<div className="group__submit">
<input
type="submit"
value={
props.state.resetPasswordMode
? "Reset"
: props.state.loginMode
? "Login"
: "Create"
}
/>
</div>
{!props.state.resetPasswordMode ? (
<div className="create__account">
{props.state.loginMode ? (
<p>
Don't have an account?{" "}
<a onClick={props.switchLoginMode}>
Create account
</a>
</p>
) : (
<p>
Back to <a onClick={props.switchLoginMode}>Login</a>
</p>
)}
</div>
) : (
<div className="create__account">
<p>
Back to{" "}
<a onClick={props.switchResetPasswordMode}>Login</a>
</p>
</div>
)}
{props.loginFailed ? (
props.loginFailedCode === 404 ? (
<div>
<div className="login__image__wrapper">
<img
className="login__image"
src="/images/error-red.png"
/>
<p className="login__title">Email Not Verified</p>
</div>
<div className="login-resend-email__wrapper">
<p
className="login-resend-email"
onClick={props.resendEmail}
>
Resend Email Verification
</p>
<p
className="login-resend-email"
onClick={props.logout}
>
Logout
</p>
</div>
</div>
) : (
<div className="login__image__wrapper">
<img
className="login__image"
src="/images/error-red.png"
/>
<p className="login__title">{props.loginFailed}</p>
</div>
)
) : undefined}
</form>
</div>
{/* <!-- Forgot password block --> */}
<div className="forgotpass__form" style={{ display: "none" }}>
<h2>Forgot your password?</h2>
<p>
Type in your email address and well send you instructions
to reset your password.
</p>
<form action="">
<div className="group__input">
<input type="text" placeholder="Email address" />
</div>
<div className="group__submit">
<input type="submit" value="Submit" />
</div>
</form>
</div>
<div className="checkemail__pass" style={{ display: "none" }}>
<h2>Check your email</h2>
<p>
If the email address matches any in our database, well send
you an email with instructions on how to reset your password
</p>
</div>
</div>
</div>
)}
{/* <!-- Bottom copyright --> */}
{/* <div className="bottom__float">
<p>Copyright © 2020 myDrive. All Rights Reserved.</p>
</div> */}
</div>
)}
</div>
);
};
)
}
export default LoginPage
export default LoginPage;
+279 -254
View File
@@ -1,287 +1,312 @@
import {startLoadMoreFiles} from "../../actions/files";
import {startSetSelectedItem, setLastSelected} from "../../actions/selectedItem";
import {setLoading, setLeftSectionMode, setRightSectionMode} from "../../actions/main";
import {setPopupFile} from "../../actions/popupFile";
import mobileCheck from "../../utils/mobileCheck"
import { startLoadMoreFiles } from "../../actions/files";
import {
startSetSelectedItem,
setLastSelected,
} from "../../actions/selectedItem";
import {
setLoading,
setLeftSectionMode,
setRightSectionMode,
} from "../../actions/main";
import { setPopupFile } from "../../actions/popupFile";
import mobileCheck from "../../utils/mobileCheck";
import MainSection from "./MainSection";
import env from "../../enviroment/envFrontEnd";
import axios from "../../axiosInterceptor";
import {connect} from "react-redux";
import {history} from "../../routers/AppRouter";
import { connect } from "react-redux";
import { history } from "../../routers/AppRouter";
import React from "react";
import { getUpdateSettingsID } from "../../utils/updateSettings";
class MainSectionContainer extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.doubleClickFoldersMobile = false;
this.lastSettingsUpdateID = "";
}
this.doubleClickFoldersMobile = false;
this.lastSettingsUpdateID = "";
folderClick = (id, folder, bypass = false) => {
const currentDate = Date.now();
const mobile = mobileCheck();
const selectedID = this.props.selected;
const doubleClickMobile =
localStorage.getItem("double-click-folders") || false;
if (
(currentDate - this.props.lastSelected < 1500 && selectedID === id) ||
(mobile && !doubleClickMobile) ||
bypass
) {
const folderPush = folder.drive
? `/folder-google/${id}`
: folder.personalFolder
? `/folder-personal/${id}`
: `/folder/${id}`;
history.push(folderPush);
} else {
const isGoogleDrive = folder.drive;
this.props.dispatch(
startSetSelectedItem(id, false, false, isGoogleDrive)
);
}
};
fileClick = (fileID, file, fromQuickItems = false, bypass = false) => {
const currentDate = Date.now();
let selectedFileID = fileID;
if (fromQuickItems) {
selectedFileID = "quick-" + fileID;
}
folderClick = (id, folder, bypass=false) => {
const isMobile = mobileCheck();
const currentDate = Date.now();
const mobile = mobileCheck();
const selectedID = this.props.selected;
if (
(currentDate - this.props.lastSelected < 1500 &&
selectedFileID === this.props.selected) ||
bypass
) {
this.props.dispatch(setPopupFile({ showPopup: true, ...file }));
} else {
const isGoogleDrive = file.metadata.drive;
const doubleClickMobile = localStorage.getItem("double-click-folders") || false;
this.props.dispatch(
startSetSelectedItem(fileID, true, fromQuickItems, isGoogleDrive)
);
}
};
if ((currentDate - this.props.lastSelected < 1500 && selectedID === id) || (mobile && !doubleClickMobile)|| bypass) {
scrollEvent = (e) => {
//if (!mobileCheck()) return;
const folderPush = folder.drive ? `/folder-google/${id}` : folder.personalFolder ? `/folder-personal/${id}` : `/folder/${id}`;
history.push(folderPush)
return;
} else {
const scrollY = window.pageYOffset;
const windowY = document.documentElement.scrollHeight;
const isGoogleDrive = folder.drive;
let limit = window.localStorage.getItem("list-size") || 50;
limit = parseInt(limit);
this.props.dispatch(startSetSelectedItem(id, false, false, isGoogleDrive));
}
if (this.props.loading) return;
if (windowY / 2 < scrollY && this.props.allowLoadMoreItems) {
console.log("load more main");
if (this.props.files.length >= limit) {
const parent = this.props.parent;
const search = this.props.filter.search;
const sortBy = this.props.filter.sortBy;
const lastFileDate =
this.props.files[this.props.files.length - 1].uploadDate;
const lastFileName =
this.props.files[this.props.files.length - 1].filename;
this.props.dispatch(setLoading(true));
this.props.dispatch(
startLoadMoreFiles(parent, sortBy, search, lastFileDate, lastFileName)
);
}
}
};
componentDidMount = () => {
window.addEventListener("scroll", this.scrollEvent);
window.addEventListener("resize", this.resizeEvent);
this.getSettings();
};
componentDidUpdate = () => {
console.log("main updated");
// console.log("update ID main", getUpdateSettingsID());
// if (this.lastSettingsUpdateID !== getUpdateSettingsID()) {
// console.log("Settings Update!");
// this.getSettings();
// }
// this.lastSettingsUpdateID = getUpdateSettingsID();
// console.log("update settings id", updateSettingsID);
// console.log("Main Section Updated", this.props.resetSettingsMain);
// if (this.lastSettingsUpdateID !== this.props.resetSettingsMain) {
// console.log("Settings Update!");
// this.getSettings();
// }
// this.lastSettingsUpdateID = this.props.resetSettingsMain;
};
getSettings = () => {
this.doubleClickFoldersMobile =
localStorage.getItem("double-click-folders") || false;
};
componentWillUnmount = () => {
window.removeEventListener("scroll", this.scrollEvent);
};
resizeEvent = () => {
if (this.props.leftSectionMode === "open")
this.props.dispatch(setLeftSectionMode(""));
if (this.props.rightSectionMode === "open")
this.props.dispatch(setRightSectionMode(""));
};
downloadFile = (fileID, file) => {
const isGoogle = file.metadata.drive;
const isGoogleDoc = file.metadata.googleDoc;
const isPersonal = file.metadata.personalFile;
this.props.dispatch(setLastSelected(0));
axios
.post("/user-service/get-token")
.then((response) => {
let finalUrl = isGoogle
? !isGoogleDoc
? `/file-service-google/download/${fileID}`
: `/file-service-google-doc/download/${fileID}`
: !isPersonal
? `/file-service/download/${fileID}`
: `/file-service-personal/download/${fileID}`;
finalUrl = `http://localhost:3000${finalUrl}`;
console.log("download file", finalUrl);
const link = document.createElement("a");
document.body.appendChild(link);
link.href = finalUrl;
link.setAttribute("type", "hidden");
link.setAttribute("download", true);
link.click();
})
.catch((e) => {
console.log("Download file get refresh token error", e);
});
// axios.get(currentURL +'/file-service/download/get-token')
// .then((response) => {
// const tempToken = response.data.tempToken;
// const finalUrl =
// isGoogle ? !isGoogleDoc ? currentURL + `/file-service-google/download/${fileID}` : currentURL + `/file-service-google-doc/download/${fileID}`
// : !isPersonal ? currentURL + `/file-service/download/${fileID}` : currentURL + `/file-service-personal/download/${fileID}`
// const link = document.createElement('a');
// document.body.appendChild(link);
// link.href = finalUrl;
// link.setAttribute('type', 'hidden');
// link.setAttribute("download", true);
// link.click();
// }).catch((err) => {
// console.log(err)
// })
};
loadMoreItems = () => {
return;
console.log("load more main");
if (mobileCheck()) return;
let limit = window.localStorage.getItem("list-size") || 50;
limit = parseInt(limit);
if (this.props.loading) {
return;
}
fileClick = (fileID, file, fromQuickItems=false, bypass=false) => {
const currentDate = Date.now();
let selectedFileID = fileID;
if (fromQuickItems) {
selectedFileID = "quick-" + fileID;
}
const isMobile = mobileCheck();
if ((currentDate - this.props.lastSelected < 1500 && selectedFileID === this.props.selected) || bypass) {
this.props.dispatch(setPopupFile({showPopup: true, ...file}))
} else {
const isGoogleDrive = file.metadata.drive
this.props.dispatch(startSetSelectedItem(fileID, true, fromQuickItems, isGoogleDrive))
}
if (this.props.files.length >= limit) {
const parent = this.props.parent;
const search = this.props.filter.search;
const sortBy = this.props.filter.sortBy;
const lastFileDate =
this.props.files[this.props.files.length - 1].uploadDate;
const lastFileName =
this.props.files[this.props.files.length - 1].filename;
const lastPageToken =
this.props.files[this.props.files.length - 1].pageToken;
const isGoogle = this.props.filter.isGoogle;
this.props.dispatch(
startLoadMoreFiles(
parent,
sortBy,
search,
lastFileDate,
lastFileName,
lastPageToken,
isGoogle
)
);
}
};
scrollEvent = (e) => {
switchLeftSectionMode = () => {
const leftSectionMode = this.props.leftSectionMode;
//if (!mobileCheck()) return;
return;
const scrollY = window.pageYOffset;
const windowY = document.documentElement.scrollHeight;
let limit = window.localStorage.getItem("list-size") || 50
limit = parseInt(limit)
if (this.props.loading) return;
if ((windowY / 2) < scrollY && this.props.allowLoadMoreItems) {
console.log("load more main")
if (this.props.files.length >= limit) {
const parent = this.props.parent;
const search = this.props.filter.search;
const sortBy = this.props.filter.sortBy;
const lastFileDate = this.props.files[this.props.files.length - 1].uploadDate
const lastFileName = this.props.files[this.props.files.length - 1].filename
this.props.dispatch(setLoading(true));
this.props.dispatch(startLoadMoreFiles(parent, sortBy, search, lastFileDate, lastFileName));
}
}
if (leftSectionMode === "" || leftSectionMode === "close") {
this.props.dispatch(setLeftSectionMode("open"));
} else {
this.props.dispatch(setLeftSectionMode("close"));
}
};
componentDidMount = () => {
window.addEventListener("scroll", this.scrollEvent);
window.addEventListener("resize", this.resizeEvent);
switchRightSectionMode = () => {
const rightSectionMode = this.props.rightSectionMode;
this.getSettings();
}
componentDidUpdate = () => {
console.log("main updated");
// console.log("update ID main", getUpdateSettingsID());
// if (this.lastSettingsUpdateID !== getUpdateSettingsID()) {
// console.log("Settings Update!");
// this.getSettings();
// }
// this.lastSettingsUpdateID = getUpdateSettingsID();
// console.log("update settings id", updateSettingsID);
// console.log("Main Section Updated", this.props.resetSettingsMain);
// if (this.lastSettingsUpdateID !== this.props.resetSettingsMain) {
// console.log("Settings Update!");
// this.getSettings();
// }
// this.lastSettingsUpdateID = this.props.resetSettingsMain;
}
getSettings = () => {
this.doubleClickFoldersMobile = localStorage.getItem("double-click-folders") || false;
}
componentWillUnmount = () => {
window.removeEventListener("scroll", this.scrollEvent);
}
resizeEvent = () => {
if (this.props.leftSectionMode === 'open') this.props.dispatch(setLeftSectionMode(''))
if (this.props.rightSectionMode === 'open') this.props.dispatch(setRightSectionMode(''))
}
downloadFile = (fileID, file) => {
const isGoogle = file.metadata.drive;
const isGoogleDoc = file.metadata.googleDoc;
const isPersonal = file.metadata.personalFile;
this.props.dispatch(setLastSelected(0));
axios.post("/user-service/get-token").then((response) => {
const finalUrl =
isGoogle ? !isGoogleDoc ? `/file-service-google/download/${fileID}` : `/file-service-google-doc/download/${fileID}`
: !isPersonal ? `/file-service/download/${fileID}` : `/file-service-personal/download/${fileID}`
console.log("download file", finalUrl);
const link = document.createElement('a');
document.body.appendChild(link);
link.href = finalUrl;
link.setAttribute('type', 'hidden');
link.setAttribute("download", true);
link.click();
}).catch((e) => {
console.log("Download file get refresh token error", e);
})
// axios.get(currentURL +'/file-service/download/get-token')
// .then((response) => {
// const tempToken = response.data.tempToken;
// const finalUrl =
// isGoogle ? !isGoogleDoc ? currentURL + `/file-service-google/download/${fileID}` : currentURL + `/file-service-google-doc/download/${fileID}`
// : !isPersonal ? currentURL + `/file-service/download/${fileID}` : currentURL + `/file-service-personal/download/${fileID}`
// const link = document.createElement('a');
// document.body.appendChild(link);
// link.href = finalUrl;
// link.setAttribute('type', 'hidden');
// link.setAttribute("download", true);
// link.click();
// }).catch((err) => {
// console.log(err)
// })
}
loadMoreItems = () => {
return;
console.log("load more main")
if (mobileCheck()) return;
let limit = window.localStorage.getItem("list-size") || 50
limit = parseInt(limit)
if (this.props.loading) {
return;
}
if (this.props.files.length >= limit) {
const parent = this.props.parent;
const search = this.props.filter.search;
const sortBy = this.props.filter.sortBy;
const lastFileDate = this.props.files[this.props.files.length - 1].uploadDate
const lastFileName = this.props.files[this.props.files.length - 1].filename
const lastPageToken = this.props.files[this.props.files.length - 1].pageToken
const isGoogle = this.props.filter.isGoogle;
this.props.dispatch(startLoadMoreFiles(parent, sortBy, search, lastFileDate, lastFileName, lastPageToken, isGoogle))
}
}
switchLeftSectionMode = () => {
const leftSectionMode = this.props.leftSectionMode;
if (leftSectionMode === '' || leftSectionMode === 'close') {
this.props.dispatch(setLeftSectionMode('open'))
} else {
this.props.dispatch(setLeftSectionMode('close'))
}
}
switchRightSectionMode = () => {
const rightSectionMode = this.props.rightSectionMode;
if (rightSectionMode === '' || rightSectionMode === 'close') {
this.props.dispatch(setRightSectionMode('open'))
} else {
this.props.dispatch(setRightSectionMode('close'))
}
}
render() {
return <MainSection
folderClick={this.folderClick}
fileClick={this.fileClick}
downloadFile={this.downloadFile}
loadMoreItems={this.loadMoreItems}
switchLeftSectionMode={this.switchLeftSectionMode}
switchRightSectionMode={this.switchRightSectionMode}
{...this.props}/>
if (rightSectionMode === "" || rightSectionMode === "close") {
this.props.dispatch(setRightSectionMode("open"));
} else {
this.props.dispatch(setRightSectionMode("close"));
}
};
render() {
return (
<MainSection
folderClick={this.folderClick}
fileClick={this.fileClick}
downloadFile={this.downloadFile}
loadMoreItems={this.loadMoreItems}
switchLeftSectionMode={this.switchLeftSectionMode}
switchRightSectionMode={this.switchRightSectionMode}
{...this.props}
/>
);
}
}
const connectPropToState = (state) => ({
filter: state.filter,
files: state.files,
folders: state.folders,
allowLoadMoreItems: state.main.loadMoreItems,
loading: state.main.loading,
showPopup: state.popupFile.showPopup,
quickFiles: state.quickFiles,
selected: state.selectedItem.selected,
lastSelected: state.selectedItem.lastSelected,
parent: state.parent.parent,
parentNameList: state.parent.parentNameList,
moverID: state.mover.id,
routeType: state.main.currentRouteType,
cachedSearch: state.main.cachedSearch,
leftSectionMode: state.main.leftSectionMode,
rightSectionMode: state.main.rightSectionMode,
// resetSettingsMain: state.main.resetSettingsMain
})
filter: state.filter,
files: state.files,
folders: state.folders,
allowLoadMoreItems: state.main.loadMoreItems,
loading: state.main.loading,
showPopup: state.popupFile.showPopup,
quickFiles: state.quickFiles,
selected: state.selectedItem.selected,
lastSelected: state.selectedItem.lastSelected,
parent: state.parent.parent,
parentNameList: state.parent.parentNameList,
moverID: state.mover.id,
routeType: state.main.currentRouteType,
cachedSearch: state.main.cachedSearch,
leftSectionMode: state.main.leftSectionMode,
rightSectionMode: state.main.rightSectionMode,
// resetSettingsMain: state.main.resetSettingsMain
});
export default connect(connectPropToState)(MainSectionContainer);
export default connect(connectPropToState)(MainSectionContainer);
+23 -20
View File
@@ -2,26 +2,29 @@ import QuickAccessItem from ".././QuickAccessItem";
import React from "react";
const QuickAccess = (props) => (
<div className="quick__access" style={props.currentRouteType === "home" ? {display:"block"} : {display:"none"}}>
<div className="head__access">
<h2 className="noSelect">Quick Access</h2>
</div>
<div className="main__access">
{props.quickFiles
.map((file) => <QuickAccessItem
key={file._id}
downloadFile={props.downloadFile}
fileClick={props.fileClick}
{...file}/>)}
</div>
<div
className="quick__access"
style={
props.currentRouteType === "home"
? { display: "block" }
: { display: "none" }
}
>
<div className="head__access">
<h2 className="noSelect">Quick Access</h2>
</div>
)
<div className="main__access">
{props.quickFiles.map((file) => (
<QuickAccessItem
key={file._id}
downloadFile={props.downloadFile}
fileClick={props.fileClick}
{...file}
/>
))}
</div>
</div>
);
export default QuickAccess;
export default QuickAccess;
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -1,15 +1,15 @@
const env = {
port: process.env.PORT,
url: process.env.REMOTE_URL,
enableVideoTranscoding: process.env.ENABLE_VIDEO_TRANSCODING,
disableStorage: process.env.DISABLE_STORAGE,
googleDriveEnabled: false,
s3Enabled: false,
activeSubscription: false,
commercialMode: process.env.COMMERCIAL_MODE,
uploadMode: "",
emailAddress:"",
name: ""
}
port: 5173,
url: "http://localhost",
// enableVideoTranscoding: process.env.ENABLE_VIDEO_TRANSCODING,
// disableStorage: process.env.DISABLE_STORAGE,
googleDriveEnabled: false,
s3Enabled: false,
activeSubscription: false,
// commercialMode: process.env.COMMERCIAL_MODE,
uploadMode: "",
emailAddress: "",
name: "",
};
export default env;
export default env;
+10 -11
View File
@@ -1,16 +1,15 @@
const { default: mobilecheck } = require("./mobileCheck");
import mobilecheck from "./mobileCheck";
const reduceQuickItemList = (quickItemList) => {
const isMobile = mobilecheck()
const isMobile = mobilecheck();
if (quickItemList.length > 10 && !isMobile) {
quickItemList = quickItemList.slice(0, 10);
} else if (quickItemList.length > 2 && isMobile) {
quickItemList = quickItemList.slice(0, 2);
}
if (quickItemList.length > 10 && !isMobile) {
quickItemList = quickItemList.slice(0, 10);
} else if (quickItemList.length > 2 && isMobile) {
quickItemList = quickItemList.slice(0, 2);
}
return quickItemList;
}
return quickItemList;
};
export default reduceQuickItemList;
export default reduceQuickItemList;
+2 -1
View File
@@ -77,6 +77,7 @@
"webUI",
"webUI.config.js",
"webUISetup",
"webUISetup.config.js"
"webUISetup.config.js",
"vite.config.js"
]
}
+16 -1
View File
@@ -3,9 +3,24 @@ import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
esbuild: {
loader: "jsx",
include: [
// Process all .js files in the src directory as JSX
/src\/.*\.js$/,
],
exclude: [
// Exclude node_modules from processing
/node_modules/,
],
},
server: {
proxy: {
"/api": "http://localhost:3000", // Proxy API requests to Express server
"/api": {
target: "http://localhost:3000", // The port where your backend is running
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
});