Merge branch 'next' into some-tweaks

This commit is contained in:
Kaname
2022-09-07 17:14:09 +00:00
55 changed files with 2814 additions and 1076 deletions

View File

@@ -0,0 +1,13 @@
-- CreateTable
CREATE TABLE "DatabaseSecret" (
"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,
"databaseId" TEXT NOT NULL,
CONSTRAINT "DatabaseSecret_databaseId_fkey" FOREIGN KEY ("databaseId") REFERENCES "Database" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "DatabaseSecret_name_databaseId_key" ON "DatabaseSecret"("name", "databaseId");

View File

@@ -328,6 +328,19 @@ model Database {
settings DatabaseSettings?
teams Team[]
applicationConnectedDatabase ApplicationConnectedDatabase[]
databaseSecret DatabaseSecret[]
}
model DatabaseSecret {
id String @id @default(cuid())
name String
value String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
databaseId String
database Database @relation(fields: [databaseId], references: [id])
@@unique([name, databaseId])
}
model DatabaseSettings {

View File

@@ -17,7 +17,6 @@ const algorithm = 'aes-256-ctr';
async function main() {
// Enable registration for the first user
// Set initial HAProxy password
const settingsFound = await prisma.setting.findFirst({});
if (!settingsFound) {
await prisma.setting.create({
@@ -25,7 +24,8 @@ async function main() {
isRegistrationEnabled: true,
proxyPassword: encrypt(generatePassword()),
proxyUser: cuid(),
arch: process.arch
arch: process.arch,
DNSServers: '1.1.1.1,8.8.8.8'
}
});
} else {

View File

@@ -89,6 +89,22 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st
}
];
const phpVersions = [
{
value: 'webdevops/php-apache:8.2',
label: 'webdevops/php-apache:8.2'
},
{
value: 'webdevops/php-nginx:8.2',
label: 'webdevops/php-nginx:8.2'
},
{
value: 'webdevops/php-apache:8.1',
label: 'webdevops/php-apache:8.1'
},
{
value: 'webdevops/php-nginx:8.1',
label: 'webdevops/php-nginx:8.1'
},
{
value: 'webdevops/php-apache:8.0',
label: 'webdevops/php-apache:8.0'
@@ -145,6 +161,22 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st
value: 'webdevops/php-nginx:5.6',
label: 'webdevops/php-nginx:5.6'
},
{
value: 'webdevops/php-apache:8.2-alpine',
label: 'webdevops/php-apache:8.2-alpine'
},
{
value: 'webdevops/php-nginx:8.2-alpine',
label: 'webdevops/php-nginx:8.2-alpine'
},
{
value: 'webdevops/php-apache:8.1-alpine',
label: 'webdevops/php-apache:8.1-alpine'
},
{
value: 'webdevops/php-nginx:8.1-alpine',
label: 'webdevops/php-nginx:8.1-alpine'
},
{
value: 'webdevops/php-apache:8.0-alpine',
label: 'webdevops/php-apache:8.0-alpine'
@@ -305,11 +337,11 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st
payload.baseImage = 'denoland/deno:latest';
}
if (buildPack === 'php') {
payload.baseImage = 'webdevops/php-apache:8.0-alpine';
payload.baseImage = 'webdevops/php-apache:8.2-alpine';
payload.baseImages = phpVersions;
}
if (buildPack === 'laravel') {
payload.baseImage = 'webdevops/php-apache:8.0-alpine';
payload.baseImage = 'webdevops/php-apache:8.2-alpine';
payload.baseBuildImage = 'node:18';
payload.baseBuildImages = nodeVersions;
}

View File

@@ -21,7 +21,7 @@ import { scheduler } from './scheduler';
import { supportedServiceTypesAndVersions } from './services/supportedVersions';
import { includeServices } from './services/common';
export const version = '3.9.2';
export const version = '3.10.0';
export const isDev = process.env.NODE_ENV === 'development';
const algorithm = 'aes-256-ctr';
@@ -440,6 +440,12 @@ export const supportedDatabaseTypesAndVersions = [
baseImageARM: 'couchdb',
versions: ['3.2.2', '3.1.2', '2.3.1'],
versionsARM: ['3.2.2', '3.1.2', '2.3.1']
},
{
name: 'edgedb',
fancyName: 'EdgeDB',
baseImage: 'edgedb/edgedb',
versions: ['latest', '2.1', '2.0', '1.4']
}
];
@@ -714,24 +720,20 @@ export function generatePassword({
return password;
}
export function generateDatabaseConfiguration(
database: any,
arch: string
):
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MYSQL_DATABASE: string;
MYSQL_PASSWORD: string;
MYSQL_ROOT_USER: string;
MYSQL_USER: string;
MYSQL_ROOT_PASSWORD: string;
};
}
type DatabaseConfiguration = {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MYSQL_DATABASE: string;
MYSQL_PASSWORD: string;
MYSQL_ROOT_USER: string;
MYSQL_USER: string;
MYSQL_ROOT_PASSWORD: string;
};
}
| {
volume: string;
image: string;
@@ -760,52 +762,57 @@ export function generateDatabaseConfiguration(
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
POSTGRESQL_POSTGRES_PASSWORD: string;
POSTGRESQL_USERNAME: string;
POSTGRESQL_PASSWORD: string;
POSTGRESQL_DATABASE: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
POSTGRES_PASSWORD?: string;
POSTGRES_USER?: string;
POSTGRES_DB?: string;
POSTGRESQL_POSTGRES_PASSWORD?: string;
POSTGRESQL_USERNAME?: string;
POSTGRESQL_PASSWORD?: string;
POSTGRESQL_DATABASE?: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
POSTGRES_USER: string;
POSTGRES_PASSWORD: string;
POSTGRES_DB: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
REDIS_AOF_ENABLED: string;
REDIS_PASSWORD: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
REDIS_AOF_ENABLED: string;
REDIS_PASSWORD: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
COUCHDB_PASSWORD: string;
COUCHDB_USER: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
COUCHDB_PASSWORD: string;
COUCHDB_USER: string;
};
} {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
EDGEDB_SERVER_PASSWORD: string;
EDGEDB_SERVER_USER: string;
EDGEDB_SERVER_DATABASE: string;
EDGEDB_SERVER_TLS_CERT_MODE: string;
};
}
export function generateDatabaseConfiguration(database: any, arch: string): DatabaseConfiguration {
const {
id,
dbUser,
@@ -837,7 +844,7 @@ export function generateDatabaseConfiguration(
}
return configuration;
} else if (type === 'mariadb') {
const configuration = {
const configuration: DatabaseConfiguration = {
privatePort: 3306,
environmentVariables: {
MARIADB_ROOT_USER: rootUser,
@@ -855,7 +862,7 @@ export function generateDatabaseConfiguration(
}
return configuration;
} else if (type === 'mongodb') {
const configuration = {
const configuration: DatabaseConfiguration = {
privatePort: 27017,
environmentVariables: {
MONGODB_ROOT_USER: rootUser,
@@ -874,7 +881,7 @@ export function generateDatabaseConfiguration(
}
return configuration;
} else if (type === 'postgresql') {
const configuration = {
const configuration: DatabaseConfiguration = {
privatePort: 5432,
environmentVariables: {
POSTGRESQL_POSTGRES_PASSWORD: rootUserPassword,
@@ -896,7 +903,7 @@ export function generateDatabaseConfiguration(
}
return configuration;
} else if (type === 'redis') {
const configuration = {
const configuration: DatabaseConfiguration = {
privatePort: 6379,
command: undefined,
environmentVariables: {
@@ -915,7 +922,7 @@ export function generateDatabaseConfiguration(
}
return configuration;
} else if (type === 'couchdb') {
const configuration = {
const configuration: DatabaseConfiguration = {
privatePort: 5984,
environmentVariables: {
COUCHDB_PASSWORD: dbUserPassword,
@@ -928,7 +935,21 @@ export function generateDatabaseConfiguration(
if (isARM(arch)) {
configuration.volume = `${id}-${type}-data:/opt/couchdb/data`;
}
return configuration;
return configuration
} else if (type === 'edgedb') {
const configuration: DatabaseConfiguration = {
privatePort: 5656,
environmentVariables: {
EDGEDB_SERVER_PASSWORD: rootUserPassword,
EDGEDB_SERVER_USER: rootUser,
EDGEDB_SERVER_DATABASE: defaultDatabase,
EDGEDB_SERVER_TLS_CERT_MODE: 'generate_self_signed'
},
image: `${baseImage}:${version}`,
volume: `${id}-${type}-data:/var/lib/edgedb/data`,
ulimits: {}
};
return configuration
}
}
export function isARM(arch: string) {

View File

@@ -198,7 +198,7 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile);
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.plausibleAnalytics)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
@@ -333,6 +333,8 @@ async function startMinioService(request: FastifyRequest<ServiceStartStop>) {
image: `${image}:${version}`,
volumes: [`${id}-minio-data:/data`],
environmentVariables: {
MINIO_SERVER_URL: fqdn,
MINIO_DOMAIN: getDomain(fqdn),
MINIO_ROOT_USER: rootUser,
MINIO_ROOT_PASSWORD: rootUserPassword,
MINIO_BROWSER_REDIRECT_URL: fqdn
@@ -852,7 +854,7 @@ async function startGhostService(request: FastifyRequest<ServiceStartStop>) {
});
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.ghost)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -1086,7 +1088,7 @@ async function startUmamiService(request: FastifyRequest<ServiceStartStop>) {
FROM ${config.postgresql.image}
COPY ./schema.postgresql.sql /docker-entrypoint-initdb.d/schema.postgresql.sql`;
await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile);
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.umami)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -1114,6 +1116,7 @@ async function startUmamiService(request: FastifyRequest<ServiceStartStop>) {
},
volumes: volumeMounts
};
console.log(composeFile)
const composeFileDestination = `${workdir}/docker-compose.yaml`;
await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
await startServiceContainers(destinationDocker.id, composeFileDestination)
@@ -1167,7 +1170,7 @@ async function startHasuraService(request: FastifyRequest<ServiceStartStop>) {
});
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.hasura)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -1272,7 +1275,7 @@ async function startFiderService(request: FastifyRequest<ServiceStartStop>) {
config.fider.environmentVariables[secret.name] = secret.value;
});
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.fider)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -1880,7 +1883,7 @@ async function startMoodleService(request: FastifyRequest<ServiceStartStop>) {
config.moodle.environmentVariables[secret.name] = secret.value;
});
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.moodle)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -2006,7 +2009,7 @@ async function startGlitchTipService(request: FastifyRequest<ServiceStartStop>)
config.glitchTip.environmentVariables[secret.name] = secret.value;
});
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config.glitchTip)
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -2475,7 +2478,7 @@ async function startTaigaService(request: FastifyRequest<ServiceStartStop>) {
TAIGA_SECRET_KEY: secretKey,
}
},
postgresql: {
image: `postgres:12.3`,
volumes: [`${id}-postgresql-data:/var/lib/postgresql/data`],

View File

@@ -525,9 +525,7 @@ export async function checkDomain(request: FastifyRequest<CheckDomain>) {
}
export async function checkDNS(request: FastifyRequest<CheckDNS>) {
try {
const { id } = request.params
let { exposePort, fqdn, forceSave, dualCerts } = request.body
if (!fqdn) {
return {}

View File

@@ -11,6 +11,7 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
version,
whiteLabeled: process.env.COOLIFY_WHITE_LABELED === 'true',
whiteLabeledIcon: process.env.COOLIFY_WHITE_LABELED_ICON,
isRegistrationEnabled: settings.isRegistrationEnabled,
}
} catch ({ status, message }) {
return errorHandler({ status, message })

View File

@@ -3,10 +3,10 @@ import type { FastifyRequest } from 'fastify';
import { FastifyReply } from 'fastify';
import yaml from 'js-yaml';
import fs from 'fs/promises';
import { ComposeFile, createDirectories, decrypt, encrypt, errorHandler, executeDockerCmd, generateDatabaseConfiguration, generatePassword, getContainerUsage, getDatabaseImage, getDatabaseVersions, getFreePublicPort, listSettings, makeLabelForStandaloneDatabase, prisma, startTraefikTCPProxy, stopDatabaseContainer, stopTcpHttpProxy, supportedDatabaseTypesAndVersions, uniqueName, updatePasswordInDb } from '../../../../lib/common';
import { ComposeFile, createDirectories, decrypt, defaultComposeConfiguration, encrypt, errorHandler, executeDockerCmd, generateDatabaseConfiguration, generatePassword, getContainerUsage, getDatabaseImage, getDatabaseVersions, getFreePublicPort, listSettings, makeLabelForStandaloneDatabase, prisma, startTraefikTCPProxy, stopDatabaseContainer, stopTcpHttpProxy, supportedDatabaseTypesAndVersions, uniqueName, updatePasswordInDb } from '../../../../lib/common';
import { day } from '../../../../lib/dayjs';
import { GetDatabaseLogs, OnlyId, SaveDatabase, SaveDatabaseDestination, SaveDatabaseSettings, SaveVersion } from '../../../../types';
import { DeleteDatabaseSecret, GetDatabaseLogs, OnlyId, SaveDatabase, SaveDatabaseDestination, SaveDatabaseSecret, SaveDatabaseSettings, SaveVersion } from '../../../../types';
import { DeleteDatabase, SaveDatabaseType } from './types';
export async function listDatabases(request: FastifyRequest) {
@@ -61,16 +61,18 @@ export async function getDatabaseStatus(request: FastifyRequest<OnlyId>) {
where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { destinationDocker: true, settings: true }
});
const { destinationDockerId, destinationDocker } = database;
if (destinationDockerId) {
try {
const { stdout } = await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker inspect --format '{{json .State}}' ${id}` })
if (database) {
const { destinationDockerId, destinationDocker } = database;
if (destinationDockerId) {
try {
const { stdout } = await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker inspect --format '{{json .State}}' ${id}` })
if (JSON.parse(stdout).Running) {
isRunning = true;
if (JSON.parse(stdout).Running) {
isRunning = true;
}
} catch (error) {
//
}
} catch (error) {
//
}
}
return {
@@ -220,7 +222,7 @@ export async function startDatabase(request: FastifyRequest<OnlyId>) {
const database = await prisma.database.findFirst({
where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { destinationDocker: true, settings: true }
include: { destinationDocker: true, settings: true, databaseSecret: true }
});
const { arch } = await listSettings();
if (database.dbUserPassword) database.dbUserPassword = decrypt(database.dbUserPassword);
@@ -230,7 +232,8 @@ export async function startDatabase(request: FastifyRequest<OnlyId>) {
destinationDockerId,
destinationDocker,
publicPort,
settings: { isPublic }
settings: { isPublic },
databaseSecret
} = database;
const { privatePort, command, environmentVariables, image, volume, ulimits } =
generateDatabaseConfiguration(database, arch);
@@ -240,7 +243,11 @@ export async function startDatabase(request: FastifyRequest<OnlyId>) {
const labels = await makeLabelForStandaloneDatabase({ id, image, volume });
const { workdir } = await createDirectories({ repository: type, buildId: id });
if (databaseSecret.length > 0) {
databaseSecret.forEach((secret) => {
environmentVariables[secret.name] = decrypt(secret.value);
});
}
const composeFile: ComposeFile = {
version: '3.8',
services: {
@@ -248,20 +255,11 @@ export async function startDatabase(request: FastifyRequest<OnlyId>) {
container_name: id,
image,
command,
networks: [network],
environment: environmentVariables,
volumes: [volume],
ulimits,
labels,
restart: 'always',
deploy: {
restart_policy: {
condition: 'on-failure',
delay: '5s',
max_attempts: 3,
window: '120s'
}
}
...defaultComposeConfiguration(network),
}
},
networks: {
@@ -271,25 +269,16 @@ export async function startDatabase(request: FastifyRequest<OnlyId>) {
},
volumes: {
[volumeName]: {
external: true
name: volumeName,
}
}
};
const composeFileDestination = `${workdir}/docker-compose.yaml`;
await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
try {
await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker volume create ${volumeName}` })
} catch (error) { }
try {
await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up -d` })
if (isPublic) await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort);
return {};
} catch (error) {
throw {
error
};
}
await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up -d` })
if (isPublic) await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort);
return {};
} catch ({ status, message }) {
return errorHandler({ status, message })
}
@@ -376,6 +365,7 @@ export async function deleteDatabase(request: FastifyRequest<DeleteDatabase>) {
}
}
await prisma.databaseSettings.deleteMany({ where: { databaseId: id } });
await prisma.databaseSecret.deleteMany({ where: { databaseId: id } });
await prisma.database.delete({ where: { id } });
return {}
} catch ({ status, message }) {
@@ -471,4 +461,69 @@ export async function saveDatabaseSettings(request: FastifyRequest<SaveDatabaseS
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}
}
export async function getDatabaseSecrets(request: FastifyRequest<OnlyId>) {
try {
const { id } = request.params
let secrets = await prisma.databaseSecret.findMany({
where: { databaseId: id },
orderBy: { createdAt: 'desc' }
});
secrets = secrets.map((secret) => {
secret.value = decrypt(secret.value);
return secret;
});
return {
secrets
}
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}
export async function saveDatabaseSecret(request: FastifyRequest<SaveDatabaseSecret>, reply: FastifyReply) {
try {
const { id } = request.params
let { name, value, isNew } = request.body
if (isNew) {
const found = await prisma.databaseSecret.findFirst({ where: { name, databaseId: id } });
if (found) {
throw `Secret ${name} already exists.`
} else {
value = encrypt(value.trim());
await prisma.databaseSecret.create({
data: { name, value, database: { connect: { id } } }
});
}
} else {
value = encrypt(value.trim());
const found = await prisma.databaseSecret.findFirst({ where: { databaseId: id, name } });
if (found) {
await prisma.databaseSecret.updateMany({
where: { databaseId: id, name },
data: { value }
});
} else {
await prisma.databaseSecret.create({
data: { name, value, database: { connect: { id } } }
});
}
}
return reply.code(201).send()
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}
export async function deleteDatabaseSecret(request: FastifyRequest<DeleteDatabaseSecret>) {
try {
const { id } = request.params
const { name } = request.body
await prisma.databaseSecret.deleteMany({ where: { databaseId: id, name } });
return {}
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}

View File

@@ -1,8 +1,9 @@
import { FastifyPluginAsync } from 'fastify';
import { deleteDatabase, getDatabase, getDatabaseLogs, getDatabaseStatus, getDatabaseTypes, getDatabaseUsage, getVersions, listDatabases, newDatabase, saveDatabase, saveDatabaseDestination, saveDatabaseSettings, saveDatabaseType, saveVersion, startDatabase, stopDatabase } from './handlers';
import { deleteDatabase, deleteDatabaseSecret, getDatabase, getDatabaseLogs, getDatabaseSecrets, getDatabaseStatus, getDatabaseTypes, getDatabaseUsage, getVersions, listDatabases, newDatabase, saveDatabase, saveDatabaseDestination, saveDatabaseSecret, saveDatabaseSettings, saveDatabaseType, saveVersion, startDatabase, stopDatabase } from './handlers';
import type { DeleteDatabase, GetDatabaseLogs, OnlyId, SaveDatabase, SaveDatabaseDestination, SaveDatabaseSettings, SaveVersion } from '../../../../types';
import type { SaveDatabaseType } from './types';
import type { OnlyId } from '../../../../types';
import type { DeleteDatabase, SaveDatabaseType, DeleteDatabaseSecret, GetDatabaseLogs, SaveDatabase, SaveDatabaseDestination, SaveDatabaseSecret, SaveDatabaseSettings, SaveVersion } from './types';
const root: FastifyPluginAsync = async (fastify): Promise<void> => {
fastify.addHook('onRequest', async (request) => {
@@ -19,6 +20,10 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
fastify.post<SaveDatabaseSettings>('/:id/settings', async (request) => await saveDatabaseSettings(request));
fastify.get<OnlyId>('/:id/secrets', async (request) => await getDatabaseSecrets(request));
fastify.post<SaveDatabaseSecret>('/:id/secrets', async (request, reply) => await saveDatabaseSecret(request, reply));
fastify.delete<DeleteDatabaseSecret>('/:id/secrets', async (request) => await deleteDatabaseSecret(request));
fastify.get('/:id/configuration/type', async (request) => await getDatabaseTypes(request));
fastify.post<SaveDatabaseType>('/:id/configuration/type', async (request, reply) => await saveDatabaseType(request, reply));

View File

@@ -5,4 +5,51 @@ export interface SaveDatabaseType extends OnlyId {
}
export interface DeleteDatabase extends OnlyId {
Body: { force: string }
}
}
export interface SaveVersion extends OnlyId {
Body: {
version: string
}
}
export interface SaveDatabaseDestination extends OnlyId {
Body: {
destinationId: string
}
}
export interface GetDatabaseLogs extends OnlyId {
Querystring: {
since: number
}
}
export interface SaveDatabase extends OnlyId {
Body: {
name: string,
defaultDatabase: string,
dbUser: string,
dbUserPassword: string,
rootUser: string,
rootUserPassword: string,
version: string,
isRunning: boolean
}
}
export interface SaveDatabaseSettings extends OnlyId {
Body: {
isPublic: boolean,
appendOnly: boolean
}
}
export interface SaveDatabaseSecret extends OnlyId {
Body: {
name: string,
value: string,
isNew: string,
}
}
export interface DeleteDatabaseSecret extends OnlyId {
Body: {
name: string,
}
}

View File

@@ -52,9 +52,7 @@ export async function update(request: FastifyRequest<Update>) {
const { latestVersion } = request.body;
try {
if (!isDev) {
const { isAutoUpdateEnabled } = (await prisma.setting.findFirst()) || {
isAutoUpdateEnabled: false
};
const { isAutoUpdateEnabled } = await prisma.setting.findFirst();
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
await asyncExecShell(`env | grep COOLIFY > .env`);
await asyncExecShell(
@@ -113,20 +111,31 @@ export async function showDashboard(request: FastifyRequest) {
const teamId = request.user.teamId;
const applications = await prisma.application.findMany({
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { settings: true }
include: { settings: true, destinationDocker: true, teams: true }
});
const databases = await prisma.database.findMany({
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { settings: true }
include: { settings: true, destinationDocker: true, teams: true }
});
const services = await prisma.service.findMany({
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { destinationDocker: true, teams: true }
});
const gitSources = await prisma.gitSource.findMany({
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { teams: true }
});
const destinations = await prisma.destinationDocker.findMany({
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } },
include: { teams: true }
});
const settings = await listSettings();
return {
applications,
databases,
services,
gitSources,
destinations,
settings,
};
} catch ({ status, message }) {

View File

@@ -173,16 +173,16 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi
where: { id: application.id },
data: { updatedAt: new Date() }
});
if (application.connectedDatabase && pullmergeRequestAction === 'opened' || pullmergeRequestAction === 'reopened') {
// Coolify hosted database
if (application.connectedDatabase.databaseId) {
const databaseId = application.connectedDatabase.databaseId;
const database = await prisma.database.findUnique({ where: { id: databaseId } });
if (database) {
await createdBranchDatabase(database, application.connectedDatabase.hostedDatabaseDBName, pullmergeRequestId);
}
}
}
// if (application.connectedDatabase && pullmergeRequestAction === 'opened' || pullmergeRequestAction === 'reopened') {
// // Coolify hosted database
// if (application.connectedDatabase.databaseId) {
// const databaseId = application.connectedDatabase.databaseId;
// const database = await prisma.database.findUnique({ where: { id: databaseId } });
// if (database) {
// await createdBranchDatabase(database, application.connectedDatabase.hostedDatabaseDBName, pullmergeRequestId);
// }
// }
// }
await prisma.build.create({
data: {
id: buildId,

View File

@@ -1,38 +1,4 @@
export interface OnlyId {
Params: { id: string },
}
export interface SaveVersion extends OnlyId {
Body: {
version: string
}
}
export interface SaveDatabaseDestination extends OnlyId {
Body: {
destinationId: string
}
}
export interface GetDatabaseLogs extends OnlyId {
Querystring: {
since: number
}
}
export interface SaveDatabase extends OnlyId {
Body: {
name: string,
defaultDatabase: string,
dbUser: string,
dbUserPassword: string,
rootUser: string,
rootUserPassword: string,
version: string,
isRunning: boolean
}
}
export interface SaveDatabaseSettings extends OnlyId {
Body: {
isPublic: boolean,
appendOnly: boolean
}
}