From 90597389c9315117f33f107b37a0626b27213daf Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 14 Jul 2022 12:47:26 +0000 Subject: [PATCH] fix: more types for API --- apps/api/src/index.ts | 2 +- apps/api/src/lib/common.ts | 4 +- .../routes/api/v1/applications/handlers.ts | 67 +++++----- .../src/routes/api/v1/applications/index.ts | 84 ++++--------- .../src/routes/api/v1/applications/types.ts | 117 +++++++++++++++++ apps/api/src/routes/api/v1/base/index.ts | 4 +- .../src/routes/api/v1/databases/handlers.ts | 29 +++-- apps/api/src/routes/api/v1/databases/index.ts | 31 ++--- apps/api/src/routes/api/v1/databases/types.ts | 5 + .../routes/api/v1/destinations/handlers.ts | 22 ++-- .../src/routes/api/v1/destinations/index.ts | 26 ++-- .../src/routes/api/v1/destinations/types.ts | 26 ++++ apps/api/src/routes/api/v1/handlers.ts | 14 +-- apps/api/src/routes/api/v1/iam/handlers.ts | 32 ++--- apps/api/src/routes/api/v1/iam/index.ts | 25 ++-- apps/api/src/routes/api/v1/iam/types.ts | 27 ++++ apps/api/src/routes/api/v1/index.ts | 6 +- .../src/routes/api/v1/services/handlers.ts | 119 +++++++++--------- apps/api/src/routes/api/v1/services/index.ts | 51 ++++---- apps/api/src/routes/api/v1/services/types.ts | 87 +++++++++++++ .../src/routes/api/v1/settings/handlers.ts | 11 +- apps/api/src/routes/api/v1/settings/index.ts | 13 +- apps/api/src/routes/api/v1/settings/types.ts | 31 +++++ .../api/src/routes/api/v1/sources/handlers.ts | 12 +- apps/api/src/routes/api/v1/sources/index.ts | 15 +-- apps/api/src/routes/api/v1/sources/types.ts | 29 +++++ apps/api/src/routes/api/v1/types.ts | 3 + .../src/routes/webhooks/github/handlers.ts | 12 +- apps/api/src/routes/webhooks/github/index.ts | 8 +- apps/api/src/routes/webhooks/github/types.ts | 20 +++ .../src/routes/webhooks/gitlab/handlers.ts | 13 +- apps/api/src/routes/webhooks/gitlab/index.ts | 8 +- apps/api/src/routes/webhooks/gitlab/types.ts | 24 ++++ .../src/routes/webhooks/traefik/handlers.ts | 3 +- apps/api/src/routes/webhooks/traefik/index.ts | 5 +- apps/api/src/routes/webhooks/traefik/types.ts | 9 ++ apps/api/src/types.ts | 38 ++++++ apps/ui/src/routes/iam/index.svelte | 2 +- apps/ui/src/routes/webhooks/success.svelte | 2 +- package.json | 2 +- 40 files changed, 722 insertions(+), 316 deletions(-) create mode 100644 apps/api/src/routes/api/v1/applications/types.ts create mode 100644 apps/api/src/routes/api/v1/databases/types.ts create mode 100644 apps/api/src/routes/api/v1/destinations/types.ts create mode 100644 apps/api/src/routes/api/v1/iam/types.ts create mode 100644 apps/api/src/routes/api/v1/services/types.ts create mode 100644 apps/api/src/routes/api/v1/settings/types.ts create mode 100644 apps/api/src/routes/api/v1/sources/types.ts create mode 100644 apps/api/src/routes/api/v1/types.ts create mode 100644 apps/api/src/routes/webhooks/github/types.ts create mode 100644 apps/api/src/routes/webhooks/gitlab/types.ts create mode 100644 apps/api/src/routes/webhooks/traefik/types.ts create mode 100644 apps/api/src/types.ts diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 073732c5f..e302df635 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -77,7 +77,7 @@ if (!isDev) { root: path.join(__dirname, './public'), preCompressed: true }); - fastify.setNotFoundHandler({}, function (request, reply) { + fastify.setNotFoundHandler(async function (request, reply) { if (request.raw.url && request.raw.url.startsWith('/api')) { return reply.status(404).send({ success: false diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index 06a06d21c..96edde3fc 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -16,7 +16,7 @@ import { day } from './dayjs'; import * as serviceFields from './serviceFields' import axios from 'axios'; -export const version = '3.1.2'; +export const version = '3.1.3'; export const isDev = process.env.NODE_ENV === 'development'; const algorithm = 'aes-256-ctr'; @@ -825,7 +825,7 @@ export type ComposeFileService = { context: string; dockerfile: string; args?: Record; - }; + } | string; deploy?: { restart_policy?: { condition?: string; diff --git a/apps/api/src/routes/api/v1/applications/handlers.ts b/apps/api/src/routes/api/v1/applications/handlers.ts index b5e235335..7d794e2d3 100644 --- a/apps/api/src/routes/api/v1/applications/handlers.ts +++ b/apps/api/src/routes/api/v1/applications/handlers.ts @@ -2,18 +2,16 @@ import cuid from 'cuid'; import crypto from 'node:crypto' import jsonwebtoken from 'jsonwebtoken'; import axios from 'axios'; -import { day } from '../../../../lib/dayjs'; - - -import type { FastifyRequest } from 'fastify'; import { FastifyReply } from 'fastify'; - -import { CheckDNS, DeleteApplication, DeployApplication, GetApplication, SaveApplication, SaveApplicationSettings } from '.'; +import { day } from '../../../../lib/dayjs'; import { setDefaultBaseImage, setDefaultConfiguration } from '../../../../lib/buildPacks/common'; import { asyncExecShell, checkDomainsIsValidInDNS, checkDoubleBranch, decrypt, encrypt, errorHandler, generateSshKeyPair, getContainerUsage, getDomain, isDev, isDomainConfigured, prisma, stopBuild, uniqueName } from '../../../../lib/common'; import { checkContainer, dockerInstance, getEngine, isContainerExited, removeContainer } from '../../../../lib/docker'; import { scheduler } from '../../../../lib/scheduler'; +import type { FastifyRequest } from 'fastify'; +import type { GetImages, CancelDeployment, CheckDNS, CheckRepository, DeleteApplication, DeleteSecret, DeleteStorage, GetApplicationLogs, GetBuildIdLogs, GetBuildLogs, OnlyId, SaveApplication, SaveApplicationSettings, SaveApplicationSource, SaveDeployKey, SaveDestination, SaveSecret, SaveStorage, DeployApplication } from './types'; +import { Application, DestinationDocker } from '@prisma/client'; export async function listApplications(request: FastifyRequest) { try { @@ -31,7 +29,7 @@ export async function listApplications(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function getImages(request: FastifyRequest) { +export async function getImages(request: FastifyRequest) { try { const { buildPack, deploymentType } = request.body let publishDirectory = undefined; @@ -65,14 +63,14 @@ export async function getImages(request: FastifyRequest) { } } -export async function getApplication(request: FastifyRequest) { +export async function getApplication(request: FastifyRequest) { try { const { id } = request.params const { teamId } = request.user const appId = process.env['COOLIFY_APP_ID']; let isRunning = false; let isExited = false; - const application = await getApplicationFromDB(id, teamId); + const application: any = await getApplicationFromDB(id, teamId); if (application?.destinationDockerId && application.destinationDocker?.engine) { isRunning = await checkContainer(application.destinationDocker.engine, id); isExited = await isContainerExited(application.destinationDocker.engine, id); @@ -281,11 +279,11 @@ export async function saveApplicationSettings(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { teamId } = request.user - const application = await getApplicationFromDB(id, teamId); + const application: any = await getApplicationFromDB(id, teamId); if (application?.destinationDockerId && application.destinationDocker?.engine) { const { engine } = application.destinationDocker; const found = await checkContainer(engine, id); @@ -373,8 +371,9 @@ export async function getUsage(request) { try { const { id } = request.params const teamId = request.user?.teamId; - const application = await getApplicationFromDB(id, teamId); let usage = {}; + + const application: any = await getApplicationFromDB(id, teamId); if (application.destinationDockerId) { [usage] = await Promise.all([getContainerUsage(application.destinationDocker.engine, id)]); } @@ -389,7 +388,6 @@ export async function deployApplication(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { gitSourceId } = request.body @@ -464,11 +462,11 @@ export async function saveApplicationSource(request: FastifyRequest, reply: Fast } } -export async function getGitHubToken(request: FastifyRequest, reply: FastifyReply) { +export async function getGitHubToken(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { teamId } = request.user - const application = await getApplicationFromDB(id, teamId); + const application: any = await getApplicationFromDB(id, teamId); const payload = { iat: Math.round(new Date().getTime() / 1000), exp: Math.round(new Date().getTime() / 1000 + 60), @@ -490,7 +488,7 @@ export async function getGitHubToken(request: FastifyRequest, reply: FastifyRepl } } -export async function checkRepository(request: FastifyRequest) { +export async function checkRepository(request: FastifyRequest) { try { const { id } = request.params const { repository, branch } = request.query @@ -537,7 +535,7 @@ export async function saveRepository(request, reply) { } } -export async function saveDestination(request: FastifyRequest, reply: FastifyReply) { +export async function saveDestination(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { destinationId } = request.body @@ -555,7 +553,7 @@ export async function getBuildPack(request) { try { const { id } = request.params const teamId = request.user?.teamId; - const application = await getApplicationFromDB(id, teamId); + const application: any = await getApplicationFromDB(id, teamId); return { type: application.gitSource.type, projectId: application.projectId, @@ -579,7 +577,7 @@ export async function saveBuildPack(request, reply) { } } -export async function getSecrets(request: FastifyRequest) { +export async function getSecrets(request: FastifyRequest) { try { const { id } = request.params let secrets = await prisma.secret.findMany({ @@ -601,7 +599,7 @@ export async function getSecrets(request: FastifyRequest) { } } -export async function saveSecret(request: FastifyRequest, reply: FastifyReply) { +export async function saveSecret(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params let { name, value, isBuildSecret, isPRMRSecret, isNew } = request.body @@ -636,7 +634,7 @@ export async function saveSecret(request: FastifyRequest, reply: FastifyReply) { return errorHandler({ status, message }) } } -export async function deleteSecret(request: FastifyRequest) { +export async function deleteSecret(request: FastifyRequest) { try { const { id } = request.params const { name } = request.body @@ -647,7 +645,7 @@ export async function deleteSecret(request: FastifyRequest) { } } -export async function getStorages(request: FastifyRequest) { +export async function getStorages(request: FastifyRequest) { try { const { id } = request.params const persistentStorages = await prisma.applicationPersistentStorage.findMany({ where: { applicationId: id } }); @@ -659,7 +657,7 @@ export async function getStorages(request: FastifyRequest) { } } -export async function saveStorage(request: FastifyRequest, reply: FastifyReply) { +export async function saveStorage(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { path, newStorage, storageId } = request.body @@ -680,7 +678,7 @@ export async function saveStorage(request: FastifyRequest, reply: FastifyReply) } } -export async function deleteStorage(request: FastifyRequest) { +export async function deleteStorage(request: FastifyRequest) { try { const { id } = request.params const { path } = request.body @@ -691,7 +689,7 @@ export async function deleteStorage(request: FastifyRequest) { } } -export async function getPreviews(request: FastifyRequest) { +export async function getPreviews(request: FastifyRequest) { try { const { id } = request.params const { teamId } = request.user @@ -739,7 +737,7 @@ export async function getPreviews(request: FastifyRequest) { } } -export async function getApplicationLogs(request: FastifyRequest) { +export async function getApplicationLogs(request: FastifyRequest) { try { const { id } = request.params let { since = 0 } = request.query @@ -783,7 +781,7 @@ export async function getApplicationLogs(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function getBuildLogs(request: FastifyRequest) { +export async function getBuildLogs(request: FastifyRequest) { try { const { id } = request.params let { buildId, skip = 0 } = request.query @@ -820,9 +818,9 @@ export async function getBuildLogs(request: FastifyRequest) { } } -export async function getBuildIdLogs(request: FastifyRequest) { +export async function getBuildIdLogs(request: FastifyRequest) { try { - const { id, buildId } = request.params + const { buildId } = request.params let { sequence = 0 } = request.query if (typeof sequence !== 'number') { sequence = Number(sequence) @@ -841,7 +839,7 @@ export async function getBuildIdLogs(request: FastifyRequest) { } } -export async function getGitLabSSHKey(request: FastifyRequest) { +export async function getGitLabSSHKey(request: FastifyRequest) { try { const { id } = request.params const application = await prisma.application.findUnique({ @@ -854,7 +852,7 @@ export async function getGitLabSSHKey(request: FastifyRequest) { } } -export async function saveGitLabSSHKey(request: FastifyRequest, reply: FastifyReply) { +export async function saveGitLabSSHKey(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const application = await prisma.application.findUnique({ @@ -876,7 +874,7 @@ export async function saveGitLabSSHKey(request: FastifyRequest, reply: FastifyRe } } -export async function saveDeployKey(request: FastifyRequest, reply: FastifyReply) { +export async function saveDeployKey(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params let { deployKeyId } = request.body; @@ -896,9 +894,8 @@ export async function saveDeployKey(request: FastifyRequest, reply: FastifyReply } } -export async function cancelDeployment(request: FastifyRequest, reply: FastifyReply) { +export async function cancelDeployment(request: FastifyRequest, reply: FastifyReply) { try { - const { id } = request.params const { buildId, applicationId } = request.body; if (!buildId) { throw { status: 500, message: 'buildId is required' } diff --git a/apps/api/src/routes/api/v1/applications/index.ts b/apps/api/src/routes/api/v1/applications/index.ts index 224bacc22..aa359f973 100644 --- a/apps/api/src/routes/api/v1/applications/index.ts +++ b/apps/api/src/routes/api/v1/applications/index.ts @@ -1,90 +1,60 @@ import { FastifyPluginAsync } from 'fastify'; +import { OnlyId } from '../../../../types'; import { cancelDeployment, checkDNS, checkRepository, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getBuildIdLogs, getBuildLogs, getBuildPack, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getSecrets, getStorages, getUsage, listApplications, newApplication, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication } from './handlers'; -export interface GetApplication { - Params: { id: string; } -} +import type { CancelDeployment, CheckDNS, CheckRepository, DeleteApplication, DeleteSecret, DeleteStorage, DeployApplication, GetApplicationLogs, GetBuildIdLogs, GetBuildLogs, GetImages, SaveApplication, SaveApplicationSettings, SaveApplicationSource, SaveDeployKey, SaveDestination, SaveSecret, SaveStorage } from './types'; -export interface SaveApplication { - Params: { id: string; }, - Body: any -} - -export interface SaveApplicationSettings { - Params: { id: string; }; - Querystring: { domain: string; }; - Body: { debug: boolean; previews: boolean; dualCerts: boolean; autodeploy: boolean; branch: string; projectId: number; }; -} - -export interface DeleteApplication { - Params: { id: string; }; - Querystring: { domain: string; }; -} - -export interface CheckDNS { - Params: { id: string; }; - Querystring: { domain: string; }; -} - -export interface DeployApplication { - Params: { id: string }, - Querystring: { domain: string } - Body: { pullmergeRequestId: string | null, branch: string } -} - -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listApplications(request)); - fastify.post('/images', async (request) => await getImages(request)); + fastify.post('/images', async (request) => await getImages(request)); fastify.post('/new', async (request, reply) => await newApplication(request, reply)); - fastify.get('/:id', async (request) => await getApplication(request)); + fastify.get('/:id', async (request) => await getApplication(request)); fastify.post('/:id', async (request, reply) => await saveApplication(request, reply)); fastify.delete('/:id', async (request, reply) => await deleteApplication(request, reply)); - fastify.post('/:id/stop', async (request, reply) => await stopApplication(request, reply)); + fastify.post('/:id/stop', async (request, reply) => await stopApplication(request, reply)); fastify.post('/:id/settings', async (request, reply) => await saveApplicationSettings(request, reply)); - fastify.post('/:id/check', async (request) => await checkDNS(request)); + fastify.post('/:id/check', async (request) => await checkDNS(request)); - fastify.get('/:id/secrets', async (request) => await getSecrets(request)); - fastify.post('/:id/secrets', async (request, reply) => await saveSecret(request, reply)); - fastify.delete('/:id/secrets', async (request) => await deleteSecret(request)); + fastify.get('/:id/secrets', async (request) => await getSecrets(request)); + fastify.post('/:id/secrets', async (request, reply) => await saveSecret(request, reply)); + fastify.delete('/:id/secrets', async (request) => await deleteSecret(request)); - fastify.get('/:id/storages', async (request) => await getStorages(request)); - fastify.post('/:id/storages', async (request, reply) => await saveStorage(request, reply)); - fastify.delete('/:id/storages', async (request) => await deleteStorage(request)); + fastify.get('/:id/storages', async (request) => await getStorages(request)); + fastify.post('/:id/storages', async (request, reply) => await saveStorage(request, reply)); + fastify.delete('/:id/storages', async (request) => await deleteStorage(request)); - fastify.get('/:id/previews', async (request) => await getPreviews(request)); + fastify.get('/:id/previews', async (request) => await getPreviews(request)); - fastify.get('/:id/logs', async (request) => await getApplicationLogs(request)); - fastify.get('/:id/logs/build', async (request) => await getBuildLogs(request)); - fastify.get('/:id/logs/build/:buildId', async (request) => await getBuildIdLogs(request)); + fastify.get('/:id/logs', async (request) => await getApplicationLogs(request)); + fastify.get('/:id/logs/build', async (request) => await getBuildLogs(request)); + fastify.get('/:id/logs/build/:buildId', async (request) => await getBuildIdLogs(request)); - fastify.get('/:id/usage', async (request) => await getUsage(request)) + fastify.get('/:id/usage', async (request) => await getUsage(request)) fastify.post('/:id/deploy', async (request) => await deployApplication(request)) - fastify.post('/:id/cancel', async (request, reply) => await cancelDeployment(request, reply)); + fastify.post('/:id/cancel', async (request, reply) => await cancelDeployment(request, reply)); - fastify.post('/:id/configuration/source', async (request, reply) => await saveApplicationSource(request, reply)); + fastify.post('/:id/configuration/source', async (request, reply) => await saveApplicationSource(request, reply)); - fastify.get('/:id/configuration/repository', async (request) => await checkRepository(request)); + fastify.get('/:id/configuration/repository', async (request) => await checkRepository(request)); fastify.post('/:id/configuration/repository', async (request, reply) => await saveRepository(request, reply)); - fastify.post('/:id/configuration/destination', async (request, reply) => await saveDestination(request, reply)); + fastify.post('/:id/configuration/destination', async (request, reply) => await saveDestination(request, reply)); fastify.get('/:id/configuration/buildpack', async (request) => await getBuildPack(request)); fastify.post('/:id/configuration/buildpack', async (request, reply) => await saveBuildPack(request, reply)); - fastify.get('/:id/configuration/sshkey', async (request) => await getGitLabSSHKey(request)); - fastify.post('/:id/configuration/sshkey', async (request, reply) => await saveGitLabSSHKey(request, reply)); + fastify.get('/:id/configuration/sshkey', async (request) => await getGitLabSSHKey(request)); + fastify.post('/:id/configuration/sshkey', async (request, reply) => await saveGitLabSSHKey(request, reply)); - fastify.post('/:id/configuration/deploykey', async (request, reply) => await saveDeployKey(request, reply)); + fastify.post('/:id/configuration/deploykey', async (request, reply) => await saveDeployKey(request, reply)); - - - fastify.get('/:id/configuration/githubToken', async (request, reply) => await getGitHubToken(request, reply)); + fastify.get('/:id/configuration/githubToken', async (request, reply) => await getGitHubToken(request, reply)); }; export default root; diff --git a/apps/api/src/routes/api/v1/applications/types.ts b/apps/api/src/routes/api/v1/applications/types.ts new file mode 100644 index 000000000..2d9b9913d --- /dev/null +++ b/apps/api/src/routes/api/v1/applications/types.ts @@ -0,0 +1,117 @@ +import type { OnlyId } from "../../../../types"; + +export interface SaveApplication extends OnlyId { + Body: { + name: string, + buildPack: string, + fqdn: string, + port: number, + exposePort: number, + installCommand: string, + buildCommand: string, + startCommand: string, + baseDirectory: string, + publishDirectory: string, + pythonWSGI: string, + pythonModule: string, + pythonVariable: string, + dockerFileLocation: string, + denoMainFile: string, + denoOptions: string, + baseImage: string, + baseBuildImage: string, + deploymentType: string + } +} +export interface SaveApplicationSettings extends OnlyId { + Querystring: { domain: string; }; + Body: { debug: boolean; previews: boolean; dualCerts: boolean; autodeploy: boolean; branch: string; projectId: number; }; +} +export interface DeleteApplication extends OnlyId { + Querystring: { domain: string; }; +} +export interface CheckDNS extends OnlyId { + Querystring: { domain: string; }; + Body: { + exposePort: number, + fqdn: string, + forceSave: boolean, + dualCerts: boolean + } +} +export interface DeployApplication { + Querystring: { domain: string } + Body: { pullmergeRequestId: string | null, branch: string } +} +export interface GetImages { + Body: { buildPack: string, deploymentType: string } +} +export interface SaveApplicationSource extends OnlyId { + Body: { gitSourceId: string } +} +export interface CheckRepository extends OnlyId { + Querystring: { repository: string, branch: string } +} +export interface SaveDestination extends OnlyId { + Body: { destinationId: string } +} +export interface SaveSecret extends OnlyId { + Body: { + name: string, + value: string, + isBuildSecret: boolean, + isPRMRSecret: boolean, + isNew: boolean + } +} +export interface DeleteSecret extends OnlyId { + Body: { name: string } +} +export interface SaveStorage extends OnlyId { + Body: { + path: string, + newStorage: boolean, + storageId: string + } +} +export interface DeleteStorage extends OnlyId { + Body: { + path: string, + } +} +export interface GetApplicationLogs extends OnlyId { + Querystring: { + since: number, + } +} +export interface GetBuildLogs extends OnlyId { + Querystring: { + buildId: string + skip: number, + } +} +export interface GetBuildIdLogs { + Params: { + buildId: string + }, + Querystring: { + sequence: number + } +} +export interface SaveDeployKey extends OnlyId { + Body: { + deployKeyId: number + } +} +export interface CancelDeployment { + Body: { + buildId: string, + applicationId: string + } +} +export interface DeployApplication extends OnlyId { + Body: { + pullmergeRequestId: string | null, + branch: string + } +} diff --git a/apps/api/src/routes/api/v1/base/index.ts b/apps/api/src/routes/api/v1/base/index.ts index 37972a1a7..9eaa8c40a 100644 --- a/apps/api/src/routes/api/v1/base/index.ts +++ b/apps/api/src/routes/api/v1/base/index.ts @@ -1,8 +1,8 @@ import { FastifyPluginAsync } from 'fastify'; import { errorHandler, version } from '../../../../lib/common'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.get('/', async (request) => { +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.get('/', async () => { try { return { version, diff --git a/apps/api/src/routes/api/v1/databases/handlers.ts b/apps/api/src/routes/api/v1/databases/handlers.ts index 52110b8b7..8d05bb3a5 100644 --- a/apps/api/src/routes/api/v1/databases/handlers.ts +++ b/apps/api/src/routes/api/v1/databases/handlers.ts @@ -6,10 +6,11 @@ import fs from 'fs/promises'; import { asyncExecShell, ComposeFile, createDirectories, decrypt, encrypt, errorHandler, generateDatabaseConfiguration, generatePassword, getContainerUsage, getDatabaseImage, getDatabaseVersions, getFreePort, listSettings, makeLabelForStandaloneDatabase, prisma, startTcpProxy, startTraefikTCPProxy, stopDatabaseContainer, stopTcpHttpProxy, supportedDatabaseTypesAndVersions, uniqueName, updatePasswordInDb } from '../../../../lib/common'; import { dockerInstance, getEngine } from '../../../../lib/docker'; import { day } from '../../../../lib/dayjs'; +import { GetDatabaseLogs, OnlyId, SaveDatabase, SaveDatabaseDestination, SaveDatabaseSettings, SaveVersion } from '../../../../types'; +import { SaveDatabaseType } from './types'; export async function listDatabases(request: FastifyRequest) { try { - const userId = request.user.userId; const teamId = request.user.teamId; let databases = [] if (teamId === '0') { @@ -55,7 +56,7 @@ export async function newDatabase(request: FastifyRequest, reply: FastifyReply) return errorHandler({ status, message }) } } -export async function getDatabase(request: FastifyRequest) { +export async function getDatabase(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -107,7 +108,7 @@ export async function getDatabaseTypes(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveDatabaseType(request: FastifyRequest, reply: FastifyReply) { +export async function saveDatabaseType(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params; const { type } = request.body; @@ -120,7 +121,7 @@ export async function saveDatabaseType(request: FastifyRequest, reply: FastifyRe return errorHandler({ status, message }) } } -export async function getVersions(request: FastifyRequest) { +export async function getVersions(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -135,7 +136,7 @@ export async function getVersions(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveVersion(request: FastifyRequest, reply: FastifyReply) { +export async function saveVersion(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params; const { version } = request.body; @@ -144,7 +145,6 @@ export async function saveVersion(request: FastifyRequest, reply: FastifyReply) where: { id }, data: { version, - } }); return reply.code(201).send({}) @@ -152,7 +152,7 @@ export async function saveVersion(request: FastifyRequest, reply: FastifyReply) return errorHandler({ status, message }) } } -export async function saveDatabaseDestination(request: FastifyRequest, reply: FastifyReply) { +export async function saveDatabaseDestination(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params; const { destinationId } = request.body; @@ -181,7 +181,7 @@ export async function saveDatabaseDestination(request: FastifyRequest, reply: Fa return errorHandler({ status, message }) } } -export async function getDatabaseUsage(request: FastifyRequest) { +export async function getDatabaseUsage(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -203,7 +203,7 @@ export async function getDatabaseUsage(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function startDatabase(request: FastifyRequest) { +export async function startDatabase(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -226,7 +226,6 @@ export async function startDatabase(request: FastifyRequest) { const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); - const engine = destinationDocker.engine; const volumeName = volume.split(':')[0]; const labels = await makeLabelForStandaloneDatabase({ id, image, volume }); @@ -285,7 +284,7 @@ export async function startDatabase(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function stopDatabase(request: FastifyRequest) { +export async function stopDatabase(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -310,7 +309,7 @@ export async function stopDatabase(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function getDatabaseLogs(request: FastifyRequest) { +export async function getDatabaseLogs(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -361,7 +360,7 @@ export async function getDatabaseLogs(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function deleteDatabase(request: FastifyRequest) { +export async function deleteDatabase(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -382,7 +381,7 @@ export async function deleteDatabase(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveDatabase(request: FastifyRequest, reply: FastifyReply) { +export async function saveDatabase(request: FastifyRequest, reply: FastifyReply) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -428,7 +427,7 @@ export async function saveDatabase(request: FastifyRequest, reply: FastifyReply) return errorHandler({ status, message }) } } -export async function saveDatabaseSettings(request: FastifyRequest) { +export async function saveDatabaseSettings(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; diff --git a/apps/api/src/routes/api/v1/databases/index.ts b/apps/api/src/routes/api/v1/databases/index.ts index cd4a8c159..0c52938f8 100644 --- a/apps/api/src/routes/api/v1/databases/index.ts +++ b/apps/api/src/routes/api/v1/databases/index.ts @@ -1,32 +1,35 @@ import { FastifyPluginAsync } from 'fastify'; import { deleteDatabase, getDatabase, getDatabaseLogs, getDatabaseTypes, getDatabaseUsage, getVersions, listDatabases, newDatabase, saveDatabase, saveDatabaseDestination, saveDatabaseSettings, saveDatabaseType, saveVersion, startDatabase, stopDatabase } from './handlers'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +import type { GetDatabaseLogs, OnlyId, SaveDatabase, SaveDatabaseDestination, SaveDatabaseSettings, SaveVersion } from '../../../../types'; +import type { SaveDatabaseType } from './types'; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listDatabases(request)); fastify.post('/new', async (request, reply) => await newDatabase(request, reply)); - fastify.get('/:id', async (request) => await getDatabase(request)); - fastify.post('/:id', async (request, reply) => await saveDatabase(request, reply)); - fastify.delete('/:id', async (request) => await deleteDatabase(request)); + fastify.get('/:id', async (request) => await getDatabase(request)); + fastify.post('/:id', async (request, reply) => await saveDatabase(request, reply)); + fastify.delete('/:id', async (request) => await deleteDatabase(request)); - fastify.post('/:id/settings', async (request) => await saveDatabaseSettings(request)); + fastify.post('/:id/settings', async (request) => await saveDatabaseSettings(request)); fastify.get('/:id/configuration/type', async (request) => await getDatabaseTypes(request)); - fastify.post('/:id/configuration/type', async (request, reply) => await saveDatabaseType(request, reply)); + fastify.post('/:id/configuration/type', async (request, reply) => await saveDatabaseType(request, reply)); - fastify.get('/:id/configuration/version', async (request) => await getVersions(request)); - fastify.post('/:id/configuration/version', async (request, reply) => await saveVersion(request, reply)); + fastify.get('/:id/configuration/version', async (request) => await getVersions(request)); + fastify.post('/:id/configuration/version', async (request, reply) => await saveVersion(request, reply)); - fastify.post('/:id/configuration/destination', async (request, reply) => await saveDatabaseDestination(request, reply)); + fastify.post('/:id/configuration/destination', async (request, reply) => await saveDatabaseDestination(request, reply)); - fastify.get('/:id/usage', async (request) => await getDatabaseUsage(request)); - fastify.get('/:id/logs', async (request) => await getDatabaseLogs(request)); + fastify.get('/:id/usage', async (request) => await getDatabaseUsage(request)); + fastify.get('/:id/logs', async (request) => await getDatabaseLogs(request)); - fastify.post('/:id/start', async (request) => await startDatabase(request)); - fastify.post('/:id/stop', async (request) => await stopDatabase(request)); + fastify.post('/:id/start', async (request) => await startDatabase(request)); + fastify.post('/:id/stop', async (request) => await stopDatabase(request)); }; export default root; diff --git a/apps/api/src/routes/api/v1/databases/types.ts b/apps/api/src/routes/api/v1/databases/types.ts new file mode 100644 index 000000000..b7e4c8692 --- /dev/null +++ b/apps/api/src/routes/api/v1/databases/types.ts @@ -0,0 +1,5 @@ +import type { OnlyId } from "../../../../types"; + +export interface SaveDatabaseType extends OnlyId { + Body: { type: string } +} \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/destinations/handlers.ts b/apps/api/src/routes/api/v1/destinations/handlers.ts index dfc7f16ef..40d68a84b 100644 --- a/apps/api/src/routes/api/v1/destinations/handlers.ts +++ b/apps/api/src/routes/api/v1/destinations/handlers.ts @@ -3,6 +3,9 @@ import { FastifyReply } from 'fastify'; import { asyncExecShell, errorHandler, listSettings, prisma, startCoolifyProxy, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; import { checkContainer, dockerInstance, getEngine } from '../../../../lib/docker'; +import type { OnlyId } from '../../../../types'; +import type { CheckDestination, NewDestination, Proxy, SaveDestinationSettings } from './types'; + export async function listDestinations(request: FastifyRequest) { try { const teamId = request.user.teamId; @@ -22,7 +25,7 @@ export async function listDestinations(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function checkDestination(request: FastifyRequest) { +export async function checkDestination(request: FastifyRequest) { try { const { network } = request.body; const found = await prisma.destinationDocker.findFirst({ where: { network } }); @@ -36,7 +39,7 @@ export async function checkDestination(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function getDestination(request: FastifyRequest) { +export async function getDestination(request: FastifyRequest) { try { const { id } = request.params const teamId = request.user?.teamId; @@ -74,7 +77,7 @@ export async function getDestination(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function newDestination(request: FastifyRequest, reply: FastifyReply) { +export async function newDestination(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params let { name, network, engine, isCoolifyProxyUsed } = request.body @@ -119,7 +122,7 @@ export async function newDestination(request: FastifyRequest, reply: FastifyRepl return errorHandler({ status, message }) } } -export async function deleteDestination(request: FastifyRequest) { +export async function deleteDestination(request: FastifyRequest) { try { const { id } = request.params const destination = await prisma.destinationDocker.delete({ where: { id } }); @@ -143,7 +146,7 @@ export async function deleteDestination(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveDestinationSettings(request: FastifyRequest, reply: FastifyReply) { +export async function saveDestinationSettings(request: FastifyRequest) { try { const { engine, isCoolifyProxyUsed } = request.body; await prisma.destinationDocker.updateMany({ @@ -159,7 +162,7 @@ export async function saveDestinationSettings(request: FastifyRequest, reply: Fa return errorHandler({ status, message }) } } -export async function startProxy(request: FastifyRequest, reply: FastifyReply) { +export async function startProxy(request: FastifyRequest) { const { engine } = request.body; try { await startTraefikProxy(engine); @@ -169,19 +172,16 @@ export async function startProxy(request: FastifyRequest, reply: FastifyReply) { return errorHandler({ status, message }) } } -export async function stopProxy(request: FastifyRequest, reply: FastifyReply) { - const settings = await prisma.setting.findFirst({}); +export async function stopProxy(request: FastifyRequest) { const { engine } = request.body; try { await stopTraefikProxy(engine); - return {} } catch ({ status, message }) { return errorHandler({ status, message }) } } -export async function restartProxy(request: FastifyRequest, reply: FastifyReply) { - const settings = await prisma.setting.findFirst({}); +export async function restartProxy(request: FastifyRequest) { const { engine } = request.body; try { await stopTraefikProxy(engine); diff --git a/apps/api/src/routes/api/v1/destinations/index.ts b/apps/api/src/routes/api/v1/destinations/index.ts index 0e395a787..43440cc1c 100644 --- a/apps/api/src/routes/api/v1/destinations/index.ts +++ b/apps/api/src/routes/api/v1/destinations/index.ts @@ -1,24 +1,24 @@ import { FastifyPluginAsync } from 'fastify'; import { checkDestination, deleteDestination, getDestination, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy } from './handlers'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +import type { OnlyId } from '../../../../types'; +import type { CheckDestination, NewDestination, Proxy, SaveDestinationSettings } from './types'; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listDestinations(request)); - fastify.post('/check', async (request) => await checkDestination(request)); - - fastify.get('/:id', async (request) => await getDestination(request)); - fastify.post('/:id', async (request, reply) => await newDestination(request, reply)); - fastify.delete('/:id', async (request) => await deleteDestination(request)); - - fastify.post('/:id/settings', async (request, reply) => await saveDestinationSettings(request, reply)); - fastify.post('/:id/start', async (request, reply) => await startProxy(request, reply)); - fastify.post('/:id/stop', async (request, reply) => await stopProxy(request, reply)); - fastify.post('/:id/restart', async (request, reply) => await restartProxy(request, reply)); - + fastify.post('/check', async (request) => await checkDestination(request)); + fastify.get('/:id', async (request) => await getDestination(request)); + fastify.post('/:id', async (request, reply) => await newDestination(request, reply)); + fastify.delete('/:id', async (request) => await deleteDestination(request)); + fastify.post('/:id/settings', async (request, reply) => await saveDestinationSettings(request)); + fastify.post('/:id/start', async (request, reply) => await startProxy(request)); + fastify.post('/:id/stop', async (request, reply) => await stopProxy(request)); + fastify.post('/:id/restart', async (request, reply) => await restartProxy(request)); }; export default root; diff --git a/apps/api/src/routes/api/v1/destinations/types.ts b/apps/api/src/routes/api/v1/destinations/types.ts new file mode 100644 index 000000000..25691b9d8 --- /dev/null +++ b/apps/api/src/routes/api/v1/destinations/types.ts @@ -0,0 +1,26 @@ +import { OnlyId } from "../../../../types" + +export interface CheckDestination { + Body: { + network: string + } +} +export interface NewDestination extends OnlyId { + Body: { + name: string + network: string + engine: string + isCoolifyProxyUsed: boolean + } +} +export interface SaveDestinationSettings extends OnlyId { + Body: { + engine: string + isCoolifyProxyUsed: boolean + } +} +export interface Proxy extends OnlyId { + Body: { + engine: string + } +} \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/handlers.ts b/apps/api/src/routes/api/v1/handlers.ts index c76181294..7f54a356b 100644 --- a/apps/api/src/routes/api/v1/handlers.ts +++ b/apps/api/src/routes/api/v1/handlers.ts @@ -8,7 +8,7 @@ import { asyncExecShell, asyncSleep, cleanupDockerStorage, errorHandler, isDev, import type { FastifyReply, FastifyRequest } from 'fastify'; import type { Login, Update } from '.'; - +import type { GetCurrentUser } from './types'; export async function hashPassword(password: string): Promise { const saltRounds = 15; @@ -253,9 +253,9 @@ export async function login(request: FastifyRequest, reply: FastifyReply) } } -export async function getCurrentUser(request: FastifyRequest, fastify) { +export async function getCurrentUser(request: FastifyRequest, fastify) { let token = null - + const { teamId } = request.query try { const user = await prisma.user.findUnique({ where: { id: request.user.userId } @@ -266,17 +266,17 @@ export async function getCurrentUser(request: FastifyRequest, fastify) { } catch (error) { throw { status: 401, message: error }; } - if (request.query.teamId) { + if (teamId) { try { const user = await prisma.user.findFirst({ - where: { id: request.user.userId, teams: { some: { id: request.query.teamId } } }, + where: { id: request.user.userId, teams: { some: { id: teamId } } }, include: { teams: true, permission: true } }) if (user) { - const permission = user.permission.find(p => p.teamId === request.query.teamId).permission + const permission = user.permission.find(p => p.teamId === teamId).permission const payload = { ...request.user, - teamId: request.query.teamId, + teamId, permission: permission || null, isAdmin: permission === 'owner' || permission === 'admin' diff --git a/apps/api/src/routes/api/v1/iam/handlers.ts b/apps/api/src/routes/api/v1/iam/handlers.ts index 0e3668f64..7009ec794 100644 --- a/apps/api/src/routes/api/v1/iam/handlers.ts +++ b/apps/api/src/routes/api/v1/iam/handlers.ts @@ -3,6 +3,10 @@ import type { FastifyRequest } from 'fastify'; import { FastifyReply } from 'fastify'; import { decrypt, errorHandler, prisma, uniqueName } from '../../../../lib/common'; import { day } from '../../../../lib/dayjs'; + +import type { OnlyId } from '../../../../types'; +import type { BodyId, InviteToTeam, SaveTeam, SetPermission } from './types'; + export async function listTeams(request: FastifyRequest) { try { const userId = request.user.userId; @@ -36,7 +40,7 @@ export async function listTeams(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function deleteTeam(request: FastifyRequest, reply: FastifyReply) { +export async function deleteTeam(request: FastifyRequest, reply: FastifyReply) { try { const userId = request.user.userId; const { id } = request.params; @@ -136,7 +140,7 @@ export async function newTeam(request: FastifyRequest, reply: FastifyReply) { return errorHandler({ status, message }) } } -export async function getTeam(request: FastifyRequest, reply: FastifyReply) { +export async function getTeam(request: FastifyRequest, reply: FastifyReply) { try { const userId = request.user.userId; const teamId = request.user.teamId; @@ -163,7 +167,7 @@ export async function getTeam(request: FastifyRequest, reply: FastifyReply) { return errorHandler({ status, message }) } } -export async function saveTeam(request: FastifyRequest, reply: FastifyReply) { +export async function saveTeam(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params; const { name } = request.body; @@ -263,7 +267,7 @@ export async function saveTeam(request: FastifyRequest, reply: FastifyReply) { // } // } -export async function inviteToTeam(request: FastifyRequest, reply: FastifyReply) { +export async function inviteToTeam(request: FastifyRequest, reply: FastifyReply) { try { const userId = request.user.userId; const { email, permission, teamId, teamName } = request.body; @@ -306,7 +310,7 @@ export async function inviteToTeam(request: FastifyRequest, reply: FastifyReply) } } -export async function acceptInvitation(request: FastifyRequest) { +export async function acceptInvitation(request: FastifyRequest) { try { const userId = request.user.userId; const { id } = request.body; @@ -331,7 +335,7 @@ export async function acceptInvitation(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function revokeInvitation(request: FastifyRequest) { +export async function revokeInvitation(request: FastifyRequest) { try { const { id } = request.body await prisma.teamInvitation.delete({ where: { id } }); @@ -341,15 +345,15 @@ export async function revokeInvitation(request: FastifyRequest) { } } -export async function removeUser(request: FastifyRequest, reply: FastifyReply) { +export async function removeUser(request: FastifyRequest, reply: FastifyReply) { try { - const { uid } = request.body; - const user = await prisma.user.findUnique({ where: { id: uid }, include: { teams: true, permission: true } }); + const { id } = request.body; + const user = await prisma.user.findUnique({ where: { id }, include: { teams: true, permission: true } }); if (user) { const permissions = user.permission; if (permissions.length > 0) { for (const permission of permissions) { - await prisma.permission.deleteMany({ where: { id: permission.id, userId: uid } }); + await prisma.permission.deleteMany({ where: { id: permission.id, userId: id } }); } } const teams = user.teams; @@ -357,7 +361,7 @@ export async function removeUser(request: FastifyRequest, reply: FastifyReply) { for (const team of teams) { const newTeam = await prisma.team.update({ where: { id: team.id }, - data: { users: { disconnect: { id: uid } } }, + data: { users: { disconnect: { id } } }, include: { applications: true, database: true, gitHubApps: true, gitLabApps: true, gitSources: true, destinationDocker: true, service: true, users: true } }); if (newTeam.users.length === 0) { @@ -422,14 +426,14 @@ export async function removeUser(request: FastifyRequest, reply: FastifyReply) { } } } - await prisma.user.delete({ where: { id: uid } }); + await prisma.user.delete({ where: { id } }); return reply.code(201).send() } catch ({ status, message }) { return errorHandler({ status, message }) } } -export async function setPermission(request: FastifyRequest, reply: FastifyReply) { +export async function setPermission(request: FastifyRequest, reply: FastifyReply) { try { const { userId, newPermission, permissionId } = request.body; await prisma.permission.updateMany({ @@ -442,7 +446,7 @@ export async function setPermission(request: FastifyRequest, reply: FastifyReply } } -export async function changePassword(request: FastifyRequest, reply: FastifyReply) { +export async function changePassword(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.body; await prisma.user.update({ where: { id }, data: { password: 'RESETME' } }); diff --git a/apps/api/src/routes/api/v1/iam/index.ts b/apps/api/src/routes/api/v1/iam/index.ts index d82c39878..539586b2d 100644 --- a/apps/api/src/routes/api/v1/iam/index.ts +++ b/apps/api/src/routes/api/v1/iam/index.ts @@ -1,27 +1,28 @@ import { FastifyPluginAsync } from 'fastify'; import { acceptInvitation, changePassword, deleteTeam, getTeam, inviteToTeam, listTeams, newTeam, removeUser, revokeInvitation, saveTeam, setPermission } from './handlers'; +import type { OnlyId } from '../../../../types'; +import type { BodyId, InviteToTeam, SaveTeam, SetPermission } from './types'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listTeams(request)); fastify.post('/new', async (request, reply) => await newTeam(request, reply)); - fastify.get('/team/:id', async (request, reply) => await getTeam(request, reply)); - fastify.post('/team/:id', async (request, reply) => await saveTeam(request, reply)); - fastify.delete('/team/:id', async (request, reply) => await deleteTeam(request, reply)); + fastify.get('/team/:id', async (request, reply) => await getTeam(request, reply)); + fastify.post('/team/:id', async (request, reply) => await saveTeam(request, reply)); + fastify.delete('/team/:id', async (request, reply) => await deleteTeam(request, reply)); - fastify.post('/team/:id/invitation/invite', async (request, reply) => await inviteToTeam(request, reply)) - fastify.post('/team/:id/invitation/accept', async (request) => await acceptInvitation(request)); - fastify.post('/team/:id/invitation/revoke', async (request) => await revokeInvitation(request)); + fastify.post('/team/:id/invitation/invite', async (request, reply) => await inviteToTeam(request, reply)) + fastify.post('/team/:id/invitation/accept', async (request) => await acceptInvitation(request)); + fastify.post('/team/:id/invitation/revoke', async (request) => await revokeInvitation(request)); + fastify.post('/team/:id/permission', async (request, reply) => await setPermission(request, reply)); - fastify.post('/team/:id/permission', async (request, reply) => await setPermission(request, reply)); - - fastify.delete('/user/remove', async (request, reply) => await removeUser(request, reply)); - fastify.post('/user/password', async (request, reply) => await changePassword(request, reply)); + fastify.delete('/user/remove', async (request, reply) => await removeUser(request, reply)); + fastify.post('/user/password', async (request, reply) => await changePassword(request, reply)); // fastify.delete('/user', async (request, reply) => await deleteUser(request, reply)); }; diff --git a/apps/api/src/routes/api/v1/iam/types.ts b/apps/api/src/routes/api/v1/iam/types.ts new file mode 100644 index 000000000..26a896b8e --- /dev/null +++ b/apps/api/src/routes/api/v1/iam/types.ts @@ -0,0 +1,27 @@ +import { OnlyId } from "../../../../types" + +export interface SaveTeam extends OnlyId { + Body: { + name: string + } +} +export interface InviteToTeam { + Body: { + email: string, + permission: string, + teamId: string, + teamName: string + } +} +export interface BodyId { + Body: { + id: string + } +} +export interface SetPermission { + Body: { + userId: string, + newPermission: string, + permissionId: string + } +} \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/index.ts b/apps/api/src/routes/api/v1/index.ts index ef81b5792..0d145312d 100644 --- a/apps/api/src/routes/api/v1/index.ts +++ b/apps/api/src/routes/api/v1/index.ts @@ -1,6 +1,6 @@ import { FastifyPluginAsync } from 'fastify'; -import { scheduler } from '../../../lib/scheduler'; import { checkUpdate, login, showDashboard, update, showUsage, getCurrentUser, cleanupManually } from './handlers'; +import { GetCurrentUser } from './types'; export interface Update { Body: { latestVersion: string } @@ -9,7 +9,7 @@ export interface Login { Body: { email: string, password: string, isLogin: boolean } } -const root: FastifyPluginAsync = async (fastify, opts): Promise => { +const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/', async function (_request, reply) { return reply.redirect(302, '/'); }); @@ -19,7 +19,7 @@ const root: FastifyPluginAsync = async (fastify, opts): Promise => { return { token, payload } }); - fastify.get('/user', { + fastify.get('/user', { onRequest: [fastify.authenticate] }, async (request) => await getCurrentUser(request, fastify)); diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index e2fa3404a..6f14102cc 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -2,12 +2,15 @@ import type { FastifyReply, FastifyRequest } from 'fastify'; import fs from 'fs/promises'; import yaml from 'js-yaml'; import bcrypt from 'bcryptjs'; -import { prisma, uniqueName, asyncExecShell, getServiceImage, getServiceImages, configureServiceType, getServiceFromDB, getContainerUsage, removeService, isDomainConfigured, saveUpdateableFields, fixType, decrypt, encrypt, getServiceMainPort, createDirectories, ComposeFile, makeLabelForServices, getFreePort, getDomain, errorHandler, supportedServiceTypesAndVersions, generatePassword, isDev, stopTcpHttpProxy, getAvailableServices } from '../../../../lib/common'; +import { prisma, uniqueName, asyncExecShell, getServiceImage, getServiceImages, configureServiceType, getServiceFromDB, getContainerUsage, removeService, isDomainConfigured, saveUpdateableFields, fixType, decrypt, encrypt, getServiceMainPort, createDirectories, ComposeFile, makeLabelForServices, getFreePort, getDomain, errorHandler, supportedServiceTypesAndVersions, generatePassword, isDev, stopTcpHttpProxy, getAvailableServices, convertTolOldVolumeNames } from '../../../../lib/common'; import { day } from '../../../../lib/dayjs'; import { checkContainer, dockerInstance, getEngine, removeContainer } from '../../../../lib/docker'; import cuid from 'cuid'; -async function startServiceNew(request: FastifyRequest) { +import type { OnlyId } from '../../../../types'; +import type { ActivateWordpressFtp, CheckService, DeleteServiceSecret, DeleteServiceStorage, GetServiceLogs, SaveService, SaveServiceDestination, SaveServiceSecret, SaveServiceSettings, SaveServiceStorage, SaveServiceType, SaveServiceVersion, ServiceStartStop, SetWordpressSettings } from './types'; + +async function startServiceNew(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -73,7 +76,6 @@ async function startServiceNew(request: FastifyRequest) { export async function listServices(request: FastifyRequest) { try { - const userId = request.user.userId; const teamId = request.user.teamId; let services = [] if (teamId === '0') { @@ -102,7 +104,7 @@ export async function newService(request: FastifyRequest, reply: FastifyReply) { return errorHandler({ status, message }) } } -export async function getService(request: FastifyRequest) { +export async function getService(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -155,7 +157,7 @@ export async function getServiceType(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveServiceType(request: FastifyRequest, reply: FastifyReply) { +export async function saveServiceType(request: FastifyRequest, reply: FastifyReply) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -166,7 +168,7 @@ export async function saveServiceType(request: FastifyRequest, reply: FastifyRep return errorHandler({ status, message }) } } -export async function getServiceVersions(request: FastifyRequest) { +export async function getServiceVersions(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -179,9 +181,8 @@ export async function getServiceVersions(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveServiceVersion(request: FastifyRequest, reply: FastifyReply) { +export async function saveServiceVersion(request: FastifyRequest, reply: FastifyReply) { try { - const teamId = request.user.teamId; const { id } = request.params; const { version } = request.body; await prisma.service.update({ @@ -193,9 +194,8 @@ export async function saveServiceVersion(request: FastifyRequest, reply: Fastify return errorHandler({ status, message }) } } -export async function saveServiceDestination(request: FastifyRequest, reply: FastifyReply) { +export async function saveServiceDestination(request: FastifyRequest, reply: FastifyReply) { try { - const teamId = request.user.teamId; const { id } = request.params; const { destinationId } = request.body; await prisma.service.update({ @@ -207,7 +207,7 @@ export async function saveServiceDestination(request: FastifyRequest, reply: Fas return errorHandler({ status, message }) } } -export async function getServiceUsage(request: FastifyRequest) { +export async function getServiceUsage(request: FastifyRequest) { try { const teamId = request.user.teamId; const { id } = request.params; @@ -225,9 +225,8 @@ export async function getServiceUsage(request: FastifyRequest) { } } -export async function getServiceLogs(request: FastifyRequest) { +export async function getServiceLogs(request: FastifyRequest) { try { - const teamId = request.user.teamId; const { id } = request.params; let { since = 0 } = request.query if (since !== 0) { @@ -276,7 +275,7 @@ export async function getServiceLogs(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function deleteService(request: FastifyRequest) { +export async function deleteService(request: FastifyRequest) { try { const { id } = request.params; await removeService({ id }); @@ -285,7 +284,7 @@ export async function deleteService(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveServiceSettings(request: FastifyRequest, reply: FastifyReply) { +export async function saveServiceSettings(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params; const { dualCerts } = request.body; @@ -298,7 +297,7 @@ export async function saveServiceSettings(request: FastifyRequest, reply: Fastif return errorHandler({ status, message }) } } -export async function checkService(request: FastifyRequest) { +export async function checkService(request: FastifyRequest) { try { const { id } = request.params; let { fqdn, exposePort, otherFqdns } = request.body; @@ -337,7 +336,7 @@ export async function checkService(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveService(request: FastifyRequest, reply: FastifyReply) { +export async function saveService(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params; let { name, fqdn, exposePort, type } = request.body; @@ -365,7 +364,7 @@ export async function saveService(request: FastifyRequest, reply: FastifyReply) } } -export async function getServiceSecrets(request: FastifyRequest) { +export async function getServiceSecrets(request: FastifyRequest) { try { const { id } = request.params let secrets = await prisma.serviceSecret.findMany({ @@ -385,10 +384,10 @@ export async function getServiceSecrets(request: FastifyRequest) { } } -export async function saveServiceSecret(request: FastifyRequest, reply: FastifyReply) { +export async function saveServiceSecret(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params - let { name, value, isBuildSecret, isPRMRSecret, isNew } = request.body + let { name, value, isNew } = request.body if (isNew) { const found = await prisma.serviceSecret.findFirst({ where: { name, serviceId: id } }); @@ -420,7 +419,7 @@ export async function saveServiceSecret(request: FastifyRequest, reply: FastifyR return errorHandler({ status, message }) } } -export async function deleteServiceSecret(request: FastifyRequest) { +export async function deleteServiceSecret(request: FastifyRequest) { try { const { id } = request.params const { name } = request.body @@ -431,7 +430,7 @@ export async function deleteServiceSecret(request: FastifyRequest) { } } -export async function getServiceStorages(request: FastifyRequest) { +export async function getServiceStorages(request: FastifyRequest) { try { const { id } = request.params const persistentStorages = await prisma.servicePersistentStorage.findMany({ @@ -445,7 +444,7 @@ export async function getServiceStorages(request: FastifyRequest) { } } -export async function saveServiceStorage(request: FastifyRequest, reply: FastifyReply) { +export async function saveServiceStorage(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { path, newStorage, storageId } = request.body @@ -466,7 +465,7 @@ export async function saveServiceStorage(request: FastifyRequest, reply: Fastify } } -export async function deleteServiceStorage(request: FastifyRequest) { +export async function deleteServiceStorage(request: FastifyRequest) { try { const { id } = request.params const { path } = request.body @@ -477,7 +476,7 @@ export async function deleteServiceStorage(request: FastifyRequest) { } } -export async function startService(request: FastifyRequest,) { +export async function startService(request: FastifyRequest) { try { const { type } = request.params if (type === 'plausibleanalytics') { @@ -527,7 +526,7 @@ export async function startService(request: FastifyRequest,) { throw { status: 500, message: error?.message || error } } } -export async function stopService(request: FastifyRequest) { +export async function stopService(request: FastifyRequest) { try { const { type } = request.params if (type === 'plausibleanalytics') { @@ -577,7 +576,7 @@ export async function stopService(request: FastifyRequest) { throw { status: 500, message: error?.message || error } } } -export async function setSettingsService(request: FastifyRequest, reply: FastifyReply) { +export async function setSettingsService(request: FastifyRequest, reply: FastifyReply) { try { const { type } = request.params if (type === 'wordpress') { @@ -588,7 +587,7 @@ export async function setSettingsService(request: FastifyRequest, reply: Fastify return errorHandler({ status, message }) } } -async function setWordpressSettings(request: FastifyRequest, reply: FastifyReply) { +async function setWordpressSettings(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const { ownMysql } = request.body @@ -602,7 +601,7 @@ async function setWordpressSettings(request: FastifyRequest, reply: FastifyReply } } -async function startPlausibleAnalyticsService(request: FastifyRequest) { +async function startPlausibleAnalyticsService(request: FastifyRequest) { try { const { id } = request.params const teamId = request.user.teamId; @@ -796,7 +795,7 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`; return errorHandler({ status, message }) } } -async function stopPlausibleAnalyticsService(request: FastifyRequest) { +async function stopPlausibleAnalyticsService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -825,7 +824,7 @@ async function stopPlausibleAnalyticsService(request: FastifyRequest) { } } -async function startNocodbService(request: FastifyRequest) { +async function startNocodbService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -891,7 +890,7 @@ async function startNocodbService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopNocodbService(request: FastifyRequest) { +async function stopNocodbService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -910,7 +909,7 @@ async function stopNocodbService(request: FastifyRequest) { } } -async function startMinioService(request: FastifyRequest) { +async function startMinioService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -994,7 +993,7 @@ async function startMinioService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopMinioService(request: FastifyRequest) { +async function stopMinioService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1014,7 +1013,7 @@ async function stopMinioService(request: FastifyRequest) { } } -async function startVscodeService(request: FastifyRequest) { +async function startVscodeService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1119,7 +1118,7 @@ async function startVscodeService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopVscodeService(request: FastifyRequest) { +async function stopVscodeService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1138,7 +1137,7 @@ async function stopVscodeService(request: FastifyRequest) { } } -async function startWordpressService(request: FastifyRequest) { +async function startWordpressService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1146,7 +1145,6 @@ async function startWordpressService(request: FastifyRequest) { const { type, version, - fqdn, destinationDockerId, serviceSecret, destinationDocker, @@ -1264,7 +1262,7 @@ async function startWordpressService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopWordpressService(request: FastifyRequest) { +async function stopWordpressService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1313,7 +1311,7 @@ async function stopWordpressService(request: FastifyRequest) { } } -async function startVaultwardenService(request: FastifyRequest) { +async function startVaultwardenService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1380,7 +1378,7 @@ async function startVaultwardenService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopVaultwardenService(request: FastifyRequest) { +async function stopVaultwardenService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1404,7 +1402,7 @@ async function stopVaultwardenService(request: FastifyRequest) { } } -async function startLanguageToolService(request: FastifyRequest) { +async function startLanguageToolService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1472,7 +1470,7 @@ async function startLanguageToolService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopLanguageToolService(request: FastifyRequest) { +async function stopLanguageToolService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1496,7 +1494,7 @@ async function stopLanguageToolService(request: FastifyRequest) { } } -async function startN8nService(request: FastifyRequest) { +async function startN8nService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1564,7 +1562,7 @@ async function startN8nService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopN8nService(request: FastifyRequest) { +async function stopN8nService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1588,7 +1586,7 @@ async function stopN8nService(request: FastifyRequest) { } } -async function startUptimekumaService(request: FastifyRequest) { +async function startUptimekumaService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1655,7 +1653,7 @@ async function startUptimekumaService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopUptimekumaService(request: FastifyRequest) { +async function stopUptimekumaService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1679,7 +1677,7 @@ async function stopUptimekumaService(request: FastifyRequest) { } } -async function startGhostService(request: FastifyRequest) { +async function startGhostService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1708,6 +1706,7 @@ async function startGhostService(request: FastifyRequest) { const { workdir } = await createDirectories({ repository: type, buildId: id }); const image = getServiceImage(type); const domain = getDomain(fqdn); + const port = getServiceMainPort('ghost'); const isHttps = fqdn.startsWith('https://'); const config = { ghost: { @@ -1806,7 +1805,7 @@ async function startGhostService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopGhostService(request: FastifyRequest) { +async function stopGhostService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1834,7 +1833,7 @@ async function stopGhostService(request: FastifyRequest) { } } -async function startMeilisearchService(request: FastifyRequest) { +async function startMeilisearchService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1907,7 +1906,7 @@ async function startMeilisearchService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopMeilisearchService(request: FastifyRequest) { +async function stopMeilisearchService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -1931,7 +1930,7 @@ async function stopMeilisearchService(request: FastifyRequest) { } } -async function startUmamiService(request: FastifyRequest) { +async function startUmamiService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -2126,7 +2125,7 @@ async function startUmamiService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopUmamiService(request: FastifyRequest) { +async function stopUmamiService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -2158,7 +2157,7 @@ async function stopUmamiService(request: FastifyRequest) { } } -async function startHasuraService(request: FastifyRequest) { +async function startHasuraService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -2262,7 +2261,7 @@ async function startHasuraService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopHasuraService(request: FastifyRequest) { +async function stopHasuraService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -2294,7 +2293,7 @@ async function stopHasuraService(request: FastifyRequest) { } } -async function startFiderService(request: FastifyRequest) { +async function startFiderService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -2425,7 +2424,7 @@ async function startFiderService(request: FastifyRequest) { return errorHandler({ status, message }) } } -async function stopFiderService(request: FastifyRequest) { +async function stopFiderService(request: FastifyRequest) { try { const { id } = request.params; const teamId = request.user.teamId; @@ -2457,7 +2456,7 @@ async function stopFiderService(request: FastifyRequest) { } } -export async function activatePlausibleUsers(request: FastifyRequest, reply: FastifyReply) { +export async function activatePlausibleUsers(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params const teamId = request.user.teamId; @@ -2482,10 +2481,8 @@ export async function activatePlausibleUsers(request: FastifyRequest, reply: Fas return errorHandler({ status, message }) } } -export async function activateWordpressFtp(request: FastifyRequest, reply: FastifyReply) { +export async function activateWordpressFtp(request: FastifyRequest, reply: FastifyReply) { const { id } = request.params - const teamId = request.user.teamId; - const { ftpEnabled } = request.body; const publicPort = await getFreePort(); diff --git a/apps/api/src/routes/api/v1/services/index.ts b/apps/api/src/routes/api/v1/services/index.ts index be4b7964e..e4fcb20c7 100644 --- a/apps/api/src/routes/api/v1/services/index.ts +++ b/apps/api/src/routes/api/v1/services/index.ts @@ -27,46 +27,49 @@ import { stopService } from './handlers'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +import type { OnlyId } from '../../../../types'; +import type { ActivateWordpressFtp, CheckService, DeleteServiceSecret, DeleteServiceStorage, GetServiceLogs, SaveService, SaveServiceDestination, SaveServiceSecret, SaveServiceSettings, SaveServiceStorage, SaveServiceType, SaveServiceVersion, ServiceStartStop, SetWordpressSettings } from './types'; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listServices(request)); fastify.post('/new', async (request, reply) => await newService(request, reply)); - fastify.get('/:id', async (request) => await getService(request)); - fastify.post('/:id', async (request, reply) => await saveService(request, reply)); - fastify.delete('/:id', async (request) => await deleteService(request)); + fastify.get('/:id', async (request) => await getService(request)); + fastify.post('/:id', async (request, reply) => await saveService(request, reply)); + fastify.delete('/:id', async (request) => await deleteService(request)); - fastify.post('/:id/check', async (request) => await checkService(request)); + fastify.post('/:id/check', async (request) => await checkService(request)); - fastify.post('/:id/settings', async (request, reply) => await saveServiceSettings(request, reply)); + fastify.post('/:id/settings', async (request, reply) => await saveServiceSettings(request, reply)); - fastify.get('/:id/secrets', async (request) => await getServiceSecrets(request)); - fastify.post('/:id/secrets', async (request, reply) => await saveServiceSecret(request, reply)); - fastify.delete('/:id/secrets', async (request) => await deleteServiceSecret(request)); + fastify.get('/:id/secrets', async (request) => await getServiceSecrets(request)); + fastify.post('/:id/secrets', async (request, reply) => await saveServiceSecret(request, reply)); + fastify.delete('/:id/secrets', async (request) => await deleteServiceSecret(request)); - fastify.get('/:id/storages', async (request) => await getServiceStorages(request)); - fastify.post('/:id/storages', async (request, reply) => await saveServiceStorage(request, reply)); - fastify.delete('/:id/storages', async (request) => await deleteServiceStorage(request)); + fastify.get('/:id/storages', async (request) => await getServiceStorages(request)); + fastify.post('/:id/storages', async (request, reply) => await saveServiceStorage(request, reply)); + fastify.delete('/:id/storages', async (request) => await deleteServiceStorage(request)); fastify.get('/:id/configuration/type', async (request) => await getServiceType(request)); - fastify.post('/:id/configuration/type', async (request, reply) => await saveServiceType(request, reply)); + fastify.post('/:id/configuration/type', async (request, reply) => await saveServiceType(request, reply)); - fastify.get('/:id/configuration/version', async (request) => await getServiceVersions(request)); - fastify.post('/:id/configuration/version', async (request, reply) => await saveServiceVersion(request, reply)); + fastify.get('/:id/configuration/version', async (request) => await getServiceVersions(request)); + fastify.post('/:id/configuration/version', async (request, reply) => await saveServiceVersion(request, reply)); - fastify.post('/:id/configuration/destination', async (request, reply) => await saveServiceDestination(request, reply)); + fastify.post('/:id/configuration/destination', async (request, reply) => await saveServiceDestination(request, reply)); - fastify.get('/:id/usage', async (request) => await getServiceUsage(request)); - fastify.get('/:id/logs', async (request) => await getServiceLogs(request)); + fastify.get('/:id/usage', async (request) => await getServiceUsage(request)); + fastify.get('/:id/logs', async (request) => await getServiceLogs(request)); - fastify.post('/:id/:type/start', async (request) => await startService(request)); - fastify.post('/:id/:type/stop', async (request) => await stopService(request)); - fastify.post('/:id/:type/settings', async (request, reply) => await setSettingsService(request, reply)); + fastify.post('/:id/:type/start', async (request) => await startService(request)); + fastify.post('/:id/:type/stop', async (request) => await stopService(request)); + fastify.post('/:id/:type/settings', async (request, reply) => await setSettingsService(request, reply)); - fastify.post('/:id/plausibleanalytics/activate', async (request, reply) => await activatePlausibleUsers(request, reply)); - fastify.post('/:id/wordpress/ftp', async (request, reply) => await activateWordpressFtp(request, reply)); + fastify.post('/:id/plausibleanalytics/activate', async (request, reply) => await activatePlausibleUsers(request, reply)); + fastify.post('/:id/wordpress/ftp', async (request, reply) => await activateWordpressFtp(request, reply)); }; export default root; diff --git a/apps/api/src/routes/api/v1/services/types.ts b/apps/api/src/routes/api/v1/services/types.ts new file mode 100644 index 000000000..4ed631998 --- /dev/null +++ b/apps/api/src/routes/api/v1/services/types.ts @@ -0,0 +1,87 @@ +import { OnlyId } from "../../../../types"; + +export interface SaveServiceType extends OnlyId { + Body: { + type: string + } +} +export interface SaveServiceVersion extends OnlyId { + Body: { + version: string + } +} +export interface SaveServiceDestination extends OnlyId { + Body: { + destinationId: string + } +} +export interface GetServiceLogs extends OnlyId { + Querystring: { + since: number + } +} +export interface SaveServiceSettings extends OnlyId { + Body: { + dualCerts: boolean + } +} +export interface CheckService extends OnlyId { + Body: { + fqdn: string, + exposePort: number, + otherFqdns: Array + } +} +export interface SaveService extends OnlyId { + Body: { + name: string, + fqdn: string, + exposePort: number, + type: string + } +} +export interface SaveServiceSecret extends OnlyId { + Body: { + name: string, + value: string, + isNew: string, + } +} +export interface DeleteServiceSecret extends OnlyId { + Body: { + name: string, + } +} +export interface SaveServiceStorage extends OnlyId { + Body: { + path: string, + newStorage: string, + storageId: string, + } +} + +export interface DeleteServiceStorage extends OnlyId { + Body: { + path: string, + } +} +export interface ServiceStartStop { + Params: { + id?: string, + type: string, + } +} +export interface SetWordpressSettings extends OnlyId { + Body: { + ownMysql: boolean + } +} +export interface ActivateWordpressFtp extends OnlyId { + Body: { + ftpEnabled: boolean + } +} + + + + diff --git a/apps/api/src/routes/api/v1/settings/handlers.ts b/apps/api/src/routes/api/v1/settings/handlers.ts index f2bb90812..0c0c727d1 100644 --- a/apps/api/src/routes/api/v1/settings/handlers.ts +++ b/apps/api/src/routes/api/v1/settings/handlers.ts @@ -2,6 +2,7 @@ import { promises as dns } from 'dns'; import type { FastifyReply, FastifyRequest } from 'fastify'; import { checkDomainsIsValidInDNS, errorHandler, getDomain, isDNSValid, isDomainConfigured, listSettings, prisma } from '../../../../lib/common'; +import { CheckDNS, CheckDomain, DeleteDomain, SaveSettings } from './types'; export async function listAllSettings(request: FastifyRequest) { @@ -14,7 +15,7 @@ export async function listAllSettings(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function saveSettings(request: FastifyRequest, reply: FastifyReply) { +export async function saveSettings(request: FastifyRequest, reply: FastifyReply) { try { const { fqdn, @@ -41,7 +42,7 @@ export async function saveSettings(request: FastifyRequest, reply: FastifyReply) return errorHandler({ status, message }) } } -export async function deleteDomain(request: FastifyRequest, reply: FastifyReply) { +export async function deleteDomain(request: FastifyRequest, reply: FastifyReply) { try { const { fqdn } = request.body let ip; @@ -57,7 +58,7 @@ export async function deleteDomain(request: FastifyRequest, reply: FastifyReply) } } -export async function checkDomain(request: FastifyRequest, reply: FastifyReply) { +export async function checkDomain(request: FastifyRequest) { try { const { id } = request.params; let { fqdn, forceSave, dualCerts, isDNSCheckEnabled } = request.body @@ -74,9 +75,9 @@ export async function checkDomain(request: FastifyRequest, reply: FastifyReply) return errorHandler({ status, message }) } } -export async function checkDNS(request: FastifyRequest, reply: FastifyReply) { +export async function checkDNS(request: FastifyRequest) { try { - const { id, domain } = request.params; + const { domain } = request.params; await isDNSValid(request.hostname, domain); return {} } catch ({ status, message }) { diff --git a/apps/api/src/routes/api/v1/settings/index.ts b/apps/api/src/routes/api/v1/settings/index.ts index 2c7a69738..f5181a14e 100644 --- a/apps/api/src/routes/api/v1/settings/index.ts +++ b/apps/api/src/routes/api/v1/settings/index.ts @@ -1,17 +1,18 @@ import { FastifyPluginAsync } from 'fastify'; import { checkDNS, checkDomain, deleteDomain, listAllSettings, saveSettings } from './handlers'; +import { CheckDNS, CheckDomain, DeleteDomain, SaveSettings } from './types'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listAllSettings(request)); - fastify.post('/', async (request, reply) => await saveSettings(request, reply)); - fastify.delete('/', async (request, reply) => await deleteDomain(request, reply)); + fastify.post('/', async (request, reply) => await saveSettings(request, reply)); + fastify.delete('/', async (request, reply) => await deleteDomain(request, reply)); - fastify.get('/check', async (request, reply) => await checkDNS(request, reply)); - fastify.post('/check', async (request, reply) => await checkDomain(request, reply)); + fastify.get('/check', async (request) => await checkDNS(request)); + fastify.post('/check', async (request) => await checkDomain(request)); }; export default root; diff --git a/apps/api/src/routes/api/v1/settings/types.ts b/apps/api/src/routes/api/v1/settings/types.ts new file mode 100644 index 000000000..aa7398804 --- /dev/null +++ b/apps/api/src/routes/api/v1/settings/types.ts @@ -0,0 +1,31 @@ +import { OnlyId } from "../../../../types" + +export interface SaveSettings { + Body: { + fqdn: string, + isRegistrationEnabled: boolean, + dualCerts: boolean, + minPort: number, + maxPort: number, + isAutoUpdateEnabled: boolean, + isDNSCheckEnabled: boolean + } +} +export interface DeleteDomain { + Body: { + fqdn: string + } +} +export interface CheckDomain extends OnlyId { + Body: { + fqdn: string, + forceSave: boolean, + dualCerts: boolean, + isDNSCheckEnabled: boolean, + } +} +export interface CheckDNS { + Params: { + domain: string, + } +} \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/sources/handlers.ts b/apps/api/src/routes/api/v1/sources/handlers.ts index 9bed930d7..8a1c19987 100644 --- a/apps/api/src/routes/api/v1/sources/handlers.ts +++ b/apps/api/src/routes/api/v1/sources/handlers.ts @@ -2,6 +2,8 @@ import cuid from 'cuid'; import type { FastifyRequest } from 'fastify'; import { FastifyReply } from 'fastify'; import { decrypt, encrypt, errorHandler, prisma } from '../../../../lib/common'; +import { OnlyId } from '../../../../types'; +import { CheckGitLabOAuthId, SaveGitHubSource, SaveGitLabSource } from './types'; export async function listSources(request: FastifyRequest) { try { @@ -31,7 +33,7 @@ export async function saveSource(request, reply) { return errorHandler({ status, message }) } } -export async function getSource(request: FastifyRequest) { +export async function getSource(request: FastifyRequest) { try { const { id } = request.params const { teamId } = request.user @@ -97,12 +99,12 @@ export async function deleteSource(request) { } } -export async function saveGitHubSource(request: FastifyRequest, reply: FastifyReply) { +export async function saveGitHubSource(request: FastifyRequest) { try { const { teamId } = request.user const { id } = request.params - let { name, type, htmlUrl, apiUrl, organization, customPort } = request.body + let { name, htmlUrl, apiUrl, organization, customPort } = request.body if (customPort) customPort = Number(customPort) if (id === 'new') { @@ -128,7 +130,7 @@ export async function saveGitHubSource(request: FastifyRequest, reply: FastifyRe return errorHandler({ status, message }) } } -export async function saveGitLabSource(request: FastifyRequest, reply: FastifyReply) { +export async function saveGitLabSource(request: FastifyRequest) { try { const { id } = request.params const { teamId } = request.user @@ -175,7 +177,7 @@ export async function saveGitLabSource(request: FastifyRequest, reply: FastifyRe } } -export async function checkGitLabOAuthID(request: FastifyRequest) { +export async function checkGitLabOAuthID(request: FastifyRequest) { try { const { oauthId } = request.body const found = await prisma.gitlabApp.findFirst({ where: { oauthId: Number(oauthId) } }); diff --git a/apps/api/src/routes/api/v1/sources/index.ts b/apps/api/src/routes/api/v1/sources/index.ts index f741627f3..3d904162f 100644 --- a/apps/api/src/routes/api/v1/sources/index.ts +++ b/apps/api/src/routes/api/v1/sources/index.ts @@ -1,21 +1,22 @@ import { FastifyPluginAsync } from 'fastify'; import { checkGitLabOAuthID, deleteSource, getSource, listSources, saveGitHubSource, saveGitLabSource, saveSource } from './handlers'; +import type { OnlyId } from '../../../../types'; +import type { CheckGitLabOAuthId, SaveGitHubSource, SaveGitLabSource } from './types'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.addHook('onRequest', async (request, reply) => { +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.addHook('onRequest', async (request) => { return await request.jwtVerify() }) fastify.get('/', async (request) => await listSources(request)); - fastify.get('/:id', async (request) => await getSource(request)); + fastify.get('/:id', async (request) => await getSource(request)); fastify.post('/:id', async (request, reply) => await saveSource(request, reply)); fastify.delete('/:id', async (request) => await deleteSource(request)); - fastify.post('/:id/check', async (request) => await checkGitLabOAuthID(request)); - fastify.post('/:id/github', async (request, reply) => await saveGitHubSource(request, reply)); - fastify.post('/:id/gitlab', async (request, reply) => await saveGitLabSource(request, reply)); - + fastify.post('/:id/check', async (request) => await checkGitLabOAuthID(request)); + fastify.post('/:id/github', async (request) => await saveGitHubSource(request)); + fastify.post('/:id/gitlab', async (request) => await saveGitLabSource(request)); }; export default root; diff --git a/apps/api/src/routes/api/v1/sources/types.ts b/apps/api/src/routes/api/v1/sources/types.ts new file mode 100644 index 000000000..a748b3943 --- /dev/null +++ b/apps/api/src/routes/api/v1/sources/types.ts @@ -0,0 +1,29 @@ +import { OnlyId } from "../../../../types"; + +export interface SaveGitHubSource extends OnlyId { + Body: { + name: string, + htmlUrl: string, + apiUrl: string, + organization: string, + customPort: number, + } +} +export interface SaveGitLabSource extends OnlyId { + Body: { + type: string, + name: string, + htmlUrl: string, + apiUrl: string, + oauthId: number, + appId: string, + appSecret: string, + groupName: string, + customPort: number, + } +} +export interface CheckGitLabOAuthId extends OnlyId { + Body: { + oauthId: number, + } +} \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/types.ts b/apps/api/src/routes/api/v1/types.ts new file mode 100644 index 000000000..945355df7 --- /dev/null +++ b/apps/api/src/routes/api/v1/types.ts @@ -0,0 +1,3 @@ +export interface GetCurrentUser { + Querystring: { teamId: string } +} \ No newline at end of file diff --git a/apps/api/src/routes/webhooks/github/handlers.ts b/apps/api/src/routes/webhooks/github/handlers.ts index 5e9e403ee..cb37029f4 100644 --- a/apps/api/src/routes/webhooks/github/handlers.ts +++ b/apps/api/src/routes/webhooks/github/handlers.ts @@ -1,13 +1,15 @@ import axios from "axios"; import cuid from "cuid"; import crypto from "crypto"; -import type { FastifyReply, FastifyRequest } from "fastify"; -import { encrypt, errorHandler, getAPIUrl, getUIUrl, isDev, prisma } from "../../../lib/common"; +import { encrypt, errorHandler, getUIUrl, isDev, prisma } from "../../../lib/common"; import { checkContainer, removeContainer } from "../../../lib/docker"; import { scheduler } from "../../../lib/scheduler"; -import { getApplicationFromDB, getApplicationFromDBWebhook } from "../../api/v1/applications/handlers"; +import { getApplicationFromDBWebhook } from "../../api/v1/applications/handlers"; -export async function installGithub(request: FastifyRequest, reply: FastifyReply): Promise { +import type { FastifyReply, FastifyRequest } from "fastify"; +import type { GitHubEvents, InstallGithub } from "./types"; + +export async function installGithub(request: FastifyRequest, reply: FastifyReply): Promise { try { const { gitSourceId, installation_id } = request.query; const source = await prisma.gitSource.findUnique({ @@ -63,7 +65,7 @@ export async function configureGitHubApp(request, reply) { return errorHandler({ status, message }) } } -export async function gitHubEvents(request: FastifyRequest, reply: FastifyReply): Promise { +export async function gitHubEvents(request: FastifyRequest): Promise { try { const buildId = cuid(); const allowedGithubEvents = ['push', 'pull_request']; diff --git a/apps/api/src/routes/webhooks/github/index.ts b/apps/api/src/routes/webhooks/github/index.ts index 2af33366a..c4a3afbb9 100644 --- a/apps/api/src/routes/webhooks/github/index.ts +++ b/apps/api/src/routes/webhooks/github/index.ts @@ -1,10 +1,12 @@ import { FastifyPluginAsync } from 'fastify'; import { configureGitHubApp, gitHubEvents, installGithub } from './handlers'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { +import type { GitHubEvents, InstallGithub } from './types'; + +const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/', async (request, reply) => configureGitHubApp(request, reply)); - fastify.get('/install', async (request, reply) => installGithub(request, reply)); - fastify.post('/events', async (request, reply) => gitHubEvents(request, reply)); + fastify.get('/install', async (request, reply) => installGithub(request, reply)); + fastify.post('/events', async (request, reply) => gitHubEvents(request)); }; export default root; diff --git a/apps/api/src/routes/webhooks/github/types.ts b/apps/api/src/routes/webhooks/github/types.ts new file mode 100644 index 000000000..c7502ec6d --- /dev/null +++ b/apps/api/src/routes/webhooks/github/types.ts @@ -0,0 +1,20 @@ +export interface InstallGithub { + Querystring: { + gitSourceId: string, + installation_id: string + } +} +export interface GitHubEvents { + Body: { + number: string, + action: string, + repository: string, + ref: string, + pull_request: { + head: { + ref: string, + repo: string + } + } + } +} \ No newline at end of file diff --git a/apps/api/src/routes/webhooks/gitlab/handlers.ts b/apps/api/src/routes/webhooks/gitlab/handlers.ts index fab40cf05..dfe310ed7 100644 --- a/apps/api/src/routes/webhooks/gitlab/handlers.ts +++ b/apps/api/src/routes/webhooks/gitlab/handlers.ts @@ -2,16 +2,18 @@ import axios from "axios"; import cuid from "cuid"; import crypto from "crypto"; import type { FastifyReply, FastifyRequest } from "fastify"; -import { encrypt, errorHandler, getAPIUrl, isDev, listSettings, prisma } from "../../../lib/common"; +import { errorHandler, getAPIUrl, isDev, listSettings, prisma } from "../../../lib/common"; import { checkContainer, removeContainer } from "../../../lib/docker"; import { scheduler } from "../../../lib/scheduler"; import { getApplicationFromDB, getApplicationFromDBWebhook } from "../../api/v1/applications/handlers"; -export async function configureGitLabApp(request: FastifyRequest, reply: FastifyReply) { +import type { ConfigureGitLabApp, GitLabEvents } from "./types"; + +export async function configureGitLabApp(request: FastifyRequest, reply: FastifyReply) { try { const { code, state } = request.query; const { fqdn } = await listSettings(); - const { gitSource: { gitlabApp: { appId, appSecret }, htmlUrl } } = await getApplicationFromDB(state, undefined); + const { gitSource: { gitlabApp: { appId, appSecret }, htmlUrl } }: any = await getApplicationFromDB(state, undefined); let domain = `http://${request.hostname}`; if (fqdn) domain = fqdn; @@ -36,12 +38,13 @@ export async function configureGitLabApp(request: FastifyRequest, reply: Fastify return errorHandler({ status, message }) } } -export async function gitLabEvents(request: FastifyRequest, reply: FastifyReply) { +export async function gitLabEvents(request: FastifyRequest) { + const { object_kind: objectKind, ref, project_id } = request.body try { const buildId = cuid(); const allowedActions = ['opened', 'reopen', 'close', 'open', 'update']; - const { object_kind: objectKind, ref, project_id } = request.body + const webhookToken = request.headers['x-gitlab-token']; if (!webhookToken) { throw { status: 500, message: 'Invalid webhookToken.' } diff --git a/apps/api/src/routes/webhooks/gitlab/index.ts b/apps/api/src/routes/webhooks/gitlab/index.ts index 22badd03f..77f3067e4 100644 --- a/apps/api/src/routes/webhooks/gitlab/index.ts +++ b/apps/api/src/routes/webhooks/gitlab/index.ts @@ -1,9 +1,11 @@ import { FastifyPluginAsync } from 'fastify'; import { configureGitLabApp, gitLabEvents } from './handlers'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { - fastify.get('/', async (request, reply) => configureGitLabApp(request, reply)); - fastify.post('/events', async (request, reply) => gitLabEvents(request, reply)); +import type { ConfigureGitLabApp, GitLabEvents } from './types'; + +const root: FastifyPluginAsync = async (fastify): Promise => { + fastify.get('/', async (request, reply) => configureGitLabApp(request, reply)); + fastify.post('/events', async (request) => gitLabEvents(request)); }; export default root; diff --git a/apps/api/src/routes/webhooks/gitlab/types.ts b/apps/api/src/routes/webhooks/gitlab/types.ts new file mode 100644 index 000000000..42af0f6ae --- /dev/null +++ b/apps/api/src/routes/webhooks/gitlab/types.ts @@ -0,0 +1,24 @@ +export interface ConfigureGitLabApp { + Querystring: { + code: string, + state: string + } +} +export interface GitLabEvents { + Body: { + object_attributes: { + work_in_progress: string + isDraft: string + action: string + source_branch: string + target_branch: string + iid: string + }, + project: { + id: string + }, + object_kind: string, + ref: string, + project_id: string + } +} \ No newline at end of file diff --git a/apps/api/src/routes/webhooks/traefik/handlers.ts b/apps/api/src/routes/webhooks/traefik/handlers.ts index 2c91c851d..879ccd960 100644 --- a/apps/api/src/routes/webhooks/traefik/handlers.ts +++ b/apps/api/src/routes/webhooks/traefik/handlers.ts @@ -1,6 +1,7 @@ import { FastifyRequest } from "fastify"; import { asyncExecShell, errorHandler, getDomain, isDev, listServicesWithIncludes, prisma, supportedServiceTypesAndVersions } from "../../../lib/common"; import { getEngine } from "../../../lib/docker"; +import { TraefikOtherConfiguration } from "./types"; function configureMiddleware( { id, container, port, domain, nakedDomain, isHttps, isWWW, isDualCerts, scriptName, type }, @@ -362,7 +363,7 @@ export async function traefikConfiguration(request, reply) { } } -export async function traefikOtherConfiguration(request: FastifyRequest, reply) { +export async function traefikOtherConfiguration(request: FastifyRequest) { try { const { id } = request.query if (id) { diff --git a/apps/api/src/routes/webhooks/traefik/index.ts b/apps/api/src/routes/webhooks/traefik/index.ts index bb79c6b05..1d69be739 100644 --- a/apps/api/src/routes/webhooks/traefik/index.ts +++ b/apps/api/src/routes/webhooks/traefik/index.ts @@ -1,9 +1,10 @@ import { FastifyPluginAsync } from 'fastify'; import { traefikConfiguration, traefikOtherConfiguration } from './handlers'; +import { TraefikOtherConfiguration } from './types'; -const root: FastifyPluginAsync = async (fastify, opts): Promise => { +const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/main.json', async (request, reply) => traefikConfiguration(request, reply)); - fastify.get('/other.json', async (request, reply) => traefikOtherConfiguration(request, reply)); + fastify.get('/other.json', async (request, reply) => traefikOtherConfiguration(request)); }; export default root; diff --git a/apps/api/src/routes/webhooks/traefik/types.ts b/apps/api/src/routes/webhooks/traefik/types.ts new file mode 100644 index 000000000..237d746fe --- /dev/null +++ b/apps/api/src/routes/webhooks/traefik/types.ts @@ -0,0 +1,9 @@ +export interface TraefikOtherConfiguration { + Querystring: { + id: string, + privatePort: number, + publicPort: number, + type: string, + address: string + } +} \ No newline at end of file diff --git a/apps/api/src/types.ts b/apps/api/src/types.ts new file mode 100644 index 000000000..71f3db158 --- /dev/null +++ b/apps/api/src/types.ts @@ -0,0 +1,38 @@ +export interface OnlyId { + Params: { id: string }, +} +export interface SaveVersion extends OnlyId { + Body: { + version: string + } +} +export interface SaveDatabaseDestination extends OnlyId { + Body: { + destinationId: string + } +} +export interface GetDatabaseLogs extends OnlyId { + Querystring: { + since: number + } +} +export interface SaveDatabase extends OnlyId { + Body: { + name: string, + defaultDatabase: string, + dbUser: string, + dbUserPassword: string, + rootUser: string, + rootUserPassword: string, + version: string, + isRunning: boolean + } +} +export interface SaveDatabaseSettings extends OnlyId { + Body: { + isPublic: boolean, + appendOnly: boolean + } +} + + diff --git a/apps/ui/src/routes/iam/index.svelte b/apps/ui/src/routes/iam/index.svelte index 4f000dc16..4e75d98ae 100644 --- a/apps/ui/src/routes/iam/index.svelte +++ b/apps/ui/src/routes/iam/index.svelte @@ -53,7 +53,7 @@ return; } try { - await del(`/iam/user/remove`, { uid: id }); + await del(`/iam/user/remove`, { id }); toast.push('Account deleted.'); const data = await get('/iam'); accounts = data.accounts; diff --git a/apps/ui/src/routes/webhooks/success.svelte b/apps/ui/src/routes/webhooks/success.svelte index a216b8276..469e4f8da 100644 --- a/apps/ui/src/routes/webhooks/success.svelte +++ b/apps/ui/src/routes/webhooks/success.svelte @@ -1,6 +1,6 @@ diff --git a/package.json b/package.json index e6b7f6407..042e0a2cc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source & self-hostable Heroku / Netlify alternative.", - "version": "3.1.2", + "version": "3.1.3", "license": "AGPL-3.0", "scripts": { "db:studio": "pnpm run --filter coolify-api db:studio",