From 0a8fd0516db5d855d6de26a87272cb7655ddf926 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 18 Jul 2022 08:37:10 +0000 Subject: [PATCH 001/115] feat: Moodle init --- .../20220718083646_moodle/migration.sql | 20 +++++++++++++++++++ apps/api/src/lib/common.ts | 2 +- package.json | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 apps/api/prisma/migrations/20220718083646_moodle/migration.sql diff --git a/apps/api/prisma/migrations/20220718083646_moodle/migration.sql b/apps/api/prisma/migrations/20220718083646_moodle/migration.sql new file mode 100644 index 000000000..eaed14a4a --- /dev/null +++ b/apps/api/prisma/migrations/20220718083646_moodle/migration.sql @@ -0,0 +1,20 @@ +-- CreateTable +CREATE TABLE "Moodle" ( + "id" TEXT NOT NULL PRIMARY KEY, + "serviceId" TEXT NOT NULL, + "defaultUsername" TEXT NOT NULL, + "defaultPassword" TEXT NOT NULL, + "defaultEmail" TEXT NOT NULL, + "mariadbUser" TEXT NOT NULL, + "mariadbPassword" TEXT NOT NULL, + "mariadbRootUser" TEXT NOT NULL, + "mariadbRootUserPassword" TEXT NOT NULL, + "mariadbDatabase" TEXT NOT NULL, + "mariadbPublicPort" INTEGER, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "Moodle_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateIndex +CREATE UNIQUE INDEX "Moodle_serviceId_key" ON "Moodle"("serviceId"); diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index b18bfd003..600f80c55 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -15,7 +15,7 @@ import { checkContainer, getEngine, removeContainer } from './docker'; import { day } from './dayjs'; import * as serviceFields from './serviceFields' -export const version = '3.1.3'; +export const version = '3.2.0'; export const isDev = process.env.NODE_ENV === 'development'; const algorithm = 'aes-256-ctr'; diff --git a/package.json b/package.json index 4d7071d38..4b8717635 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source & self-hostable Heroku / Netlify alternative.", - "version": "3.1.3", + "version": "3.2.0", "license": "AGPL-3.0", "scripts": { "db:studio": "pnpm run --filter coolify-api db:studio", From 537209d3fbc799abf096857e2fcc4cdb4d098b4c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 18 Jul 2022 14:02:53 +0000 Subject: [PATCH 002/115] feat: remote docker engine init --- apps/api/package.json | 7 +- .../migration.sql | 21 + .../20220718134234_ssh_key/migration.sql | 36 ++ apps/api/prisma/schema.prisma | 17 +- .../routes/api/v1/destinations/handlers.ts | 117 +++- .../src/routes/api/v1/destinations/index.ts | 14 +- .../src/routes/api/v1/settings/handlers.ts | 40 +- apps/api/src/routes/api/v1/settings/index.ts | 7 +- apps/api/src/routes/api/v1/settings/types.ts | 11 + apps/ui/package.json | 10 +- .../destinations/[id]/_LocalDocker.svelte | 7 - .../src/routes/destinations/[id]/_New.svelte | 2 +- .../destinations/[id]/_NewRemoteDocker.svelte | 24 +- .../destinations/[id]/_RemoteDocker.svelte | 142 ++--- .../routes/destinations/[id]/__layout.svelte | 22 +- .../[id]/configuration/sshkey.svelte | 59 ++ apps/ui/src/routes/destinations/index.svelte | 3 + apps/ui/src/routes/settings/index.svelte | 509 +++++++++++------- apps/ui/src/tailwind.css | 8 + pnpm-lock.yaml | 182 +++---- 20 files changed, 809 insertions(+), 429 deletions(-) create mode 100644 apps/api/prisma/migrations/20220718114551_remote_docker_engine/migration.sql create mode 100644 apps/api/prisma/migrations/20220718134234_ssh_key/migration.sql create mode 100644 apps/ui/src/routes/destinations/[id]/configuration/sshkey.svelte diff --git a/apps/api/package.json b/apps/api/package.json index 9a37a9366..ef63a504b 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -16,7 +16,7 @@ "dependencies": { "@breejs/ts-worker": "2.0.0", "@fastify/autoload": "5.1.0", - "@fastify/cookie": "7.1.0", + "@fastify/cookie": "7.2.0", "@fastify/cors": "8.0.0", "@fastify/env": "4.0.0", "@fastify/jwt": "6.3.1", @@ -43,16 +43,17 @@ "node-forge": "1.3.1", "node-os-utils": "1.3.7", "p-queue": "7.2.0", + "ssh-config": "4.1.6", "strip-ansi": "7.0.1", "unique-names-generator": "4.7.1" }, "devDependencies": { - "@types/node": "18.0.4", + "@types/node": "18.0.6", "@types/node-os-utils": "1.3.0", "@typescript-eslint/eslint-plugin": "5.30.6", "@typescript-eslint/parser": "5.30.6", "esbuild": "0.14.49", - "eslint": "8.19.0", + "eslint": "8.20.0", "eslint-config-prettier": "8.5.0", "eslint-plugin-prettier": "4.2.1", "nodemon": "2.0.19", diff --git a/apps/api/prisma/migrations/20220718114551_remote_docker_engine/migration.sql b/apps/api/prisma/migrations/20220718114551_remote_docker_engine/migration.sql new file mode 100644 index 000000000..e80df22f2 --- /dev/null +++ b/apps/api/prisma/migrations/20220718114551_remote_docker_engine/migration.sql @@ -0,0 +1,21 @@ +-- RedefineTables +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_DestinationDocker" ( + "id" TEXT NOT NULL PRIMARY KEY, + "network" TEXT NOT NULL, + "name" TEXT NOT NULL, + "engine" TEXT, + "remoteEngine" BOOLEAN NOT NULL DEFAULT false, + "remoteIpAddress" TEXT, + "remoteUser" TEXT, + "remotePort" INTEGER, + "isCoolifyProxyUsed" BOOLEAN DEFAULT false, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_DestinationDocker" ("createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "updatedAt") SELECT "createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "updatedAt" FROM "DestinationDocker"; +DROP TABLE "DestinationDocker"; +ALTER TABLE "new_DestinationDocker" RENAME TO "DestinationDocker"; +CREATE UNIQUE INDEX "DestinationDocker_network_key" ON "DestinationDocker"("network"); +PRAGMA foreign_key_check; +PRAGMA foreign_keys=ON; diff --git a/apps/api/prisma/migrations/20220718134234_ssh_key/migration.sql b/apps/api/prisma/migrations/20220718134234_ssh_key/migration.sql new file mode 100644 index 000000000..08812482c --- /dev/null +++ b/apps/api/prisma/migrations/20220718134234_ssh_key/migration.sql @@ -0,0 +1,36 @@ +-- CreateTable +CREATE TABLE "SshKey" ( + "id" TEXT NOT NULL PRIMARY KEY, + "name" TEXT NOT NULL, + "privateKey" TEXT NOT NULL, + "destinationDockerId" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "SshKey_destinationDockerId_fkey" FOREIGN KEY ("destinationDockerId") REFERENCES "DestinationDocker" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- RedefineTables +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_DestinationDocker" ( + "id" TEXT NOT NULL PRIMARY KEY, + "network" TEXT NOT NULL, + "name" TEXT NOT NULL, + "engine" TEXT, + "remoteEngine" BOOLEAN NOT NULL DEFAULT false, + "remoteIpAddress" TEXT, + "remoteUser" TEXT, + "remotePort" INTEGER, + "remoteVerified" BOOLEAN NOT NULL DEFAULT false, + "isCoolifyProxyUsed" BOOLEAN DEFAULT false, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_DestinationDocker" ("createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "remoteIpAddress", "remotePort", "remoteUser", "updatedAt") SELECT "createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "remoteIpAddress", "remotePort", "remoteUser", "updatedAt" FROM "DestinationDocker"; +DROP TABLE "DestinationDocker"; +ALTER TABLE "new_DestinationDocker" RENAME TO "DestinationDocker"; +CREATE UNIQUE INDEX "DestinationDocker_network_key" ON "DestinationDocker"("network"); +PRAGMA foreign_key_check; +PRAGMA foreign_keys=ON; + +-- CreateIndex +CREATE UNIQUE INDEX "SshKey_destinationDockerId_key" ON "SshKey"("destinationDockerId"); diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 8d1e0bbfe..e35e06290 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -200,8 +200,12 @@ model DestinationDocker { id String @id @default(cuid()) network String @unique name String - engine String + engine String? remoteEngine Boolean @default(false) + remoteIpAddress String? + remoteUser String? + remotePort Int? + remoteVerified Boolean @default(false) isCoolifyProxyUsed Boolean? @default(false) teams Team[] application Application[] @@ -209,6 +213,17 @@ model DestinationDocker { updatedAt DateTime @updatedAt database Database[] service Service[] + sshKey SshKey? +} + +model SshKey { + id String @id @default(cuid()) + name String + privateKey String + destinationDocker DestinationDocker? @relation(fields: [destinationDockerId], references: [id]) + destinationDockerId String? @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model GitSource { diff --git a/apps/api/src/routes/api/v1/destinations/handlers.ts b/apps/api/src/routes/api/v1/destinations/handlers.ts index 40d68a84b..ff3596f4d 100644 --- a/apps/api/src/routes/api/v1/destinations/handlers.ts +++ b/apps/api/src/routes/api/v1/destinations/handlers.ts @@ -1,6 +1,8 @@ import type { FastifyRequest } from 'fastify'; import { FastifyReply } from 'fastify'; -import { asyncExecShell, errorHandler, listSettings, prisma, startCoolifyProxy, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; +import sshConfig from 'ssh-config' +import fs from 'fs/promises' +import { asyncExecShell, decrypt, errorHandler, listSettings, prisma, startCoolifyProxy, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; import { checkContainer, dockerInstance, getEngine } from '../../../../lib/docker'; import type { OnlyId } from '../../../../types'; @@ -44,7 +46,8 @@ export async function getDestination(request: FastifyRequest) { const { id } = request.params const teamId = request.user?.teamId; const destination = await prisma.destinationDocker.findFirst({ - where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } } + where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } }, + include: { sshKey: true } }); if (!destination && id !== 'new') { throw { status: 404, message: `Destination not found.` }; @@ -80,39 +83,51 @@ export async function getDestination(request: FastifyRequest) { export async function newDestination(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params - let { name, network, engine, isCoolifyProxyUsed } = request.body + let { name, network, engine, isCoolifyProxyUsed, ipAddress, user, port, sshPrivateKey } = request.body const teamId = request.user.teamId; if (id === 'new') { - const host = getEngine(engine); - const docker = dockerInstance({ destinationDocker: { engine, network } }); - const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } }); - if (found.length === 0) { - await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`); - } - await prisma.destinationDocker.create({ - data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed } - }); - const destinations = await prisma.destinationDocker.findMany({ where: { engine } }); - const destination = destinations.find((destination) => destination.network === network); + if (engine) { + const host = getEngine(engine); + const docker = dockerInstance({ destinationDocker: { engine, network } }); + const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } }); + if (found.length === 0) { + await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`); + } + await prisma.destinationDocker.create({ + data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed } + }); + const destinations = await prisma.destinationDocker.findMany({ where: { engine } }); + const destination = destinations.find((destination) => destination.network === network); - if (destinations.length > 0) { - const proxyConfigured = destinations.find( - (destination) => destination.network !== network && destination.isCoolifyProxyUsed === true - ); - if (proxyConfigured) { - isCoolifyProxyUsed = !!proxyConfigured.isCoolifyProxyUsed; + if (destinations.length > 0) { + const proxyConfigured = destinations.find( + (destination) => destination.network !== network && destination.isCoolifyProxyUsed === true + ); + if (proxyConfigured) { + isCoolifyProxyUsed = !!proxyConfigured.isCoolifyProxyUsed; + } + await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } }); } - await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } }); - } - if (isCoolifyProxyUsed) { - const settings = await prisma.setting.findFirst(); - if (settings?.isTraefikUsed) { - await startTraefikProxy(engine); - } else { - await startCoolifyProxy(engine); + if (isCoolifyProxyUsed) { + const settings = await prisma.setting.findFirst(); + if (settings?.isTraefikUsed) { + await startTraefikProxy(engine); + } else { + await startCoolifyProxy(engine); + } } + return reply.code(201).send({ id: destination.id }); } - return reply.code(201).send({ id: destination.id }); + if (ipAddress) { + await prisma.destinationDocker.create({ + data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed, remoteEngine: true, remoteIpAddress: ipAddress, remoteUser: user, remotePort: port } + }); + return reply.code(201).send() + + } + throw { + message: `Cannot save Docker Engine.` + }; } else { await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } }); return reply.code(201).send(); @@ -120,6 +135,8 @@ export async function newDestination(request: FastifyRequest, re } catch ({ status, message }) { return errorHandler({ status, message }) + } finally { + await fs.rm('./id_rsa') } } export async function deleteDestination(request: FastifyRequest) { @@ -195,3 +212,45 @@ export async function restartProxy(request: FastifyRequest) { return errorHandler({ status, message }) } } + +export async function assignSSHKey(request: FastifyRequest) { + try { + const { id: sshKeyId } = request.body; + const { id } = request.params; + console.log({ id, sshKeyId }) + await prisma.destinationDocker.update({ where: { id }, data: { sshKey: { connect: { id: sshKeyId } } } }) + return {} + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} +export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: FastifyReply) { + try { + const { id } = request.params; + const { sshKey: { privateKey }, remoteIpAddress, remotePort, remoteUser, network } = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } }) + await fs.writeFile('./id_rsa', decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 }) + const host = `ssh://${remoteUser}@${remoteIpAddress}` + const config = sshConfig.parse('') + const found = config.find({ Host: remoteIpAddress }) + if (!found) { + config.append({ + Host: remoteIpAddress, + Port: remotePort.toString(), + User: remoteUser, + IdentityFile: '/workspace/coolify/apps/api/id_rsa', + StrictHostKeyChecking: 'no' + }) + } + await fs.writeFile('/home/gitpod/.ssh/config', sshConfig.stringify(config)) + const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`); + console.log({ stdout }) + if (!stdout) { + await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`); + } + await prisma.destinationDocker.update({ where: { id }, data: { remoteVerified: true } }) + return reply.code(201).send() + + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} diff --git a/apps/api/src/routes/api/v1/destinations/index.ts b/apps/api/src/routes/api/v1/destinations/index.ts index 43440cc1c..46897817b 100644 --- a/apps/api/src/routes/api/v1/destinations/index.ts +++ b/apps/api/src/routes/api/v1/destinations/index.ts @@ -1,5 +1,5 @@ import { FastifyPluginAsync } from 'fastify'; -import { checkDestination, deleteDestination, getDestination, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy } from './handlers'; +import { assignSSHKey, checkDestination, deleteDestination, getDestination, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy, verifyRemoteDockerEngine } from './handlers'; import type { OnlyId } from '../../../../types'; import type { CheckDestination, NewDestination, Proxy, SaveDestinationSettings } from './types'; @@ -15,10 +15,14 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.post('/:id', async (request, reply) => await newDestination(request, reply)); fastify.delete('/:id', async (request) => await deleteDestination(request)); - fastify.post('/:id/settings', async (request, reply) => await saveDestinationSettings(request)); - fastify.post('/:id/start', async (request, reply) => await startProxy(request)); - fastify.post('/:id/stop', async (request, reply) => await stopProxy(request)); - fastify.post('/:id/restart', async (request, reply) => await restartProxy(request)); + fastify.post('/:id/settings', async (request) => await saveDestinationSettings(request)); + fastify.post('/:id/start', async (request,) => await startProxy(request)); + fastify.post('/:id/stop', async (request) => await stopProxy(request)); + fastify.post('/:id/restart', async (request) => await restartProxy(request)); + + fastify.post('/:id/configuration/sshKey', async (request) => await assignSSHKey(request)); + + fastify.post('/:id/verify', async (request, reply) => await verifyRemoteDockerEngine(request, reply)); }; export default root; diff --git a/apps/api/src/routes/api/v1/settings/handlers.ts b/apps/api/src/routes/api/v1/settings/handlers.ts index 0c0c727d1..052b2e944 100644 --- a/apps/api/src/routes/api/v1/settings/handlers.ts +++ b/apps/api/src/routes/api/v1/settings/handlers.ts @@ -1,15 +1,23 @@ import { promises as dns } from 'dns'; import type { FastifyReply, FastifyRequest } from 'fastify'; -import { checkDomainsIsValidInDNS, errorHandler, getDomain, isDNSValid, isDomainConfigured, listSettings, prisma } from '../../../../lib/common'; -import { CheckDNS, CheckDomain, DeleteDomain, SaveSettings } from './types'; +import { checkDomainsIsValidInDNS, decrypt, encrypt, errorHandler, getDomain, isDNSValid, isDomainConfigured, listSettings, prisma } from '../../../../lib/common'; +import { CheckDNS, CheckDomain, DeleteDomain, DeleteSSHKey, SaveSettings, SaveSSHKey } from './types'; export async function listAllSettings(request: FastifyRequest) { try { const settings = await listSettings(); + const sshKeys = await prisma.sshKey.findMany() + const unencryptedKeys = [] + if (sshKeys.length > 0) { + for (const key of sshKeys) { + unencryptedKeys.push({ id: key.id, name: key.name, privateKey: decrypt(key.privateKey), createdAt: key.createdAt }) + } + } return { - settings + settings, + sshKeys: unencryptedKeys } } catch ({ status, message }) { return errorHandler({ status, message }) @@ -83,4 +91,30 @@ export async function checkDNS(request: FastifyRequest) { } catch ({ status, message }) { return errorHandler({ status, message }) } +} + +export async function saveSSHKey(request: FastifyRequest, reply: FastifyReply) { + try { + const { privateKey, name } = request.body; + const found = await prisma.sshKey.findMany({ where: { name } }) + if (found.length > 0) { + throw { + message: "Name already used. Choose another one please." + } + } + const encryptedSSHKey = encrypt(privateKey) + await prisma.sshKey.create({ data: { name, privateKey: encryptedSSHKey } }) + return reply.code(201).send() + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} +export async function deleteSSHKey(request: FastifyRequest, reply: FastifyReply) { + try { + const { id } = request.body; + await prisma.sshKey.delete({ where: { id } }) + return reply.code(201).send() + } catch ({ status, message }) { + return errorHandler({ status, message }) + } } \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/settings/index.ts b/apps/api/src/routes/api/v1/settings/index.ts index f5181a14e..96da5948b 100644 --- a/apps/api/src/routes/api/v1/settings/index.ts +++ b/apps/api/src/routes/api/v1/settings/index.ts @@ -1,6 +1,6 @@ import { FastifyPluginAsync } from 'fastify'; -import { checkDNS, checkDomain, deleteDomain, listAllSettings, saveSettings } from './handlers'; -import { CheckDNS, CheckDomain, DeleteDomain, SaveSettings } from './types'; +import { checkDNS, checkDomain, deleteDomain, deleteSSHKey, listAllSettings, saveSettings, saveSSHKey } from './handlers'; +import { CheckDNS, CheckDomain, DeleteDomain, DeleteSSHKey, SaveSettings, SaveSSHKey } from './types'; const root: FastifyPluginAsync = async (fastify): Promise => { @@ -13,6 +13,9 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/check', async (request) => await checkDNS(request)); fastify.post('/check', async (request) => await checkDomain(request)); + + fastify.post('/sshKey', async (request, reply) => await saveSSHKey(request, reply)); + fastify.delete('/sshKey', async (request, reply) => await deleteSSHKey(request, reply)); }; export default root; diff --git a/apps/api/src/routes/api/v1/settings/types.ts b/apps/api/src/routes/api/v1/settings/types.ts index aa7398804..a33b614a4 100644 --- a/apps/api/src/routes/api/v1/settings/types.ts +++ b/apps/api/src/routes/api/v1/settings/types.ts @@ -28,4 +28,15 @@ export interface CheckDNS { Params: { domain: string, } +} +export interface SaveSSHKey { + Body: { + privateKey: string, + name: string + } +} +export interface DeleteSSHKey { + Body: { + id: string + } } \ No newline at end of file diff --git a/apps/ui/package.json b/apps/ui/package.json index babb6755c..10b2d5219 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -15,13 +15,13 @@ "format": "prettier --write --plugin-search-dir=. ." }, "devDependencies": { - "@playwright/test": "1.23.3", - "@sveltejs/kit": "1.0.0-next.375", + "@playwright/test": "1.23.4", + "@sveltejs/kit": "1.0.0-next.377", "@types/js-cookie": "3.0.2", "@typescript-eslint/eslint-plugin": "5.30.6", "@typescript-eslint/parser": "5.30.6", "autoprefixer": "10.4.7", - "eslint": "8.19.0", + "eslint": "8.20.0", "eslint-config-prettier": "8.5.0", "eslint-plugin-svelte3": "4.0.0", "postcss": "8.4.14", @@ -34,11 +34,11 @@ "tailwindcss-scrollbar": "0.1.0", "tslib": "2.4.0", "typescript": "4.7.4", - "vite": "^3.0.0" + "vite": "3.0.1" }, "type": "module", "dependencies": { - "@sveltejs/adapter-static": "1.0.0-next.36", + "@sveltejs/adapter-static": "1.0.0-next.37", "@zerodevx/svelte-toast": "0.7.2", "cuid": "2.1.8", "js-cookie": "3.0.1", diff --git a/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte b/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte index 7da9ffd88..cad681963 100644 --- a/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte +++ b/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte @@ -142,9 +142,6 @@ : $t('destination.force_restart_proxy')} {/if} -
@@ -168,10 +165,6 @@ value={destination.engine} />
-
setPredefined('localDocker')} >{$t('sources.local_docker')} - +
diff --git a/apps/ui/src/routes/destinations/[id]/_NewRemoteDocker.svelte b/apps/ui/src/routes/destinations/[id]/_NewRemoteDocker.svelte index 13e45e4a1..8776b3840 100644 --- a/apps/ui/src/routes/destinations/[id]/_NewRemoteDocker.svelte +++ b/apps/ui/src/routes/destinations/[id]/_NewRemoteDocker.svelte @@ -11,13 +11,19 @@ let loading = false; async function handleSubmit() { + if (loading) return; try { - const { id } = await post('/new/destination/docker', { + loading = true; + await post(`/destinations/check`, { network: payload.network }); + const { id } = await post(`/destinations/new`, { ...payload }); - return await goto(`/destinations/${id}`); + await goto(`/destinations/${id}`); + window.location.reload(); } catch (error) { return errorNotification(error); + } finally { + loading = false; } } @@ -64,20 +70,6 @@ -
- -