csp: allow multiple lines and add presets

This commit is contained in:
Girish Ramakrishnan
2026-01-13 17:38:31 +01:00
parent b9ea1573ea
commit a1b4fdf624
18 changed files with 56 additions and 59 deletions
+24 -8
View File
@@ -12,16 +12,16 @@ const props = defineProps([ 'app' ]);
const appsModel = AppsModel.create();
function addRobotsTxtPreset(pattern) {
if (robotsTxt.value) robotsTxt.value += '\n';
robotsTxt.value += pattern;
}
const busy = ref(false);
const robotsTxt = ref('');
const csp = ref('');
const hstsPreload = ref(false);
function addRobotsTxtPreset(pattern) {
if (robotsTxt.value) robotsTxt.value += '\n';
robotsTxt.value += pattern;
}
const commonRobotsTxtMenu = [
{ label: t('app.security.robots.commonPattern.allowAll'), action: () => addRobotsTxtPreset('# Allow all\nUser-agent: *\nDisallow:') },
{ label: t('app.security.robots.commonPattern.disallowAll'), action: () => addRobotsTxtPreset('# Disable search engine indexing\n\nUser-agent: *\nDisallow: /') },
@@ -30,6 +30,19 @@ const commonRobotsTxtMenu = [
{ label: t('app.security.robots.commonPattern.disallowApiPaths'), action: () => addRobotsTxtPreset('# Disallow API paths\nUser-agent: *\nDisallow: /api/\nDisallow: /v1/\nDisallow: /v2/') },
];
function addCspPreset(pattern) {
if (csp.value) csp.value += '\n';
csp.value += pattern;
}
const commonCspMenu = [
{ label: t('app.security.csp.commonPattern.allowEmbedding'), action: () => addCspPreset("# Allow embedding from all sites\ndefault-src 'self';\nframe-ancestors 'none';") },
{ label: t('app.security.csp.commonPattern.sameOriginEmbedding'), action: () => addCspPreset("# Allow embedding from subdomains\ndefault-src 'self';\nframe-ancestors 'self';") },
{ label: t('app.security.csp.commonPattern.allowCdnAssets'), action: () => addCspPreset("# Allow CDN assets\ndefault-src 'self';\nscript-src 'self' https://cdn.example.com;\nstyle-src 'self' https://cdn.example.com;\nimg-src 'self' data: https://cdn.example.com;\nfont-src 'self' https://cdn.example.com;\nobject-src 'none';\nframe-ancestors 'none';") },
{ label: t('app.security.csp.commonPattern.reportOnly'), action: () => addCspPreset("# Report violations. A POST request will be sent to URL below\ndefault-src 'self';\nreport-uri /csp-report;") },
{ label: t('app.security.csp.commonPattern.strictBaseline'), action: () => addCspPreset("# Secure CSP that restricts all resources to the same origin\ndefault-src 'self';\nbase-uri 'self';\nobject-src 'none';\nframe-ancestors 'none';\nform-action 'self';\nscript-src 'self';\nstyle-src 'self';\nimg-src 'self' data:;\nfont-src 'self';\nconnect-src 'self';\nmedia-src 'self';\nframe-src 'self';\nworker-src 'self';\nmanifest-src 'self';") },
];
async function onSubmit() {
busy.value = true;
@@ -65,13 +78,16 @@ onMounted(() => {
<Button small outline :menu="commonRobotsTxtMenu">{{ $t('app.security.robots.insertCommonRobotsTxt') }}</Button>
</label>
<div description>{{ $t('app.security.robots.description') }}</div>
<textarea id="robotsTxtInput" style="white-space: pre-wrap; font-family: monospace;" v-model="robotsTxt" rows="10"></textarea>
<textarea id="robotsTxtInput" spellcheck="false" style="white-space: pre-wrap; font-family: monospace;" v-model="robotsTxt" rows="10"></textarea>
</FormGroup>
<FormGroup>
<label for="cspInput">{{ $t('app.security.csp.title') }} <sup><a href="https://docs.cloudron.io/apps/#custom-csp" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup> </label>
<label for="cspInput" style="display: flex; justify-content: space-between;">
<span>{{ $t('app.security.csp.title') }} <sup><a href="https://docs.cloudron.io/apps/#custom-csp" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></span>
<Button small outline :menu="commonCspMenu">{{ $t('app.security.csp.insertCommonCsp') }}</Button>
</label>
<div description>{{ $t('app.security.csp.description') }}</div>
<textarea id="cspInput" style="white-space: pre-wrap; font-family: monospace;" v-model="csp" placeholder="default-src 'self'; frame-ancestors 'none';" rows="2"></textarea>
<textarea id="cspInput" spellcheck="false" style="white-space: pre-wrap; font-family: monospace;" v-model="csp" rows="5"></textarea>
</FormGroup>
<FormGroup>