mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-19 04:45:23 +02:00
Merge branch 'canary' into cucumber-sp/canary
This commit is contained in:
@@ -1,24 +1,40 @@
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { drizzle, type PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
import { dbUrl } from "./constants";
|
||||
import * as schema from "./schema";
|
||||
|
||||
declare global {
|
||||
var db: PostgresJsDatabase<typeof schema> | undefined;
|
||||
}
|
||||
export { and, eq };
|
||||
export * from "./schema";
|
||||
|
||||
type Database = PostgresJsDatabase<typeof schema>;
|
||||
|
||||
/**
|
||||
* Evita problemas de redeclaración global en monorepos.
|
||||
* No usamos `declare global`.
|
||||
*/
|
||||
const globalForDb = globalThis as unknown as {
|
||||
db?: Database;
|
||||
};
|
||||
|
||||
let dbConnection: Database;
|
||||
|
||||
export let db: PostgresJsDatabase<typeof schema>;
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
db = drizzle(postgres(dbUrl), {
|
||||
// En producción no usamos global cache
|
||||
dbConnection = drizzle(postgres(dbUrl), {
|
||||
schema,
|
||||
});
|
||||
} else {
|
||||
if (!global.db)
|
||||
global.db = drizzle(postgres(dbUrl), {
|
||||
// En desarrollo reutilizamos conexión para evitar múltiples conexiones
|
||||
if (!globalForDb.db) {
|
||||
globalForDb.db = drizzle(postgres(dbUrl), {
|
||||
schema,
|
||||
});
|
||||
}
|
||||
|
||||
db = global.db;
|
||||
dbConnection = globalForDb.db;
|
||||
}
|
||||
|
||||
export const db: Database = dbConnection;
|
||||
|
||||
export { dbUrl };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import {
|
||||
boolean,
|
||||
index,
|
||||
integer,
|
||||
pgTable,
|
||||
text,
|
||||
@@ -69,6 +70,36 @@ export const organization = pgTable("organization", {
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const organizationRole = pgTable(
|
||||
"organization_role",
|
||||
{
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
role: text("role").notNull(),
|
||||
permission: text("permission").notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at").$onUpdate(() => new Date()),
|
||||
},
|
||||
(table) => [
|
||||
index("organizationRole_organizationId_idx").on(table.organizationId),
|
||||
index("organizationRole_role_idx").on(table.role),
|
||||
],
|
||||
);
|
||||
|
||||
export const organizationRoleRelations = relations(
|
||||
organizationRole,
|
||||
({ one }) => ({
|
||||
organization: one(organization, {
|
||||
fields: [organizationRole.organizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const organizationRelations = relations(
|
||||
organization,
|
||||
({ one, many }) => ({
|
||||
@@ -80,6 +111,7 @@ export const organizationRelations = relations(
|
||||
projects: many(projects),
|
||||
members: many(member),
|
||||
ssoProviders: many(ssoProvider),
|
||||
roles: many(organizationRole),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -93,7 +125,9 @@ export const member = pgTable("member", {
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
role: text("role").notNull().$type<"owner" | "member" | "admin">(),
|
||||
role: text("role")
|
||||
.notNull()
|
||||
.$type<"owner" | "member" | "admin" | (string & {})>(),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
teamId: text("team_id"),
|
||||
isDefault: boolean("is_default").notNull().default(false),
|
||||
@@ -148,7 +182,7 @@ export const invitation = pgTable("invitation", {
|
||||
.notNull()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
email: text("email").notNull(),
|
||||
role: text("role").$type<"owner" | "member" | "admin">(),
|
||||
role: text("role").$type<"owner" | "member" | "admin" | (string & {})>(),
|
||||
status: text("status").notNull(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
inviterId: text("inviter_id")
|
||||
@@ -180,7 +214,8 @@ export const apikey = pgTable("apikey", {
|
||||
start: text("start"),
|
||||
prefix: text("prefix"),
|
||||
key: text("key").notNull(),
|
||||
userId: text("user_id")
|
||||
configId: text("config_id").default("default").notNull(),
|
||||
referenceId: text("reference_id")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
refillInterval: integer("refill_interval"),
|
||||
@@ -202,7 +237,7 @@ export const apikey = pgTable("apikey", {
|
||||
|
||||
export const apikeyRelations = relations(apikey, ({ one }) => ({
|
||||
user: one(user, {
|
||||
fields: [apikey.userId],
|
||||
fields: [apikey.referenceId],
|
||||
references: [user.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -19,6 +19,7 @@ import { gitea } from "./gitea";
|
||||
import { github } from "./github";
|
||||
import { gitlab } from "./gitlab";
|
||||
import { mounts } from "./mount";
|
||||
import { patch } from "./patch";
|
||||
import { ports } from "./port";
|
||||
import { previewDeployments } from "./preview-deployments";
|
||||
import { redirects } from "./redirects";
|
||||
@@ -158,7 +159,7 @@ export const applications = pgTable("application", {
|
||||
},
|
||||
),
|
||||
enableSubmodules: boolean("enableSubmodules").notNull().default(false),
|
||||
dockerfile: text("dockerfile"),
|
||||
dockerfile: text("dockerfile").default("Dockerfile"),
|
||||
dockerContextPath: text("dockerContextPath"),
|
||||
dockerBuildStage: text("dockerBuildStage"),
|
||||
// Drop
|
||||
@@ -286,6 +287,7 @@ export const applicationsRelations = relations(
|
||||
references: [registry.registryId],
|
||||
relationName: "applicationRollbackRegistry",
|
||||
}),
|
||||
patches: many(patch),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -329,6 +331,7 @@ const createSchema = createInsertSchema(applications, {
|
||||
sourceType: z
|
||||
.enum(["github", "docker", "git", "gitlab", "bitbucket", "gitea", "drop"])
|
||||
.optional(),
|
||||
triggerType: z.enum(["push", "tag"]).optional(),
|
||||
applicationStatus: z.enum(["idle", "running", "done", "error"]),
|
||||
buildType: z.enum([
|
||||
"dockerfile",
|
||||
@@ -362,12 +365,13 @@ const createSchema = createInsertSchema(applications, {
|
||||
previewPath: z.string().optional(),
|
||||
previewCertificateType: z.enum(["letsencrypt", "none", "custom"]).optional(),
|
||||
previewRequireCollaboratorPermissions: z.boolean().optional(),
|
||||
watchPaths: z.array(z.string()).optional(),
|
||||
watchPaths: z.array(z.string()).optional().optional(),
|
||||
previewLabels: z.array(z.string()).optional(),
|
||||
cleanCache: z.boolean().optional(),
|
||||
stopGracePeriodSwarm: z.bigint().nullable(),
|
||||
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
|
||||
ulimitsSwarm: UlimitsSwarmSchema.nullable(),
|
||||
enableSubmodules: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const apiCreateApplication = createSchema.pick({
|
||||
@@ -378,11 +382,9 @@ export const apiCreateApplication = createSchema.pick({
|
||||
serverId: true,
|
||||
});
|
||||
|
||||
export const apiFindOneApplication = createSchema
|
||||
.pick({
|
||||
applicationId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneApplication = z.object({
|
||||
applicationId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiDeployApplication = createSchema
|
||||
.pick({
|
||||
@@ -432,13 +434,13 @@ export const apiSaveGithubProvider = createSchema
|
||||
owner: true,
|
||||
buildPath: true,
|
||||
githubId: true,
|
||||
watchPaths: true,
|
||||
enableSubmodules: true,
|
||||
})
|
||||
.required()
|
||||
.extend({
|
||||
triggerType: z.enum(["push", "tag"]).default("push"),
|
||||
});
|
||||
})
|
||||
.required()
|
||||
.merge(createSchema.pick({ enableSubmodules: true, watchPaths: true }));
|
||||
|
||||
export const apiSaveGitlabProvider = createSchema
|
||||
.pick({
|
||||
@@ -450,10 +452,9 @@ export const apiSaveGitlabProvider = createSchema
|
||||
gitlabId: true,
|
||||
gitlabProjectId: true,
|
||||
gitlabPathNamespace: true,
|
||||
watchPaths: true,
|
||||
enableSubmodules: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.merge(createSchema.pick({ enableSubmodules: true, watchPaths: true }));
|
||||
|
||||
export const apiSaveBitbucketProvider = createSchema
|
||||
.pick({
|
||||
@@ -464,10 +465,9 @@ export const apiSaveBitbucketProvider = createSchema
|
||||
bitbucketRepositorySlug: true,
|
||||
bitbucketId: true,
|
||||
applicationId: true,
|
||||
watchPaths: true,
|
||||
enableSubmodules: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.merge(createSchema.pick({ enableSubmodules: true, watchPaths: true }));
|
||||
|
||||
export const apiSaveGiteaProvider = createSchema
|
||||
.pick({
|
||||
@@ -477,10 +477,9 @@ export const apiSaveGiteaProvider = createSchema
|
||||
giteaOwner: true,
|
||||
giteaRepository: true,
|
||||
giteaId: true,
|
||||
watchPaths: true,
|
||||
enableSubmodules: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.merge(createSchema.pick({ enableSubmodules: true, watchPaths: true }));
|
||||
|
||||
export const apiSaveDockerProvider = createSchema
|
||||
.pick({
|
||||
@@ -505,6 +504,7 @@ export const apiSaveGitProvider = createSchema
|
||||
.merge(
|
||||
createSchema.pick({
|
||||
customGitSSHKeyId: true,
|
||||
enableSubmodules: true,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -518,11 +518,9 @@ export const apiSaveEnvironmentVariables = createSchema
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiFindMonitoringStats = createSchema
|
||||
.pick({
|
||||
appName: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindMonitoringStats = z.object({
|
||||
appName: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiUpdateApplication = createSchema
|
||||
.partial()
|
||||
|
||||
94
packages/server/src/db/schema/audit-log.ts
Normal file
94
packages/server/src/db/schema/audit-log.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { index, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import { nanoid } from "nanoid";
|
||||
import { organization } from "./account";
|
||||
import { user } from "./user";
|
||||
|
||||
export const auditLog = pgTable(
|
||||
"audit_log",
|
||||
{
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
organizationId: text("organization_id").references(() => organization.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
userId: text("user_id").references(() => user.id, { onDelete: "set null" }),
|
||||
userEmail: text("user_email").notNull(),
|
||||
userRole: text("user_role").notNull(),
|
||||
action: text("action").notNull(),
|
||||
resourceType: text("resource_type").notNull(),
|
||||
resourceId: text("resource_id"),
|
||||
resourceName: text("resource_name"),
|
||||
metadata: text("metadata"),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
},
|
||||
(t) => ({
|
||||
orgIdx: index("auditLog_organizationId_idx").on(t.organizationId),
|
||||
userIdx: index("auditLog_userId_idx").on(t.userId),
|
||||
createdAtIdx: index("auditLog_createdAt_idx").on(t.createdAt),
|
||||
}),
|
||||
);
|
||||
|
||||
export const auditLogRelations = relations(auditLog, ({ one }) => ({
|
||||
organization: one(organization, {
|
||||
fields: [auditLog.organizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
user: one(user, {
|
||||
fields: [auditLog.userId],
|
||||
references: [user.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export type AuditLog = typeof auditLog.$inferSelect;
|
||||
export type NewAuditLog = typeof auditLog.$inferInsert;
|
||||
|
||||
export type AuditAction =
|
||||
| "create"
|
||||
| "update"
|
||||
| "delete"
|
||||
| "deploy"
|
||||
| "cancel"
|
||||
| "redeploy"
|
||||
| "login"
|
||||
| "logout"
|
||||
| "restore"
|
||||
| "run"
|
||||
| "start"
|
||||
| "stop"
|
||||
| "reload"
|
||||
| "rebuild"
|
||||
| "move";
|
||||
|
||||
export type AuditResourceType =
|
||||
| "project"
|
||||
| "service"
|
||||
| "environment"
|
||||
| "deployment"
|
||||
| "user"
|
||||
| "customRole"
|
||||
| "domain"
|
||||
| "certificate"
|
||||
| "registry"
|
||||
| "server"
|
||||
| "sshKey"
|
||||
| "gitProvider"
|
||||
| "destination"
|
||||
| "notification"
|
||||
| "settings"
|
||||
| "session"
|
||||
| "port"
|
||||
| "redirect"
|
||||
| "security"
|
||||
| "schedule"
|
||||
| "backup"
|
||||
| "volumeBackup"
|
||||
| "docker"
|
||||
| "swarm"
|
||||
| "previewDeployment"
|
||||
| "organization"
|
||||
| "cluster"
|
||||
| "mount"
|
||||
| "application"
|
||||
| "compose";
|
||||
@@ -165,11 +165,9 @@ export const apiCreateBackup = createSchema.pick({
|
||||
metadata: true,
|
||||
});
|
||||
|
||||
export const apiFindOneBackup = createSchema
|
||||
.pick({
|
||||
backupId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneBackup = z.object({
|
||||
backupId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiRemoveBackup = createSchema
|
||||
.pick({
|
||||
|
||||
@@ -12,6 +12,7 @@ import { gitea } from "./gitea";
|
||||
import { github } from "./github";
|
||||
import { gitlab } from "./gitlab";
|
||||
import { mounts } from "./mount";
|
||||
import { patch } from "./patch";
|
||||
import { schedules } from "./schedule";
|
||||
import { server } from "./server";
|
||||
import { applicationStatus, triggerType } from "./shared";
|
||||
@@ -143,6 +144,7 @@ export const composeRelations = relations(compose, ({ one, many }) => ({
|
||||
}),
|
||||
backups: many(backups),
|
||||
schedules: many(schedules),
|
||||
patches: many(patch),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(compose, {
|
||||
@@ -162,6 +164,11 @@ const createSchema = createInsertSchema(compose, {
|
||||
composePath: z.string().min(1),
|
||||
composeType: z.enum(["docker-compose", "stack"]).optional(),
|
||||
watchPaths: z.array(z.string()).optional(),
|
||||
sourceType: z
|
||||
.enum(["git", "github", "gitlab", "bitbucket", "gitea", "raw"])
|
||||
.optional(),
|
||||
triggerType: z.enum(["push", "tag"]).optional(),
|
||||
composeStatus: z.enum(["idle", "running", "done", "error"]).optional(),
|
||||
});
|
||||
|
||||
export const apiCreateCompose = createSchema.pick({
|
||||
|
||||
@@ -126,7 +126,6 @@ const schema = createInsertSchema(deployments, {
|
||||
previewDeploymentId: z.string(),
|
||||
buildServerId: z.string(),
|
||||
});
|
||||
|
||||
export const apiCreateDeployment = schema
|
||||
.pick({
|
||||
title: true,
|
||||
@@ -210,44 +209,27 @@ export const apiCreateDeploymentVolumeBackup = schema
|
||||
volumeBackupId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindAllByApplication = schema
|
||||
.pick({
|
||||
applicationId: true,
|
||||
})
|
||||
.extend({
|
||||
applicationId: z.string().min(1),
|
||||
})
|
||||
.required();
|
||||
export const apiFindAllByApplication = z.object({
|
||||
applicationId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindAllByCompose = schema
|
||||
.pick({
|
||||
composeId: true,
|
||||
})
|
||||
.extend({
|
||||
composeId: z.string().min(1),
|
||||
})
|
||||
.required();
|
||||
export const apiFindAllByCompose = z.object({
|
||||
composeId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindAllByServer = schema
|
||||
.pick({
|
||||
serverId: true,
|
||||
})
|
||||
.extend({
|
||||
serverId: z.string().min(1),
|
||||
})
|
||||
.required();
|
||||
export const apiFindAllByServer = z.object({
|
||||
serverId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindAllByType = z
|
||||
.object({
|
||||
id: z.string().min(1),
|
||||
type: z.enum([
|
||||
"application",
|
||||
"compose",
|
||||
"server",
|
||||
"schedule",
|
||||
"previewDeployment",
|
||||
"backup",
|
||||
"volumeBackup",
|
||||
]),
|
||||
})
|
||||
.required();
|
||||
export const apiFindAllByType = z.object({
|
||||
id: z.string().min(1),
|
||||
type: z.enum([
|
||||
"application",
|
||||
"compose",
|
||||
"server",
|
||||
"schedule",
|
||||
"previewDeployment",
|
||||
"backup",
|
||||
"volumeBackup",
|
||||
]),
|
||||
});
|
||||
|
||||
@@ -61,11 +61,9 @@ export const apiCreateDestination = createSchema
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiFindOneDestination = createSchema
|
||||
.pick({
|
||||
destinationId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneDestination = z.object({
|
||||
destinationId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiRemoveDestination = createSchema
|
||||
.pick({
|
||||
|
||||
@@ -70,7 +70,11 @@ export const domainsRelations = relations(domains, ({ one }) => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(domains, domain._def.schema.shape);
|
||||
const createSchema = createInsertSchema(domains, {
|
||||
...domain.shape,
|
||||
// Override pgEnum so Zod 4 infers only string literals, not numeric enum index
|
||||
domainType: z.enum(["compose", "application", "preview"]).optional(),
|
||||
});
|
||||
|
||||
export const apiCreateDomain = createSchema.pick({
|
||||
host: true,
|
||||
@@ -88,11 +92,9 @@ export const apiCreateDomain = createSchema.pick({
|
||||
stripPath: true,
|
||||
});
|
||||
|
||||
export const apiFindDomain = createSchema
|
||||
.pick({
|
||||
domainId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindDomain = z.object({
|
||||
domainId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindDomainByApplication = createSchema.pick({
|
||||
applicationId: true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { boolean, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { applications } from "./application";
|
||||
@@ -46,46 +45,30 @@ export const environmentRelations = relations(
|
||||
}),
|
||||
);
|
||||
|
||||
const createSchema = createInsertSchema(environments, {
|
||||
export const apiCreateEnvironment = z.object({
|
||||
name: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
projectId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindOneEnvironment = z.object({
|
||||
environmentId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiRemoveEnvironment = z.object({
|
||||
environmentId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiUpdateEnvironment = z.object({
|
||||
environmentId: z.string().min(1),
|
||||
name: z.string().min(1).optional(),
|
||||
description: z.string().optional(),
|
||||
projectId: z.string().optional(),
|
||||
env: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiDuplicateEnvironment = z.object({
|
||||
environmentId: z.string().min(1),
|
||||
name: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiCreateEnvironment = createSchema.pick({
|
||||
name: true,
|
||||
description: true,
|
||||
projectId: true,
|
||||
});
|
||||
|
||||
export const apiFindOneEnvironment = createSchema
|
||||
.pick({
|
||||
environmentId: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiRemoveEnvironment = createSchema
|
||||
.pick({
|
||||
environmentId: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiUpdateEnvironment = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
environmentId: z.string().min(1),
|
||||
})
|
||||
.omit({
|
||||
isDefault: true,
|
||||
});
|
||||
|
||||
export const apiDuplicateEnvironment = createSchema
|
||||
.pick({
|
||||
environmentId: true,
|
||||
name: true,
|
||||
description: true,
|
||||
})
|
||||
.required({
|
||||
environmentId: true,
|
||||
name: true,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { pgEnum, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { organization } from "./account";
|
||||
@@ -62,10 +61,6 @@ export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(gitProvider);
|
||||
|
||||
export const apiRemoveGitProvider = createSchema
|
||||
.extend({
|
||||
gitProviderId: z.string().min(1),
|
||||
})
|
||||
.pick({ gitProviderId: true });
|
||||
export const apiRemoveGitProvider = z.object({
|
||||
gitProviderId: z.string().min(1),
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { gitProvider } from "./git-provider";
|
||||
@@ -29,8 +28,7 @@ export const githubProviderRelations = relations(github, ({ one }) => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(github);
|
||||
export const apiCreateGithub = createSchema.extend({
|
||||
export const apiCreateGithub = z.object({
|
||||
githubAppName: z.string().optional(),
|
||||
githubAppId: z.number().optional(),
|
||||
githubClientId: z.string().optional(),
|
||||
@@ -48,13 +46,11 @@ export const apiFindGithubBranches = z.object({
|
||||
githubId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiFindOneGithub = createSchema
|
||||
.extend({
|
||||
githubId: z.string().min(1),
|
||||
})
|
||||
.pick({ githubId: true });
|
||||
export const apiFindOneGithub = z.object({
|
||||
githubId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiUpdateGithub = createSchema.extend({
|
||||
export const apiUpdateGithub = z.object({
|
||||
githubId: z.string().min(1),
|
||||
name: z.string().min(1),
|
||||
gitProviderId: z.string().min(1),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { gitProvider } from "./git-provider";
|
||||
@@ -31,9 +30,7 @@ export const gitlabProviderRelations = relations(gitlab, ({ one }) => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(gitlab);
|
||||
|
||||
export const apiCreateGitlab = createSchema.extend({
|
||||
export const apiCreateGitlab = z.object({
|
||||
applicationId: z.string().optional(),
|
||||
secret: z.string().optional(),
|
||||
groupName: z.string().optional(),
|
||||
@@ -45,17 +42,14 @@ export const apiCreateGitlab = createSchema.extend({
|
||||
gitlabInternalUrl: z.string().optional().nullable(),
|
||||
});
|
||||
|
||||
export const apiFindOneGitlab = createSchema
|
||||
.extend({
|
||||
gitlabId: z.string().min(1),
|
||||
})
|
||||
.pick({ gitlabId: true });
|
||||
export const apiFindOneGitlab = z.object({
|
||||
gitlabId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiGitlabTestConnection = createSchema
|
||||
.extend({
|
||||
groupName: z.string().optional(),
|
||||
})
|
||||
.pick({ gitlabId: true, groupName: true });
|
||||
export const apiGitlabTestConnection = z.object({
|
||||
gitlabId: z.string().min(1),
|
||||
groupName: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiFindGitlabBranches = z.object({
|
||||
id: z.number().optional(),
|
||||
@@ -64,7 +58,7 @@ export const apiFindGitlabBranches = z.object({
|
||||
gitlabId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiUpdateGitlab = createSchema.extend({
|
||||
export const apiUpdateGitlab = z.object({
|
||||
applicationId: z.string().optional(),
|
||||
secret: z.string().optional(),
|
||||
groupName: z.string().optional(),
|
||||
@@ -72,5 +66,6 @@ export const apiUpdateGitlab = createSchema.extend({
|
||||
name: z.string().min(1),
|
||||
gitlabId: z.string().min(1),
|
||||
gitlabUrl: z.string().min(1),
|
||||
gitProviderId: z.string().min(1),
|
||||
gitlabInternalUrl: z.string().optional().nullable(),
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./account";
|
||||
export * from "./ai";
|
||||
export * from "./audit-log";
|
||||
export * from "./application";
|
||||
export * from "./backups";
|
||||
export * from "./bitbucket";
|
||||
@@ -18,6 +19,7 @@ export * from "./mongo";
|
||||
export * from "./mount";
|
||||
export * from "./mysql";
|
||||
export * from "./notification";
|
||||
export * from "./patch";
|
||||
export * from "./port";
|
||||
export * from "./postgres";
|
||||
export * from "./preview-deployments";
|
||||
|
||||
@@ -160,11 +160,9 @@ export const apiCreateMariaDB = createSchema.pick({
|
||||
serverId: true,
|
||||
});
|
||||
|
||||
export const apiFindOneMariaDB = createSchema
|
||||
.pick({
|
||||
mariadbId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneMariaDB = z.object({
|
||||
mariadbId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiChangeMariaDBStatus = createSchema
|
||||
.pick({
|
||||
@@ -204,6 +202,7 @@ export const apiUpdateMariaDB = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
mariadbId: z.string().min(1),
|
||||
dockerImage: z.string().optional(),
|
||||
})
|
||||
.omit({ serverId: true });
|
||||
|
||||
|
||||
@@ -156,11 +156,9 @@ export const apiCreateMongo = createSchema.pick({
|
||||
replicaSets: true,
|
||||
});
|
||||
|
||||
export const apiFindOneMongo = createSchema
|
||||
.pick({
|
||||
mongoId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneMongo = z.object({
|
||||
mongoId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiChangeMongoStatus = createSchema
|
||||
.pick({
|
||||
@@ -193,6 +191,7 @@ export const apiUpdateMongo = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
mongoId: z.string().min(1),
|
||||
dockerImage: z.string().optional(),
|
||||
})
|
||||
.omit({ serverId: true });
|
||||
|
||||
|
||||
@@ -99,17 +99,15 @@ const createSchema = createInsertSchema(mounts, {
|
||||
mountPath: z.string().min(1),
|
||||
mountId: z.string().optional(),
|
||||
filePath: z.string().optional(),
|
||||
serviceType: z
|
||||
.enum([
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis",
|
||||
"compose",
|
||||
])
|
||||
.default("application"),
|
||||
serviceType: z.enum([
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis",
|
||||
"compose",
|
||||
]),
|
||||
});
|
||||
|
||||
export type ServiceType = NonNullable<
|
||||
@@ -130,11 +128,9 @@ export const apiCreateMount = createSchema
|
||||
serviceId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindOneMount = createSchema
|
||||
.pick({
|
||||
mountId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneMount = z.object({
|
||||
mountId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiRemoveMount = createSchema
|
||||
.pick({
|
||||
@@ -148,12 +144,20 @@ export const apiRemoveMount = createSchema
|
||||
export const apiFindMountByApplicationId = createSchema
|
||||
.extend({
|
||||
serviceId: z.string().min(1),
|
||||
serviceType: z.enum([
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis",
|
||||
"compose",
|
||||
]),
|
||||
})
|
||||
.pick({
|
||||
serviceId: true,
|
||||
serviceType: true,
|
||||
})
|
||||
.required();
|
||||
});
|
||||
|
||||
export const apiUpdateMount = createSchema.partial().extend({
|
||||
mountId: z.string().min(1),
|
||||
|
||||
@@ -157,11 +157,9 @@ export const apiCreateMySql = createSchema.pick({
|
||||
serverId: true,
|
||||
});
|
||||
|
||||
export const apiFindOneMySql = createSchema
|
||||
.pick({
|
||||
mysqlId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneMySql = z.object({
|
||||
mysqlId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiChangeMySqlStatus = createSchema
|
||||
.pick({
|
||||
@@ -201,6 +199,7 @@ export const apiUpdateMySql = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
mysqlId: z.string().min(1),
|
||||
dockerImage: z.string().optional(),
|
||||
})
|
||||
.omit({ serverId: true });
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ export const notificationType = pgEnum("notificationType", [
|
||||
"pushover",
|
||||
"custom",
|
||||
"lark",
|
||||
"teams",
|
||||
]);
|
||||
|
||||
export const notifications = pgTable("notification", {
|
||||
@@ -72,6 +73,9 @@ export const notifications = pgTable("notification", {
|
||||
pushoverId: text("pushoverId").references(() => pushover.pushoverId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
teamsId: text("teamsId").references(() => teams.teamsId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
organizationId: text("organizationId")
|
||||
.notNull()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
@@ -179,6 +183,14 @@ export const pushover = pgTable("pushover", {
|
||||
expire: integer("expire"),
|
||||
});
|
||||
|
||||
export const teams = pgTable("teams", {
|
||||
teamsId: text("teamsId")
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
webhookUrl: text("webhookUrl").notNull(),
|
||||
});
|
||||
|
||||
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
||||
slack: one(slack, {
|
||||
fields: [notifications.slackId],
|
||||
@@ -220,6 +232,10 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({
|
||||
fields: [notifications.pushoverId],
|
||||
references: [pushover.pushoverId],
|
||||
}),
|
||||
teams: one(teams, {
|
||||
fields: [notifications.teamsId],
|
||||
references: [teams.teamsId],
|
||||
}),
|
||||
organization: one(organization, {
|
||||
fields: [notifications.organizationId],
|
||||
references: [organization.id],
|
||||
@@ -448,11 +464,9 @@ export const apiTestNtfyConnection = apiCreateNtfy.pick({
|
||||
priority: true,
|
||||
});
|
||||
|
||||
export const apiFindOneNotification = notificationsSchema
|
||||
.pick({
|
||||
notificationId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneNotification = z.object({
|
||||
notificationId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiCreateCustom = notificationsSchema
|
||||
.pick({
|
||||
@@ -467,7 +481,7 @@ export const apiCreateCustom = notificationsSchema
|
||||
})
|
||||
.extend({
|
||||
endpoint: z.string().min(1),
|
||||
headers: z.record(z.string()).optional(),
|
||||
headers: z.record(z.string(), z.string()).optional(),
|
||||
});
|
||||
|
||||
export const apiUpdateCustom = apiCreateCustom.partial().extend({
|
||||
@@ -478,7 +492,7 @@ export const apiUpdateCustom = apiCreateCustom.partial().extend({
|
||||
|
||||
export const apiTestCustomConnection = z.object({
|
||||
endpoint: z.string().min(1),
|
||||
headers: z.record(z.string()).optional(),
|
||||
headers: z.record(z.string(), z.string()).optional(),
|
||||
});
|
||||
|
||||
export const apiCreateLark = notificationsSchema
|
||||
@@ -507,6 +521,32 @@ export const apiTestLarkConnection = apiCreateLark.pick({
|
||||
webhookUrl: true,
|
||||
});
|
||||
|
||||
export const apiCreateTeams = notificationsSchema
|
||||
.pick({
|
||||
appBuildError: true,
|
||||
databaseBackup: true,
|
||||
volumeBackup: true,
|
||||
dokployRestart: true,
|
||||
name: true,
|
||||
appDeploy: true,
|
||||
dockerCleanup: true,
|
||||
serverThreshold: true,
|
||||
})
|
||||
.extend({
|
||||
webhookUrl: z.string().min(1),
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiUpdateTeams = apiCreateTeams.partial().extend({
|
||||
notificationId: z.string().min(1),
|
||||
teamsId: z.string().min(1),
|
||||
organizationId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiTestTeamsConnection = apiCreateTeams.pick({
|
||||
webhookUrl: true,
|
||||
});
|
||||
|
||||
export const apiCreatePushover = notificationsSchema
|
||||
.pick({
|
||||
appBuildError: true,
|
||||
|
||||
100
packages/server/src/db/schema/patch.ts
Normal file
100
packages/server/src/db/schema/patch.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { boolean, pgEnum, pgTable, text, unique } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { applications } from "./application";
|
||||
import { compose } from "./compose";
|
||||
|
||||
export const patchType = pgEnum("patchType", ["create", "update", "delete"]);
|
||||
|
||||
export const patch = pgTable(
|
||||
"patch",
|
||||
{
|
||||
patchId: text("patchId")
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
type: patchType("type").notNull().default("update"),
|
||||
filePath: text("filePath").notNull(),
|
||||
enabled: boolean("enabled").notNull().default(true),
|
||||
content: text("content").notNull(),
|
||||
createdAt: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
updatedAt: text("updatedAt").$defaultFn(() => new Date().toISOString()),
|
||||
// Relations - one of these must be set
|
||||
applicationId: text("applicationId").references(
|
||||
() => applications.applicationId,
|
||||
{ onDelete: "cascade" },
|
||||
),
|
||||
composeId: text("composeId").references(() => compose.composeId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
},
|
||||
(table) => [
|
||||
// Unique constraint: one patch per file per application/compose
|
||||
unique("patch_filepath_application_unique").on(
|
||||
table.filePath,
|
||||
table.applicationId,
|
||||
),
|
||||
unique("patch_filepath_compose_unique").on(table.filePath, table.composeId),
|
||||
],
|
||||
);
|
||||
|
||||
export const patchRelations = relations(patch, ({ one }) => ({
|
||||
application: one(applications, {
|
||||
fields: [patch.applicationId],
|
||||
references: [applications.applicationId],
|
||||
}),
|
||||
compose: one(compose, {
|
||||
fields: [patch.composeId],
|
||||
references: [compose.composeId],
|
||||
}),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(patch, {
|
||||
filePath: z.string().min(1),
|
||||
content: z.string(),
|
||||
type: z.enum(["create", "update", "delete"]).optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
applicationId: z.string().optional(),
|
||||
composeId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiCreatePatch = createSchema.pick({
|
||||
filePath: true,
|
||||
content: true,
|
||||
type: true,
|
||||
enabled: true,
|
||||
applicationId: true,
|
||||
composeId: true,
|
||||
});
|
||||
|
||||
export const apiFindPatch = z.object({
|
||||
patchId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindPatchesByApplicationId = z.object({
|
||||
applicationId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindPatchesByComposeId = z.object({
|
||||
composeId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiUpdatePatch = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
patchId: z.string().min(1),
|
||||
})
|
||||
.omit({ applicationId: true, composeId: true });
|
||||
|
||||
export const apiDeletePatch = z.object({
|
||||
patchId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiTogglePatchEnabled = z.object({
|
||||
patchId: z.string().min(1),
|
||||
enabled: z.boolean(),
|
||||
});
|
||||
@@ -49,11 +49,9 @@ export const apiCreatePort = createSchema
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiFindOnePort = createSchema
|
||||
.pick({
|
||||
portId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOnePort = z.object({
|
||||
portId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiUpdatePort = createSchema
|
||||
.pick({
|
||||
|
||||
@@ -150,11 +150,9 @@ export const apiCreatePostgres = createSchema.pick({
|
||||
serverId: true,
|
||||
});
|
||||
|
||||
export const apiFindOnePostgres = createSchema
|
||||
.pick({
|
||||
postgresId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOnePostgres = z.object({
|
||||
postgresId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiChangePostgresStatus = createSchema
|
||||
.pick({
|
||||
@@ -194,6 +192,7 @@ export const apiUpdatePostgres = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
postgresId: z.string().min(1),
|
||||
dockerImage: z.string().optional(),
|
||||
})
|
||||
.omit({ serverId: true });
|
||||
|
||||
|
||||
@@ -58,17 +58,12 @@ export const createSchema = createInsertSchema(previewDeployments, {
|
||||
applicationId: z.string(),
|
||||
});
|
||||
|
||||
export const apiCreatePreviewDeployment = createSchema
|
||||
.pick({
|
||||
applicationId: true,
|
||||
domainId: true,
|
||||
branch: true,
|
||||
pullRequestId: true,
|
||||
pullRequestNumber: true,
|
||||
pullRequestURL: true,
|
||||
pullRequestTitle: true,
|
||||
})
|
||||
.extend({
|
||||
applicationId: z.string().min(1),
|
||||
// deploymentId: z.string().min(1),
|
||||
});
|
||||
export const apiCreatePreviewDeployment = z.object({
|
||||
applicationId: z.string().min(1),
|
||||
domainId: z.string().optional(),
|
||||
branch: z.string().min(1),
|
||||
pullRequestId: z.string().min(1),
|
||||
pullRequestNumber: z.string().min(1),
|
||||
pullRequestURL: z.string().min(1),
|
||||
pullRequestTitle: z.string().min(1),
|
||||
});
|
||||
|
||||
@@ -45,12 +45,9 @@ export const apiCreateProject = createSchema.pick({
|
||||
env: true,
|
||||
});
|
||||
|
||||
export const apiFindOneProject = createSchema
|
||||
.pick({
|
||||
projectId: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiFindOneProject = z.object({
|
||||
projectId: z.string().min(1),
|
||||
});
|
||||
export const apiRemoveProject = createSchema
|
||||
.pick({
|
||||
projectId: true,
|
||||
|
||||
@@ -35,11 +35,9 @@ const createSchema = createInsertSchema(redirects, {
|
||||
permanent: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const apiFindOneRedirect = createSchema
|
||||
.pick({
|
||||
redirectId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneRedirect = z.object({
|
||||
redirectId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiCreateRedirect = createSchema
|
||||
.pick({
|
||||
|
||||
@@ -136,11 +136,9 @@ export const apiCreateRedis = createSchema.pick({
|
||||
serverId: true,
|
||||
});
|
||||
|
||||
export const apiFindOneRedis = createSchema
|
||||
.pick({
|
||||
redisId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneRedis = z.object({
|
||||
redisId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiChangeRedisStatus = createSchema
|
||||
.pick({
|
||||
@@ -180,6 +178,7 @@ export const apiUpdateRedis = createSchema
|
||||
.partial()
|
||||
.extend({
|
||||
redisId: z.string().min(1),
|
||||
dockerImage: z.string().optional(),
|
||||
})
|
||||
.omit({ serverId: true });
|
||||
|
||||
|
||||
@@ -94,11 +94,9 @@ export const apiRemoveRegistry = createSchema
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiFindOneRegistry = createSchema
|
||||
.pick({
|
||||
registryId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneRegistry = z.object({
|
||||
registryId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiUpdateRegistry = createSchema.partial().extend({
|
||||
registryId: z.string().min(1),
|
||||
|
||||
@@ -38,11 +38,9 @@ const createSchema = createInsertSchema(security, {
|
||||
password: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiFindOneSecurity = createSchema
|
||||
.pick({
|
||||
securityId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneSecurity = z.object({
|
||||
securityId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiCreateSecurity = createSchema
|
||||
.pick({
|
||||
|
||||
@@ -133,6 +133,7 @@ const createSchema = createInsertSchema(server, {
|
||||
serverId: z.string().min(1),
|
||||
name: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
serverType: z.enum(["deploy", "build"]).optional(),
|
||||
});
|
||||
|
||||
export const apiCreateServer = createSchema
|
||||
@@ -147,11 +148,9 @@ export const apiCreateServer = createSchema
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiFindOneServer = createSchema
|
||||
.pick({
|
||||
serverId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneServer = z.object({
|
||||
serverId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiRemoveServer = createSchema
|
||||
.pick({
|
||||
|
||||
@@ -2,7 +2,7 @@ import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import { user } from "./user";
|
||||
|
||||
// OLD TABLE
|
||||
export const session = pgTable("session_temp", {
|
||||
export const session = pgTable("session", {
|
||||
id: text("id").primaryKey(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
token: text("token").notNull().unique(),
|
||||
|
||||
@@ -175,12 +175,12 @@ export const NetworkSwarmSchema = z.array(
|
||||
.object({
|
||||
Target: z.string().optional(),
|
||||
Aliases: z.array(z.string()).optional(),
|
||||
DriverOpts: z.record(z.string()).optional(),
|
||||
DriverOpts: z.record(z.string(), z.string()).optional(),
|
||||
})
|
||||
.strict(),
|
||||
);
|
||||
|
||||
export const LabelsSwarmSchema = z.record(z.string());
|
||||
export const LabelsSwarmSchema = z.record(z.string(), z.string());
|
||||
|
||||
export const EndpointPortConfigSwarmSchema = z
|
||||
.object({
|
||||
|
||||
@@ -2,6 +2,7 @@ import { relations } from "drizzle-orm";
|
||||
import { pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { sshKeyCreate, sshKeyType } from "../validations";
|
||||
import { organization } from "./account";
|
||||
import { applications } from "./application";
|
||||
@@ -52,11 +53,9 @@ export const apiCreateSshKey = createSchema
|
||||
})
|
||||
.merge(sshKeyCreate.pick({ privateKey: true }));
|
||||
|
||||
export const apiFindOneSshKey = createSchema
|
||||
.pick({
|
||||
sshKeyId: true,
|
||||
})
|
||||
.required();
|
||||
export const apiFindOneSshKey = z.object({
|
||||
sshKeyId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const apiGenerateSSHKey = sshKeyType;
|
||||
|
||||
|
||||
@@ -66,6 +66,36 @@ export const webServerSettings = pgTable("webServerSettings", {
|
||||
},
|
||||
},
|
||||
}),
|
||||
// Whitelabeling Configuration (Enterprise / Proprietary)
|
||||
whitelabelingConfig: jsonb("whitelabelingConfig")
|
||||
.$type<{
|
||||
appName: string | null;
|
||||
appDescription: string | null;
|
||||
logoUrl: string | null;
|
||||
faviconUrl: string | null;
|
||||
customCss: string | null;
|
||||
loginLogoUrl: string | null;
|
||||
supportUrl: string | null;
|
||||
docsUrl: string | null;
|
||||
errorPageTitle: string | null;
|
||||
errorPageDescription: string | null;
|
||||
metaTitle: string | null;
|
||||
footerText: string | null;
|
||||
}>()
|
||||
.default({
|
||||
appName: null,
|
||||
appDescription: null,
|
||||
logoUrl: null,
|
||||
faviconUrl: null,
|
||||
customCss: null,
|
||||
loginLogoUrl: null,
|
||||
supportUrl: null,
|
||||
docsUrl: null,
|
||||
errorPageTitle: null,
|
||||
errorPageDescription: null,
|
||||
metaTitle: null,
|
||||
footerText: null,
|
||||
}),
|
||||
// Cache Cleanup Configuration
|
||||
cleanupCacheApplications: boolean("cleanupCacheApplications")
|
||||
.notNull()
|
||||
@@ -154,6 +184,33 @@ export const apiUpdateDockerCleanup = z.object({
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
// Whitelabeling validation schemas
|
||||
const safeUrl = z
|
||||
.string()
|
||||
.refine((url) => /^https?:\/\//i.test(url), {
|
||||
message: "Only http:// and https:// URLs are allowed",
|
||||
})
|
||||
.nullable();
|
||||
|
||||
export const whitelabelingConfigSchema = z.object({
|
||||
appName: z.string().nullable(),
|
||||
appDescription: z.string().nullable(),
|
||||
logoUrl: safeUrl,
|
||||
faviconUrl: safeUrl,
|
||||
customCss: z.string().nullable(),
|
||||
loginLogoUrl: safeUrl,
|
||||
supportUrl: safeUrl,
|
||||
docsUrl: safeUrl,
|
||||
errorPageTitle: z.string().nullable(),
|
||||
errorPageDescription: z.string().nullable(),
|
||||
metaTitle: z.string().nullable(),
|
||||
footerText: z.string().nullable(),
|
||||
});
|
||||
|
||||
export const apiUpdateWhitelabeling = z.object({
|
||||
whitelabelingConfig: whitelabelingConfigSchema,
|
||||
});
|
||||
|
||||
export const apiUpdateWebServerMonitoring = z.object({
|
||||
metricsConfig: z
|
||||
.object({
|
||||
|
||||
Reference in New Issue
Block a user