diff --git a/client/src/screens/browse/components/file-display/index.jsx b/client/src/screens/browse/components/file-display/index.jsx
index b0e0065..a7a58d3 100644
--- a/client/src/screens/browse/components/file-display/index.jsx
+++ b/client/src/screens/browse/components/file-display/index.jsx
@@ -8,6 +8,7 @@ import { getThumbnail } from "../../../../api/File";
import clientRoot from "../../../../api/server";
import capitalise from "../../../../utils/capitalise.js";
import Share from "../../../share";
+import API_BASE_URL from "../../../../api/server";
import { verifyFile, unverifyFile } from "../../../../api/File";
import {
RemoveFileFromFolder,
@@ -18,12 +19,13 @@ import { getFileDownloadLink } from "../../../../api/File";
import { fetchFolder } from "../../../../api/Folder.js";
const FileDisplay = ({ file, path, code, isMobileView = false }) => {
+
const user = useSelector((state) => state.user?.user);
const fileSize = formatFileSize(file.size);
const fileType = formatFileType(file.name);
const [showDialog, setShowDialog] = useState(false);
const [dialogType, setDialogType] = useState("verify");
- const [onConfirmAction, setOnConfirmAction] = useState(() => () => {});
+ const [onConfirmAction, setOnConfirmAction] = useState(() => () => { });
const [isProcessing, setIsProcessing] = useState(false);
let name = file.name;
@@ -96,7 +98,11 @@ const FileDisplay = ({ file, path, code, isMobileView = false }) => {
toast.error("Please login to preview file.");
return;
}
- window.open(preview_url, "_blank");
+ window.open(
+ `${API_BASE_URL}/api/contribution/view/${file._id}`,
+ "_blank"
+ );
+
};
@@ -144,9 +150,8 @@ const FileDisplay = ({ file, path, code, isMobileView = false }) => {
return (

{
logger.error(
{
message: err.message,
+ microsoftResponse: err.response?.data,
route: req.originalUrl,
method: req.method,
},
diff --git a/server/modules/contribution/contribution.controller.js b/server/modules/contribution/contribution.controller.js
index c607f19..cc010ec 100644
--- a/server/modules/contribution/contribution.controller.js
+++ b/server/modules/contribution/contribution.controller.js
@@ -4,9 +4,11 @@ import AppError from "../../utils/appError.js";
import validatePayload from "../../utils/validate.js";
import UploadFile from "../../services/UploadFile.js";
import fs from "fs";
-import { FolderModel } from "../course/course.model.js";
+import { FolderModel, FileModel } from "../course/course.model.js";
import logger from "../../utils/logger.js";
import { normalizeCourseCode, getCourseCodeCaseInsensitiveRegex } from "../../utils/course.js";
+import { getAccessToken } from "../onedrive/onedrive.controller.js";
+import axios from "axios";
async function ContributionCreation(contributionId, data) {
const existingContribution = await Contribution.findOne({ contributionId });
@@ -50,7 +52,6 @@ async function HandleFileUpload(req, res, next) {
logger.info("Handling File Upload");
const contributionId = req.headers["contribution-id"];
const files = req.files;
-
if (!files || files.length === 0) {
return res.status(400).json({ error: "No files were uploaded" });
}
@@ -157,6 +158,36 @@ async function GetBrContribution(req, res, next) {
}
}
+async function viewFile(req, res, next) {
+ try {
+ const { id } = req.params;
+ const file = await FileModel.findById(id);
+ if (!file) {
+ return res.status(404).json({ message: "File not found" });
+ }
+ const accessToken = await getAccessToken();
+ if (!accessToken) {
+ return res.status(500).json({ message: "Access token not found" });
+ }
+
+ const response = await axios.get(`https://graph.microsoft.com/v1.0/me/drive/items/${file.fileId}/content`, {
+ headers: {
+ Authorization: `Bearer ${accessToken}`
+ },
+ responseType: "stream"
+ })
+ if (!response) {
+ return res.status(500).json({ message: "File not found" });
+ }
+ res.setHeader("Content-Type", response.headers["content-type"])
+
+ response.data.pipe(res)
+
+ } catch (error) {
+ next(error);
+ }
+}
+
export default {
GetAllContributions,
CreateNewContribution,
@@ -164,5 +195,6 @@ export default {
GetMyContributions,
DeleteContribution,
GetContributionsUpdatedSince,
- GetBrContribution
+ GetBrContribution,
+ viewFile
};
diff --git a/server/modules/contribution/contribution.routes.js b/server/modules/contribution/contribution.routes.js
index 45c3f96..5caa4ab 100644
--- a/server/modules/contribution/contribution.routes.js
+++ b/server/modules/contribution/contribution.routes.js
@@ -14,5 +14,5 @@ router.post("/upload", upload.array("file"), catchAsync(ContributionController.H
// router.get("/:id", catchAsync(ContributionController.CreateNewContribution));
router.post("/updated", catchAsync(ContributionController.GetContributionsUpdatedSince));
router.post("/br",isAuthenticated, ContributionController.GetBrContribution)
-
+router.get('/view/:id',catchAsync(ContributionController.viewFile))
export default router;
diff --git a/server/modules/onedrive/onedrive.controller.js b/server/modules/onedrive/onedrive.controller.js
index 4479f15..896b357 100644
--- a/server/modules/onedrive/onedrive.controller.js
+++ b/server/modules/onedrive/onedrive.controller.js
@@ -37,8 +37,6 @@ export async function generateDeviceCode(req, res) {
if (!response.data) throw new AppError(500, "Something went wrong");
- console.log(response.data.user_code);
-
fs.writeFileSync("./onedrive-device-code.token", response.data.device_code, "utf-8");
if (fs.existsSync("./onedrive-access-token.token")) {
fs.unlinkSync("./onedrive-access-token.token");
@@ -204,14 +202,12 @@ async function visitAllFiles() {
const searchDocument = await SearchResults.findOne({
code: getCourseCodeCaseInsensitiveRegex(courseCode),
});
- console.log(searchDocument);
if (!searchDocument) {
await SearchResults.create({
name: courseName,
code: courseCode,
isAvailable: true,
});
- console.log("Created", folder.name);
} else {
await SearchResults.updateOne(
{ code: getCourseCodeCaseInsensitiveRegex(courseCode) },
@@ -219,7 +215,6 @@ async function visitAllFiles() {
isAvailable: true,
}
);
- console.log("Updated", folder.name);
}
}));
return "ok";
@@ -254,7 +249,6 @@ export async function visitCourseById(id) {
code: courseCode,
isAvailable: true,
});
- console.log("Created", required_course.name);
} else {
await SearchResults.updateOne(
{ code: getCourseCodeCaseInsensitiveRegex(courseCode) },
@@ -262,7 +256,6 @@ export async function visitCourseById(id) {
isAvailable: true,
}
);
- console.log("Updated", required_course.name);
}
return "ok";
@@ -319,14 +312,53 @@ async function visitFile(file, currCourse) {
return NewFile._id;
}
+// export async function getAccessToken() {
+// let data;
+// if (fs.existsSync("./onedrive-refresh-token.token")) {
+// data = await refreshAccessToken();
+// } else {
+// data = await generateAccessToken();
+// }
+// return data.access_token;
+// }
+let cachedAccessToken = null;
+let tokenExpiry = 0;
+let refreshPromise = null;
export async function getAccessToken() {
- let data;
- if (fs.existsSync("./onedrive-refresh-token.token")) {
- data = await refreshAccessToken();
- } else {
- data = await generateAccessToken();
+
+ if (
+ cachedAccessToken &&
+ Date.now() < tokenExpiry
+ ) {
+ return cachedAccessToken;
+ }
+ if (refreshPromise) {
+ return refreshPromise;
+ }
+
+ refreshPromise = (async () => {
+ let data;
+
+ if (fs.existsSync("./onedrive-refresh-token.token")) {
+ data = await refreshAccessToken();
+ } else {
+ data = await generateAccessToken();
+ }
+
+ cachedAccessToken = data.access_token;
+
+ tokenExpiry =
+ Date.now() +
+ (data.expires_in - 60) * 1000;
+
+ return cachedAccessToken;
+ })();
+ try {
+ return await refreshPromise;
+ } finally {
+ refreshPromise = null;
}
- return data.access_token;
+
}
async function refreshAccessToken() {