remove enable_clients flag from config

This commit is contained in:
miloschwartz
2025-12-03 15:02:39 -05:00
parent e1edbe6067
commit 357f297a3e
18 changed files with 138 additions and 232 deletions

View File

@@ -25,4 +25,3 @@ flags:
disable_user_create_org: true
allow_raw_resources: true
enable_integration_api: true
enable_clients: true

View File

@@ -85,10 +85,6 @@ export class Config {
? "true"
: "false";
process.env.FLAGS_ENABLE_CLIENTS = parsedConfig.flags?.enable_clients
? "true"
: "false";
process.env.PRODUCT_UPDATES_NOTIFICATION_ENABLED = parsedConfig.app
.notifications.product_updates
? "true"

View File

@@ -325,8 +325,7 @@ export const configSchema = z
enable_integration_api: z.boolean().optional(),
disable_local_sites: z.boolean().optional(),
disable_basic_wireguard_sites: z.boolean().optional(),
disable_config_managed_domains: z.boolean().optional(),
enable_clients: z.boolean().optional().default(true)
disable_config_managed_domains: z.boolean().optional()
})
.optional(),
dns: z

View File

@@ -25,7 +25,6 @@ export * from "./integration";
export * from "./verifyUserHasAction";
export * from "./verifyApiKeyAccess";
export * from "./verifyDomainAccess";
export * from "./verifyClientsEnabled";
export * from "./verifyUserIsOrgOwner";
export * from "./verifySiteResourceAccess";
export * from "./logActionAudit";

View File

@@ -1,29 +0,0 @@
import { Request, Response, NextFunction } from "express";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import config from "@server/lib/config";
export async function verifyClientsEnabled(
req: Request,
res: Response,
next: NextFunction
) {
try {
if (!config.getRawConfig().flags?.enable_clients) {
return next(
createHttpError(
HttpCode.NOT_IMPLEMENTED,
"Clients are not enabled on this server."
)
);
}
return next();
} catch (error) {
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to check if clients are enabled"
)
);
}
}

View File

@@ -31,7 +31,6 @@ import {
verifyUserIsServerAdmin,
verifySiteAccess,
verifyClientAccess,
verifyClientsEnabled,
} from "@server/middlewares";
import { ActionsEnum } from "@server/auth/actions";
import {
@@ -410,7 +409,6 @@ authenticated.get(
authenticated.post(
"/re-key/:clientId/regenerate-client-secret",
verifyClientsEnabled,
verifyClientAccess,
verifyUserHasAction(ActionsEnum.reGenerateSecret),
reKey.reGenerateClientSecret

View File

@@ -37,7 +37,6 @@ import {
verifyClientAccess,
verifyApiKeyAccess,
verifyDomainAccess,
verifyClientsEnabled,
verifyUserHasAction,
verifyUserIsOrgOwner,
verifySiteResourceAccess,
@@ -131,7 +130,6 @@ authenticated.get(
authenticated.get(
"/org/:orgId/pick-client-defaults",
verifyClientsEnabled,
verifyOrgAccess,
verifyUserHasAction(ActionsEnum.createClient),
client.pickClientDefaults
@@ -139,7 +137,6 @@ authenticated.get(
authenticated.get(
"/org/:orgId/clients",
verifyClientsEnabled,
verifyOrgAccess,
verifyUserHasAction(ActionsEnum.listClients),
client.listClients
@@ -147,7 +144,6 @@ authenticated.get(
authenticated.get(
"/client/:clientId",
verifyClientsEnabled,
verifyClientAccess,
verifyUserHasAction(ActionsEnum.getClient),
client.getClient
@@ -155,7 +151,6 @@ authenticated.get(
authenticated.put(
"/org/:orgId/client",
verifyClientsEnabled,
verifyOrgAccess,
verifyUserHasAction(ActionsEnum.createClient),
logActionAudit(ActionsEnum.createClient),
@@ -165,7 +160,6 @@ authenticated.put(
// TODO: Separate into a deleteUserClient (for user clients) and deleteClient (for machine clients)
authenticated.delete(
"/client/:clientId",
verifyClientsEnabled,
verifyClientAccess,
verifyUserHasAction(ActionsEnum.deleteClient),
logActionAudit(ActionsEnum.deleteClient),
@@ -174,7 +168,6 @@ authenticated.delete(
authenticated.post(
"/client/:clientId",
verifyClientsEnabled,
verifyClientAccess, // this will check if the user has access to the client
verifyUserHasAction(ActionsEnum.updateClient), // this will check if the user has permission to update the client
logActionAudit(ActionsEnum.updateClient),

View File

@@ -24,7 +24,6 @@ import {
verifyApiKeyAccessTokenAccess,
verifyApiKeyIsRoot,
verifyApiKeyClientAccess,
verifyClientsEnabled,
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients
} from "@server/middlewares";
@@ -796,7 +795,6 @@ authenticated.get(
authenticated.get(
"/org/:orgId/pick-client-defaults",
verifyClientsEnabled,
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.createClient),
client.pickClientDefaults
@@ -804,7 +802,6 @@ authenticated.get(
authenticated.get(
"/org/:orgId/clients",
verifyClientsEnabled,
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.listClients),
client.listClients
@@ -812,7 +809,6 @@ authenticated.get(
authenticated.get(
"/client/:clientId",
verifyClientsEnabled,
verifyApiKeyClientAccess,
verifyApiKeyHasAction(ActionsEnum.getClient),
client.getClient
@@ -820,7 +816,6 @@ authenticated.get(
authenticated.put(
"/org/:orgId/client",
verifyClientsEnabled,
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.createClient),
logActionAudit(ActionsEnum.createClient),
@@ -839,7 +834,6 @@ authenticated.put(
authenticated.delete(
"/client/:clientId",
verifyClientsEnabled,
verifyApiKeyClientAccess,
verifyApiKeyHasAction(ActionsEnum.deleteClient),
logActionAudit(ActionsEnum.deleteClient),
@@ -848,7 +842,6 @@ authenticated.delete(
authenticated.post(
"/client/:clientId",
verifyClientsEnabled,
verifyApiKeyClientAccess,
verifyApiKeyHasAction(ActionsEnum.updateClient),
logActionAudit(ActionsEnum.updateClient),

View File

@@ -13,9 +13,5 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
const { children } = props;
const env = pullEnv();
if (!env.flags.enableClients) {
redirect(`/${params.orgId}/settings`);
}
return children;
}

View File

@@ -342,29 +342,25 @@ export default function GeneralPage() {
</FormItem>
)}
/>
{env.flags.enableClients && (
<FormField
control={form.control}
name="subnet"
render={({ field }) => (
<FormItem>
<FormLabel>
{t("subnet")}
</FormLabel>
<FormControl>
<Input
{...field}
disabled={true}
/>
</FormControl>
<FormMessage />
<FormDescription>
{t("subnetDescription")}
</FormDescription>
</FormItem>
)}
/>
)}
<FormField
control={form.control}
name="subnet"
render={({ field }) => (
<FormItem>
<FormLabel>{t("subnet")}</FormLabel>
<FormControl>
<Input
{...field}
disabled={true}
/>
</FormControl>
<FormMessage />
<FormDescription>
{t("subnetDescription")}
</FormDescription>
</FormItem>
)}
/>
</SettingsSectionForm>
</SettingsSectionBody>
</SettingsSection>
@@ -600,7 +596,7 @@ export default function GeneralPage() {
</SettingsSectionHeader>
<SettingsSectionBody>
<SettingsSectionForm>
<SecurityFeaturesAlert />
<SecurityFeaturesAlert />
<FormField
control={form.control}
name="requireTwoFactor"

View File

@@ -82,7 +82,7 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
<Layout
orgId={params.orgId}
orgs={orgs}
navItems={orgNavSections(env.flags.enableClients)}
navItems={orgNavSections()}
>
{children}
</Layout>

View File

@@ -708,51 +708,50 @@ WantedBy=default.target`
</FormItem>
)}
/>
{env.flags.enableClients &&
form.watch("method") ===
"newt" && (
<FormField
control={form.control}
name="clientAddress"
render={({ field }) => (
<FormItem>
<FormLabel>
{t(
"siteAddress"
)}
</FormLabel>
<FormControl>
<Input
autoComplete="off"
value={
clientAddress
}
onChange={(
{form.watch("method") ===
"newt" && (
<FormField
control={form.control}
name="clientAddress"
render={({ field }) => (
<FormItem>
<FormLabel>
{t(
"siteAddress"
)}
</FormLabel>
<FormControl>
<Input
autoComplete="off"
value={
clientAddress
}
onChange={(
e
) => {
setClientAddress(
e
) => {
setClientAddress(
e
.target
.value
);
field.onChange(
e
.target
.value
);
}}
/>
</FormControl>
<FormMessage />
<FormDescription>
{t(
"siteAddressDescription"
)}
</FormDescription>
</FormItem>
)}
/>
)}
.target
.value
);
field.onChange(
e
.target
.value
);
}}
/>
</FormControl>
<FormMessage />
<FormDescription>
{t(
"siteAddressDescription"
)}
</FormDescription>
</FormItem>
)}
/>
)}
</form>
</Form>
</SettingsSectionForm>

View File

@@ -38,9 +38,7 @@ export const orgLangingNavItems: SidebarNavItem[] = [
}
];
export const orgNavSections = (
enableClients: boolean = true
): SidebarNavSection[] => [
export const orgNavSections = (): SidebarNavSection[] => [
{
heading: "General",
items: [
@@ -58,42 +56,30 @@ export const orgNavSections = (
href: "/{orgId}/settings/resources/proxy",
icon: <Globe className="size-4 flex-none" />
},
...(enableClients
? [
{
title: "sidebarClientResources",
href: "/{orgId}/settings/resources/client",
icon: (
<GlobeLock className="size-4 flex-none" />
)
}
]
: [])
{
title: "sidebarClientResources",
href: "/{orgId}/settings/resources/client",
icon: <GlobeLock className="size-4 flex-none" />
}
]
},
{
title: "sidebarClients",
icon: <MonitorUp className="size-4 flex-none" />,
isBeta: true,
items: [
{
href: "/{orgId}/settings/clients/user",
title: "sidebarUserDevices",
icon: <Laptop className="size-4 flex-none" />
},
{
href: "/{orgId}/settings/clients/machine",
title: "sidebarMachineClients",
icon: <Server className="size-4 flex-none" />
}
]
},
...(enableClients
? [
{
title: "sidebarClients",
icon: <MonitorUp className="size-4 flex-none" />,
isBeta: true,
items: [
{
href: "/{orgId}/settings/clients/user",
title: "sidebarUserDevices",
icon: (
<Laptop className="size-4 flex-none" />
)
},
{
href: "/{orgId}/settings/clients/machine",
title: "sidebarMachineClients",
icon: <Server className="size-4 flex-none" />
}
]
}
]
: []),
...(build == "saas"
? [
{

View File

@@ -296,31 +296,27 @@ export default function StepperForm() {
)}
/>
{env.flags.enableClients && (
<FormField
control={orgForm.control}
name="subnet"
render={({ field }) => (
<FormItem>
<FormLabel>
Subnet
</FormLabel>
<FormControl>
<Input
type="text"
{...field}
/>
</FormControl>
<FormMessage />
<FormDescription>
The subnet for this
organization's internal
network.
</FormDescription>
</FormItem>
)}
/>
)}
<FormField
control={orgForm.control}
name="subnet"
render={({ field }) => (
<FormItem>
<FormLabel>Subnet</FormLabel>
<FormControl>
<Input
type="text"
{...field}
/>
</FormControl>
<FormMessage />
<FormDescription>
The subnet for this
organization's internal
network.
</FormDescription>
</FormItem>
)}
/>
{orgIdTaken && !orgCreated ? (
<Alert variant="destructive">

View File

@@ -35,7 +35,7 @@ export default function SiteInfoCard({ }: SiteInfoCardProps) {
return (
<Alert>
<AlertDescription>
<InfoSections cols={env.flags.enableClients ? 4 : 3}>
<InfoSections cols={4}>
<InfoSection>
<InfoSectionTitle>
{t("identifier")}
@@ -75,7 +75,7 @@ export default function SiteInfoCard({ }: SiteInfoCardProps) {
</InfoSectionContent>
</InfoSection>
{env.flags.enableClients && site.type == "newt" && (
{site.type == "newt" && (
<InfoSection>
<InfoSectionTitle>Address</InfoSectionTitle>
<InfoSectionContent>

View File

@@ -306,42 +306,32 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
);
}
},
...(env.flags.enableClients
? [
{
accessorKey: "address",
header: ({
column
}: {
column: Column<SiteRow, unknown>;
}) => {
return (
<Button
variant="ghost"
onClick={() =>
column.toggleSorting(
column.getIsSorted() === "asc"
)
}
>
Address
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
cell: ({ row }: { row: any }) => {
const originalRow = row.original;
return originalRow.address ? (
<div className="flex items-center space-x-2">
<span>{originalRow.address}</span>
</div>
) : (
"-"
);
}
}
]
: []),
{
accessorKey: "address",
header: ({ column }: { column: Column<SiteRow, unknown> }) => {
return (
<Button
variant="ghost"
onClick={() =>
column.toggleSorting(column.getIsSorted() === "asc")
}
>
Address
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
cell: ({ row }: { row: any }) => {
const originalRow = row.original;
return originalRow.address ? (
<div className="flex items-center space-x-2">
<span>{originalRow.address}</span>
</div>
) : (
"-"
);
}
},
{
id: "actions",
enableHiding: false,
@@ -403,9 +393,7 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
}}
dialog={
<div className="">
<p>
{t("siteQuestionRemove")}
</p>
<p>{t("siteQuestionRemove")}</p>
<p>{t("siteMessageRemove")}</p>
</div>
}

View File

@@ -55,8 +55,6 @@ export function pullEnv(): Env {
process.env.FLAGS_DISABLE_BASIC_WIREGUARD_SITES === "true"
? true
: false,
enableClients:
process.env.FLAGS_ENABLE_CLIENTS === "true" ? true : false,
hideSupporterKey:
process.env.HIDE_SUPPORTER_KEY === "true" ? true : false,
usePangolinDns:

View File

@@ -30,7 +30,6 @@ export type Env = {
allowRawResources: boolean;
disableLocalSites: boolean;
disableBasicWireguardSites: boolean;
enableClients: boolean;
hideSupporterKey: boolean;
usePangolinDns: boolean;
};