Files
at-mintel/scripts/patch-cms.sh
2026-02-21 19:08:06 +01:00

117 lines
5.0 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONTAINERS=("cms-infra-infra-cms-1" "at-mintel-directus-1")
echo "🔧 Checking for Directus containers to patch..."
for CONTAINER in "${CONTAINERS[@]}"; do
if [ "$(docker ps -q -f name=^/${CONTAINER}$)" ]; then
echo "🔧 Applying core patches to: $CONTAINER..."
# Capture output to determine if restart is needed
OUTPUT=$(docker exec -i "$CONTAINER" node << 'EOF'
const fs = require("node:fs");
const { execSync } = require("node:child_process");
let patched = false;
try {
// 1. Patch @directus/extensions node.js (Entrypoints)
const findNodeCmd = "find /directus/node_modules -path \"*/@directus/extensions/dist/node.js\"";
const nodePaths = execSync(findNodeCmd).toString().trim().split("\n").filter(Boolean);
nodePaths.forEach(targetPath => {
let content = fs.readFileSync(targetPath, "utf8");
let modified = false;
const filterPatch = 'extension.host === "app" && (extension.entrypoint.app || extension.entrypoint)';
// Only replace if the OLD pattern exists
if (content.includes('extension.host === "app" && !!extension.entrypoint.app')) {
content = content.replace(/extension\.host === "app" && !!extension\.entrypoint\.app/g, filterPatch);
modified = true;
}
// Only replace if the OLD pattern exists for entrypoint
// We check if "extension.entrypoint.app" is present but NOT part of our patch
// This is a simple heuristic: if the patch string is NOT present, but the target IS.
if (!content.includes("(extension.entrypoint.app || extension.entrypoint)")) {
if (content.includes("extension.entrypoint.app")) {
content = content.replace(/extension\.entrypoint\.app/g, "(extension.entrypoint.app || extension.entrypoint)");
modified = true;
}
}
if (modified) {
fs.writeFileSync(targetPath, content);
console.log(`✅ Entrypoint patched.`);
patched = true;
}
});
// 2. Patch @directus/api manager.js (HTML Injection)
const findManagerCmd = "find /directus/node_modules -path \"*/@directus/api/dist/extensions/manager.js\"";
const managerPaths = execSync(findManagerCmd).toString().trim().split("\n").filter(Boolean);
managerPaths.forEach(targetPath => {
let content = fs.readFileSync(targetPath, "utf8");
const original = "head: wrapEmbeds('Custom Embed Head', this.hookEmbedsHead),";
const injection = "head: '<script type=\"module\" src=\"/extensions/sources/index.js\"></script>\\n' + wrapEmbeds('Custom Embed Head', this.hookEmbedsHead),";
if (content.includes(original) && !content.includes("/extensions/sources/index.js")) {
content = content.replace(original, injection);
fs.writeFileSync(targetPath, content);
console.log(`✅ Injection patched.`);
patched = true;
}
});
// 3. Patch @directus/api app.js (CSP for unsafe-inline)
const findAppCmd = "find /directus/node_modules -path \"*/@directus/api/dist/app.js\"";
const appPaths = execSync(findAppCmd).toString().trim().split("\n").filter(Boolean);
appPaths.forEach(targetPath => {
let content = fs.readFileSync(targetPath, "utf8");
let modified = false;
const original = "scriptSrc: [\"'self'\", \"'unsafe-eval'\"],";
const patchedStr = "scriptSrc: [\"'self'\", \"'unsafe-eval'\", \"'unsafe-inline'\"],";
if (content.includes(original)) {
content = content.replace(original, patchedStr);
modified = true;
}
if (modified) {
fs.writeFileSync(targetPath, content);
console.log(`✅ CSP patched in app.js.`);
patched = true;
}
});
if (patched) process.exit(100); // Signal restart needed
} catch (error) {
console.error("❌ Error applying patch:", error.message);
process.exit(1);
}
EOF
)
EXIT_CODE=$?
echo "$OUTPUT"
if [ $EXIT_CODE -eq 100 ]; then
echo "🔄 Patches applied. Restarting Directus container: $CONTAINER..."
docker restart "$CONTAINER"
else
echo "✅ Container $CONTAINER is already patched. No restart needed."
fi
else
echo " Container $CONTAINER not found. Skipping."
fi
done
echo "✨ All patches check complete."