Merge branch 'v2.3.0' of github.com:coollabsio/coolify into v2.3.0
This commit is contained in:
commit
01e0fb70c9
@ -80,6 +80,7 @@
|
|||||||
"jsonwebtoken": "8.5.1",
|
"jsonwebtoken": "8.5.1",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
"node-forge": "1.3.0",
|
"node-forge": "1.3.0",
|
||||||
|
"p-limit": "^4.0.0",
|
||||||
"svelte-kit-cookie-session": "2.1.2",
|
"svelte-kit-cookie-session": "2.1.2",
|
||||||
"tailwindcss-scrollbar": "^0.1.0",
|
"tailwindcss-scrollbar": "^0.1.0",
|
||||||
"unique-names-generator": "4.7.1"
|
"unique-names-generator": "4.7.1"
|
||||||
|
@ -144,7 +144,7 @@
|
|||||||
{#if logs.length === 0}
|
{#if logs.length === 0}
|
||||||
<div class="text-xl font-bold tracking-tighter">Waiting for the logs...</div>
|
<div class="text-xl font-bold tracking-tighter">Waiting for the logs...</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="relative">
|
<div class="relative w-full">
|
||||||
<LoadingLogs />
|
<LoadingLogs />
|
||||||
<div class="flex justify-end sticky top-0 p-2">
|
<div class="flex justify-end sticky top-0 p-2">
|
||||||
<button
|
<button
|
||||||
@ -172,7 +172,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 py-5 px-6 whitespace-pre-wrap break-words overflow-auto max-h-[80vh] -mt-12 overflow-y-scroll scrollbar-w-1 scrollbar-thumb-coollabs scrollbar-track-coolgray-200"
|
class="font-mono w-full leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 py-5 px-6 whitespace-pre-wrap break-words overflow-auto max-h-[80vh] -mt-12 overflow-y-scroll scrollbar-w-1 scrollbar-thumb-coollabs scrollbar-track-coolgray-200"
|
||||||
bind:this={logsEl}
|
bind:this={logsEl}
|
||||||
>
|
>
|
||||||
<div class="px-2">
|
<div class="px-2">
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: res.status,
|
status: res.status,
|
||||||
error: new Error(`Could not load ${endpoint}`)
|
error: new Error(`Could not load ${endpoint}`)
|
||||||
@ -31,6 +30,7 @@
|
|||||||
import Explainer from '$lib/components/Explainer.svelte';
|
import Explainer from '$lib/components/Explainer.svelte';
|
||||||
import { errorNotification } from '$lib/form';
|
import { errorNotification } from '$lib/form';
|
||||||
import { toast } from '@zerodevx/svelte-toast';
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
|
import BatchSecrets from '../secrets/_BatchSecrets.svelte';
|
||||||
|
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
async function refreshSecrets() {
|
async function refreshSecrets() {
|
||||||
@ -183,3 +183,4 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<BatchSecrets secrets={PRMRSecrets} {id} {refreshSecrets} />
|
||||||
|
48
src/routes/applications/[id]/secrets/_BatchSecrets.svelte
Normal file
48
src/routes/applications/[id]/secrets/_BatchSecrets.svelte
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<script>
|
||||||
|
export let secrets;
|
||||||
|
export let refreshSecrets;
|
||||||
|
export let id;
|
||||||
|
|
||||||
|
import { saveSecret } from './utils';
|
||||||
|
import pLimit from 'p-limit';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
let batchSecrets = '';
|
||||||
|
function setBatchValue(event) {
|
||||||
|
batchSecrets = event.target?.value;
|
||||||
|
}
|
||||||
|
const limit = pLimit(1);
|
||||||
|
async function getValues(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const eachValuePair = batchSecrets.split('\n');
|
||||||
|
const batchSecretsPairs = eachValuePair
|
||||||
|
.filter((secret) => !secret.startsWith('#') && secret)
|
||||||
|
.map((secret) => {
|
||||||
|
const [name, value] = secret.split('=');
|
||||||
|
const cleanValue = value?.replaceAll('"', '') || '';
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
value: cleanValue,
|
||||||
|
isNew: !secrets.find((secret) => name === secret.name)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
batchSecretsPairs.map(({ name, value, isNew }) =>
|
||||||
|
limit(() => saveSecret({ name, value, applicationId: id, isNew, dispatch }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
batchSecrets = '';
|
||||||
|
refreshSecrets();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h2 class="title my-6 font-bold">Paste .env file</h2>
|
||||||
|
<form on:submit={getValues} class="mb-12 w-full">
|
||||||
|
<textarea value={batchSecrets} on:change={setBatchValue} class="mb-2 min-h-[200px] w-full" />
|
||||||
|
<button
|
||||||
|
class="bg-green-600 hover:bg-green-500 disabled:text-white disabled:opacity-40"
|
||||||
|
type="submit">Batch add secrets</button
|
||||||
|
>
|
||||||
|
</form>
|
@ -9,11 +9,11 @@
|
|||||||
if (isPRMRSecret) value = PRMRSecret.value;
|
if (isPRMRSecret) value = PRMRSecret.value;
|
||||||
|
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { del, post } from '$lib/api';
|
import { del } from '$lib/api';
|
||||||
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||||
import { errorNotification } from '$lib/form';
|
import { errorNotification } from '$lib/form';
|
||||||
import { toast } from '@zerodevx/svelte-toast';
|
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import { saveSecret } from './utils';
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
@ -30,28 +30,20 @@
|
|||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function saveSecret(isNew = false) {
|
|
||||||
if (!name) return errorNotification('Name is required.');
|
async function createSecret(isNew) {
|
||||||
if (!value) return errorNotification('Value is required.');
|
saveSecret({
|
||||||
try {
|
isNew,
|
||||||
await post(`/applications/${id}/secrets.json`, {
|
name,
|
||||||
name,
|
value,
|
||||||
value,
|
isBuildSecret,
|
||||||
isBuildSecret,
|
isPRMRSecret,
|
||||||
isPRMRSecret,
|
isNewSecret,
|
||||||
isNew
|
applicationId: id,
|
||||||
});
|
dispatch
|
||||||
dispatch('refresh');
|
});
|
||||||
if (isNewSecret) {
|
|
||||||
name = '';
|
|
||||||
value = '';
|
|
||||||
isBuildSecret = false;
|
|
||||||
}
|
|
||||||
toast.push('Secret saved.');
|
|
||||||
} catch ({ error }) {
|
|
||||||
return errorNotification(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSecretValue() {
|
function setSecretValue() {
|
||||||
if (isNewSecret) {
|
if (isNewSecret) {
|
||||||
isBuildSecret = !isBuildSecret;
|
isBuildSecret = !isBuildSecret;
|
||||||
@ -133,12 +125,14 @@
|
|||||||
<td>
|
<td>
|
||||||
{#if isNewSecret}
|
{#if isNewSecret}
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<button class="bg-green-600 hover:bg-green-500" on:click={() => saveSecret(true)}>Add</button>
|
<button class="bg-green-600 hover:bg-green-500" on:click={() => createSecret(true)}
|
||||||
|
>Add</button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex flex-row justify-center space-x-2">
|
<div class="flex flex-row justify-center space-x-2">
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<button class="" on:click={() => saveSecret(false)}>Set</button>
|
<button class="" on:click={() => createSecret(false)}>Set</button>
|
||||||
</div>
|
</div>
|
||||||
{#if !isPRMRSecret}
|
{#if !isPRMRSecret}
|
||||||
<div class="flex justify-center items-end">
|
<div class="flex justify-center items-end">
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { getTeam, getUserDetails } from '$lib/common';
|
import { getUserDetails } from '$lib/common';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const get: RequestHandler = async (event) => {
|
export const get: RequestHandler = async (event) => {
|
||||||
const { teamId, status, body } = await getUserDetails(event);
|
const { status, body } = await getUserDetails(event);
|
||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
@ -24,7 +24,7 @@ export const get: RequestHandler = async (event) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
const { teamId, status, body } = await getUserDetails(event);
|
const { status, body } = await getUserDetails(event);
|
||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
@ -53,7 +53,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const del: RequestHandler = async (event) => {
|
export const del: RequestHandler = async (event) => {
|
||||||
const { teamId, status, body } = await getUserDetails(event);
|
const { status, body } = await getUserDetails(event);
|
||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { get } from '$lib/api';
|
import { get } from '$lib/api';
|
||||||
|
import BatchSecrets from './_BatchSecrets.svelte';
|
||||||
|
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
|
|
||||||
@ -133,4 +134,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<BatchSecrets {secrets} {id} {refreshSecrets} />
|
||||||
</div>
|
</div>
|
||||||
|
46
src/routes/applications/[id]/secrets/utils.ts
Normal file
46
src/routes/applications/[id]/secrets/utils.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
|
import { errorNotification } from '$lib/form';
|
||||||
|
import { post } from '$lib/api';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isNew: boolean;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
isBuildSecret?: boolean;
|
||||||
|
isPRMRSecret?: boolean;
|
||||||
|
isNewSecret?: boolean;
|
||||||
|
applicationId: string;
|
||||||
|
dispatch: (name: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function saveSecret({
|
||||||
|
isNew,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret,
|
||||||
|
isNewSecret,
|
||||||
|
applicationId,
|
||||||
|
dispatch
|
||||||
|
}: Props): Promise<void> {
|
||||||
|
if (!name) return errorNotification('Name is required.');
|
||||||
|
if (!value) return errorNotification('Value is required.');
|
||||||
|
try {
|
||||||
|
await post(`/applications/${applicationId}/secrets.json`, {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret,
|
||||||
|
isNew: isNew || false
|
||||||
|
});
|
||||||
|
dispatch('refresh');
|
||||||
|
if (isNewSecret) {
|
||||||
|
name = '';
|
||||||
|
value = '';
|
||||||
|
isBuildSecret = false;
|
||||||
|
}
|
||||||
|
toast.push('Secret saved.');
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user