Merge pull request #3702 from fosrl/dev

1.22.2
This commit is contained in:
Owen Schwartz
2026-09-04 17:18:42 -04:00
committed by GitHub
19 changed files with 124 additions and 25 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ import { encrypt } from "@server/lib/crypto";
import { configFilePath1, configFilePath2 } from "@server/lib/consts"; import { configFilePath1, configFilePath2 } from "@server/lib/consts";
import { generateCA } from "@server/lib/sshCA"; import { generateCA } from "@server/lib/sshCA";
import fs from "fs"; import fs from "fs";
import yaml from "js-yaml"; import * as yaml from "js-yaml";
type GenerateOrgCaKeysArgs = { type GenerateOrgCaKeysArgs = {
orgId: string; orgId: string;
+1 -1
View File
@@ -4,7 +4,7 @@ import { encrypt, decrypt } from "@server/lib/crypto";
import { configFilePath1, configFilePath2 } from "@server/lib/consts"; import { configFilePath1, configFilePath2 } from "@server/lib/consts";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import fs from "fs"; import fs from "fs";
import yaml from "js-yaml"; import * as yaml from "js-yaml";
type RotateServerSecretArgs = { type RotateServerSecretArgs = {
"old-secret": string; "old-secret": string;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

+20
View File
@@ -0,0 +1,20 @@
import config from "@server/lib/config";
// Mirrors the optional fields on the olm client's TunnelConfig - any field
// present here overrides the value the olm client is otherwise locally
// configured with; an absent field leaves the client's own config alone.
export type OlmDnsConfig = {
upstreamDns?: string[];
overrideDns?: boolean;
tunnelDns?: boolean;
matchDomains?: string[];
};
export function buildOlmDnsConfig(): OlmDnsConfig | undefined {
return {
upstreamDns: undefined,
overrideDns: undefined,
tunnelDns: undefined,
matchDomains: undefined
};
}
@@ -15,6 +15,7 @@ import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2"; import { sha256 } from "@oslojs/crypto/sha2";
import { getUserDeviceName } from "@server/db/names"; import { getUserDeviceName } from "@server/db/names";
import { buildSiteConfigurationForOlmClient } from "./buildConfiguration"; import { buildSiteConfigurationForOlmClient } from "./buildConfiguration";
import { buildOlmDnsConfig } from "./dnsConfig";
import { OlmErrorCodes, sendOlmError } from "./error"; import { OlmErrorCodes, sendOlmError } from "./error";
import { handleFingerprintInsertion } from "./fingerprintingUtils"; import { handleFingerprintInsertion } from "./fingerprintingUtils";
import { build } from "@server/build"; import { build } from "@server/build";
@@ -512,6 +513,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
tunnelIP: `${clientSubnet.split("/")[0]}/${exitNode.address.split("/")[1]}` // we need to use the exit node's subnet mask here because the client will be using the exit node's subnet mask for its routing table so we can address it tunnelIP: `${clientSubnet.split("/")[0]}/${exitNode.address.split("/")[1]}` // we need to use the exit node's subnet mask here because the client will be using the exit node's subnet mask for its routing table so we can address it
} }
: undefined, : undefined,
dnsConfig: buildOlmDnsConfig(),
chainId: chainId chainId: chainId
} }
}, },
@@ -13,7 +13,12 @@ import { StrategyOption, StrategySelect } from "@app/components/StrategySelect";
import HeaderTitle from "@app/components/SettingsSectionTitle"; import HeaderTitle from "@app/components/SettingsSectionTitle";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
import { useParams, useRouter } from "next/navigation"; import { useParams, useRouter } from "next/navigation";
import { useActionState, useRef, useState } from "react"; import {
useActionState,
useRef,
useState,
startTransition
} from "react";
import { import {
Form, Form,
FormControl, FormControl,
@@ -518,9 +523,12 @@ export default function Page() {
<SettingsSectionForm> <SettingsSectionForm>
<Form {...internalForm}> <Form {...internalForm}>
<form <form
action={ onSubmit={(e) => {
submitInternalAction e.preventDefault();
} startTransition(() => {
submitInternalAction();
});
}}
className="space-y-4" className="space-y-4"
id="create-user-form" id="create-user-form"
> >
+12 -2
View File
@@ -3,7 +3,12 @@ import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
import { useOrgContext } from "@app/hooks/useOrgContext"; import { useOrgContext } from "@app/hooks/useOrgContext";
import { toast } from "@app/hooks/useToast"; import { toast } from "@app/hooks/useToast";
import { useState, useTransition, useActionState } from "react"; import {
useState,
useTransition,
useActionState,
startTransition
} from "react";
import { import {
Form, Form,
FormControl, FormControl,
@@ -243,7 +248,12 @@ function GeneralSectionForm({ org }: SectionFormProps) {
<SettingsSectionForm> <SettingsSectionForm>
<Form {...form}> <Form {...form}>
<form <form
action={formAction} onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
className="grid gap-4" className="grid gap-4"
id="org-general-settings-form" id="org-general-settings-form"
> >
@@ -3,7 +3,13 @@ import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
import { useOrgContext } from "@app/hooks/useOrgContext"; import { useOrgContext } from "@app/hooks/useOrgContext";
import { toast } from "@app/hooks/useToast"; import { toast } from "@app/hooks/useToast";
import { useState, useRef, useActionState, type ComponentRef } from "react"; import {
useState,
useRef,
useActionState,
startTransition,
type ComponentRef
} from "react";
import { import {
Form, Form,
FormControl, FormControl,
@@ -207,7 +213,9 @@ function LogRetentionSectionForm({ org }: SectionFormProps) {
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
startTransition(() => {
formAction(); formAction();
});
}} }}
className="grid gap-4" className="grid gap-4"
id="org-log-retention-settings-form" id="org-log-retention-settings-form"
@@ -959,7 +967,9 @@ function SecuritySettingsSectionForm({ org }: SectionFormProps) {
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
startTransition(() => {
formAction(); formAction();
});
}} }}
ref={formRef} ref={formRef}
id="security-settings-section-form" id="security-settings-section-form"
@@ -41,7 +41,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useActionState, useEffect, useMemo } from "react"; import { useActionState, useEffect, useMemo, startTransition } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
@@ -232,7 +232,12 @@ export default function PrivateResourceInferencePage() {
<SettingsSectionForm variant="half"> <SettingsSectionForm variant="half">
<Form {...form}> <Form {...form}>
<form <form
action={formAction} onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
id="private-resource-providers-form" id="private-resource-providers-form"
> >
<SettingsFormGrid> <SettingsFormGrid>
@@ -29,7 +29,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import Link from "next/link"; import Link from "next/link";
import { ExternalLink } from "lucide-react"; import { ExternalLink } from "lucide-react";
import { useActionState, useMemo } from "react"; import { useActionState, useMemo, startTransition } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
import { useSaveSiteResource } from "@app/hooks/useSaveSiteResource"; import { useSaveSiteResource } from "@app/hooks/useSaveSiteResource";
@@ -97,7 +97,12 @@ export default function PrivateResourceGeneralPage() {
<SettingsSectionForm variant="half"> <SettingsSectionForm variant="half">
<Form {...form}> <Form {...form}>
<form <form
action={formAction} onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
id="private-resource-general-form" id="private-resource-general-form"
> >
<SettingsFormGrid> <SettingsFormGrid>
@@ -41,7 +41,13 @@ import { AxiosResponse } from "axios";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useParams, useRouter } from "next/navigation"; import { useParams, useRouter } from "next/navigation";
import { toASCII, toUnicode } from "punycode"; import { toASCII, toUnicode } from "punycode";
import { useActionState, useEffect, useMemo, useState } from "react"; import {
useActionState,
useEffect,
useMemo,
useState,
startTransition
} from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import z from "zod"; import z from "zod";
@@ -282,7 +288,12 @@ export default function GeneralForm() {
<SettingsSectionForm variant="half"> <SettingsSectionForm variant="half">
<Form {...form}> <Form {...form}>
<form <form
action={formAction} onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
id="general-settings-form" id="general-settings-form"
> >
<SettingsFormGrid> <SettingsFormGrid>
@@ -41,7 +41,7 @@ import {
import { AxiosResponse } from "axios"; import { AxiosResponse } from "axios";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useParams, useRouter } from "next/navigation"; import { useParams, useRouter } from "next/navigation";
import { useActionState, useState } from "react"; import { useActionState, useState, startTransition } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
@@ -209,7 +209,15 @@ function ProxyResourceHttpForm({
<SettingsSectionBody> <SettingsSectionBody>
<SettingsSectionForm variant="half"> <SettingsSectionForm variant="half">
<Form {...form}> <Form {...form}>
<form action={formAction} id="http-settings-form"> <form
onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
id="http-settings-form"
>
<SettingsFormGrid> <SettingsFormGrid>
{!env.flags.usePangolinDns && ( {!env.flags.usePangolinDns && (
<SettingsFormCell span="full"> <SettingsFormCell span="full">
@@ -37,7 +37,7 @@ import { AxiosResponse } from "axios";
import { AlertCircle } from "lucide-react"; import { AlertCircle } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useParams, useRouter } from "next/navigation"; import { useParams, useRouter } from "next/navigation";
import { useActionState, useEffect } from "react"; import { useActionState, useEffect, startTransition } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import z from "zod"; import z from "zod";
@@ -203,7 +203,12 @@ export default function ResourceMaintenancePage() {
<SettingsSectionForm variant="half"> <SettingsSectionForm variant="half">
<Form {...maintenanceForm}> <Form {...maintenanceForm}>
<form <form
action={maintenanceFormAction} onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
maintenanceFormAction();
});
}}
id="maintenance-settings-form" id="maintenance-settings-form"
> >
<SettingsFormGrid> <SettingsFormGrid>
@@ -48,7 +48,8 @@ import { useRouter } from "next/navigation";
import { import {
use, use,
useActionState, useActionState,
useMemo useMemo,
startTransition
} from "react"; } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
@@ -206,7 +207,12 @@ function ProxyResourceProtocolForm({
<SettingsSectionForm variant="half"> <SettingsSectionForm variant="half">
<Form {...proxySettingsForm}> <Form {...proxySettingsForm}>
<form <form
action={formAction} onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
id="proxy-protocol-settings-form" id="proxy-protocol-settings-form"
> >
<SettingsFormGrid> <SettingsFormGrid>
+2 -1
View File
@@ -62,7 +62,8 @@ export function OrgLabelForm({
<form <form
id="org-label-form" id="org-label-form"
className="flex flex-col gap-4 px-0.5" className="flex flex-col gap-4 px-0.5"
action={async () => { onSubmit={async (e) => {
e.preventDefault();
if (await form.trigger()) { if (await form.trigger()) {
onSubmit(form.getValues()); onSubmit(form.getValues());
} }
@@ -211,7 +211,15 @@ export default function AlertRuleGraphEditor({
return ( return (
<Form {...form}> <Form {...form}>
<form id={FORM_ID} action={formAction}> <form
id={FORM_ID}
onSubmit={(e) => {
e.preventDefault();
startTransition(() => {
formAction();
});
}}
>
<SettingsContainer> <SettingsContainer>
<PaidFeaturesAlert tiers={tierMatrix.alertingRules} /> <PaidFeaturesAlert tiers={tierMatrix.alertingRules} />
<div className="flex flex-col lg:flex-row gap-6 lg:gap-8 items-start"> <div className="flex flex-col lg:flex-row gap-6 lg:gap-8 items-start">