all resources at the base domain closes #137

This commit is contained in:
Milo Schwartz 2025-02-03 21:18:16 -05:00
parent 0840c166ab
commit e475c1ea50
No known key found for this signature in database
15 changed files with 496 additions and 141 deletions

View file

@ -34,7 +34,8 @@ const createResourceSchema = z
siteId: z.number(),
http: z.boolean(),
protocol: z.string(),
proxyPort: z.number().optional()
proxyPort: z.number().optional(),
isBaseDomain: z.boolean().optional()
})
.refine(
(data) => {
@ -55,7 +56,7 @@ const createResourceSchema = z
)
.refine(
(data) => {
if (data.http) {
if (data.http && !data.isBaseDomain) {
return subdomainSchema.safeParse(data.subdomain).success;
}
return true;
@ -75,7 +76,7 @@ const createResourceSchema = z
return true;
},
{
message: "Cannot update proxyPort"
message: "Proxy port cannot be set"
}
)
.refine(
@ -88,6 +89,19 @@ const createResourceSchema = z
{
message: "Port 80 and 443 are reserved for http and https resources"
}
)
.refine(
(data) => {
if (!config.getRawConfig().flags?.allow_base_domain_resources) {
if (data.isBaseDomain) {
return false;
}
}
return true;
},
{
message: "Base domain resources are not allowed"
}
);
export type CreateResourceResponse = Resource;
@ -108,7 +122,7 @@ export async function createResource(
);
}
let { name, subdomain, protocol, proxyPort, http } = parsedBody.data;
let { name, subdomain, protocol, proxyPort, http, isBaseDomain } = parsedBody.data;
// Validate request params
const parsedParams = createResourceParamsSchema.safeParse(req.params);
@ -145,7 +159,13 @@ export async function createResource(
);
}
const fullDomain = `${subdomain}.${org[0].domain}`;
let fullDomain = "";
if (isBaseDomain) {
fullDomain = org[0].domain;
} else {
fullDomain = `${subdomain}.${org[0].domain}`;
}
// if http is false check to see if there is already a resource with the same port and protocol
if (!http) {
const existingResource = await db
@ -195,7 +215,8 @@ export async function createResource(
http,
protocol,
proxyPort,
ssl: true
ssl: true,
isBaseDomain
})
.returning();

View file

@ -28,7 +28,8 @@ const updateResourceBodySchema = z
sso: z.boolean().optional(),
blockAccess: z.boolean().optional(),
proxyPort: z.number().int().min(1).max(65535).optional(),
emailWhitelistEnabled: z.boolean().optional()
emailWhitelistEnabled: z.boolean().optional(),
isBaseDomain: z.boolean().optional()
})
.strict()
.refine((data) => Object.keys(data).length > 0, {
@ -55,6 +56,19 @@ const updateResourceBodySchema = z
{
message: "Port 80 and 443 are reserved for http and https resources"
}
)
.refine(
(data) => {
if (!config.getRawConfig().flags?.allow_base_domain_resources) {
if (data.isBaseDomain) {
return false;
}
}
return true;
},
{
message: "Base domain resources are not allowed"
}
);
export async function updateResource(
@ -104,6 +118,29 @@ export async function updateResource(
);
}
if (updateData.subdomain) {
if (!resource.http) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Cannot update subdomain for non-http resource"
)
);
}
const valid = subdomainSchema.safeParse(
updateData.subdomain
).success;
if (!valid) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid subdomain provided"
)
);
}
}
if (updateData.proxyPort) {
const proxyPort = updateData.proxyPort;
const existingResource = await db
@ -138,15 +175,32 @@ export async function updateResource(
);
}
const fullDomain = updateData.subdomain
? `${updateData.subdomain}.${org.domain}`
: undefined;
let fullDomain = "";
if (updateData.isBaseDomain) {
fullDomain = org.domain;
} else {
fullDomain = `${updateData.subdomain}.${org.domain}`;
}
const updatePayload = {
...updateData,
...(fullDomain && { fullDomain })
};
const [existingDomain] = await db
.select()
.from(resources)
.where(eq(resources.fullDomain, fullDomain));
if (existingDomain && existingDomain.resourceId !== resourceId) {
return next(
createHttpError(
HttpCode.CONFLICT,
"Resource with that domain already exists"
)
);
}
const updatedResource = await db
.update(resources)
.set(updatePayload)

View file

@ -25,6 +25,7 @@ export async function traefikConfigProvider(
http: resources.http,
proxyPort: resources.proxyPort,
protocol: resources.protocol,
isBaseDomain: resources.isBaseDomain,
// Site fields
site: {
siteId: sites.siteId,
@ -110,11 +111,11 @@ export async function traefikConfigProvider(
const routerName = `${resource.resourceId}-router`;
const serviceName = `${resource.resourceId}-service`;
const fullDomain = `${resource.subdomain}.${org.domain}`;
const fullDomain = `${resource.fullDomain}`;
if (resource.http) {
// HTTP configuration remains the same
if (!resource.subdomain) {
if (!resource.subdomain && !resource.isBaseDomain) {
continue;
}
@ -148,6 +149,8 @@ export async function traefikConfigProvider(
: {})
};
logger.debug(config.getRawConfig().traefik.prefer_wildcard_cert)
const additionalMiddlewares =
config.getRawConfig().traefik.additional_middlewares || [];