feat: implement whitelabeling features including settings, preview, and provider components

This commit is contained in:
Mauricio Siu
2026-03-10 00:27:58 -06:00
parent 6e67864204
commit b84bc9b7c6
36 changed files with 16148 additions and 98 deletions

View File

@@ -25,6 +25,7 @@ import { organizationRouter } from "./routers/organization";
import { patchRouter } from "./routers/patch";
import { licenseKeyRouter } from "./routers/proprietary/license-key";
import { ssoRouter } from "./routers/proprietary/sso";
import { whitelabelingRouter } from "./routers/proprietary/whitelabeling";
import { portRouter } from "./routers/port";
import { postgresRouter } from "./routers/postgres";
import { previewDeploymentRouter } from "./routers/preview-deployment";
@@ -87,6 +88,7 @@ export const appRouter = createTRPCRouter({
organization: organizationRouter,
licenseKey: licenseKeyRouter,
sso: ssoRouter,
whitelabeling: whitelabelingRouter,
schedule: scheduleRouter,
rollback: rollbackRouter,
volumeBackups: volumeBackupsRouter,

View File

@@ -0,0 +1,88 @@
import {
getWebServerSettings,
IS_CLOUD,
updateWebServerSettings,
} from "@dokploy/server";
import { TRPCError } from "@trpc/server";
import { apiUpdateWhitelabeling } from "@/server/db/schema";
import { adminProcedure, createTRPCRouter, publicProcedure } from "../../trpc";
export const whitelabelingRouter = createTRPCRouter({
get: adminProcedure.query(async () => {
if (IS_CLOUD) {
return null;
}
const settings = await getWebServerSettings();
return settings?.whitelabelingConfig ?? null;
}),
update: adminProcedure
.input(apiUpdateWhitelabeling)
.mutation(async ({ input, ctx }) => {
if (IS_CLOUD) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Whitelabeling is not available in Cloud",
});
}
if (ctx.user.role !== "owner") {
throw new TRPCError({
code: "FORBIDDEN",
message: "Only the owner can update whitelabeling settings",
});
}
await updateWebServerSettings({
whitelabelingConfig: input.whitelabelingConfig,
});
return { success: true };
}),
reset: adminProcedure.mutation(async ({ ctx }) => {
if (IS_CLOUD) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Whitelabeling is not available in Cloud",
});
}
if (ctx.user.role !== "owner") {
throw new TRPCError({
code: "FORBIDDEN",
message: "Only the owner can reset whitelabeling settings",
});
}
await updateWebServerSettings({
whitelabelingConfig: {
appName: null,
appDescription: null,
logoUrl: null,
faviconUrl: null,
primaryColor: null,
customCss: null,
loginLogoUrl: null,
supportUrl: null,
docsUrl: null,
errorPageTitle: null,
errorPageDescription: null,
metaTitle: null,
footerText: null,
},
});
return { success: true };
}),
// Public endpoint so the whitelabeling config can be applied globally
// (including on the login page before auth)
getPublic: publicProcedure.query(async () => {
if (IS_CLOUD) {
return null;
}
const settings = await getWebServerSettings();
return settings?.whitelabelingConfig ?? null;
}),
});

View File

@@ -101,7 +101,10 @@ export const userRouter = createTRPCRouter({
return memberResult;
}),
session: protectedProcedure.query(async ({ ctx }) => {
session: publicProcedure.query(async ({ ctx }) => {
if (!ctx.user || !ctx.session || !ctx.session.activeOrganizationId) {
return null;
}
return {
user: {
id: ctx.user.id,