fix: read-only permission

This commit is contained in:
Andras Bacsai 2023-01-10 10:15:03 +01:00
parent 395df36d57
commit 30cd2149ea
15 changed files with 135 additions and 83 deletions

View File

@ -1,6 +1,6 @@
<script lang="ts">
export let application: any;
import { status } from '$lib/store';
import { appSession, status } from '$lib/store';
import { page } from '$app/stores';
</script>
@ -220,7 +220,7 @@
<li class="menu-title">
<span>Advanced</span>
</li>
{#if application.gitSourceId}
{#if application.gitSourceId && $appSession.isAdmin}
<li
class="rounded"
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/revert`}
@ -295,6 +295,7 @@
>
</li>
{/if}
{#if $appSession.isAdmin}
<li
class="rounded"
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/danger`}
@ -318,4 +319,5 @@
</svg>Danger Zone</a
>
</li>
{/if}
</ul>

View File

@ -9,7 +9,7 @@
import { del, post, put } from '$lib/api';
import { errorNotification } from '$lib/common';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { addToast } from '$lib/store';
import { addToast, appSession } from '$lib/store';
import { t } from '$lib/translations';
import { createEventDispatcher } from 'svelte';
@ -120,6 +120,7 @@
<label for="name" class="pb-5 uppercase lg:block hidden font-bold" />
{/if}
{#if $appSession.isAdmin}
<div class="flex justify-center h-full items-center pt-3">
<div class="flex flex-row justify-center space-x-2">
<div class="flex items-center justify-center">
@ -127,5 +128,6 @@
</div>
</div>
</div>
{/if}
</div>
</div>

View File

@ -10,7 +10,7 @@
import { del, post, put } from '$lib/api';
import { errorNotification } from '$lib/common';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { addToast } from '$lib/store';
import { addToast, appSession } from '$lib/store';
import { t } from '$lib/translations';
import { createEventDispatcher } from 'svelte';
@ -124,8 +124,9 @@
<div class="flex justify-center h-full items-center pt-0 lg:pt-0 pl-4 lg:pl-0">
<button
on:click={() => updateSecret({ changeIsBuildSecret: true })}
disabled={!$appSession.isAdmin}
aria-pressed="false"
class="relative inline-flex h-6 w-11 flex-shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out "
class="relative inline-flex h-6 w-11 flex-shrink-0 rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out"
class:bg-green-600={isBuildSecret}
class:bg-stone-700={!isBuildSecret}
>
@ -177,7 +178,7 @@
<div class="flex items-center justify-center">
<button class="btn btn-sm btn-primary" on:click={addNewSecret}>Add</button>
</div>
{:else}
{:else if $appSession.isAdmin}
<div class="flex flex-row justify-center space-x-2">
<div class="flex items-center justify-center">
<button class="btn btn-sm btn-primary" on:click={() => updateSecret()}>Set</button>

View File

@ -51,6 +51,7 @@
let isDBBranching = application.settings.isDBBranching;
async function changeSettings(name: any) {
if (!$appSession.isAdmin) return
if (name === 'previews') {
previews = !previews;
}
@ -119,6 +120,7 @@
id="autodeploy"
isCenter={false}
bind:setting={autodeploy}
disabled={!$appSession.isAdmin}
on:click={() => changeSettings('autodeploy')}
title={$t('application.enable_automatic_deployment')}
description={$t('application.enable_auto_deploy_webhooks')}
@ -130,6 +132,7 @@
id="previews"
isCenter={false}
bind:setting={previews}
disabled={!$appSession.isAdmin}
on:click={() => changeSettings('previews')}
title={$t('application.enable_mr_pr_previews')}
description={$t('application.enable_preview_deploy_mr_pr_requests')}

View File

@ -490,7 +490,7 @@
<div class="grid grid-flow-row gap-2 px-4">
<div class="mt-2 grid grid-cols-2 items-center">
<label for="name">{$t('forms.name')}</label>
<input name="name" id="name" class="w-full" bind:value={application.name} required />
<input name="name" id="name" class="w-full" bind:value={application.name} disabled={!$appSession.isAdmin} required />
</div>
{#if !isSimpleDockerfile}
<div class="grid grid-cols-2 items-center">

View File

@ -23,7 +23,7 @@
import { goto } from '$app/navigation';
import { asyncSleep, errorNotification, getRndInteger } from '$lib/common';
import { onDestroy, onMount } from 'svelte';
import { addToast } from '$lib/store';
import { addToast, appSession } from '$lib/store';
import Tooltip from '$lib/components/Tooltip.svelte';
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
@ -264,6 +264,7 @@
{:else}
<button
id="restart"
disabled={!$appSession.isAdmin}
on:click={() => restartPreview(preview)}
type="submit"
class="icons bg-transparent text-sm flex items-center space-x-2"
@ -286,7 +287,12 @@
{/if}
<Tooltip triggeredBy="#restart">Restart (useful to change secrets)</Tooltip>
<button id="forceredeploypreview" class="icons" on:click={() => redeploy(preview)}>
<button
id="forceredeploypreview"
class="icons"
disabled={!$appSession.isAdmin}
on:click={() => redeploy(preview)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
@ -310,7 +316,7 @@
id="deletepreview"
class="icons"
class:hover:text-error={!loading.removing}
disabled={loading.removing}
disabled={loading.removing || !$appSession.isAdmin}
on:click={() => removeApplication(preview)}
><DeleteIcon />
</button>

View File

@ -25,7 +25,7 @@
import pLimit from 'p-limit';
import { page } from '$app/stores';
import { get, post, put } from '$lib/api';
import { addToast } from '$lib/store';
import { addToast, appSession } from '$lib/store';
import Secret from './_Secret.svelte';
import PreviewSecret from './_PreviewSecret.svelte';
import { errorNotification } from '$lib/common';
@ -106,46 +106,50 @@
/>
{/key}
{/each}
<div class="lg:pt-0 pt-10">
<Secret on:refresh={refreshSecrets} length={secrets.length} isNewSecret />
</div>
{#if !application.settings.isBot && !application.simpleDockerfile}
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2">
<div class="title font-bold pb-3 pt-8">
Preview Secrets <Explainer
explanation="These values overwrite application secrets in PR/MR deployments. <br>Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."
/>
{#if $appSession.isAdmin}
<div class="lg:pt-0 pt-10">
<Secret on:refresh={refreshSecrets} length={secrets.length} isNewSecret />
</div>
</div>
{#if previewSecrets.length !== 0}
{#each previewSecrets as secret, index}
{#key index}
<PreviewSecret
{index}
length={secrets.length}
name={secret.name}
value={secret.value}
isBuildSecret={secret.isBuildSecret}
on:refresh={refreshSecrets}
/>
{/key}
{/each}
{:else}
Add secrets first to see Preview Secrets.
{/if}
{#if !application.settings.isBot && !application.simpleDockerfile}
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2">
<div class="title font-bold pb-3 pt-8">
Preview Secrets <Explainer
explanation="These values overwrite application secrets in PR/MR deployments. <br>Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."
/>
</div>
</div>
{#if previewSecrets.length !== 0}
{#each previewSecrets as secret, index}
{#key index}
<PreviewSecret
{index}
length={secrets.length}
name={secret.name}
value={secret.value}
isBuildSecret={secret.isBuildSecret}
on:refresh={refreshSecrets}
/>
{/key}
{/each}
{:else}
Add secrets first to see Preview Secrets.
{/if}
{/if}
</div>
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2 pt-10">
<div class="flex flex-row space-x-2">
<div class="title font-bold pb-3 ">Paste <code>.env</code> file</div>
<button type="submit" class="btn btn-sm bg-primary">Add Secrets in Batch</button>
{#if $appSession.isAdmin}
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2 pt-10">
<div class="flex flex-row space-x-2">
<div class="title font-bold pb-3 ">Paste <code>.env</code> file</div>
<button type="submit" class="btn btn-sm bg-primary">Add Secrets in Batch</button>
</div>
</div>
</div>
<textarea
placeholder={`PORT=1337\nPASSWORD=supersecret`}
bind:value={batchSecrets}
class="mb-2 min-h-[200px] w-full"
/>
</form>
<textarea
placeholder={`PORT=1337\nPASSWORD=supersecret`}
bind:value={batchSecrets}
class="mb-2 min-h-[200px] w-full"
/>
</form>
{/if}

View File

@ -27,6 +27,7 @@
import { get } from '$lib/api';
import { t } from '$lib/translations';
import Explainer from '$lib/components/Explainer.svelte';
import { appSession } from '$lib/store';
let composeJson = JSON.parse(application?.dockerComposeFile || '{}');
let predefinedVolumes: any[] = [];
@ -86,12 +87,16 @@
<Storage on:refresh={refreshStorage} {storage} />
{/key}
{/each}
<div class="Preview Secrets" class:pt-10={predefinedVolumes.length > 0}>
{#if $appSession.isAdmin}
<div class:pt-10={predefinedVolumes.length > 0}>
Add New Volume <Explainer
position="dropdown-bottom"
explanation={$t('application.storage.persistent_storage_explainer')}
/>
</div>
<Storage on:refresh={refreshStorage} isNew />
{}
{/if}
</div>
</div>

View File

@ -669,7 +669,7 @@
<button class="btn btn-sm btn-primary" on:click={refreshStatusApplications}
>{noInitialStatus.applications ? 'Load Status' : 'Refresh Status'}</button
>
{#if foundUnconfiguredApplication}
{#if foundUnconfiguredApplication && $appSession.isAdmin}
<button
class="btn btn-sm"
class:loading={loading.applications}
@ -783,11 +783,13 @@
</svg>
</a>
{/if}
{#if $appSession.isAdmin}
<button
class="icons hover:bg-green-500"
on:click|stopPropagation|preventDefault={() =>
deleteApplication(application.id)}><DeleteIcon /></button
>
{/if}
</div>
</div>
</div>
@ -896,11 +898,13 @@
</svg>
</a>
{/if}
{#if $appSession.isAdmin}
<button
class="icons hover:bg-green-500"
on:click|stopPropagation|preventDefault={() =>
deleteApplication(application.id)}><DeleteIcon /></button
>
{/if}
</div>
</div>
</div>
@ -991,11 +995,13 @@
</svg>
</a>
{/if}
{#if $appSession.isAdmin}
<button
class="icons hover:bg-pink-500"
on:click|stopPropagation|preventDefault={() => deleteService(service.id)}
><DeleteIcon /></button
>
{/if}
</div>
</div>
</div>
@ -1077,11 +1083,13 @@
</svg>
</a>
{/if}
{#if $appSession.isAdmin}
<button
class="icons hover:bg-pink-500"
on:click|stopPropagation|preventDefault={() => deleteService(service.id)}
><DeleteIcon /></button
>
{/if}
</div>
</div>
</div>
@ -1173,11 +1181,13 @@
</svg>
</div>
{/if}
{#if $appSession.isAdmin}
<button
class="icons hover:bg-databases-100"
on:click|stopPropagation|preventDefault={() => deleteDatabase(database.id)}
><DeleteIcon /></button
>
{/if}
</div>
</div>
</div>
@ -1259,11 +1269,13 @@
</svg>
</div>
{/if}
{#if $appSession.isAdmin}
<button
class="icons hover:bg-databases"
on:click|stopPropagation|preventDefault={() => deleteDatabase(database.id)}
><DeleteIcon /></button
>
{/if}
</div>
</div>
</div>

View File

@ -2,6 +2,7 @@
export let service: any;
export let template: any;
import { page } from '$app/stores';
import { appSession } from '$lib/store';
import ServiceLinks from './_ServiceLinks.svelte';
</script>
@ -106,6 +107,7 @@
</svg>Service</a
>
</li>
{#if $appSession.isAdmin}
<li class="menu-title">
<span>Advanced</span>
</li>
@ -132,4 +134,5 @@
</svg>Danger Zone</a
>
</li>
{/if}
</ul>

View File

@ -8,7 +8,7 @@
import { del, post } from '$lib/api';
import { errorNotification } from '$lib/common';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { addToast } from '$lib/store';
import { addToast, appSession } from '$lib/store';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
@ -77,6 +77,7 @@
/>
</td>
{#if $appSession.isAdmin}
<td>
{#if isNewSecret}
<div class="flex items-center justify-center">
@ -93,3 +94,4 @@
</div>
{/if}
</td>
{/if}

View File

@ -165,6 +165,7 @@
}
}
async function changeSettings(name: any) {
if (!$appSession.isAdmin) return
try {
if (name === 'dualCerts') {
dualCerts = !dualCerts;
@ -277,7 +278,7 @@
<div class="grid grid-flow-row gap-2 px-4">
<div class="mt-2 grid grid-cols-2 items-center">
<label for="name">{$t('forms.name')}</label>
<input name="name" id="name" class="w-full" bind:value={service.name} required />
<input name="name" id="name" class="w-full" disabled={!$appSession.isAdmin} bind:value={service.name} required />
</div>
<div class="grid grid-cols-2 items-center">
<label for="version">Version / Tag</label>
@ -386,7 +387,7 @@
<div class="grid grid-cols-2 items-center">
<Setting
id="dualCerts"
disabled={$status.service.isRunning}
disabled={$status.service.isRunning || !$appSession.isAdmin}
dataTooltip={$t('forms.must_be_stopped_to_modify')}
bind:setting={dualCerts}
title={$t('application.ssl_www_and_non_www')}

View File

@ -25,7 +25,7 @@
import { get } from '$lib/api';
import { t } from '$lib/translations';
import pLimit from 'p-limit';
import { addToast } from '$lib/store';
import { addToast, appSession } from '$lib/store';
import { saveSecret } from './utils';
const limit = pLimit(1);
@ -83,7 +83,12 @@
{#each secrets as secret}
{#key secret.id}
<tr>
<Secret name={secret.name} value={secret.value} readonly={secret.readOnly} on:refresh={refreshSecrets} />
<Secret
name={secret.name}
value={secret.value}
readonly={secret.readOnly}
on:refresh={refreshSecrets}
/>
</tr>
{/key}
{/each}
@ -93,18 +98,20 @@
</tbody>
</table>
</div>
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2 pt-10">
<div class="flex flex-row space-x-2">
<div class="title font-bold pb-3 ">Paste <code>.env</code> file</div>
<button type="submit" class="btn btn-sm bg-primary">Add Secrets in Batch</button>
{#if $appSession.isAdmin}
<form on:submit|preventDefault={getValues} class="mb-12 w-full">
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2 pt-10">
<div class="flex flex-row space-x-2">
<div class="title font-bold pb-3 ">Paste <code>.env</code> file</div>
<button type="submit" class="btn btn-sm bg-primary">Add Secrets in Batch</button>
</div>
</div>
</div>
<textarea
placeholder={`PORT=1337\nPASSWORD=supersecret`}
bind:value={batchSecrets}
class="mb-2 min-h-[200px] w-full"
/>
</form>
<textarea
placeholder={`PORT=1337\nPASSWORD=supersecret`}
bind:value={batchSecrets}
class="mb-2 min-h-[200px] w-full"
/>
</form>
{/if}
</div>

View File

@ -26,6 +26,7 @@
import { get } from '$lib/api';
import { t } from '$lib/translations';
import Explainer from '$lib/components/Explainer.svelte';
import { appSession } from '$lib/store';
const { id } = $page.params;
async function refreshStorage() {
@ -81,10 +82,11 @@
{/key}
{/each}
{/if}
<div class="title" class:pt-10={persistentStorages.filter((s) => s.predefined).length > 0}>
Add New Volume
</div>
<Storage on:refresh={refreshStorage} isNew {services} />
{#if $appSession.isAdmin}
<div class="title" class:pt-10={persistentStorages.filter((s) => s.predefined).length > 0}>
Add New Volume
</div>
<Storage on:refresh={refreshStorage} isNew {services} />
{/if}
</div>
</div>

View File

@ -190,7 +190,7 @@
id="name"
required
bind:value={source.name}
disabled={$appSession.teamId !== '0'}
disabled={!$appSession.isAdmin}
/>
<label for="htmlUrl">HTML URL</label>
<input
@ -236,16 +236,18 @@
placeholder="eg: coollabsio"
bind:value={source.organization}
/>
<Setting
customClass="pt-4"
id="autodeploy"
isCenter={false}
disabled={$appSession.teamId !== '0'}
bind:setting={source.isSystemWide}
on:click={() => changeSettings('isSystemWide', true)}
title="System Wide Git Source"
description="System Wide Git Sources are available to all the users in your Coolify instance. <br><br> <span class='font-bold text-warning'>Use with caution, as it can be a security risk.</span>"
/>
{#if $appSession.isAdmin}
<Setting
customClass="pt-4"
id="autodeploy"
isCenter={false}
disabled={$appSession.teamId !== '0'}
bind:setting={source.isSystemWide}
on:click={() => changeSettings('isSystemWide', true)}
title="System Wide Git Source"
description="System Wide Git Sources are available to all the users in your Coolify instance. <br><br> <span class='font-bold text-warning'>Use with caution, as it can be a security risk.</span>"
/>
{/if}
</div>
</form>
{:else}