Merge pull request #277 from SaraVieira/allow-paste-env

feat: Add ability to paste env files
This commit is contained in:
Andras Bacsai 2022-04-02 23:52:53 +02:00 committed by GitHub
commit 6ac54e17f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 125 additions and 32 deletions

View File

@ -80,6 +80,7 @@
"jsonwebtoken": "8.5.1",
"mustache": "^4.2.0",
"node-forge": "1.3.0",
"p-limit": "^4.0.0",
"svelte-kit-cookie-session": "2.1.2",
"tailwindcss-scrollbar": "^0.1.0",
"unique-names-generator": "4.7.1"

View File

@ -144,7 +144,7 @@
{#if logs.length === 0}
<div class="text-xl font-bold tracking-tighter">Waiting for the logs...</div>
{:else}
<div class="relative">
<div class="relative w-full">
<LoadingLogs />
<div class="flex justify-end sticky top-0 p-2">
<button
@ -172,7 +172,7 @@
</button>
</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}
>
<div class="px-2">

View File

@ -11,7 +11,6 @@
}
};
}
return {
status: res.status,
error: new Error(`Could not load ${endpoint}`)
@ -31,6 +30,7 @@
import Explainer from '$lib/components/Explainer.svelte';
import { errorNotification } from '$lib/form';
import { toast } from '@zerodevx/svelte-toast';
import BatchSecrets from '../secrets/_BatchSecrets.svelte';
const { id } = $page.params;
async function refreshSecrets() {
@ -183,3 +183,4 @@
{/if}
</div>
</div>
<BatchSecrets secrets={PRMRSecrets} {id} {refreshSecrets} />

View 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>

View File

@ -9,11 +9,11 @@
if (isPRMRSecret) value = PRMRSecret.value;
import { page } from '$app/stores';
import { del, post } from '$lib/api';
import { del } from '$lib/api';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { errorNotification } from '$lib/form';
import { toast } from '@zerodevx/svelte-toast';
import { createEventDispatcher } from 'svelte';
import { saveSecret } from './utils';
const dispatch = createEventDispatcher();
const { id } = $page.params;
@ -30,28 +30,20 @@
return errorNotification(error);
}
}
async function saveSecret(isNew = false) {
if (!name) return errorNotification('Name is required.');
if (!value) return errorNotification('Value is required.');
try {
await post(`/applications/${id}/secrets.json`, {
name,
value,
isBuildSecret,
isPRMRSecret,
isNew
});
dispatch('refresh');
if (isNewSecret) {
name = '';
value = '';
isBuildSecret = false;
}
toast.push('Secret saved.');
} catch ({ error }) {
return errorNotification(error);
}
async function createSecret(isNew) {
saveSecret({
isNew,
name,
value,
isBuildSecret,
isPRMRSecret,
isNewSecret,
applicationId: id,
dispatch
});
}
function setSecretValue() {
if (isNewSecret) {
isBuildSecret = !isBuildSecret;
@ -133,12 +125,14 @@
<td>
{#if isNewSecret}
<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>
{:else}
<div class="flex flex-row justify-center space-x-2">
<div class="flex items-center justify-center">
<button class="" on:click={() => saveSecret(false)}>Set</button>
<button class="" on:click={() => createSecret(false)}>Set</button>
</div>
{#if !isPRMRSecret}
<div class="flex justify-center items-end">

View File

@ -1,10 +1,10 @@
import { getTeam, getUserDetails } from '$lib/common';
import { getUserDetails } from '$lib/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import type { RequestHandler } from '@sveltejs/kit';
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 };
const { id } = event.params;
@ -24,7 +24,7 @@ export const get: 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 };
const { id } = event.params;
@ -53,7 +53,7 @@ export const post: 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 };
const { id } = event.params;

View File

@ -26,6 +26,7 @@
import { getDomain } from '$lib/components/common';
import { page } from '$app/stores';
import { get } from '$lib/api';
import BatchSecrets from './_BatchSecrets.svelte';
const { id } = $page.params;
@ -133,4 +134,6 @@
</tr>
</tbody>
</table>
<BatchSecrets {secrets} {id} {refreshSecrets} />
</div>

View 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);
}
}