@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
@@ -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"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||