Merged PR 1813: ticket number not ref/title/pinswg_name

Related work items: #18356
This commit is contained in:
Robert Bond
2025-08-12 11:57:18 +00:00
5 changed files with 141 additions and 2 deletions
+42
View File
@@ -1693,3 +1693,45 @@ export const listBlobHierarchical = async (
}
}
};
export async function listBlobHierarchicalForUser(containerClient) {
const blobNames = [];
for await (const blob of containerClient.listBlobsFlat()) {
blobNames.push(blob.name);
}
return blobNames;
}
export async function listContainersForUser(
blobServiceClient,
containerNamePrefix,
emailAddress
) {
const options = {
includeDeleted: false,
includeMetadata: true,
includeSystem: true,
prefix: containerNamePrefix,
};
const results = [];
for await (const containerItem of blobServiceClient.listContainers(
options
)) {
const containerClient = blobServiceClient.getContainerClient(
containerItem.name
);
const blobNames = await listBlobHierarchicalForUser(
containerClient
).catch(console.error);
if (blobNames && blobNames.length > 0) {
results.push({
container: containerItem.name,
blobs: blobNames,
});
}
}
return results; // array of non-empty containers
}
+2
View File
@@ -62,6 +62,7 @@ let MakeRepresentation = (props) => {
showQuestionnaireSection,
initialValues,
setCurrentReference,
ticketnumber,
} = props;
const formObj = props.props.form;
let setCaseQueryObj = props[currentType] || {};
@@ -458,6 +459,7 @@ let MakeRepresentation = (props) => {
setSubmitBack={setSubmitBack}
props={props}
caseReference={caseReference}
ticketnumber={ticketnumber}
setRepFileName={setRepFileName}
updateRepresentation={updateRepresentation}
setSavingStatus={setSavingStatus}
@@ -34,6 +34,7 @@ let RepLPACapacitySelection = (props) => {
casesObj={casesObj}
detailsObj={detailsObj}
caseReference={props.props.caseReference}
ticketnumber={props.props.ticketnumber}
searchResultsObj={props.props.searchResultsObj}
props={props.props}
/>{" "}
@@ -8,7 +8,7 @@ const RepLPADetails = (props) => {
const router = useRouter();
const { locale } = router;
const { currentType, casesObj, caseReference } = props;
const { currentType, casesObj, caseReference, ticketnumber } = props;
let setCaseDetailsObj = router.query.hasOwnProperty("state")
? router.query.state == "edit"
@@ -21,7 +21,7 @@ const RepLPADetails = (props) => {
var detailsObj = {};
detailsObj = jsonpath({
path: '$..[?(@ && @.pinswg_name=="' + caseReference + '")]',
path: '$..[?(@ && @.ticketnumber=="' + ticketnumber + '")]',
json: setCaseDetailsObj,
eval: true,
});
+94
View File
@@ -0,0 +1,94 @@
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 { PrismaClient } from "@prisma/client";
import { consoleLogger, getIP } from "../actions";
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 data = await Promise.all(
users.map(async (user) => {
const containers = await listContainersForUser(
blobServiceClient,
`${user.id}`,
user.email
);
return containers.length > 0
? { id: user.id, email: user.email, containers }
: null;
})
);
return { props: { data: data.filter(Boolean) } };
}
export default function StoragePage({ data }) {
return (
<div>
<h1>Storage Account Contents</h1>
{data.map((user) => (
<div key={user.id}>
{user.containers.map((c) => (
<div key={c.container}>
<h3>
{c.container} - {user.email}
</h3>
<ul>
{c.blobs.map((blob) => (
<li key={blob}>{blob}</li>
))}
</ul>
</div>
))}
</div>
))}
</div>
);
}