Merge pull request #293 from dominicbachmann/improve-typing
Started to introduce more typing
This commit is contained in:
commit
6a833934ce
@ -1,9 +1,17 @@
|
|||||||
async function send({ method, path, data = {}, headers, timeout = 30000 }) {
|
// TODO: Make this functions generic
|
||||||
|
|
||||||
|
async function send({
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
data = {},
|
||||||
|
headers,
|
||||||
|
timeout = 30000
|
||||||
|
}): Promise<Record<string, unknown>> {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const id = setTimeout(() => controller.abort(), timeout);
|
const id = setTimeout(() => controller.abort(), timeout);
|
||||||
const opts = { method, headers: {}, body: null, signal: controller.signal };
|
const opts = { method, headers: {}, body: null, signal: controller.signal };
|
||||||
if (Object.keys(data).length > 0) {
|
if (Object.keys(data).length > 0) {
|
||||||
let parsedData = data;
|
const parsedData = data;
|
||||||
for (const [key, value] of Object.entries(data)) {
|
for (const [key, value] of Object.entries(data)) {
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
parsedData[key] = null;
|
parsedData[key] = null;
|
||||||
@ -43,18 +51,33 @@ async function send({ method, path, data = {}, headers, timeout = 30000 }) {
|
|||||||
return responseData;
|
return responseData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get(path, headers = {}): Promise<any> {
|
export function get(
|
||||||
|
path: string,
|
||||||
|
headers: Record<string, unknown>
|
||||||
|
): Promise<Record<string, unknown>> {
|
||||||
return send({ method: 'GET', path, headers });
|
return send({ method: 'GET', path, headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function del(path, data = {}, headers = {}): Promise<any> {
|
export function del(
|
||||||
|
path: string,
|
||||||
|
data: Record<string, unknown>,
|
||||||
|
headers: Record<string, unknown>
|
||||||
|
): Promise<Record<string, unknown>> {
|
||||||
return send({ method: 'DELETE', path, data, headers });
|
return send({ method: 'DELETE', path, data, headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function post(path, data, headers = {}): Promise<any> {
|
export function post(
|
||||||
|
path: string,
|
||||||
|
data: Record<string, unknown>,
|
||||||
|
headers: Record<string, unknown>
|
||||||
|
): Promise<Record<string, unknown>> {
|
||||||
return send({ method: 'POST', path, data, headers });
|
return send({ method: 'POST', path, data, headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function put(path, data, headers = {}): Promise<any> {
|
export function put(
|
||||||
|
path: string,
|
||||||
|
data: Record<string, unknown>,
|
||||||
|
headers: Record<string, unknown>
|
||||||
|
): Promise<Record<string, unknown>> {
|
||||||
return send({ method: 'PUT', path, data, headers });
|
return send({ method: 'PUT', path, data, headers });
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,8 @@ import { version as currentVersion } from '../../package.json';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import Cookie from 'cookie';
|
import Cookie from 'cookie';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import cuid from 'cuid';
|
import type { RequestEvent } from '@sveltejs/kit/types/internal';
|
||||||
|
import type { Job } from 'bullmq';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
@ -45,13 +46,21 @@ const customConfig: Config = {
|
|||||||
|
|
||||||
export const version = currentVersion;
|
export const version = currentVersion;
|
||||||
export const asyncExecShell = util.promisify(child.exec);
|
export const asyncExecShell = util.promisify(child.exec);
|
||||||
export const asyncSleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
|
export const asyncSleep = (delay: number): Promise<unknown> =>
|
||||||
|
new Promise((resolve) => setTimeout(resolve, delay));
|
||||||
export const sentry = Sentry;
|
export const sentry = Sentry;
|
||||||
|
|
||||||
export const uniqueName = () => uniqueNamesGenerator(customConfig);
|
export const uniqueName = (): string => uniqueNamesGenerator(customConfig);
|
||||||
|
|
||||||
export const saveBuildLog = async ({ line, buildId, applicationId }) => {
|
export const saveBuildLog = async ({
|
||||||
|
line,
|
||||||
|
buildId,
|
||||||
|
applicationId
|
||||||
|
}: {
|
||||||
|
line: string;
|
||||||
|
buildId: string;
|
||||||
|
applicationId: string;
|
||||||
|
}): Promise<Job> => {
|
||||||
if (line) {
|
if (line) {
|
||||||
if (line.includes('ghs_')) {
|
if (line.includes('ghs_')) {
|
||||||
const regex = /ghs_.*@/g;
|
const regex = /ghs_.*@/g;
|
||||||
@ -62,20 +71,7 @@ export const saveBuildLog = async ({ line, buildId, applicationId }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isTeamIdTokenAvailable = (request) => {
|
export const getTeam = (event: RequestEvent): string | null => {
|
||||||
const cookie = request.headers.cookie
|
|
||||||
?.split(';')
|
|
||||||
.map((s) => s.trim())
|
|
||||||
.find((s) => s.startsWith('teamId='))
|
|
||||||
?.split('=')[1];
|
|
||||||
if (!cookie) {
|
|
||||||
return getTeam(request);
|
|
||||||
} else {
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getTeam = (event) => {
|
|
||||||
const cookies = Cookie.parse(event.request.headers.get('cookie'));
|
const cookies = Cookie.parse(event.request.headers.get('cookie'));
|
||||||
if (cookies?.teamId) {
|
if (cookies?.teamId) {
|
||||||
return cookies.teamId;
|
return cookies.teamId;
|
||||||
@ -85,7 +81,16 @@ export const getTeam = (event) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getUserDetails = async (event, isAdminRequired = true) => {
|
export const getUserDetails = async (
|
||||||
|
event: RequestEvent,
|
||||||
|
isAdminRequired = true
|
||||||
|
): Promise<{
|
||||||
|
teamId: string;
|
||||||
|
userId: string;
|
||||||
|
permission: string;
|
||||||
|
status: number;
|
||||||
|
body: { message: string };
|
||||||
|
}> => {
|
||||||
const teamId = getTeam(event);
|
const teamId = getTeam(event);
|
||||||
const userId = event?.locals?.session?.data?.userId || null;
|
const userId = event?.locals?.session?.data?.userId || null;
|
||||||
const { permission = 'read' } = await db.prisma.permission.findFirst({
|
const { permission = 'read' } = await db.prisma.permission.findFirst({
|
||||||
@ -112,11 +117,11 @@ export const getUserDetails = async (event, isAdminRequired = true) => {
|
|||||||
return payload;
|
return payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getEngine(engine) {
|
export function getEngine(engine: string): string {
|
||||||
return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : engine;
|
return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeContainer(id, engine) {
|
export async function removeContainer(id: string, engine: string): Promise<void> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
try {
|
try {
|
||||||
const { stdout } = await asyncExecShell(
|
const { stdout } = await asyncExecShell(
|
||||||
@ -132,11 +137,23 @@ export async function removeContainer(id, engine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeDestinationDocker = async ({ id, engine }) => {
|
export const removeDestinationDocker = async ({
|
||||||
|
id,
|
||||||
|
engine
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
engine: string;
|
||||||
|
}): Promise<void> => {
|
||||||
return await removeContainer(id, engine);
|
return await removeContainer(id, engine);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createDirectories = async ({ repository, buildId }) => {
|
export const createDirectories = async ({
|
||||||
|
repository,
|
||||||
|
buildId
|
||||||
|
}: {
|
||||||
|
repository: string;
|
||||||
|
buildId: string;
|
||||||
|
}): Promise<{ workdir: string; repodir: string }> => {
|
||||||
const repodir = `/tmp/build-sources/${repository}/`;
|
const repodir = `/tmp/build-sources/${repository}/`;
|
||||||
const workdir = `/tmp/build-sources/${repository}/${buildId}`;
|
const workdir = `/tmp/build-sources/${repository}/${buildId}`;
|
||||||
|
|
||||||
@ -148,20 +165,10 @@ export const createDirectories = async ({ repository, buildId }) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function generateTimestamp() {
|
export function generateTimestamp(): string {
|
||||||
return `${dayjs().format('HH:mm:ss.SSS')} `;
|
return `${dayjs().format('HH:mm:ss.SSS')} `;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDomain(domain) {
|
export function getDomain(domain: string): string {
|
||||||
return domain?.replace('https://', '').replace('http://', '');
|
return domain?.replace('https://', '').replace('http://', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function dashify(str: string, options?: any): string {
|
|
||||||
if (typeof str !== 'string') return str;
|
|
||||||
return str
|
|
||||||
.trim()
|
|
||||||
.replace(/\W/g, (m) => (/[À-ž]/.test(m) ? m : '-'))
|
|
||||||
.replace(/^-+|-+$/g, '')
|
|
||||||
.replace(/-{2,}/g, (m) => (options && options.condense ? '-' : m))
|
|
||||||
.toLowerCase();
|
|
||||||
}
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
const algorithm = 'aes-256-ctr';
|
const algorithm = 'aes-256-ctr';
|
||||||
|
|
||||||
export const base64Encode = (text: string) => {
|
export const base64Encode = (text: string): string => {
|
||||||
return Buffer.from(text).toString('base64');
|
return Buffer.from(text).toString('base64');
|
||||||
};
|
};
|
||||||
export const base64Decode = (text: string) => {
|
export const base64Decode = (text: string): string => {
|
||||||
return Buffer.from(text, 'base64').toString('ascii');
|
return Buffer.from(text, 'base64').toString('ascii');
|
||||||
};
|
};
|
||||||
export const encrypt = (text: string) => {
|
export const encrypt = (text: string): string => {
|
||||||
if (text) {
|
if (text) {
|
||||||
const iv = crypto.randomBytes(16);
|
const iv = crypto.randomBytes(16);
|
||||||
const cipher = crypto.createCipheriv(algorithm, process.env['COOLIFY_SECRET_KEY'], iv);
|
const cipher = crypto.createCipheriv(algorithm, process.env['COOLIFY_SECRET_KEY'], iv);
|
||||||
@ -19,7 +19,7 @@ export const encrypt = (text: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decrypt = (hashString: string) => {
|
export const decrypt = (hashString: string): string => {
|
||||||
if (hashString) {
|
if (hashString) {
|
||||||
const hash: Hash = JSON.parse(hashString);
|
const hash: Hash = JSON.parse(hashString);
|
||||||
const decipher = crypto.createDecipheriv(
|
const decipher = crypto.createDecipheriv(
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
import { decrypt, encrypt } from '$lib/crypto';
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
import { asyncExecShell, getEngine } from '$lib/common';
|
import { asyncExecShell, getEngine } from '$lib/common';
|
||||||
|
|
||||||
import { getDomain, removeDestinationDocker } from '$lib/common';
|
import { removeDestinationDocker } from '$lib/common';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
|
||||||
export async function listApplications(teamId) {
|
import type {
|
||||||
|
DestinationDocker,
|
||||||
|
GitSource,
|
||||||
|
Secret,
|
||||||
|
ApplicationSettings,
|
||||||
|
Application,
|
||||||
|
ApplicationPersistentStorage
|
||||||
|
} from '@prisma/client';
|
||||||
|
|
||||||
|
export async function listApplications(teamId: string): Promise<Application[]> {
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
return await prisma.application.findMany({ include: { teams: true } });
|
return await prisma.application.findMany({ include: { teams: true } });
|
||||||
}
|
}
|
||||||
@ -14,7 +23,13 @@ export async function listApplications(teamId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function newApplication({ name, teamId }) {
|
export async function newApplication({
|
||||||
|
name,
|
||||||
|
teamId
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
teamId: string;
|
||||||
|
}): Promise<Application> {
|
||||||
return await prisma.application.create({
|
return await prisma.application.create({
|
||||||
data: {
|
data: {
|
||||||
name,
|
name,
|
||||||
@ -24,34 +39,17 @@ export async function newApplication({ name, teamId }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function importApplication({
|
export async function removeApplication({
|
||||||
name,
|
id,
|
||||||
teamId,
|
teamId
|
||||||
fqdn,
|
}: {
|
||||||
port,
|
id: string;
|
||||||
buildCommand,
|
teamId: string;
|
||||||
startCommand,
|
}): Promise<void> {
|
||||||
installCommand
|
const { destinationDockerId, destinationDocker } = await prisma.application.findUnique({
|
||||||
}) {
|
|
||||||
return await prisma.application.create({
|
|
||||||
data: {
|
|
||||||
name,
|
|
||||||
fqdn,
|
|
||||||
port,
|
|
||||||
buildCommand,
|
|
||||||
startCommand,
|
|
||||||
installCommand,
|
|
||||||
teams: { connect: { id: teamId } }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeApplication({ id, teamId }) {
|
|
||||||
const { fqdn, destinationDockerId, destinationDocker } = await prisma.application.findUnique({
|
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { destinationDocker: true }
|
include: { destinationDocker: true }
|
||||||
});
|
});
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
const { stdout: containers } = await asyncExecShell(
|
const { stdout: containers } = await asyncExecShell(
|
||||||
@ -62,7 +60,6 @@ export async function removeApplication({ id, teamId }) {
|
|||||||
for (const container of containersArray) {
|
for (const container of containersArray) {
|
||||||
const containerObj = JSON.parse(container);
|
const containerObj = JSON.parse(container);
|
||||||
const id = containerObj.ID;
|
const id = containerObj.ID;
|
||||||
const preview = containerObj.Image.split('-')[1];
|
|
||||||
await removeDestinationDocker({ id, engine: destinationDocker.engine });
|
await removeDestinationDocker({ id, engine: destinationDocker.engine });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,9 +77,23 @@ export async function removeApplication({ id, teamId }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getApplicationWebhook({ projectId, branch }) {
|
export async function getApplicationWebhook({
|
||||||
|
projectId,
|
||||||
|
branch
|
||||||
|
}: {
|
||||||
|
projectId: number;
|
||||||
|
branch: string;
|
||||||
|
}): Promise<
|
||||||
|
Application & {
|
||||||
|
destinationDocker: DestinationDocker;
|
||||||
|
settings: ApplicationSettings;
|
||||||
|
gitSource: GitSource;
|
||||||
|
secrets: Secret[];
|
||||||
|
persistentStorage: ApplicationPersistentStorage[];
|
||||||
|
}
|
||||||
|
> {
|
||||||
try {
|
try {
|
||||||
let application = await prisma.application.findFirst({
|
const application = await prisma.application.findFirst({
|
||||||
where: { projectId, branch, settings: { autodeploy: true } },
|
where: { projectId, branch, settings: { autodeploy: true } },
|
||||||
include: {
|
include: {
|
||||||
destinationDocker: true,
|
destinationDocker: true,
|
||||||
@ -131,16 +142,17 @@ export async function getApplicationWebhook({ projectId, branch }) {
|
|||||||
throw { status: 404, body: { message: e.message } };
|
throw { status: 404, body: { message: e.message } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function getApplicationById({ id }) {
|
|
||||||
const body = await prisma.application.findFirst({
|
|
||||||
where: { id },
|
|
||||||
include: { destinationDocker: true }
|
|
||||||
});
|
|
||||||
|
|
||||||
return { ...body };
|
export async function getApplication({ id, teamId }: { id: string; teamId: string }): Promise<
|
||||||
}
|
Application & {
|
||||||
export async function getApplication({ id, teamId }) {
|
destinationDocker: DestinationDocker;
|
||||||
let body = {};
|
settings: ApplicationSettings;
|
||||||
|
gitSource: GitSource;
|
||||||
|
secrets: Secret[];
|
||||||
|
persistentStorage: ApplicationPersistentStorage[];
|
||||||
|
}
|
||||||
|
> {
|
||||||
|
let body;
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
body = await prisma.application.findFirst({
|
body = await prisma.application.findFirst({
|
||||||
where: { id },
|
where: { id },
|
||||||
@ -194,7 +206,14 @@ export async function configureGitRepository({
|
|||||||
projectId,
|
projectId,
|
||||||
webhookToken,
|
webhookToken,
|
||||||
autodeploy
|
autodeploy
|
||||||
}) {
|
}: {
|
||||||
|
id: string;
|
||||||
|
repository: string;
|
||||||
|
branch: string;
|
||||||
|
projectId: number;
|
||||||
|
webhookToken: string;
|
||||||
|
autodeploy: boolean;
|
||||||
|
}): Promise<void> {
|
||||||
if (webhookToken) {
|
if (webhookToken) {
|
||||||
const encryptedWebhookToken = encrypt(webhookToken);
|
const encryptedWebhookToken = encrypt(webhookToken);
|
||||||
await prisma.application.update({
|
await prisma.application.update({
|
||||||
@ -224,7 +243,10 @@ export async function configureGitRepository({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureBuildPack({ id, buildPack }) {
|
export async function configureBuildPack({
|
||||||
|
id,
|
||||||
|
buildPack
|
||||||
|
}: Pick<Application, 'id' | 'buildPack'>): Promise<Application> {
|
||||||
return await prisma.application.update({ where: { id }, data: { buildPack } });
|
return await prisma.application.update({ where: { id }, data: { buildPack } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +264,21 @@ export async function configureApplication({
|
|||||||
pythonWSGI,
|
pythonWSGI,
|
||||||
pythonModule,
|
pythonModule,
|
||||||
pythonVariable
|
pythonVariable
|
||||||
}) {
|
}: {
|
||||||
|
id: string;
|
||||||
|
buildPack: string;
|
||||||
|
name: string;
|
||||||
|
fqdn: string;
|
||||||
|
port: number;
|
||||||
|
installCommand: string;
|
||||||
|
buildCommand: string;
|
||||||
|
startCommand: string;
|
||||||
|
baseDirectory: string;
|
||||||
|
publishDirectory: string;
|
||||||
|
pythonWSGI: string;
|
||||||
|
pythonModule: string;
|
||||||
|
pythonVariable: string;
|
||||||
|
}): Promise<Application> {
|
||||||
return await prisma.application.update({
|
return await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
@ -262,11 +298,24 @@ export async function configureApplication({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkDoubleBranch(branch, projectId) {
|
export async function checkDoubleBranch(branch: string, projectId: number): Promise<boolean> {
|
||||||
const applications = await prisma.application.findMany({ where: { branch, projectId } });
|
const applications = await prisma.application.findMany({ where: { branch, projectId } });
|
||||||
return applications.length > 1;
|
return applications.length > 1;
|
||||||
}
|
}
|
||||||
export async function setApplicationSettings({ id, debug, previews, dualCerts, autodeploy }) {
|
|
||||||
|
export async function setApplicationSettings({
|
||||||
|
id,
|
||||||
|
debug,
|
||||||
|
previews,
|
||||||
|
dualCerts,
|
||||||
|
autodeploy
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
debug: boolean;
|
||||||
|
previews: boolean;
|
||||||
|
dualCerts: boolean;
|
||||||
|
autodeploy: boolean;
|
||||||
|
}): Promise<Application & { destinationDocker: DestinationDocker }> {
|
||||||
return await prisma.application.update({
|
return await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { settings: { update: { debug, previews, dualCerts, autodeploy } } },
|
data: { settings: { update: { debug, previews, dualCerts, autodeploy } } },
|
||||||
@ -274,29 +323,6 @@ export async function setApplicationSettings({ id, debug, previews, dualCerts, a
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createBuild({
|
export async function getPersistentStorage(id: string): Promise<ApplicationPersistentStorage[]> {
|
||||||
id,
|
|
||||||
applicationId,
|
|
||||||
destinationDockerId,
|
|
||||||
gitSourceId,
|
|
||||||
githubAppId,
|
|
||||||
gitlabAppId,
|
|
||||||
type
|
|
||||||
}) {
|
|
||||||
return await prisma.build.create({
|
|
||||||
data: {
|
|
||||||
id,
|
|
||||||
applicationId,
|
|
||||||
destinationDockerId,
|
|
||||||
gitSourceId,
|
|
||||||
githubAppId,
|
|
||||||
gitlabAppId,
|
|
||||||
status: 'running',
|
|
||||||
type
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getPersistentStorage(id) {
|
|
||||||
return await prisma.applicationPersistentStorage.findMany({ where: { applicationId: id } });
|
return await prisma.applicationPersistentStorage.findMany({ where: { applicationId: id } });
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
import { getDomain } from '$lib/common';
|
import { getDomain } from '$lib/common';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
import type { Application, ServiceSecret, DestinationDocker, Secret } from '@prisma/client';
|
||||||
|
|
||||||
export async function isBranchAlreadyUsed({ repository, branch, id }) {
|
export async function isBranchAlreadyUsed({
|
||||||
|
repository,
|
||||||
|
branch,
|
||||||
|
id
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
repository: string;
|
||||||
|
branch: string;
|
||||||
|
}): Promise<Application> {
|
||||||
const application = await prisma.application.findUnique({
|
const application = await prisma.application.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { gitSource: true }
|
include: { gitSource: true }
|
||||||
@ -11,18 +20,42 @@ export async function isBranchAlreadyUsed({ repository, branch, id }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isDockerNetworkExists({ network }) {
|
export async function isDockerNetworkExists({
|
||||||
|
network
|
||||||
|
}: {
|
||||||
|
network: string;
|
||||||
|
}): Promise<DestinationDocker> {
|
||||||
return await prisma.destinationDocker.findFirst({ where: { network } });
|
return await prisma.destinationDocker.findFirst({ where: { network } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isServiceSecretExists({ id, name }) {
|
export async function isServiceSecretExists({
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<ServiceSecret> {
|
||||||
return await prisma.serviceSecret.findFirst({ where: { name, serviceId: id } });
|
return await prisma.serviceSecret.findFirst({ where: { name, serviceId: id } });
|
||||||
}
|
}
|
||||||
export async function isSecretExists({ id, name, isPRMRSecret }) {
|
export async function isSecretExists({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
isPRMRSecret
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
isPRMRSecret: boolean;
|
||||||
|
}): Promise<Secret> {
|
||||||
return await prisma.secret.findFirst({ where: { name, applicationId: id, isPRMRSecret } });
|
return await prisma.secret.findFirst({ where: { name, applicationId: id, isPRMRSecret } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isDomainConfigured({ id, fqdn }) {
|
export async function isDomainConfigured({
|
||||||
|
id,
|
||||||
|
fqdn
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
}): Promise<boolean> {
|
||||||
const domain = getDomain(fqdn);
|
const domain = getDomain(fqdn);
|
||||||
const nakedDomain = domain.replace('www.', '');
|
const nakedDomain = domain.replace('www.', '');
|
||||||
const foundApp = await prisma.application.findFirst({
|
const foundApp = await prisma.application.findFirst({
|
||||||
@ -55,6 +88,5 @@ export async function isDomainConfigured({ id, fqdn }) {
|
|||||||
},
|
},
|
||||||
select: { fqdn: true }
|
select: { fqdn: true }
|
||||||
});
|
});
|
||||||
if (foundApp || foundService || coolifyFqdn) return true;
|
return !!(foundApp || foundService || coolifyFqdn);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@ import {
|
|||||||
} from '$lib/components/common';
|
} from '$lib/components/common';
|
||||||
import * as Prisma from '@prisma/client';
|
import * as Prisma from '@prisma/client';
|
||||||
import { default as ProdPrisma } from '@prisma/client';
|
import { default as ProdPrisma } from '@prisma/client';
|
||||||
import type { PrismaClientOptions } from '@prisma/client/runtime';
|
import type { Database, DatabaseSettings } from '@prisma/client';
|
||||||
import generator from 'generate-password';
|
import generator from 'generate-password';
|
||||||
import forge from 'node-forge';
|
import forge from 'node-forge';
|
||||||
|
|
||||||
export function generatePassword(length = 24) {
|
export function generatePassword(length = 24): string {
|
||||||
return generator.generate({
|
return generator.generate({
|
||||||
length,
|
length,
|
||||||
numbers: true,
|
numbers: true,
|
||||||
@ -30,8 +30,14 @@ export const prisma = new PrismaClient({
|
|||||||
rejectOnNotFound: false
|
rejectOnNotFound: false
|
||||||
});
|
});
|
||||||
|
|
||||||
export function ErrorHandler(e) {
|
export function ErrorHandler(e: {
|
||||||
if (e! instanceof Error) {
|
stdout?;
|
||||||
|
message?: string;
|
||||||
|
status?: number;
|
||||||
|
name?: string;
|
||||||
|
error?: string;
|
||||||
|
}): { status: number; body: { message: string; error: string } } {
|
||||||
|
if (e && e instanceof Error) {
|
||||||
e = new Error(e.toString());
|
e = new Error(e.toString());
|
||||||
}
|
}
|
||||||
let truncatedError = e;
|
let truncatedError = e;
|
||||||
@ -39,8 +45,7 @@ export function ErrorHandler(e) {
|
|||||||
truncatedError = e.stdout;
|
truncatedError = e.stdout;
|
||||||
}
|
}
|
||||||
if (e.message?.includes('docker run')) {
|
if (e.message?.includes('docker run')) {
|
||||||
let truncatedArray = [];
|
const truncatedArray: string[] = truncatedError.message.split('-').filter((line) => {
|
||||||
truncatedArray = truncatedError.message.split('-').filter((line) => {
|
|
||||||
if (!line.startsWith('e ')) {
|
if (!line.startsWith('e ')) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@ -68,11 +73,11 @@ export function ErrorHandler(e) {
|
|||||||
payload.body.message = 'Already exists. Choose another name.';
|
payload.body.message = 'Already exists. Choose another name.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.error(e)
|
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateSshKeyPair(): Promise<{ publicKey: string; privateKey: string }> {
|
export async function generateSshKeyPair(): Promise<{ publicKey: string; privateKey: string }> {
|
||||||
return await new Promise(async (resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
forge.pki.rsa.generateKeyPair({ bits: 4096, workers: -1 }, function (err, keys) {
|
forge.pki.rsa.generateKeyPair({ bits: 4096, workers: -1 }, function (err, keys) {
|
||||||
if (keys) {
|
if (keys) {
|
||||||
resolve({
|
resolve({
|
||||||
@ -86,35 +91,93 @@ export async function generateSshKeyPair(): Promise<{ publicKey: string; private
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getVersions(type) {
|
export function getVersions(type: string): string[] {
|
||||||
const found = supportedDatabaseTypesAndVersions.find((t) => t.name === type);
|
const found = supportedDatabaseTypesAndVersions.find((t) => t.name === type);
|
||||||
if (found) {
|
if (found) {
|
||||||
return found.versions;
|
return found.versions;
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
export function getDatabaseImage(type) {
|
|
||||||
|
export function getDatabaseImage(type: string): string {
|
||||||
const found = supportedDatabaseTypesAndVersions.find((t) => t.name === type);
|
const found = supportedDatabaseTypesAndVersions.find((t) => t.name === type);
|
||||||
if (found) {
|
if (found) {
|
||||||
return found.baseImage;
|
return found.baseImage;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
export function getServiceImage(type) {
|
|
||||||
|
export function getServiceImage(type: string): string {
|
||||||
const found = supportedServiceTypesAndVersions.find((t) => t.name === type);
|
const found = supportedServiceTypesAndVersions.find((t) => t.name === type);
|
||||||
if (found) {
|
if (found) {
|
||||||
return found.baseImage;
|
return found.baseImage;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
export function getServiceImages(type) {
|
|
||||||
|
export function getServiceImages(type: string): string[] {
|
||||||
const found = supportedServiceTypesAndVersions.find((t) => t.name === type);
|
const found = supportedServiceTypesAndVersions.find((t) => t.name === type);
|
||||||
if (found) {
|
if (found) {
|
||||||
return found.images;
|
return found.images;
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
export function generateDatabaseConfiguration(database) {
|
|
||||||
|
export function generateDatabaseConfiguration(database: Database & { settings: DatabaseSettings }):
|
||||||
|
| {
|
||||||
|
volume: string;
|
||||||
|
image: 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;
|
||||||
|
ulimits: Record<string, unknown>;
|
||||||
|
privatePort: number;
|
||||||
|
environmentVariables: {
|
||||||
|
MONGODB_ROOT_USER: string;
|
||||||
|
MONGODB_ROOT_PASSWORD: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
volume: string;
|
||||||
|
image: string;
|
||||||
|
ulimits: Record<string, unknown>;
|
||||||
|
privatePort: number;
|
||||||
|
environmentVariables: {
|
||||||
|
POSTGRESQL_USERNAME: string;
|
||||||
|
POSTGRESQL_PASSWORD: string;
|
||||||
|
POSTGRESQL_DATABASE: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
volume: string;
|
||||||
|
image: string;
|
||||||
|
ulimits: Record<string, unknown>;
|
||||||
|
privatePort: number;
|
||||||
|
environmentVariables: {
|
||||||
|
REDIS_AOF_ENABLED: string;
|
||||||
|
REDIS_PASSWORD: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
volume: string;
|
||||||
|
image: string;
|
||||||
|
ulimits: Record<string, unknown>;
|
||||||
|
privatePort: number;
|
||||||
|
environmentVariables: {
|
||||||
|
COUCHDB_PASSWORD: string;
|
||||||
|
COUCHDB_USER: string;
|
||||||
|
};
|
||||||
|
} {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
dbUser,
|
dbUser,
|
||||||
@ -129,7 +192,6 @@ export function generateDatabaseConfiguration(database) {
|
|||||||
const baseImage = getDatabaseImage(type);
|
const baseImage = getDatabaseImage(type);
|
||||||
if (type === 'mysql') {
|
if (type === 'mysql') {
|
||||||
return {
|
return {
|
||||||
// url: `mysql://${dbUser}:${dbUserPassword}@${id}:${isPublic ? port : 3306}/${defaultDatabase}`,
|
|
||||||
privatePort: 3306,
|
privatePort: 3306,
|
||||||
environmentVariables: {
|
environmentVariables: {
|
||||||
MYSQL_USER: dbUser,
|
MYSQL_USER: dbUser,
|
||||||
@ -144,7 +206,6 @@ export function generateDatabaseConfiguration(database) {
|
|||||||
};
|
};
|
||||||
} else if (type === 'mongodb') {
|
} else if (type === 'mongodb') {
|
||||||
return {
|
return {
|
||||||
// url: `mongodb://${dbUser}:${dbUserPassword}@${id}:${isPublic ? port : 27017}/${defaultDatabase}`,
|
|
||||||
privatePort: 27017,
|
privatePort: 27017,
|
||||||
environmentVariables: {
|
environmentVariables: {
|
||||||
MONGODB_ROOT_USER: rootUser,
|
MONGODB_ROOT_USER: rootUser,
|
||||||
@ -156,7 +217,6 @@ export function generateDatabaseConfiguration(database) {
|
|||||||
};
|
};
|
||||||
} else if (type === 'postgresql') {
|
} else if (type === 'postgresql') {
|
||||||
return {
|
return {
|
||||||
// url: `psql://${dbUser}:${dbUserPassword}@${id}:${isPublic ? port : 5432}/${defaultDatabase}`,
|
|
||||||
privatePort: 5432,
|
privatePort: 5432,
|
||||||
environmentVariables: {
|
environmentVariables: {
|
||||||
POSTGRESQL_POSTGRES_PASSWORD: rootUserPassword,
|
POSTGRESQL_POSTGRES_PASSWORD: rootUserPassword,
|
||||||
@ -170,7 +230,6 @@ export function generateDatabaseConfiguration(database) {
|
|||||||
};
|
};
|
||||||
} else if (type === 'redis') {
|
} else if (type === 'redis') {
|
||||||
return {
|
return {
|
||||||
// url: `redis://${dbUser}:${dbUserPassword}@${id}:${isPublic ? port : 6379}/${defaultDatabase}`,
|
|
||||||
privatePort: 6379,
|
privatePort: 6379,
|
||||||
environmentVariables: {
|
environmentVariables: {
|
||||||
REDIS_PASSWORD: dbUserPassword,
|
REDIS_PASSWORD: dbUserPassword,
|
||||||
@ -182,7 +241,6 @@ export function generateDatabaseConfiguration(database) {
|
|||||||
};
|
};
|
||||||
} else if (type === 'couchdb') {
|
} else if (type === 'couchdb') {
|
||||||
return {
|
return {
|
||||||
// url: `couchdb://${dbUser}:${dbUserPassword}@${id}:${isPublic ? port : 5984}/${defaultDatabase}`,
|
|
||||||
privatePort: 5984,
|
privatePort: 5984,
|
||||||
environmentVariables: {
|
environmentVariables: {
|
||||||
COUCHDB_PASSWORD: dbUserPassword,
|
COUCHDB_PASSWORD: dbUserPassword,
|
||||||
@ -193,18 +251,4 @@ export function generateDatabaseConfiguration(database) {
|
|||||||
ulimits: {}
|
ulimits: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// } else if (type === 'clickhouse') {
|
|
||||||
// return {
|
|
||||||
// url: `clickhouse://${dbUser}:${dbUserPassword}@${id}:${port}/${defaultDatabase}`,
|
|
||||||
// privatePort: 9000,
|
|
||||||
// image: `bitnami/clickhouse-server:${version}`,
|
|
||||||
// volume: `${id}-${type}-data:/var/lib/clickhouse`,
|
|
||||||
// ulimits: {
|
|
||||||
// nofile: {
|
|
||||||
// soft: 262144,
|
|
||||||
// hard: 262144
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import { decrypt, encrypt } from '$lib/crypto';
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
import * as db from '$lib/database';
|
|
||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
import { generatePassword } from '.';
|
import { generatePassword } from '.';
|
||||||
import { prisma, ErrorHandler } from './common';
|
import { prisma } from './common';
|
||||||
import getPort, { portNumbers } from 'get-port';
|
|
||||||
import { asyncExecShell, getEngine, removeContainer } from '$lib/common';
|
import { asyncExecShell, getEngine, removeContainer } from '$lib/common';
|
||||||
|
import type { Database, DatabaseSettings, DestinationDocker } from '@prisma/client';
|
||||||
|
|
||||||
export async function listDatabases(teamId) {
|
export async function listDatabases(teamId: string): Promise<Database[]> {
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
return await prisma.database.findMany({ include: { teams: true } });
|
return await prisma.database.findMany({ include: { teams: true } });
|
||||||
} else {
|
} else {
|
||||||
@ -16,7 +15,14 @@ export async function listDatabases(teamId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function newDatabase({ name, teamId }) {
|
|
||||||
|
export async function newDatabase({
|
||||||
|
name,
|
||||||
|
teamId
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
teamId: string;
|
||||||
|
}): Promise<Database> {
|
||||||
const dbUser = cuid();
|
const dbUser = cuid();
|
||||||
const dbUserPassword = encrypt(generatePassword());
|
const dbUserPassword = encrypt(generatePassword());
|
||||||
const rootUser = cuid();
|
const rootUser = cuid();
|
||||||
@ -37,8 +43,14 @@ export async function newDatabase({ name, teamId }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getDatabase({ id, teamId }) {
|
export async function getDatabase({
|
||||||
let body = {};
|
id,
|
||||||
|
teamId
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
teamId: string;
|
||||||
|
}): Promise<Database & { destinationDocker: DestinationDocker; settings: DatabaseSettings }> {
|
||||||
|
let body;
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
body = await prisma.database.findFirst({
|
body = await prisma.database.findFirst({
|
||||||
where: { id },
|
where: { id },
|
||||||
@ -50,20 +62,25 @@ export async function getDatabase({ id, teamId }) {
|
|||||||
include: { destinationDocker: true, settings: true }
|
include: { destinationDocker: true, settings: true }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.dbUserPassword) body.dbUserPassword = decrypt(body.dbUserPassword);
|
if (body.dbUserPassword) body.dbUserPassword = decrypt(body.dbUserPassword);
|
||||||
if (body.rootUserPassword) body.rootUserPassword = decrypt(body.rootUserPassword);
|
if (body.rootUserPassword) body.rootUserPassword = decrypt(body.rootUserPassword);
|
||||||
|
|
||||||
return { ...body };
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeDatabase({ id }) {
|
export async function removeDatabase({ id }: { id: string }): Promise<void> {
|
||||||
await prisma.databaseSettings.deleteMany({ where: { databaseId: id } });
|
await prisma.databaseSettings.deleteMany({ where: { databaseId: id } });
|
||||||
await prisma.database.delete({ where: { id } });
|
await prisma.database.delete({ where: { id } });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureDatabaseType({ id, type }) {
|
export async function configureDatabaseType({
|
||||||
|
id,
|
||||||
|
type
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
}): Promise<Database> {
|
||||||
return await prisma.database.update({
|
return await prisma.database.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { type }
|
data: { type }
|
||||||
@ -79,7 +96,7 @@ export async function setDatabase({
|
|||||||
version?: string;
|
version?: string;
|
||||||
isPublic?: boolean;
|
isPublic?: boolean;
|
||||||
appendOnly?: boolean;
|
appendOnly?: boolean;
|
||||||
}) {
|
}): Promise<Database> {
|
||||||
return await prisma.database.update({
|
return await prisma.database.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
@ -97,7 +114,16 @@ export async function updateDatabase({
|
|||||||
rootUser,
|
rootUser,
|
||||||
rootUserPassword,
|
rootUserPassword,
|
||||||
version
|
version
|
||||||
}) {
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
defaultDatabase: string;
|
||||||
|
dbUser: string;
|
||||||
|
dbUserPassword: string;
|
||||||
|
rootUser: string;
|
||||||
|
rootUserPassword: string;
|
||||||
|
version: string;
|
||||||
|
}): Promise<Database> {
|
||||||
const encryptedDbUserPassword = dbUserPassword && encrypt(dbUserPassword);
|
const encryptedDbUserPassword = dbUserPassword && encrypt(dbUserPassword);
|
||||||
const encryptedRootUserPassword = rootUserPassword && encrypt(rootUserPassword);
|
const encryptedRootUserPassword = rootUserPassword && encrypt(rootUserPassword);
|
||||||
return await prisma.database.update({
|
return await prisma.database.update({
|
||||||
@ -114,7 +140,9 @@ export async function updateDatabase({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stopDatabase(database) {
|
export async function stopDatabase(
|
||||||
|
database: Database & { destinationDocker: DestinationDocker }
|
||||||
|
): Promise<boolean> {
|
||||||
let everStarted = false;
|
let everStarted = false;
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
import { asyncExecShell, getEngine } from '$lib/common';
|
import { asyncExecShell, getEngine } from '$lib/common';
|
||||||
import { decrypt, encrypt } from '$lib/crypto';
|
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { dockerInstance } from '$lib/docker';
|
||||||
import { startCoolifyProxy } from '$lib/haproxy';
|
import { startCoolifyProxy } from '$lib/haproxy';
|
||||||
import { getDatabaseImage } from '.';
|
import { getDatabaseImage } from '.';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
import type { DestinationDocker, Service, Application, Prisma } from '@prisma/client';
|
||||||
|
import type { CreateDockerDestination } from '$lib/types/destinations';
|
||||||
|
|
||||||
export async function listDestinations(teamId) {
|
type DestinationConfigurationObject = {
|
||||||
|
id: string;
|
||||||
|
destinationId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FindDestinationFromTeam = {
|
||||||
|
id: string;
|
||||||
|
teamId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function listDestinations(teamId: string): Promise<DestinationDocker[]> {
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
return await prisma.destinationDocker.findMany({ include: { teams: true } });
|
return await prisma.destinationDocker.findMany({ include: { teams: true } });
|
||||||
}
|
}
|
||||||
@ -15,19 +26,28 @@ export async function listDestinations(teamId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureDestinationForService({ id, destinationId }) {
|
export async function configureDestinationForService({
|
||||||
|
id,
|
||||||
|
destinationId
|
||||||
|
}: DestinationConfigurationObject): Promise<Service> {
|
||||||
return await prisma.service.update({
|
return await prisma.service.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { destinationDocker: { connect: { id: destinationId } } }
|
data: { destinationDocker: { connect: { id: destinationId } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function configureDestinationForApplication({ id, destinationId }) {
|
export async function configureDestinationForApplication({
|
||||||
|
id,
|
||||||
|
destinationId
|
||||||
|
}: DestinationConfigurationObject): Promise<Application> {
|
||||||
return await prisma.application.update({
|
return await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { destinationDocker: { connect: { id: destinationId } } }
|
data: { destinationDocker: { connect: { id: destinationId } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function configureDestinationForDatabase({ id, destinationId }) {
|
export async function configureDestinationForDatabase({
|
||||||
|
id,
|
||||||
|
destinationId
|
||||||
|
}: DestinationConfigurationObject): Promise<void> {
|
||||||
await prisma.database.update({
|
await prisma.database.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { destinationDocker: { connect: { id: destinationId } } }
|
data: { destinationDocker: { connect: { id: destinationId } } }
|
||||||
@ -48,7 +68,12 @@ export async function configureDestinationForDatabase({ id, destinationId }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function updateDestination({ id, name, engine, network }) {
|
export async function updateDestination({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
engine,
|
||||||
|
network
|
||||||
|
}: Pick<DestinationDocker, 'id' | 'name' | 'engine' | 'network'>): Promise<DestinationDocker> {
|
||||||
return await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } });
|
return await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,13 +83,8 @@ export async function newRemoteDestination({
|
|||||||
engine,
|
engine,
|
||||||
network,
|
network,
|
||||||
isCoolifyProxyUsed,
|
isCoolifyProxyUsed,
|
||||||
remoteEngine,
|
remoteEngine
|
||||||
ipAddress,
|
}: CreateDockerDestination): Promise<string> {
|
||||||
user,
|
|
||||||
port,
|
|
||||||
sshPrivateKey
|
|
||||||
}) {
|
|
||||||
const encryptedPrivateKey = encrypt(sshPrivateKey);
|
|
||||||
const destination = await prisma.destinationDocker.create({
|
const destination = await prisma.destinationDocker.create({
|
||||||
data: {
|
data: {
|
||||||
name,
|
name,
|
||||||
@ -72,16 +92,18 @@ export async function newRemoteDestination({
|
|||||||
engine,
|
engine,
|
||||||
network,
|
network,
|
||||||
isCoolifyProxyUsed,
|
isCoolifyProxyUsed,
|
||||||
remoteEngine,
|
remoteEngine
|
||||||
ipAddress,
|
|
||||||
user,
|
|
||||||
port,
|
|
||||||
sshPrivateKey: encryptedPrivateKey
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return destination.id;
|
return destination.id;
|
||||||
}
|
}
|
||||||
export async function newLocalDestination({ name, teamId, engine, network, isCoolifyProxyUsed }) {
|
export async function newLocalDestination({
|
||||||
|
name,
|
||||||
|
teamId,
|
||||||
|
engine,
|
||||||
|
network,
|
||||||
|
isCoolifyProxyUsed
|
||||||
|
}: CreateDockerDestination): Promise<string> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const docker = dockerInstance({ destinationDocker: { engine, network } });
|
const docker = dockerInstance({ destinationDocker: { engine, network } });
|
||||||
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } });
|
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } });
|
||||||
@ -99,18 +121,14 @@ export async function newLocalDestination({ name, teamId, engine, network, isCoo
|
|||||||
(destination) => destination.network !== network && destination.isCoolifyProxyUsed === true
|
(destination) => destination.network !== network && destination.isCoolifyProxyUsed === true
|
||||||
);
|
);
|
||||||
if (proxyConfigured) {
|
if (proxyConfigured) {
|
||||||
if (proxyConfigured.isCoolifyProxyUsed) {
|
isCoolifyProxyUsed = !!proxyConfigured.isCoolifyProxyUsed;
|
||||||
isCoolifyProxyUsed = true;
|
|
||||||
} else {
|
|
||||||
isCoolifyProxyUsed = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } });
|
await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } });
|
||||||
}
|
}
|
||||||
if (isCoolifyProxyUsed) await startCoolifyProxy(engine);
|
if (isCoolifyProxyUsed) await startCoolifyProxy(engine);
|
||||||
return destination.id;
|
return destination.id;
|
||||||
}
|
}
|
||||||
export async function removeDestination({ id }) {
|
export async function removeDestination({ id }: Pick<DestinationDocker, 'id'>): Promise<void> {
|
||||||
const destination = await prisma.destinationDocker.delete({ where: { id } });
|
const destination = await prisma.destinationDocker.delete({ where: { id } });
|
||||||
if (destination.isCoolifyProxyUsed) {
|
if (destination.isCoolifyProxyUsed) {
|
||||||
const host = getEngine(destination.engine);
|
const host = getEngine(destination.engine);
|
||||||
@ -127,8 +145,11 @@ export async function removeDestination({ id }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getDestination({ id, teamId }) {
|
export async function getDestination({
|
||||||
let destination = {};
|
id,
|
||||||
|
teamId
|
||||||
|
}: FindDestinationFromTeam): Promise<DestinationDocker & { sshPrivateKey?: string }> {
|
||||||
|
let destination;
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
destination = await prisma.destinationDocker.findFirst({
|
destination = await prisma.destinationDocker.findFirst({
|
||||||
where: { id }
|
where: { id }
|
||||||
@ -141,13 +162,22 @@ export async function getDestination({ id, teamId }) {
|
|||||||
|
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
export async function getDestinationByApplicationId({ id, teamId }) {
|
export async function getDestinationByApplicationId({
|
||||||
|
id,
|
||||||
|
teamId
|
||||||
|
}: FindDestinationFromTeam): Promise<DestinationDocker> {
|
||||||
return await prisma.destinationDocker.findFirst({
|
return await prisma.destinationDocker.findFirst({
|
||||||
where: { application: { some: { id } }, teams: { some: { id: teamId } } }
|
where: { application: { some: { id } }, teams: { some: { id: teamId } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setDestinationSettings({ engine, isCoolifyProxyUsed }) {
|
export async function setDestinationSettings({
|
||||||
|
engine,
|
||||||
|
isCoolifyProxyUsed
|
||||||
|
}: {
|
||||||
|
engine: string;
|
||||||
|
isCoolifyProxyUsed: boolean;
|
||||||
|
}): Promise<Prisma.BatchPayload> {
|
||||||
return await prisma.destinationDocker.updateMany({
|
return await prisma.destinationDocker.updateMany({
|
||||||
where: { engine },
|
where: { engine },
|
||||||
data: { isCoolifyProxyUsed }
|
data: { isCoolifyProxyUsed }
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { decrypt, encrypt } from '$lib/crypto';
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
import type { GithubApp, GitlabApp, GitSource, Prisma, Application } from '@prisma/client';
|
||||||
|
|
||||||
export async function listSources(teamId) {
|
export async function listSources(
|
||||||
|
teamId: string | Prisma.StringFilter
|
||||||
|
): Promise<(GitSource & { githubApp?: GithubApp; gitlabApp?: GitlabApp })[]> {
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
return await prisma.gitSource.findMany({
|
return await prisma.gitSource.findMany({
|
||||||
include: { githubApp: true, gitlabApp: true, teams: true }
|
include: { githubApp: true, gitlabApp: true, teams: true }
|
||||||
@ -13,7 +16,21 @@ export async function listSources(teamId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function newSource({ teamId, name }) {
|
export async function newSource({
|
||||||
|
name,
|
||||||
|
teamId,
|
||||||
|
type,
|
||||||
|
htmlUrl,
|
||||||
|
apiUrl,
|
||||||
|
organization
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
teamId: string;
|
||||||
|
type: string;
|
||||||
|
htmlUrl: string;
|
||||||
|
apiUrl: string;
|
||||||
|
organization: string;
|
||||||
|
}): Promise<GitSource> {
|
||||||
return await prisma.gitSource.create({
|
return await prisma.gitSource.create({
|
||||||
data: {
|
data: {
|
||||||
name,
|
name,
|
||||||
@ -21,7 +38,7 @@ export async function newSource({ teamId, name }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function removeSource({ id }) {
|
export async function removeSource({ id }: { id: string }): Promise<void> {
|
||||||
const source = await prisma.gitSource.delete({
|
const source = await prisma.gitSource.delete({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { githubApp: true, gitlabApp: true }
|
include: { githubApp: true, gitlabApp: true }
|
||||||
@ -30,8 +47,14 @@ export async function removeSource({ id }) {
|
|||||||
if (source.gitlabAppId) await prisma.gitlabApp.delete({ where: { id: source.gitlabAppId } });
|
if (source.gitlabAppId) await prisma.gitlabApp.delete({ where: { id: source.gitlabAppId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSource({ id, teamId }) {
|
export async function getSource({
|
||||||
let body = {};
|
id,
|
||||||
|
teamId
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
teamId: string;
|
||||||
|
}): Promise<GitSource & { githubApp: GithubApp; gitlabApp: GitlabApp }> {
|
||||||
|
let body;
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
body = await prisma.gitSource.findFirst({
|
body = await prisma.gitSource.findFirst({
|
||||||
where: { id },
|
where: { id },
|
||||||
@ -80,19 +103,31 @@ export async function addGitLabSource({
|
|||||||
appId,
|
appId,
|
||||||
oauthId,
|
oauthId,
|
||||||
groupName,
|
groupName,
|
||||||
appSecret: encrptedAppSecret,
|
appSecret: encryptedAppSecret,
|
||||||
gitSource: { connect: { id } }
|
gitSource: { connect: { id } }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureGitsource({ id, gitSourceId }) {
|
export async function configureGitsource({
|
||||||
|
id,
|
||||||
|
gitSourceId
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
gitSourceId: string;
|
||||||
|
}): Promise<Application> {
|
||||||
return await prisma.application.update({
|
return await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { gitSource: { connect: { id: gitSourceId } } }
|
data: { gitSource: { connect: { id: gitSourceId } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function updateGitsource({ id, name, htmlUrl, apiUrl }) {
|
export async function updateGitsource({
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<GitSource> {
|
||||||
return await prisma.gitSource.update({
|
return await prisma.gitSource.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { name, htmlUrl, apiUrl }
|
data: { name, htmlUrl, apiUrl }
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
import { decrypt, encrypt } from '$lib/crypto';
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
import type { GithubApp } from '@prisma/client';
|
||||||
|
|
||||||
export async function addInstallation({ gitSourceId, installation_id }) {
|
// TODO: We should change installation_id to be camelCase
|
||||||
|
export async function addInstallation({
|
||||||
|
gitSourceId,
|
||||||
|
installation_id
|
||||||
|
}: {
|
||||||
|
gitSourceId: string;
|
||||||
|
installation_id: string;
|
||||||
|
}): Promise<GithubApp> {
|
||||||
const source = await prisma.gitSource.findUnique({
|
const source = await prisma.gitSource.findUnique({
|
||||||
where: { id: gitSourceId },
|
where: { id: gitSourceId },
|
||||||
include: { githubApp: true }
|
include: { githubApp: true }
|
||||||
@ -12,8 +20,12 @@ export async function addInstallation({ gitSourceId, installation_id }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUniqueGithubApp({ githubAppId }) {
|
export async function getUniqueGithubApp({
|
||||||
let body = await prisma.githubApp.findUnique({ where: { id: githubAppId } });
|
githubAppId
|
||||||
|
}: {
|
||||||
|
githubAppId: string;
|
||||||
|
}): Promise<GithubApp> {
|
||||||
|
const body = await prisma.githubApp.findUnique({ where: { id: githubAppId } });
|
||||||
if (body.privateKey) body.privateKey = decrypt(body.privateKey);
|
if (body.privateKey) body.privateKey = decrypt(body.privateKey);
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
@ -26,7 +38,15 @@ export async function createGithubApp({
|
|||||||
pem,
|
pem,
|
||||||
webhook_secret,
|
webhook_secret,
|
||||||
state
|
state
|
||||||
}) {
|
}: {
|
||||||
|
id: number;
|
||||||
|
client_id: string;
|
||||||
|
slug: string;
|
||||||
|
client_secret: string;
|
||||||
|
pem: string;
|
||||||
|
webhook_secret: string;
|
||||||
|
state: string;
|
||||||
|
}): Promise<GithubApp> {
|
||||||
const encryptedClientSecret = encrypt(client_secret);
|
const encryptedClientSecret = encrypt(client_secret);
|
||||||
const encryptedWebhookSecret = encrypt(webhook_secret);
|
const encryptedWebhookSecret = encrypt(webhook_secret);
|
||||||
const encryptedPem = encrypt(pem);
|
const encryptedPem = encrypt(pem);
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
import { encrypt } from '$lib/crypto';
|
import { encrypt } from '$lib/crypto';
|
||||||
import { generateSshKeyPair, prisma } from './common';
|
import { generateSshKeyPair, prisma } from './common';
|
||||||
|
import type { GitlabApp } from '@prisma/client';
|
||||||
|
|
||||||
export async function updateDeployKey({ id, deployKeyId }) {
|
export async function updateDeployKey({
|
||||||
|
id,
|
||||||
|
deployKeyId
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
deployKeyId: number;
|
||||||
|
}): Promise<GitlabApp> {
|
||||||
const application = await prisma.application.findUnique({
|
const application = await prisma.application.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { gitSource: { include: { gitlabApp: true } } }
|
include: { gitSource: { include: { gitlabApp: true } } }
|
||||||
@ -11,14 +18,24 @@ export async function updateDeployKey({ id, deployKeyId }) {
|
|||||||
data: { deployKeyId }
|
data: { deployKeyId }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function getSshKey({ id }) {
|
export async function getSshKey({
|
||||||
|
id
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
}): Promise<{ status: number; body: { publicKey: string } }> {
|
||||||
const application = await prisma.application.findUnique({
|
const application = await prisma.application.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { gitSource: { include: { gitlabApp: true } } }
|
include: { gitSource: { include: { gitlabApp: true } } }
|
||||||
});
|
});
|
||||||
return { status: 200, body: { publicKey: application.gitSource.gitlabApp.publicSshKey } };
|
return { status: 200, body: { publicKey: application.gitSource.gitlabApp.publicSshKey } };
|
||||||
}
|
}
|
||||||
export async function generateSshKey({ id }) {
|
export async function generateSshKey({
|
||||||
|
id
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
}): Promise<
|
||||||
|
{ status: number; body: { publicKey: string } } | { status: number; body?: undefined }
|
||||||
|
> {
|
||||||
const application = await prisma.application.findUnique({
|
const application = await prisma.application.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { gitSource: { include: { gitlabApp: true } } }
|
include: { gitSource: { include: { gitlabApp: true } } }
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
|
import type { BuildLog } from '@prisma/client';
|
||||||
import { prisma, ErrorHandler } from './common';
|
import { prisma, ErrorHandler } from './common';
|
||||||
|
|
||||||
export async function listLogs({ buildId, last = 0 }) {
|
export async function listLogs({
|
||||||
|
buildId,
|
||||||
|
last = 0
|
||||||
|
}: {
|
||||||
|
buildId: string;
|
||||||
|
last: number;
|
||||||
|
}): Promise<BuildLog[] | { status: number; body: { message: string; error: string } }> {
|
||||||
try {
|
try {
|
||||||
const body = await prisma.buildLog.findMany({
|
const body = await prisma.buildLog.findMany({
|
||||||
where: { buildId, time: { gt: last } },
|
where: { buildId, time: { gt: last } },
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { encrypt, decrypt } from '$lib/crypto';
|
import { encrypt, decrypt } from '$lib/crypto';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
import type { ServiceSecret, Secret, Prisma } from '@prisma/client';
|
||||||
|
|
||||||
export async function listServiceSecrets(serviceId: string) {
|
export async function listServiceSecrets(serviceId: string): Promise<ServiceSecret[]> {
|
||||||
let secrets = await prisma.serviceSecret.findMany({
|
let secrets = await prisma.serviceSecret.findMany({
|
||||||
where: { serviceId },
|
where: { serviceId },
|
||||||
orderBy: { createdAt: 'desc' }
|
orderBy: { createdAt: 'desc' }
|
||||||
@ -14,7 +15,7 @@ export async function listServiceSecrets(serviceId: string) {
|
|||||||
return secrets;
|
return secrets;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listSecrets(applicationId: string) {
|
export async function listSecrets(applicationId: string): Promise<Secret[]> {
|
||||||
let secrets = await prisma.secret.findMany({
|
let secrets = await prisma.secret.findMany({
|
||||||
where: { applicationId },
|
where: { applicationId },
|
||||||
orderBy: { createdAt: 'desc' }
|
orderBy: { createdAt: 'desc' }
|
||||||
@ -27,20 +28,48 @@ export async function listSecrets(applicationId: string) {
|
|||||||
return secrets;
|
return secrets;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createServiceSecret({ id, name, value }) {
|
export async function createServiceSecret({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
value
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
}): Promise<ServiceSecret> {
|
||||||
value = encrypt(value);
|
value = encrypt(value);
|
||||||
return await prisma.serviceSecret.create({
|
return await prisma.serviceSecret.create({
|
||||||
data: { name, value, service: { connect: { id } } }
|
data: { name, value, service: { connect: { id } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function createSecret({ id, name, value, isBuildSecret, isPRMRSecret }) {
|
export async function createSecret({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
isBuildSecret: boolean;
|
||||||
|
isPRMRSecret: boolean;
|
||||||
|
}): Promise<Secret> {
|
||||||
value = encrypt(value);
|
value = encrypt(value);
|
||||||
return await prisma.secret.create({
|
return await prisma.secret.create({
|
||||||
data: { name, value, isBuildSecret, isPRMRSecret, application: { connect: { id } } }
|
data: { name, value, isBuildSecret, isPRMRSecret, application: { connect: { id } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateServiceSecret({ id, name, value }) {
|
export async function updateServiceSecret({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
value
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
}): Promise<Prisma.BatchPayload | ServiceSecret> {
|
||||||
value = encrypt(value);
|
value = encrypt(value);
|
||||||
const found = await prisma.serviceSecret.findFirst({ where: { serviceId: id, name } });
|
const found = await prisma.serviceSecret.findFirst({ where: { serviceId: id, name } });
|
||||||
|
|
||||||
@ -55,7 +84,19 @@ export async function updateServiceSecret({ id, name, value }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function updateSecret({ id, name, value, isBuildSecret, isPRMRSecret }) {
|
export async function updateSecret({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
isBuildSecret,
|
||||||
|
isPRMRSecret
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
isBuildSecret: boolean;
|
||||||
|
isPRMRSecret: boolean;
|
||||||
|
}): Promise<Prisma.BatchPayload | Secret> {
|
||||||
value = encrypt(value);
|
value = encrypt(value);
|
||||||
const found = await prisma.secret.findFirst({ where: { applicationId: id, name, isPRMRSecret } });
|
const found = await prisma.secret.findFirst({ where: { applicationId: id, name, isPRMRSecret } });
|
||||||
|
|
||||||
@ -71,10 +112,22 @@ export async function updateSecret({ id, name, value, isBuildSecret, isPRMRSecre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeServiceSecret({ id, name }) {
|
export async function removeServiceSecret({
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Prisma.BatchPayload> {
|
||||||
return await prisma.serviceSecret.deleteMany({ where: { serviceId: id, name } });
|
return await prisma.serviceSecret.deleteMany({ where: { serviceId: id, name } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeSecret({ id, name }) {
|
export async function removeSecret({
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Prisma.BatchPayload> {
|
||||||
return await prisma.secret.deleteMany({ where: { applicationId: id, name } });
|
return await prisma.secret.deleteMany({ where: { applicationId: id, name } });
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { asyncExecShell, getEngine } from '$lib/common';
|
|
||||||
import { decrypt, encrypt } from '$lib/crypto';
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
|
import type { Minio, Service } from '@prisma/client';
|
||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
import { generatePassword } from '.';
|
import { generatePassword } from '.';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
|
||||||
export async function listServices(teamId) {
|
export async function listServices(teamId: string): Promise<Service[]> {
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
return await prisma.service.findMany({ include: { teams: true } });
|
return await prisma.service.findMany({ include: { teams: true } });
|
||||||
} else {
|
} else {
|
||||||
@ -15,12 +15,18 @@ export async function listServices(teamId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function newService({ name, teamId }) {
|
export async function newService({
|
||||||
|
name,
|
||||||
|
teamId
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
teamId: string;
|
||||||
|
}): Promise<Service> {
|
||||||
return await prisma.service.create({ data: { name, teams: { connect: { id: teamId } } } });
|
return await prisma.service.create({ data: { name, teams: { connect: { id: teamId } } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getService({ id, teamId }) {
|
export async function getService({ id, teamId }: { id: string; teamId: string }): Promise<Service> {
|
||||||
let body = {};
|
let body;
|
||||||
const include = {
|
const include = {
|
||||||
destinationDocker: true,
|
destinationDocker: true,
|
||||||
plausibleAnalytics: true,
|
plausibleAnalytics: true,
|
||||||
@ -83,7 +89,13 @@ export async function getService({ id, teamId }) {
|
|||||||
return { ...body, settings };
|
return { ...body, settings };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureServiceType({ id, type }) {
|
export async function configureServiceType({
|
||||||
|
id,
|
||||||
|
type
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
}): Promise<void> {
|
||||||
if (type === 'plausibleanalytics') {
|
if (type === 'plausibleanalytics') {
|
||||||
const password = encrypt(generatePassword());
|
const password = encrypt(generatePassword());
|
||||||
const postgresqlUser = cuid();
|
const postgresqlUser = cuid();
|
||||||
@ -199,44 +211,157 @@ export async function configureServiceType({ id, type }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function setServiceVersion({ id, version }) {
|
|
||||||
|
export async function setServiceVersion({
|
||||||
|
id,
|
||||||
|
version
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
version: string;
|
||||||
|
}): Promise<Service> {
|
||||||
return await prisma.service.update({
|
return await prisma.service.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { version }
|
data: { version }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setServiceSettings({ id, dualCerts }) {
|
export async function setServiceSettings({
|
||||||
|
id,
|
||||||
|
dualCerts
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
dualCerts: boolean;
|
||||||
|
}): Promise<Service> {
|
||||||
return await prisma.service.update({
|
return await prisma.service.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { dualCerts }
|
data: { dualCerts }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePlausibleAnalyticsService({ id, fqdn, email, username, name }) {
|
export async function updatePlausibleAnalyticsService({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
email,
|
||||||
|
username,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
}): Promise<void> {
|
||||||
await prisma.plausibleAnalytics.update({ where: { serviceId: id }, data: { email, username } });
|
await prisma.plausibleAnalytics.update({ where: { serviceId: id }, data: { email, username } });
|
||||||
await prisma.service.update({ where: { id }, data: { name, fqdn } });
|
await prisma.service.update({ where: { id }, data: { name, fqdn } });
|
||||||
}
|
}
|
||||||
export async function updateService({ id, fqdn, name }) {
|
|
||||||
|
export async function updateService({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Service> {
|
||||||
return await prisma.service.update({ where: { id }, data: { fqdn, name } });
|
return await prisma.service.update({ where: { id }, data: { fqdn, name } });
|
||||||
}
|
}
|
||||||
export async function updateWordpress({ id, fqdn, name, mysqlDatabase, extraConfig }) {
|
|
||||||
|
export async function updateLanguageToolService({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Service> {
|
||||||
|
return await prisma.service.update({ where: { id }, data: { fqdn, name } });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateMeiliSearchService({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Service> {
|
||||||
|
return await prisma.service.update({ where: { id }, data: { fqdn, name } });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateVaultWardenService({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Service> {
|
||||||
|
return await prisma.service.update({ where: { id }, data: { fqdn, name } });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateVsCodeServer({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
}): Promise<Service> {
|
||||||
|
return await prisma.service.update({ where: { id }, data: { fqdn, name } });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateWordpress({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name,
|
||||||
|
mysqlDatabase,
|
||||||
|
extraConfig
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
mysqlDatabase: string;
|
||||||
|
extraConfig: string;
|
||||||
|
}): Promise<Service> {
|
||||||
return await prisma.service.update({
|
return await prisma.service.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { fqdn, name, wordpress: { update: { mysqlDatabase, extraConfig } } }
|
data: { fqdn, name, wordpress: { update: { mysqlDatabase, extraConfig } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function updateMinioService({ id, publicPort }) {
|
|
||||||
|
export async function updateMinioService({
|
||||||
|
id,
|
||||||
|
publicPort
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
publicPort: number;
|
||||||
|
}): Promise<Minio> {
|
||||||
return await prisma.minio.update({ where: { serviceId: id }, data: { publicPort } });
|
return await prisma.minio.update({ where: { serviceId: id }, data: { publicPort } });
|
||||||
}
|
}
|
||||||
export async function updateGhostService({ id, fqdn, name, mariadbDatabase }) {
|
|
||||||
|
export async function updateGhostService({
|
||||||
|
id,
|
||||||
|
fqdn,
|
||||||
|
name,
|
||||||
|
mariadbDatabase
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fqdn: string;
|
||||||
|
name: string;
|
||||||
|
mariadbDatabase: string;
|
||||||
|
}): Promise<Service> {
|
||||||
return await prisma.service.update({
|
return await prisma.service.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { fqdn, name, ghost: { update: { mariadbDatabase } } }
|
data: { fqdn, name, ghost: { update: { mariadbDatabase } } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeService({ id }) {
|
export async function removeService({ id }: { id: string }): Promise<void> {
|
||||||
await prisma.meiliSearch.deleteMany({ where: { serviceId: id } });
|
await prisma.meiliSearch.deleteMany({ where: { serviceId: id } });
|
||||||
await prisma.ghost.deleteMany({ where: { serviceId: id } });
|
await prisma.ghost.deleteMany({ where: { serviceId: id } });
|
||||||
await prisma.plausibleAnalytics.deleteMany({ where: { serviceId: id } });
|
await prisma.plausibleAnalytics.deleteMany({ where: { serviceId: id } });
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { decrypt } from '$lib/crypto';
|
import { decrypt } from '$lib/crypto';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
import type { Setting } from '@prisma/client';
|
||||||
|
|
||||||
export async function listSettings() {
|
export async function listSettings(): Promise<Setting> {
|
||||||
let settings = await prisma.setting.findFirst({});
|
const settings = await prisma.setting.findFirst({});
|
||||||
if (settings.proxyPassword) settings.proxyPassword = decrypt(settings.proxyPassword);
|
if (settings.proxyPassword) settings.proxyPassword = decrypt(settings.proxyPassword);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
import type { Team, Permission } from '@prisma/client';
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
|
|
||||||
export async function listTeams() {
|
export async function listTeams(): Promise<Team[]> {
|
||||||
return await prisma.team.findMany();
|
return await prisma.team.findMany();
|
||||||
}
|
}
|
||||||
export async function newTeam({ name, userId }) {
|
export async function newTeam({ name, userId }: { name: string; userId: string }): Promise<Team> {
|
||||||
return await prisma.team.create({
|
return await prisma.team.create({
|
||||||
data: {
|
data: {
|
||||||
name,
|
name,
|
||||||
@ -12,7 +13,11 @@ export async function newTeam({ name, userId }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export async function getMyTeams({ userId }) {
|
export async function getMyTeams({
|
||||||
|
userId
|
||||||
|
}: {
|
||||||
|
userId: string;
|
||||||
|
}): Promise<(Permission & { team: Team & { _count: { users: number } } })[]> {
|
||||||
return await prisma.permission.findMany({
|
return await prisma.permission.findMany({
|
||||||
where: { userId },
|
where: { userId },
|
||||||
include: { team: { include: { _count: { select: { users: true } } } } }
|
include: { team: { include: { _count: { select: { users: true } } } } }
|
||||||
|
@ -3,14 +3,28 @@ import bcrypt from 'bcryptjs';
|
|||||||
|
|
||||||
import { prisma } from './common';
|
import { prisma } from './common';
|
||||||
import { asyncExecShell, uniqueName } from '$lib/common';
|
import { asyncExecShell, uniqueName } from '$lib/common';
|
||||||
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { startCoolifyProxy } from '$lib/haproxy';
|
import { startCoolifyProxy } from '$lib/haproxy';
|
||||||
export async function hashPassword(password: string) {
|
import type { User } from '@prisma/client';
|
||||||
|
|
||||||
|
export async function hashPassword(password: string): Promise<string> {
|
||||||
const saltRounds = 15;
|
const saltRounds = 15;
|
||||||
return bcrypt.hash(password, saltRounds);
|
return bcrypt.hash(password, saltRounds);
|
||||||
}
|
}
|
||||||
export async function login({ email, password, isLogin }) {
|
|
||||||
|
export async function login({
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
isLogin
|
||||||
|
}: {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
isLogin: boolean;
|
||||||
|
}): Promise<{
|
||||||
|
status: number;
|
||||||
|
headers: { 'Set-Cookie': string };
|
||||||
|
body: { userId: string; teamId: string; permission: string; isAdmin: boolean };
|
||||||
|
}> {
|
||||||
const users = await prisma.user.count();
|
const users = await prisma.user.count();
|
||||||
const userFound = await prisma.user.findUnique({
|
const userFound = await prisma.user.findUnique({
|
||||||
where: { email },
|
where: { email },
|
||||||
@ -140,6 +154,6 @@ export async function login({ email, password, isLogin }) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUser({ userId }) {
|
export async function getUser({ userId }: { userId: string }): Promise<User> {
|
||||||
return await prisma.user.findUnique({ where: { id: userId } });
|
return await prisma.user.findUnique({ where: { id: userId } });
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { toast } from '@zerodevx/svelte-toast';
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
export function errorNotification(message: string) {
|
|
||||||
|
export function errorNotification(message: string): void {
|
||||||
console.error(message);
|
console.error(message);
|
||||||
if (typeof message !== 'string') {
|
if (typeof message !== 'string') {
|
||||||
toast.push('Ooops, something is not okay, are you okay?');
|
toast.push('Ooops, something is not okay, are you okay?');
|
||||||
@ -30,7 +31,7 @@ export function enhance(
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
let body = new FormData(form);
|
let body = new FormData(form);
|
||||||
let parsedData = body;
|
const parsedData = body;
|
||||||
|
|
||||||
body.forEach((data, key) => {
|
body.forEach((data, key) => {
|
||||||
if (data === '' || data === null) parsedData.delete(key);
|
if (data === '' || data === null) parsedData.delete(key);
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import { dev } from '$app/env';
|
import { dev } from '$app/env';
|
||||||
import got from 'got';
|
import got, { type Got } from 'got';
|
||||||
import mustache from 'mustache';
|
|
||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { checkContainer, checkHAProxy } from '.';
|
import { checkContainer, checkHAProxy } from '.';
|
||||||
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
||||||
@ -10,7 +7,7 @@ import { supportedServiceTypesAndVersions } from '$lib/components/common';
|
|||||||
|
|
||||||
const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555';
|
const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555';
|
||||||
|
|
||||||
let template = `program api
|
const template = `program api
|
||||||
command /usr/bin/dataplaneapi -f /usr/local/etc/haproxy/dataplaneapi.hcl --userlist haproxy-dataplaneapi
|
command /usr/bin/dataplaneapi -f /usr/local/etc/haproxy/dataplaneapi.hcl --userlist haproxy-dataplaneapi
|
||||||
no option start-on-reload
|
no option start-on-reload
|
||||||
|
|
||||||
@ -128,7 +125,8 @@ backend {{domain}}
|
|||||||
server {{id}} {{id}}:{{port}} check fall 10
|
server {{id}} {{id}}:{{port}} check fall 10
|
||||||
{{/coolify}}
|
{{/coolify}}
|
||||||
`;
|
`;
|
||||||
export async function haproxyInstance() {
|
|
||||||
|
export async function haproxyInstance(): Promise<Got> {
|
||||||
const { proxyPassword } = await db.listSettings();
|
const { proxyPassword } = await db.listSettings();
|
||||||
return got.extend({
|
return got.extend({
|
||||||
prefixUrl: url,
|
prefixUrl: url,
|
||||||
@ -137,31 +135,96 @@ export async function haproxyInstance() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureHAProxy() {
|
export async function configureHAProxy(): Promise<void> {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
await checkHAProxy(haproxy);
|
await checkHAProxy(haproxy);
|
||||||
|
|
||||||
try {
|
const data = {
|
||||||
const data = {
|
applications: [],
|
||||||
applications: [],
|
services: [],
|
||||||
services: [],
|
coolify: []
|
||||||
coolify: []
|
};
|
||||||
};
|
const applications = await db.prisma.application.findMany({
|
||||||
const applications = await db.prisma.application.findMany({
|
include: { destinationDocker: true, settings: true }
|
||||||
include: { destinationDocker: true, settings: true }
|
});
|
||||||
});
|
for (const application of applications) {
|
||||||
for (const application of applications) {
|
const {
|
||||||
const {
|
fqdn,
|
||||||
fqdn,
|
id,
|
||||||
id,
|
port,
|
||||||
port,
|
destinationDocker,
|
||||||
destinationDocker,
|
destinationDockerId,
|
||||||
destinationDockerId,
|
settings: { previews },
|
||||||
settings: { previews },
|
updatedAt
|
||||||
updatedAt
|
} = application;
|
||||||
} = application;
|
if (destinationDockerId) {
|
||||||
if (destinationDockerId) {
|
const { engine, network } = destinationDocker;
|
||||||
const { engine, network } = destinationDocker;
|
const isRunning = await checkContainer(engine, id);
|
||||||
|
if (fqdn) {
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
const isWWW = fqdn.includes('www.');
|
||||||
|
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
||||||
|
if (isRunning) {
|
||||||
|
data.applications.push({
|
||||||
|
id,
|
||||||
|
port: port || 3000,
|
||||||
|
domain,
|
||||||
|
isRunning,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? domain.replace('www.', '') : 'www.' + domain,
|
||||||
|
updatedAt: updatedAt.getTime()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (previews) {
|
||||||
|
const host = getEngine(engine);
|
||||||
|
const { stdout } = await asyncExecShell(
|
||||||
|
`DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"`
|
||||||
|
);
|
||||||
|
const containers = stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter((a) => a)
|
||||||
|
.map((c) => c.replace(/"/g, ''));
|
||||||
|
if (containers.length > 0) {
|
||||||
|
for (const container of containers) {
|
||||||
|
const previewDomain = `${container.split('-')[1]}.${domain}`;
|
||||||
|
data.applications.push({
|
||||||
|
id: container,
|
||||||
|
port: port || 3000,
|
||||||
|
domain: previewDomain,
|
||||||
|
isRunning,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? previewDomain.replace('www.', '') : 'www.' + previewDomain,
|
||||||
|
updatedAt: updatedAt.getTime()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const services = await db.prisma.service.findMany({
|
||||||
|
include: {
|
||||||
|
destinationDocker: true,
|
||||||
|
minio: true,
|
||||||
|
plausibleAnalytics: true,
|
||||||
|
vscodeserver: true,
|
||||||
|
wordpress: true,
|
||||||
|
ghost: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const service of services) {
|
||||||
|
const { fqdn, id, type, destinationDocker, destinationDockerId, updatedAt } = service;
|
||||||
|
if (destinationDockerId) {
|
||||||
|
const { engine } = destinationDocker;
|
||||||
|
const found = supportedServiceTypesAndVersions.find((a) => a.name === type);
|
||||||
|
if (found) {
|
||||||
|
const port = found.ports.main;
|
||||||
|
const publicPort = service[type]?.publicPort;
|
||||||
const isRunning = await checkContainer(engine, id);
|
const isRunning = await checkContainer(engine, id);
|
||||||
if (fqdn) {
|
if (fqdn) {
|
||||||
const domain = getDomain(fqdn);
|
const domain = getDomain(fqdn);
|
||||||
@ -169,9 +232,10 @@ export async function configureHAProxy() {
|
|||||||
const isWWW = fqdn.includes('www.');
|
const isWWW = fqdn.includes('www.');
|
||||||
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
data.applications.push({
|
data.services.push({
|
||||||
id,
|
id,
|
||||||
port: port || 3000,
|
port,
|
||||||
|
publicPort,
|
||||||
domain,
|
domain,
|
||||||
isRunning,
|
isRunning,
|
||||||
isHttps,
|
isHttps,
|
||||||
@ -180,46 +244,24 @@ export async function configureHAProxy() {
|
|||||||
updatedAt: updatedAt.getTime()
|
updatedAt: updatedAt.getTime()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (previews) {
|
|
||||||
const host = getEngine(engine);
|
|
||||||
const { stdout } = await asyncExecShell(
|
|
||||||
`DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"`
|
|
||||||
);
|
|
||||||
const containers = stdout
|
|
||||||
.trim()
|
|
||||||
.split('\n')
|
|
||||||
.filter((a) => a)
|
|
||||||
.map((c) => c.replace(/"/g, ''));
|
|
||||||
if (containers.length > 0) {
|
|
||||||
for (const container of containers) {
|
|
||||||
let previewDomain = `${container.split('-')[1]}.${domain}`;
|
|
||||||
data.applications.push({
|
|
||||||
id: container,
|
|
||||||
port: port || 3000,
|
|
||||||
domain: previewDomain,
|
|
||||||
isRunning,
|
|
||||||
isHttps,
|
|
||||||
redirectValue,
|
|
||||||
redirectTo: isWWW ? previewDomain.replace('www.', '') : 'www.' + previewDomain,
|
|
||||||
updatedAt: updatedAt.getTime()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const services = await db.prisma.service.findMany({
|
}
|
||||||
include: {
|
const { fqdn } = await db.prisma.setting.findFirst();
|
||||||
destinationDocker: true,
|
if (fqdn) {
|
||||||
minio: true,
|
const domain = getDomain(fqdn);
|
||||||
plausibleAnalytics: true,
|
const isHttps = fqdn.startsWith('https://');
|
||||||
vscodeserver: true,
|
const isWWW = fqdn.includes('www.');
|
||||||
wordpress: true,
|
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
||||||
ghost: true
|
data.coolify.push({
|
||||||
}
|
id: dev ? 'host.docker.internal' : 'coolify',
|
||||||
|
port: 3000,
|
||||||
|
domain,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? domain.replace('www.', '') : 'www.' + domain
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const service of services) {
|
for (const service of services) {
|
||||||
const { fqdn, id, type, destinationDocker, destinationDockerId, updatedAt } = service;
|
const { fqdn, id, type, destinationDocker, destinationDockerId, updatedAt } = service;
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
@ -251,37 +293,5 @@ export async function configureHAProxy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { fqdn } = await db.prisma.setting.findFirst();
|
|
||||||
if (fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
const isWWW = fqdn.includes('www.');
|
|
||||||
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
|
||||||
data.coolify.push({
|
|
||||||
id: dev ? 'host.docker.internal' : 'coolify',
|
|
||||||
port: 3000,
|
|
||||||
domain,
|
|
||||||
isHttps,
|
|
||||||
redirectValue,
|
|
||||||
redirectTo: isWWW ? domain.replace('www.', '') : 'www.' + domain
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const output = mustache.render(template, data);
|
|
||||||
const newHash = crypto.createHash('md5').update(output).digest('hex');
|
|
||||||
const { proxyHash, id } = await db.listSettings();
|
|
||||||
if (proxyHash !== newHash) {
|
|
||||||
await db.prisma.setting.update({ where: { id }, data: { proxyHash: newHash } });
|
|
||||||
await haproxy.post(`v2/services/haproxy/configuration/raw`, {
|
|
||||||
searchParams: {
|
|
||||||
skip_version: true
|
|
||||||
},
|
|
||||||
body: output,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'text/plain'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { dev } from '$app/env';
|
import { dev } from '$app/env';
|
||||||
import { asyncExecShell, getEngine } from '$lib/common';
|
import { asyncExecShell, getEngine } from '$lib/common';
|
||||||
import got from 'got';
|
import got, { type Got, type Response } from 'got';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
|
import type { DestinationDocker } from '@prisma/client';
|
||||||
|
|
||||||
const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555';
|
const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555';
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ export const defaultProxyImage = `coolify-haproxy-alpine:latest`;
|
|||||||
export const defaultProxyImageTcp = `coolify-haproxy-tcp-alpine:latest`;
|
export const defaultProxyImageTcp = `coolify-haproxy-tcp-alpine:latest`;
|
||||||
export const defaultProxyImageHttp = `coolify-haproxy-http-alpine:latest`;
|
export const defaultProxyImageHttp = `coolify-haproxy-http-alpine:latest`;
|
||||||
|
|
||||||
export async function haproxyInstance() {
|
export async function haproxyInstance(): Promise<Got> {
|
||||||
const { proxyPassword } = await db.listSettings();
|
const { proxyPassword } = await db.listSettings();
|
||||||
return got.extend({
|
return got.extend({
|
||||||
prefixUrl: url,
|
prefixUrl: url,
|
||||||
@ -17,6 +18,7 @@ export async function haproxyInstance() {
|
|||||||
password: proxyPassword
|
password: proxyPassword
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRawConfiguration(): Promise<RawHaproxyConfiguration> {
|
export async function getRawConfiguration(): Promise<RawHaproxyConfiguration> {
|
||||||
return await (await haproxyInstance()).get(`v2/services/haproxy/configuration/raw`).json();
|
return await (await haproxyInstance()).get(`v2/services/haproxy/configuration/raw`).json();
|
||||||
}
|
}
|
||||||
@ -43,11 +45,12 @@ export async function getNextTransactionId(): Promise<string> {
|
|||||||
return newTransaction.id;
|
return newTransaction.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function completeTransaction(transactionId) {
|
export async function completeTransaction(transactionId: string): Promise<Response<string>> {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
return await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`);
|
return await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`);
|
||||||
}
|
}
|
||||||
export async function deleteProxy({ id }) {
|
|
||||||
|
export async function deleteProxy({ id }: { id: string }): Promise<void> {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
await checkHAProxy(haproxy);
|
await checkHAProxy(haproxy);
|
||||||
|
|
||||||
@ -77,11 +80,12 @@ export async function deleteProxy({ id }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function reloadHaproxy(engine) {
|
export async function reloadHaproxy(engine: string): Promise<{ stdout: string; stderr: string }> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
return await asyncExecShell(`DOCKER_HOST=${host} docker exec coolify-haproxy kill -HUP 1`);
|
return await asyncExecShell(`DOCKER_HOST=${host} docker exec coolify-haproxy kill -HUP 1`);
|
||||||
}
|
}
|
||||||
export async function checkHAProxy(haproxy?: any) {
|
|
||||||
|
export async function checkHAProxy(haproxy?: Got): Promise<void> {
|
||||||
if (!haproxy) haproxy = await haproxyInstance();
|
if (!haproxy) haproxy = await haproxyInstance();
|
||||||
try {
|
try {
|
||||||
await haproxy.get('v2/info');
|
await haproxy.get('v2/info');
|
||||||
@ -93,7 +97,10 @@ export async function checkHAProxy(haproxy?: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stopTcpHttpProxy(destinationDocker, publicPort) {
|
export async function stopTcpHttpProxy(
|
||||||
|
destinationDocker: DestinationDocker,
|
||||||
|
publicPort: number
|
||||||
|
): Promise<{ stdout: string; stderr: string } | Error> {
|
||||||
const { engine } = destinationDocker;
|
const { engine } = destinationDocker;
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const containerName = `haproxy-for-${publicPort}`;
|
const containerName = `haproxy-for-${publicPort}`;
|
||||||
@ -108,7 +115,13 @@ export async function stopTcpHttpProxy(destinationDocker, publicPort) {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function startTcpProxy(destinationDocker, id, publicPort, privatePort, volume = null) {
|
export async function startTcpProxy(
|
||||||
|
destinationDocker: DestinationDocker,
|
||||||
|
id: string,
|
||||||
|
publicPort: number,
|
||||||
|
privatePort: number,
|
||||||
|
volume?: string
|
||||||
|
): Promise<{ stdout: string; stderr: string } | Error> {
|
||||||
const { network, engine } = destinationDocker;
|
const { network, engine } = destinationDocker;
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
|
|
||||||
@ -132,7 +145,13 @@ export async function startTcpProxy(destinationDocker, id, publicPort, privatePo
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function startHttpProxy(destinationDocker, id, publicPort, privatePort) {
|
|
||||||
|
export async function startHttpProxy(
|
||||||
|
destinationDocker: DestinationDocker,
|
||||||
|
id: string,
|
||||||
|
publicPort: number,
|
||||||
|
privatePort: number
|
||||||
|
): Promise<{ stdout: string; stderr: string } | Error> {
|
||||||
const { network, engine } = destinationDocker;
|
const { network, engine } = destinationDocker;
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
|
|
||||||
@ -154,7 +173,8 @@ export async function startHttpProxy(destinationDocker, id, publicPort, privateP
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function startCoolifyProxy(engine) {
|
|
||||||
|
export async function startCoolifyProxy(engine: string): Promise<void> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const found = await checkContainer(engine, 'coolify-haproxy');
|
const found = await checkContainer(engine, 'coolify-haproxy');
|
||||||
const { proxyPassword, proxyUser, id } = await db.listSettings();
|
const { proxyPassword, proxyUser, id } = await db.listSettings();
|
||||||
@ -170,7 +190,8 @@ export async function startCoolifyProxy(engine) {
|
|||||||
}
|
}
|
||||||
await configureNetworkCoolifyProxy(engine);
|
await configureNetworkCoolifyProxy(engine);
|
||||||
}
|
}
|
||||||
export async function checkContainer(engine, container) {
|
|
||||||
|
export async function checkContainer(engine: string, container: string): Promise<boolean> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
let containerFound = false;
|
let containerFound = false;
|
||||||
|
|
||||||
@ -180,7 +201,7 @@ export async function checkContainer(engine, container) {
|
|||||||
);
|
);
|
||||||
const parsedStdout = JSON.parse(stdout);
|
const parsedStdout = JSON.parse(stdout);
|
||||||
const status = parsedStdout.Status;
|
const status = parsedStdout.Status;
|
||||||
const isRunning = status === 'running' ? true : false;
|
const isRunning = status === 'running';
|
||||||
if (status === 'exited' || status === 'created') {
|
if (status === 'exited' || status === 'created') {
|
||||||
await asyncExecShell(`DOCKER_HOST="${host}" docker rm ${container}`);
|
await asyncExecShell(`DOCKER_HOST="${host}" docker rm ${container}`);
|
||||||
}
|
}
|
||||||
@ -193,7 +214,9 @@ export async function checkContainer(engine, container) {
|
|||||||
return containerFound;
|
return containerFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stopCoolifyProxy(engine) {
|
export async function stopCoolifyProxy(
|
||||||
|
engine: string
|
||||||
|
): Promise<{ stdout: string; stderr: string } | Error> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const found = await checkContainer(engine, 'coolify-haproxy');
|
const found = await checkContainer(engine, 'coolify-haproxy');
|
||||||
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: false });
|
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: false });
|
||||||
@ -210,16 +233,12 @@ export async function stopCoolifyProxy(engine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureNetworkCoolifyProxy(engine) {
|
export async function configureNetworkCoolifyProxy(engine: string): Promise<void> {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const destinations = await db.prisma.destinationDocker.findMany({ where: { engine } });
|
const destinations = await db.prisma.destinationDocker.findMany({ where: { engine } });
|
||||||
destinations.forEach(async (destination) => {
|
for (const destination of destinations) {
|
||||||
try {
|
await asyncExecShell(
|
||||||
await asyncExecShell(
|
`DOCKER_HOST="${host}" docker network connect ${destination.network} coolify-haproxy`
|
||||||
`DOCKER_HOST="${host}" docker network connect ${destination.network} coolify-haproxy`
|
);
|
||||||
);
|
}
|
||||||
} catch (err) {
|
|
||||||
// TODO: handle error
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ import { asyncExecShell, saveBuildLog } from '$lib/common';
|
|||||||
import got from 'got';
|
import got from 'got';
|
||||||
import jsonwebtoken from 'jsonwebtoken';
|
import jsonwebtoken from 'jsonwebtoken';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
|
||||||
|
|
||||||
export default async function ({
|
export default async function ({
|
||||||
applicationId,
|
applicationId,
|
||||||
debug,
|
|
||||||
workdir,
|
workdir,
|
||||||
githubAppId,
|
githubAppId,
|
||||||
repository,
|
repository,
|
||||||
@ -14,7 +12,16 @@ export default async function ({
|
|||||||
htmlUrl,
|
htmlUrl,
|
||||||
branch,
|
branch,
|
||||||
buildId
|
buildId
|
||||||
}): Promise<any> {
|
}: {
|
||||||
|
applicationId: string;
|
||||||
|
workdir: string;
|
||||||
|
githubAppId: string;
|
||||||
|
repository: string;
|
||||||
|
apiUrl: string;
|
||||||
|
htmlUrl: string;
|
||||||
|
branch: string;
|
||||||
|
buildId: string;
|
||||||
|
}): Promise<string> {
|
||||||
const url = htmlUrl.replace('https://', '').replace('http://', '');
|
const url = htmlUrl.replace('https://', '').replace('http://', '');
|
||||||
await saveBuildLog({ line: 'GitHub importer started.', buildId, applicationId });
|
await saveBuildLog({ line: 'GitHub importer started.', buildId, applicationId });
|
||||||
const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId });
|
const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId });
|
||||||
|
@ -9,7 +9,16 @@ export default async function ({
|
|||||||
branch,
|
branch,
|
||||||
buildId,
|
buildId,
|
||||||
privateSshKey
|
privateSshKey
|
||||||
}): Promise<any> {
|
}: {
|
||||||
|
applicationId: string;
|
||||||
|
workdir: string;
|
||||||
|
repository: string;
|
||||||
|
htmlUrl: string;
|
||||||
|
branch: string;
|
||||||
|
buildId: string;
|
||||||
|
repodir: string;
|
||||||
|
privateSshKey: string;
|
||||||
|
}): Promise<string> {
|
||||||
const url = htmlUrl.replace('https://', '').replace('http://', '').replace(/\/$/, '');
|
const url = htmlUrl.replace('https://', '').replace('http://', '').replace(/\/$/, '');
|
||||||
await saveBuildLog({ line: 'GitLab importer started.', buildId, applicationId });
|
await saveBuildLog({ line: 'GitLab importer started.', buildId, applicationId });
|
||||||
await asyncExecShell(`echo '${privateSshKey}' > ${repodir}/id.rsa`);
|
await asyncExecShell(`echo '${privateSshKey}' > ${repodir}/id.rsa`);
|
||||||
|
@ -7,7 +7,7 @@ import fs from 'fs/promises';
|
|||||||
import getPort, { portNumbers } from 'get-port';
|
import getPort, { portNumbers } from 'get-port';
|
||||||
import { supportedServiceTypesAndVersions } from '$lib/components/common';
|
import { supportedServiceTypesAndVersions } from '$lib/components/common';
|
||||||
|
|
||||||
export async function letsEncrypt(domain, id = null, isCoolify = false) {
|
export async function letsEncrypt(domain: string, id?: string, isCoolify = false): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const data = await db.prisma.setting.findFirst();
|
const data = await db.prisma.setting.findFirst();
|
||||||
const { minPort, maxPort } = data;
|
const { minPort, maxPort } = data;
|
||||||
@ -98,7 +98,7 @@ export async function letsEncrypt(domain, id = null, isCoolify = false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateSSLCerts() {
|
export async function generateSSLCerts(): Promise<void> {
|
||||||
const ssls = [];
|
const ssls = [];
|
||||||
const applications = await db.prisma.application.findMany({
|
const applications = await db.prisma.application.findMany({
|
||||||
include: { destinationDocker: true, settings: true },
|
include: { destinationDocker: true, settings: true },
|
||||||
@ -131,7 +131,7 @@ export async function generateSSLCerts() {
|
|||||||
.map((c) => c.replace(/"/g, ''));
|
.map((c) => c.replace(/"/g, ''));
|
||||||
if (containers.length > 0) {
|
if (containers.length > 0) {
|
||||||
for (const container of containers) {
|
for (const container of containers) {
|
||||||
let previewDomain = `${container.split('-')[1]}.${domain}`;
|
const previewDomain = `${container.split('-')[1]}.${domain}`;
|
||||||
if (isHttps) ssls.push({ domain: previewDomain, id, isCoolify: false });
|
if (isHttps) ssls.push({ domain: previewDomain, id, isCoolify: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,27 +20,22 @@ import {
|
|||||||
setDefaultConfiguration
|
setDefaultConfiguration
|
||||||
} from '$lib/buildPacks/common';
|
} from '$lib/buildPacks/common';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
|
import type { Job } from 'bullmq';
|
||||||
|
import type { BuilderJob } from '$lib/types/builderJob';
|
||||||
|
|
||||||
import type { ComposeFile } from '$lib/types/composeFile';
|
import type { ComposeFile } from '$lib/types/composeFile';
|
||||||
|
|
||||||
export default async function (job) {
|
export default async function (job: Job<BuilderJob, void, string>): Promise<void> {
|
||||||
let {
|
const {
|
||||||
id: applicationId,
|
id: applicationId,
|
||||||
repository,
|
repository,
|
||||||
branch,
|
|
||||||
buildPack,
|
|
||||||
name,
|
name,
|
||||||
destinationDocker,
|
destinationDocker,
|
||||||
destinationDockerId,
|
destinationDockerId,
|
||||||
gitSource,
|
gitSource,
|
||||||
build_id: buildId,
|
build_id: buildId,
|
||||||
configHash,
|
configHash,
|
||||||
port,
|
|
||||||
installCommand,
|
|
||||||
buildCommand,
|
|
||||||
startCommand,
|
|
||||||
fqdn,
|
fqdn,
|
||||||
baseDirectory,
|
|
||||||
publishDirectory,
|
|
||||||
projectId,
|
projectId,
|
||||||
secrets,
|
secrets,
|
||||||
phpModules,
|
phpModules,
|
||||||
@ -53,6 +48,16 @@ export default async function (job) {
|
|||||||
pythonModule,
|
pythonModule,
|
||||||
pythonVariable
|
pythonVariable
|
||||||
} = job.data;
|
} = job.data;
|
||||||
|
let {
|
||||||
|
branch,
|
||||||
|
buildPack,
|
||||||
|
port,
|
||||||
|
installCommand,
|
||||||
|
buildCommand,
|
||||||
|
startCommand,
|
||||||
|
baseDirectory,
|
||||||
|
publishDirectory
|
||||||
|
} = job.data;
|
||||||
const { debug } = settings;
|
const { debug } = settings;
|
||||||
|
|
||||||
await asyncSleep(500);
|
await asyncSleep(500);
|
||||||
@ -67,7 +72,7 @@ export default async function (job) {
|
|||||||
});
|
});
|
||||||
let imageId = applicationId;
|
let imageId = applicationId;
|
||||||
let domain = getDomain(fqdn);
|
let domain = getDomain(fqdn);
|
||||||
let volumes =
|
const volumes =
|
||||||
persistentStorage?.map((storage) => {
|
persistentStorage?.map((storage) => {
|
||||||
return `${applicationId}${storage.path.replace(/\//gi, '-')}:${
|
return `${applicationId}${storage.path.replace(/\//gi, '-')}:${
|
||||||
buildPack !== 'docker' ? '/app' : ''
|
buildPack !== 'docker' ? '/app' : ''
|
||||||
@ -103,7 +108,7 @@ export default async function (job) {
|
|||||||
publishDirectory = configuration.publishDirectory;
|
publishDirectory = configuration.publishDirectory;
|
||||||
baseDirectory = configuration.baseDirectory;
|
baseDirectory = configuration.baseDirectory;
|
||||||
|
|
||||||
let commit = await importers[gitSource.type]({
|
const commit = await importers[gitSource.type]({
|
||||||
applicationId,
|
applicationId,
|
||||||
debug,
|
debug,
|
||||||
workdir,
|
workdir,
|
||||||
@ -210,9 +215,7 @@ export default async function (job) {
|
|||||||
await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId });
|
await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId });
|
||||||
throw new Error(`Build pack ${buildPack} not found.`);
|
throw new Error(`Build pack ${buildPack} not found.`);
|
||||||
}
|
}
|
||||||
deployNeeded = true;
|
|
||||||
} else {
|
} else {
|
||||||
deployNeeded = false;
|
|
||||||
await saveBuildLog({ line: 'Nothing changed.', buildId, applicationId });
|
await saveBuildLog({ line: 'Nothing changed.', buildId, applicationId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { dev } from '$app/env';
|
|
||||||
import { asyncExecShell, getEngine, version } from '$lib/common';
|
import { asyncExecShell, getEngine, version } from '$lib/common';
|
||||||
import { prisma } from '$lib/database';
|
import { prisma } from '$lib/database';
|
||||||
import { defaultProxyImageHttp, defaultProxyImageTcp } from '$lib/haproxy';
|
export default async function (): Promise<void> {
|
||||||
export default async function () {
|
|
||||||
const destinationDockers = await prisma.destinationDocker.findMany();
|
const destinationDockers = await prisma.destinationDocker.findMany();
|
||||||
for (const destinationDocker of destinationDockers) {
|
for (const destinationDocker of destinationDockers) {
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import * as Bullmq from 'bullmq';
|
import * as Bullmq from 'bullmq';
|
||||||
import { default as ProdBullmq, Job, QueueEvents, QueueScheduler } from 'bullmq';
|
import { default as ProdBullmq, QueueScheduler } from 'bullmq';
|
||||||
import cuid from 'cuid';
|
|
||||||
import { dev } from '$app/env';
|
import { dev } from '$app/env';
|
||||||
import { prisma } from '$lib/database';
|
import { prisma } from '$lib/database';
|
||||||
|
|
||||||
import builder from './builder';
|
import builder from './builder';
|
||||||
import logger from './logger';
|
|
||||||
import cleanup from './cleanup';
|
import cleanup from './cleanup';
|
||||||
import proxy from './proxy';
|
import proxy from './proxy';
|
||||||
import ssl from './ssl';
|
import ssl from './ssl';
|
||||||
@ -28,7 +25,7 @@ const connectionOptions = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const cron = async () => {
|
const cron = async (): Promise<void> => {
|
||||||
new QueueScheduler('proxy', connectionOptions);
|
new QueueScheduler('proxy', connectionOptions);
|
||||||
new QueueScheduler('cleanup', connectionOptions);
|
new QueueScheduler('cleanup', connectionOptions);
|
||||||
new QueueScheduler('ssl', connectionOptions);
|
new QueueScheduler('ssl', connectionOptions);
|
||||||
@ -89,18 +86,6 @@ const cron = async () => {
|
|||||||
await queue.ssl.add('ssl', {}, { repeat: { every: dev ? 10000 : 60000 } });
|
await queue.ssl.add('ssl', {}, { repeat: { every: dev ? 10000 : 60000 } });
|
||||||
if (!dev) await queue.cleanup.add('cleanup', {}, { repeat: { every: 300000 } });
|
if (!dev) await queue.cleanup.add('cleanup', {}, { repeat: { every: 300000 } });
|
||||||
await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } });
|
await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } });
|
||||||
|
|
||||||
const events = {
|
|
||||||
proxy: new QueueEvents('proxy', { ...connectionOptions }),
|
|
||||||
ssl: new QueueEvents('ssl', { ...connectionOptions })
|
|
||||||
};
|
|
||||||
|
|
||||||
events.proxy.on('completed', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
});
|
|
||||||
events.ssl.on('completed', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
cron().catch((error) => {
|
cron().catch((error) => {
|
||||||
console.log('cron failed to start');
|
console.log('cron failed to start');
|
||||||
@ -157,9 +142,5 @@ buildWorker.on('failed', async (job: Bullmq.Job, failedReason) => {
|
|||||||
|
|
||||||
const buildLogQueueName = 'log_queue';
|
const buildLogQueueName = 'log_queue';
|
||||||
const buildLogQueue = new Queue(buildLogQueueName, connectionOptions);
|
const buildLogQueue = new Queue(buildLogQueueName, connectionOptions);
|
||||||
const buildLogWorker = new Worker(buildLogQueueName, async (job) => await logger(job), {
|
|
||||||
concurrency: 1,
|
|
||||||
...connectionOptions
|
|
||||||
});
|
|
||||||
|
|
||||||
export { buildQueue, buildLogQueue };
|
export { buildQueue, buildLogQueue };
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { prisma } from '$lib/database';
|
import { prisma } from '$lib/database';
|
||||||
import { dev } from '$app/env';
|
import { dev } from '$app/env';
|
||||||
|
import type { Job } from 'bullmq';
|
||||||
|
|
||||||
export default async function (job) {
|
export default async function (job: Job): Promise<void> {
|
||||||
const { line, applicationId, buildId } = job.data;
|
const { line, applicationId, buildId } = job.data;
|
||||||
if (dev) console.debug(`[${applicationId}] ${line}`);
|
if (dev) console.debug(`[${applicationId}] ${line}`);
|
||||||
await prisma.buildLog.create({ data: { line, buildId, time: Number(job.id), applicationId } });
|
await prisma.buildLog.create({ data: { line, buildId, time: Number(job.id), applicationId } });
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { configureHAProxy } from '$lib/haproxy/configuration';
|
import { configureHAProxy } from '$lib/haproxy/configuration';
|
||||||
|
|
||||||
export default async function () {
|
export default async function (): Promise<void | {
|
||||||
|
status: number;
|
||||||
|
body: { message: string; error: string };
|
||||||
|
}> {
|
||||||
try {
|
try {
|
||||||
return await configureHAProxy();
|
return await configureHAProxy();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { generateSSLCerts } from '$lib/letsencrypt';
|
import { generateSSLCerts } from '$lib/letsencrypt';
|
||||||
|
|
||||||
export default async function () {
|
export default async function (): Promise<void> {
|
||||||
try {
|
try {
|
||||||
return await generateSSLCerts();
|
return await generateSSLCerts();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
import { asyncExecShell } from '$lib/common';
|
import { asyncExecShell } from '$lib/common';
|
||||||
import { reloadHaproxy } from '$lib/haproxy';
|
import { reloadHaproxy } from '$lib/haproxy';
|
||||||
|
|
||||||
export default async function () {
|
export default async function (): Promise<void> {
|
||||||
try {
|
await asyncExecShell(
|
||||||
await asyncExecShell(
|
`docker run --rm --name certbot-renewal -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs renew`
|
||||||
`docker run --rm --name certbot-renewal -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs renew`
|
);
|
||||||
);
|
await reloadHaproxy('unix:///var/run/docker.sock');
|
||||||
await reloadHaproxy('unix:///var/run/docker.sock');
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { writable, type Writable } from 'svelte/store';
|
||||||
|
|
||||||
export const gitTokens = writable({
|
export const gitTokens: Writable<{ githubToken: string | null; gitlabToken: string | null }> =
|
||||||
githubToken: null,
|
writable({
|
||||||
gitlabToken: null
|
githubToken: null,
|
||||||
});
|
gitlabToken: null
|
||||||
|
});
|
||||||
|
51
src/lib/types/builderJob.ts
Normal file
51
src/lib/types/builderJob.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import type { DestinationDocker, GithubApp, GitlabApp, GitSource, Secret } from '@prisma/client';
|
||||||
|
|
||||||
|
export type BuilderJob = {
|
||||||
|
build_id: string;
|
||||||
|
type: BuildType;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
fqdn: string;
|
||||||
|
repository: string;
|
||||||
|
configHash: unknown;
|
||||||
|
branch: string;
|
||||||
|
buildPack: BuildPackName;
|
||||||
|
projectId: number;
|
||||||
|
port: number;
|
||||||
|
installCommand: string;
|
||||||
|
buildCommand?: string;
|
||||||
|
startCommand?: string;
|
||||||
|
baseDirectory: string;
|
||||||
|
publishDirectory: string;
|
||||||
|
phpModules: string;
|
||||||
|
pythonWSGI: string;
|
||||||
|
pythonModule: string;
|
||||||
|
pythonVariable: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
destinationDockerId: string;
|
||||||
|
destinationDocker: DestinationDocker;
|
||||||
|
gitSource: GitSource & { githubApp?: GithubApp; gitlabApp?: GitlabApp };
|
||||||
|
settings: BuilderJobSettings;
|
||||||
|
secrets: Secret[];
|
||||||
|
persistentStorage: { path: string }[];
|
||||||
|
pullmergeRequestId?: unknown;
|
||||||
|
sourceBranch?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Add the other build types
|
||||||
|
export type BuildType = 'manual';
|
||||||
|
|
||||||
|
// TODO: Add the other buildpack names
|
||||||
|
export type BuildPackName = 'node' | 'docker';
|
||||||
|
|
||||||
|
export type BuilderJobSettings = {
|
||||||
|
id: string;
|
||||||
|
applicationId: string;
|
||||||
|
dualCerts: boolean;
|
||||||
|
debug: boolean;
|
||||||
|
previews: boolean;
|
||||||
|
autodeploy: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
8
src/lib/types/destinations.ts
Normal file
8
src/lib/types/destinations.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export type CreateDockerDestination = {
|
||||||
|
name: string;
|
||||||
|
engine: string;
|
||||||
|
remoteEngine: boolean;
|
||||||
|
network: string;
|
||||||
|
isCoolifyProxyUsed: boolean;
|
||||||
|
teamId: string;
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import { getTeam, getUserDetails } from '$lib/common';
|
import { getUserDetails } from '$lib/common';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
@ -1,43 +1,22 @@
|
|||||||
import { asyncExecShell, getUserDetails } from '$lib/common';
|
import { getUserDetails } from '$lib/common';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
import type { CreateDockerDestination } from '$lib/types/destinations';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
const { teamId, status, body } = await getUserDetails(event);
|
const { teamId, status, body } = await getUserDetails(event);
|
||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const {
|
const dockerDestinationProps = {
|
||||||
name,
|
...((await event.request.json()) as Omit<CreateDockerDestination, 'teamId'>),
|
||||||
engine,
|
teamId
|
||||||
network,
|
};
|
||||||
isCoolifyProxyUsed,
|
|
||||||
remoteEngine,
|
|
||||||
ipAddress,
|
|
||||||
user,
|
|
||||||
port,
|
|
||||||
sshPrivateKey
|
|
||||||
} = await event.request.json();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let id = null;
|
const id = dockerDestinationProps.remoteEngine
|
||||||
if (remoteEngine) {
|
? await db.newRemoteDestination(dockerDestinationProps)
|
||||||
id = await db.newRemoteDestination({
|
: await db.newLocalDestination(dockerDestinationProps);
|
||||||
name,
|
|
||||||
teamId,
|
|
||||||
engine,
|
|
||||||
network,
|
|
||||||
isCoolifyProxyUsed,
|
|
||||||
remoteEngine,
|
|
||||||
ipAddress,
|
|
||||||
user,
|
|
||||||
port,
|
|
||||||
sshPrivateKey
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
id = await db.newLocalDestination({ name, teamId, engine, network, isCoolifyProxyUsed });
|
|
||||||
}
|
|
||||||
return { status: 200, body: { id } };
|
return { status: 200, body: { id } };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
|
Loading…
Reference in New Issue
Block a user