diff --git a/package.json b/package.json index 3cdad52a4..bb42f2869 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source & self-hostable Heroku / Netlify alternative.", - "version": "2.0.27", + "version": "2.0.28", "license": "AGPL-3.0", "scripts": { "dev": "docker-compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0", diff --git a/prisma/migrations/20220304141408_service_secrets/migration.sql b/prisma/migrations/20220304141408_service_secrets/migration.sql new file mode 100644 index 000000000..baa0c3f54 --- /dev/null +++ b/prisma/migrations/20220304141408_service_secrets/migration.sql @@ -0,0 +1,13 @@ +-- CreateTable +CREATE TABLE "ServiceSecret" ( + "id" TEXT NOT NULL PRIMARY KEY, + "name" TEXT NOT NULL, + "value" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "serviceId" TEXT NOT NULL, + CONSTRAINT "ServiceSecret_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateIndex +CREATE UNIQUE INDEX "ServiceSecret_name_serviceId_key" ON "ServiceSecret"("name", "serviceId"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 688e312b7..8c4fdab53 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -122,6 +122,18 @@ model Secret { @@unique([name, applicationId, isPRMRSecret]) } +model ServiceSecret { + id String @id @default(cuid()) + name String + value String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + service Service @relation(fields: [serviceId], references: [id]) + serviceId String + + @@unique([name, serviceId]) +} + model BuildLog { id String @id @default(cuid()) applicationId String? @@ -252,6 +264,7 @@ model Service { minio Minio? vscodeserver Vscodeserver? wordpress Wordpress? + serviceSecret ServiceSecret[] } model PlausibleAnalytics { diff --git a/src/lib/database/checks.ts b/src/lib/database/checks.ts index d825de701..534d81966 100644 --- a/src/lib/database/checks.ts +++ b/src/lib/database/checks.ts @@ -15,6 +15,9 @@ export async function isDockerNetworkExists({ network }) { return await prisma.destinationDocker.findFirst({ where: { network } }); } +export async function isServiceSecretExists({ id, name }) { + return await prisma.serviceSecret.findFirst({ where: { name, serviceId: id } }); +} export async function isSecretExists({ id, name, isPRMRSecret }) { return await prisma.secret.findFirst({ where: { name, applicationId: id, isPRMRSecret } }); } diff --git a/src/lib/database/secrets.ts b/src/lib/database/secrets.ts index 167d061f5..835eb4def 100644 --- a/src/lib/database/secrets.ts +++ b/src/lib/database/secrets.ts @@ -1,6 +1,19 @@ import { encrypt, decrypt } from '$lib/crypto'; import { prisma } from './common'; +export async function listServiceSecrets(serviceId: string) { + let secrets = await prisma.serviceSecret.findMany({ + where: { serviceId }, + orderBy: { createdAt: 'desc' } + }); + secrets = secrets.map((secret) => { + secret.value = decrypt(secret.value); + return secret; + }); + + return secrets; +} + export async function listSecrets(applicationId: string) { let secrets = await prisma.secret.findMany({ where: { applicationId }, @@ -14,6 +27,12 @@ export async function listSecrets(applicationId: string) { return secrets; } +export async function createServiceSecret({ id, name, value }) { + value = encrypt(value); + return await prisma.serviceSecret.create({ + data: { name, value, service: { connect: { id } } } + }); +} export async function createSecret({ id, name, value, isBuildSecret, isPRMRSecret }) { value = encrypt(value); return await prisma.secret.create({ @@ -21,10 +40,24 @@ export async function createSecret({ id, name, value, isBuildSecret, isPRMRSecre }); } +export async function updateServiceSecret({ id, name, value }) { + value = encrypt(value); + const found = await prisma.serviceSecret.findFirst({ where: { serviceId: id, name } }); + + if (found) { + return await prisma.serviceSecret.updateMany({ + where: { serviceId: id, name }, + data: { value } + }); + } else { + return await prisma.serviceSecret.create({ + data: { name, value, service: { connect: { id } } } + }); + } +} export async function updateSecret({ id, name, value, isBuildSecret, isPRMRSecret }) { value = encrypt(value); const found = await prisma.secret.findFirst({ where: { applicationId: id, name, isPRMRSecret } }); - console.log(found); if (found) { return await prisma.secret.updateMany({ @@ -38,6 +71,10 @@ export async function updateSecret({ id, name, value, isBuildSecret, isPRMRSecre } } +export async function removeServiceSecret({ id, name }) { + return await prisma.serviceSecret.deleteMany({ where: { serviceId: id, name } }); +} + export async function removeSecret({ id, name }) { return await prisma.secret.deleteMany({ where: { applicationId: id, name } }); } diff --git a/src/lib/database/services.ts b/src/lib/database/services.ts index 56606109b..ea0be0a83 100644 --- a/src/lib/database/services.ts +++ b/src/lib/database/services.ts @@ -19,7 +19,8 @@ export async function getService({ id, teamId }) { plausibleAnalytics: true, minio: true, vscodeserver: true, - wordpress: true + wordpress: true, + serviceSecret: true } }); @@ -42,6 +43,12 @@ export async function getService({ id, teamId }) { if (body.wordpress?.mysqlRootUserPassword) body.wordpress.mysqlRootUserPassword = decrypt(body.wordpress.mysqlRootUserPassword); + if (body?.serviceSecret.length > 0) { + body.serviceSecret = body.serviceSecret.map((s) => { + s.value = decrypt(s.value); + return s; + }); + } return { ...body }; } @@ -159,5 +166,7 @@ export async function removeService({ id }) { await prisma.minio.deleteMany({ where: { serviceId: id } }); await prisma.vscodeserver.deleteMany({ where: { serviceId: id } }); await prisma.wordpress.deleteMany({ where: { serviceId: id } }); + await prisma.serviceSecret.deleteMany({ where: { serviceId: id } }); + await prisma.service.delete({ where: { id } }); } diff --git a/src/lib/haproxy/configuration.ts b/src/lib/haproxy/configuration.ts index 97cb76c97..0bfebde81 100644 --- a/src/lib/haproxy/configuration.ts +++ b/src/lib/haproxy/configuration.ts @@ -112,9 +112,15 @@ export async function haproxyInstance() { } export async function configureHAProxy() { + const haproxy = await haproxyInstance(); + try { - const haproxy = await haproxyInstance(); await checkHAProxy(haproxy); + } catch (error) { + return 'Error: HAProxy is not running'; + } + + try { const data = { applications: [], services: [], diff --git a/src/lib/haproxy/index.ts b/src/lib/haproxy/index.ts index b41f9035e..39190384d 100644 --- a/src/lib/haproxy/index.ts +++ b/src/lib/haproxy/index.ts @@ -49,7 +49,12 @@ export async function completeTransaction(transactionId) { } export async function deleteProxy({ id }) { const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); + try { + await checkHAProxy(haproxy); + } catch (error) { + return 'Error: HAProxy is not running'; + } + let transactionId; try { await haproxy.get(`v2/services/haproxy/configuration/backends/${id}`).json(); diff --git a/src/lib/queues/proxy.ts b/src/lib/queues/proxy.ts index 3705139ce..a29b2a223 100644 --- a/src/lib/queues/proxy.ts +++ b/src/lib/queues/proxy.ts @@ -1,4 +1,3 @@ -import { dev } from '$app/env'; import { ErrorHandler } from '$lib/database'; import { configureHAProxy } from '$lib/haproxy/configuration'; diff --git a/src/routes/services/[id]/_Services/_Wordpress.svelte b/src/routes/services/[id]/_Services/_Wordpress.svelte index aa61aeb55..883178a22 100644 --- a/src/routes/services/[id]/_Services/_Wordpress.svelte +++ b/src/routes/services/[id]/_Services/_Wordpress.svelte @@ -25,7 +25,7 @@ define('WP_ALLOW_MULTISITE', true); define('MULTISITE', true); define('SUBDOMAIN_INSTALL', false);` - : null}>{service.wordpress.extraConfig || 'N/A'}{service.wordpress.extraConfig}
| Name | +Value | +Action | +
|---|---|---|