diff --git a/apps/api/src/routes/api/v1/applications/handlers.ts b/apps/api/src/routes/api/v1/applications/handlers.ts index ffb9e64d4..be7648bfe 100644 --- a/apps/api/src/routes/api/v1/applications/handlers.ts +++ b/apps/api/src/routes/api/v1/applications/handlers.ts @@ -787,64 +787,74 @@ export async function saveConnectedDatabase(request, reply) { export async function getSecrets(request: FastifyRequest) { try { const { id } = request.params + let secrets = await prisma.secret.findMany({ - where: { applicationId: id }, - orderBy: { createdAt: 'desc' } + where: { applicationId: id, isPRMRSecret: false }, + orderBy: { createdAt: 'asc' } }); + let previewSecrets = await prisma.secret.findMany({ + where: { applicationId: id, isPRMRSecret: true }, + orderBy: { createdAt: 'asc' } + }); + secrets = secrets.map((secret) => { secret.value = decrypt(secret.value); return secret; }); - secrets = secrets.filter((secret) => !secret.isPRMRSecret).sort((a, b) => { - return ('' + a.name).localeCompare(b.name); - }) + previewSecrets = previewSecrets.map((secret) => { + secret.value = decrypt(secret.value); + return secret; + }); + return { - secrets + previewSecrets: previewSecrets.sort((a, b) => { + return ('' + a.name).localeCompare(b.name); + }), + secrets: secrets.sort((a, b) => { + return ('' + a.name).localeCompare(b.name); + }) } } catch ({ status, message }) { return errorHandler({ status, message }) } } +export async function updatePreviewSecret(request: FastifyRequest, reply: FastifyReply) { + try { + const { id } = request.params + const { name, value } = request.body + await prisma.secret.updateMany({ + where: { applicationId: id, name, isPRMRSecret: true }, + data: { value: encrypt(value.trim()) } + }); + return reply.code(201).send() + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} +export async function updateSecret(request: FastifyRequest, reply: FastifyReply) { + try { + const { id } = request.params + const { name, value, isBuildSecret = undefined } = request.body + await prisma.secret.updateMany({ + where: { applicationId: id, name }, + data: { value: encrypt(value.trim()), isBuildSecret } + }); + return reply.code(201).send() + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} export async function saveSecret(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params - let { name, value, isBuildSecret, isPRMRSecret, isNew } = request.body - if (isNew) { - const found = await prisma.secret.findFirst({ where: { name, applicationId: id, isPRMRSecret } }); - if (found) { - throw { status: 500, message: `Secret ${name} already exists.` } - } else { - value = encrypt(value.trim()); - await prisma.secret.create({ - data: { name, value, isBuildSecret, isPRMRSecret, application: { connect: { id } } } - }); - } - } else { - if (value) { - value = encrypt(value.trim()); - } - const found = await prisma.secret.findFirst({ where: { applicationId: id, name, isPRMRSecret } }); - - if (found) { - if (!value && isPRMRSecret) { - await prisma.secret.deleteMany({ - where: { applicationId: id, name, isPRMRSecret } - }); - } else { - - await prisma.secret.updateMany({ - where: { applicationId: id, name, isPRMRSecret }, - data: { value, isBuildSecret, isPRMRSecret } - }); - } - - } else { - await prisma.secret.create({ - data: { name, value, isBuildSecret, isPRMRSecret, application: { connect: { id } } } - }); - } - } + const { name, value, isBuildSecret = false } = request.body + await prisma.secret.create({ + data: { name, value: encrypt(value.trim()), isBuildSecret, isPRMRSecret: false, application: { connect: { id } } } + }); + await prisma.secret.create({ + data: { name, value: encrypt(value.trim()), isBuildSecret, isPRMRSecret: true, application: { connect: { id } } } + }); return reply.code(201).send() } catch ({ status, message }) { return errorHandler({ status, message }) diff --git a/apps/api/src/routes/api/v1/applications/index.ts b/apps/api/src/routes/api/v1/applications/index.ts index 74370de4d..af39e63ce 100644 --- a/apps/api/src/routes/api/v1/applications/index.ts +++ b/apps/api/src/routes/api/v1/applications/index.ts @@ -1,6 +1,6 @@ import { FastifyPluginAsync } from 'fastify'; import { OnlyId } from '../../../../types'; -import { cancelDeployment, checkDNS, checkDomain, checkRepository, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getApplicationStatus, getBuildIdLogs, getBuildPack, getBuilds, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getPreviewStatus, getSecrets, getStorages, getUsage, listApplications, loadPreviews, newApplication, restartApplication, restartPreview, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveConnectedDatabase, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication, stopPreviewApplication } from './handlers'; +import { cancelDeployment, checkDNS, checkDomain, checkRepository, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getApplicationStatus, getBuildIdLogs, getBuildPack, getBuilds, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getPreviewStatus, getSecrets, getStorages, getUsage, listApplications, loadPreviews, newApplication, restartApplication, restartPreview, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveConnectedDatabase, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication, stopPreviewApplication, updatePreviewSecret, updateSecret } from './handlers'; import type { CancelDeployment, CheckDNS, CheckDomain, CheckRepository, DeleteApplication, DeleteSecret, DeleteStorage, DeployApplication, GetApplicationLogs, GetBuildIdLogs, GetBuilds, GetImages, RestartPreviewApplication, SaveApplication, SaveApplicationSettings, SaveApplicationSource, SaveDeployKey, SaveDestination, SaveSecret, SaveStorage, StopPreviewApplication } from './types'; @@ -30,6 +30,8 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/:id/secrets', async (request) => await getSecrets(request)); fastify.post('/:id/secrets', async (request, reply) => await saveSecret(request, reply)); + fastify.put('/:id/secrets', async (request, reply) => await updateSecret(request, reply)); + fastify.put('/:id/secrets/preview', async (request, reply) => await updatePreviewSecret(request, reply)); fastify.delete('/:id/secrets', async (request) => await deleteSecret(request)); fastify.get('/:id/storages', async (request) => await getStorages(request)); diff --git a/apps/api/src/routes/api/v1/applications/types.ts b/apps/api/src/routes/api/v1/applications/types.ts index 0699518a5..121d23d75 100644 --- a/apps/api/src/routes/api/v1/applications/types.ts +++ b/apps/api/src/routes/api/v1/applications/types.ts @@ -65,7 +65,7 @@ export interface SaveSecret extends OnlyId { name: string, value: string, isBuildSecret: boolean, - isPRMRSecret: boolean, + previewSecret: boolean, isNew: boolean } } diff --git a/apps/ui/src/lib/components/CopyPasswordField.svelte b/apps/ui/src/lib/components/CopyPasswordField.svelte index 24ed90f94..9083fa47c 100644 --- a/apps/ui/src/lib/components/CopyPasswordField.svelte +++ b/apps/ui/src/lib/components/CopyPasswordField.svelte @@ -15,7 +15,7 @@ export let placeholder = ''; export let inputStyle = ''; - let disabledClass = 'bg-coolback disabled:bg-coolblack lg:w-64 w-full'; + let disabledClass = 'bg-coolback disabled:bg-coolblack w-full'; let isHttps = browser && window.location.protocol === 'https:'; function copyToClipboard() { diff --git a/apps/ui/src/routes/applications/[id]/_Menu.svelte b/apps/ui/src/routes/applications/[id]/_Menu.svelte index 33247d740..19075a254 100644 --- a/apps/ui/src/routes/applications/[id]/_Menu.svelte +++ b/apps/ui/src/routes/applications/[id]/_Menu.svelte @@ -4,10 +4,72 @@ import { page } from '$app/stores'; -