#!/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: '\\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."