From ac17e2058ba438e86ef7330561a0f66ba12f65a8 Mon Sep 17 00:00:00 2001 From: rdbsolutions Date: Fri, 29 Aug 2025 08:25:01 +0100 Subject: [PATCH] removed older storage pages --- pages/storage.js | 100 ------ pages/storageAdmin.js | 759 ------------------------------------------ 2 files changed, 859 deletions(-) delete mode 100644 pages/storage.js delete mode 100644 pages/storageAdmin.js diff --git a/pages/storage.js b/pages/storage.js deleted file mode 100644 index 2c79953d..00000000 --- a/pages/storage.js +++ /dev/null @@ -1,100 +0,0 @@ -import { DefaultAzureCredential } from "@azure/identity"; -import { BlobServiceClient, ContainerClient } from "@azure/storage-blob"; -import { v4 as uuidv4 } from "uuid"; -import { wrapper } from "../store/store"; - -import { getIP } from "../actions"; - -const ShowStorage = (props) => { - const { container } = props; - //console.log("Containers:"); - // // for await (const container of blobServiceClient.listContainers()) { - // // console.log(`- ${container.name}`); - // // } - - console.log(container); - - return
hello
; -}; - -export const getServerSideProps = wrapper.getServerSideProps( - (store) => async (ctx) => { - const { query, req, res } = ctx; - getIP(req); - - console.log( - "have therese?:", - process.env.AZURE_TENANT_ID, - process.env.AZURE_CLIENT_ID, - process.env.AZURE_CLIENT_SECRET - ); - - const creds = new DefaultAzureCredential(); - - const blobServiceClient = new BlobServiceClient( - `https://pedwdev.blob.core.windows.net`, - creds - ); - - const containerName = `CAS-999999-22222`; - - const containerClient = new ContainerClient( - `https://pedwdev.blob.core.windows.net/${containerName}`, - creds - ); - - //const createContainerResponse = await containerClient.create(); - //console.log( - // `Created container ${containerName} successfully`, - // createContainerResponse.requestId - // ); - - console.log("Containers:"); - for await (const container of blobServiceClient.listContainers()) { - console.log(`- ${container.name}`); - } - - const appealID = uuidv4(); - const uploadOptions = { - metadata: { reviewer: "john", reviewDate: "2022-04-01" }, - tags: { owner: appealID }, - }; - // for (let index = 0; index < 7; index++) { - // // Create a blob - // const content = "hello"; - // const blobName = appealID + "/BOBnewblob" + new Date().getTime(); - // const blockBlobClient = - // containerClient.getBlockBlobClient(blobName); - - // //const uploadBlobResponse = await blockBlobClient.upload( - // // content, - // // Buffer.byteLength(content), - // // uploadOptions - // // ); - - // const uploadBlobResponse = await blockBlobClient.uploadFile( - // "public/assets/images/HM-Govt-Supplier-to-Govt.jpg" - // // uploadOptions - // ); - - // const tags = { - // owner: appealID, - // }; - - // //console.log(tags); - // //await blockBlobClient.setTags(tags); - - // //console.log( - // // `Uploaded block blob ${blobName} successfully`, - // // uploadBlobResponse.requestId - // // ); - // } - - console.log("Blobs:"); - for await (const blob of containerClient.listBlobsFlat()) { - console.log(`- ${blob.name}`); - } - } -); - -export default ShowStorage; diff --git a/pages/storageAdmin.js b/pages/storageAdmin.js deleted file mode 100644 index 9ccec358..00000000 --- a/pages/storageAdmin.js +++ /dev/null @@ -1,759 +0,0 @@ -import CookieBanner from "../components/cookieBanner"; -import Footer from "../components/footer"; -import Header from "../components/header"; -import { DefaultAzureCredential } from "@azure/identity"; -import { BlobServiceClient, ContainerClient } from "@azure/storage-blob"; -import { v4 as uuidv4 } from "uuid"; -import { - createContainerSas, - listContainers, - listBlobHierarchical, - listContainersForUser, -} from "../actions/azurestorage"; -import Head from "next/head"; -import Link from "next/link"; -import { PrismaClient } from "@prisma/client"; -import { - bytesToSize, - getThumbnailIconByExtension, - updateLinks, -} from "../components/utils"; -import { - consoleLogger, - getIP, - sendRepCompleteMessage, - deleteMyRepresentationsFromBlob, - deleteAwaitingSubmissionsFromBlob, -} from "../actions"; -import CryptoJS from "crypto-js"; -import { useState } from "react"; - -function getUpToLastSlash(url) { - let lastSlash = url.lastIndexOf("/"); - - url = url.substring(0, lastSlash); - - url = - url.lastIndexOf("/files") > 0 - ? url.substring(0, url.lastIndexOf("/files")) - : url; - return url; -} - -async function streamToString(readableStream) { - return new Promise((resolve, reject) => { - const chunks = []; - readableStream.on("data", (data) => { - chunks.push(data.toString()); - }); - readableStream.on("end", () => { - resolve(chunks.join("")); - }); - readableStream.on("error", reject); - }); -} - -function formatTimeSince(date) { - if (!date) return "Unknown date"; - - const now = new Date(); - const diffMs = now - date; - const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); - - if (diffDays < 7) { - return `${diffDays} day${diffDays !== 1 ? "s" : ""} ago`; - } else { - const diffWeeks = Math.floor(diffDays / 7); - return `${diffWeeks} week${diffWeeks !== 1 ? "s" : ""} ago`; - } -} - -function formatBlobDates(blob) { - const created = blob.createdOn ? new Date(blob.createdOn) : null; - const modified = blob.lastModified ? new Date(blob.lastModified) : null; - - if (!created && !modified) return "Unknown"; - - // If both exist and are the same - if (created && modified && created.getTime() === modified.getTime()) { - return `${created.toLocaleString("en-GB")} (${formatTimeSince( - created - )})`; - } - - // If modified exists and is newer than created - if (created && modified && modified.getTime() > created.getTime()) { - return `Created: ${created.toLocaleString("en-GB")} (${formatTimeSince( - created - )}), Modified: ${modified.toLocaleString("en-GB")} (${formatTimeSince( - modified - )})`; - } - - // Only one date exists - const date = modified || created; - return `${date.toLocaleString("en-GB")} (${formatTimeSince(date)})`; -} - -const deleteRepItem = (containerID, caseID, repfile) => { - deleteMyRepresentationsFromBlob(containerID, caseID, repfile).then( - (data) => { - console.log("======== rep deleted ========="); - return data; - } - ); -}; - -// const deleteCaseItem = (containerID, caseID) => { -// deleteAwaitingSubmissionsFromBlob(containerID, caseID).then((data) => { -// return data; -// }); -// }; - -const deleteCaseItem = async (containerID, caseID, setData) => { - const result = await deleteAwaitingSubmissionsFromBlob(containerID, caseID); - - if (result) { - setData((prevData) => - prevData.map((user) => ({ - ...user, - containers: user.containers.map((c) => - c.container === containerID - ? { - ...c, - folders: c.folders.filter( - (f) => f.folderPath !== caseID - ), - } - : c - ), - })) - ); - } -}; - -export default function StoragePage(props) { - const { userData, repCompleteCount } = props; - const [data, setData] = useState(props.data); - const [showRepJson, setShowRepJson] = useState(true); - const [showTmpFile, setShowTmpFile] = useState(true); - const [whichTab, setWhichTab] = useState("storage"); - - const toggleAll = () => { - const newState = !(showRepJson || showTmpFile); - setShowRepJson(newState); - setShowTmpFile(newState); - }; - return ( -
- - Storage Account Browser - -
- -
-
-
-
-

Contents

- -
-

Storage Account Contents

- {repCompleteCount > 0 && ( -

- Number of Orphaned Reps:{" "} - {repCompleteCount} -

- )} - - {/* Toggle buttons */} -
- - - -
- - {data.map((user) => ( -
- {user.containers.map((c) => ( -
-
-

- {c.container} -{" "} - -

- {folder.folderPath || - "Root"} -

- {/* {folder.hasRepJson && ( -

- rep.json file found:{" "} - {folder.repJsonBlob.name} -

- )} */} - {folder.hasTmpFile && ( - <> - - - )} - {folder.hasRepJson && ( -
- {" "} - - {folder.repComplete && ( - - )} - {folder.repComplete && ( - - )} -
- )} - -
    - {folder.blobs.map( - (blob) => ( -
  • - - { - blob.name - }{" "} - ( - {bytesToSize( - blob.contentLength || - blob.size - )} - - ) - {" "} - {blob.lastModified && ( - - {/* { - blob.displayDate - } */} - {formatBlobDates( - blob - )} - - )} -
  • - ) - )} -
-
- ))} -
-
- ))} -
- ))} -
-
-

User Accounts

-

- Number of accounts created:{" "} - {userData.length} -

-
-
-
- Name -
-
- Last accessed -
-
- - {userData.map((user) => ( -
-
- - Last accessed: {user.created}{" "} -
-
- ))} -
-
-
-
-
-
- - ); -} - -export async function getServerSideProps({ req }) { - // Load allowed IPs from env and trim spaces - const ALLOWED_IPS = process.env.ALLOWED_IPS - ? process.env.ALLOWED_IPS.split(",").map((ip) => ip.trim()) - : []; - - // Always allow localhost addresses - const LOCALHOST_IPS = ["127.0.0.1", "::1"]; - - // Get IP address from headers or socket - const forwarded = req.headers["x-forwarded-for"]; - const ip = - typeof forwarded === "string" - ? forwarded.split(",")[0] - : req.socket.remoteAddress; - - console.log("Visitor IP:", ip); - - // Check whitelist + localhost - if (![...ALLOWED_IPS, ...LOCALHOST_IPS].includes(ip)) { - return { - redirect: { - destination: "/403", // custom "Access Denied" page - permanent: false, - }, - }; - } - const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME; - - const creds = new DefaultAzureCredential(); - - const globalForPrisma = global; - - const prisma = globalForPrisma.prisma || new PrismaClient(); - - const blobServiceClient = new BlobServiceClient( - `https://${accountName}.blob.core.windows.net`, - creds - ); - - const users = await prisma.user.findMany(); - - const hashAPIPath = (queryPath, WORDKEY) => { - var hashlink = CryptoJS.HmacSHA256( - queryPath, - CryptoJS.enc.Hex.parse(WORDKEY) - ); - hashlink = hashlink.toString(CryptoJS.enc.Hex); - return hashlink; - }; - - let data = await Promise.all( - users.map(async (user) => { - const containers = await listContainersForUser( - blobServiceClient, - `${user.id}`, - user.email - ); - - const containersWithHashes = await Promise.all( - containers.map(async (container) => { - const groupedByFolder = await container.blobs.reduce( - async (accP, blob) => { - // Because we'll do async read, reduce needs to be async, so accP is a Promise - const acc = await accP; - - const folderPath = - getUpToLastSlash(blob.name.trim()) || ""; - - const hashedfilepath = hashAPIPath( - "/api/file/downloadblob?container=" + - container.container + - "&casefolderID=" + - folderPath + - "&blobname=" + - blob.name - .substring( - blob.name.lastIndexOf("/") + 1 - ) - .trim(), - process.env.HASHKEY - ); - - const fileNameOnly = blob.name.substring( - blob.name.lastIndexOf("/") + 1 - ); - const isTmpFile = fileNameOnly.startsWith("TMP-"); - - const blobWithHash = { - ...blob, - hashedfilepath, - isTmpFile, - }; - - let folderGroup = acc.find( - (f) => f.folderPath === folderPath - ); - if (!folderGroup) { - folderGroup = { - folderPath, - blobs: [], - hasRepJson: false, - repJsonBlob: null, - repComplete: false, - hasTmpFile: false, - }; - acc.push(folderGroup); - } - - folderGroup.blobs.push(blobWithHash); - - if (isTmpFile) { - folderGroup.hasTmpFile = true; - } - - // If this blob ends with rep.json, fetch and parse JSON - if (blob.name.toLowerCase().endsWith("rep.json")) { - folderGroup.hasRepJson = true; - folderGroup.repJsonBlob = blobWithHash; - - // Read blob content from Azure Storage - const containerClient = - blobServiceClient.getContainerClient( - container.container - ); - const blockBlobClient = - containerClient.getBlockBlobClient( - blob.name - ); - - try { - const downloadResponse = - await blockBlobClient.download(0); - const downloaded = await streamToString( - downloadResponse.readableStreamBody - ); - - const json = JSON.parse(downloaded); - folderGroup.repComplete = Boolean( - json.repComplete - ); - } catch (err) { - console.error( - "Error reading or parsing rep.json", - err - ); - folderGroup.repComplete = false; - } - } - - return acc; - }, - Promise.resolve([]) - ); - - return { - ...container, - folders: groupedByFolder, - }; - }) - ); - - return containersWithHashes.length > 0 - ? { - id: user.id, - email: user.email, - containers: containersWithHashes, - } - : null; - }) - ); - - let userData = await Promise.all( - users - .filter((user) => user.email && user.email.trim() !== "") - .map(async (user) => ({ - id: user.id, - email: user.email, - created: user.emailVerified?.toLocaleString("en-GB") || "", - })) - ); - - let repCompleteCount = 0; - - data = data.filter(Boolean); - - data.forEach((user) => { - user.containers.forEach((container) => { - container.folders.forEach((folder) => { - if (folder.repComplete === true) { - repCompleteCount++; - } - }); - }); - }); - - return { - props: { - data: data, - userData: userData, - repCompleteCount, - }, - }; -}