From b8fe2a985b9af41c6aabe1e89aafd691bd89480e Mon Sep 17 00:00:00 2001 From: Nico <47644445+nicotsx@users.noreply.github.com> Date: Fri, 2 Jan 2026 18:13:19 +0100 Subject: [PATCH] feat: insecure tls & cacert for self-hosted repos (#277) * feat: insecure tls & cacert for self-hosted repos * fix: extra arg --- app/client/components/ui/collapsible.tsx | 98 +++++++++++++++ .../components/create-repository-form.tsx | 3 + .../repository-forms/advanced-tls-form.tsx | 112 ++++++++++++++++++ .../components/repository-forms/index.ts | 1 + .../repository-forms/rest-repository-form.tsx | 84 ------------- app/client/modules/repositories/tabs/info.tsx | 10 +- app/schemas/restic.ts | 4 +- app/server/modules/lifecycle/migration.ts | 2 +- .../repositories/repositories.service.ts | 7 +- app/server/utils/restic.ts | 50 ++++---- bun.lock | 3 + package.json | 1 + 12 files changed, 259 insertions(+), 116 deletions(-) create mode 100644 app/client/components/ui/collapsible.tsx create mode 100644 app/client/modules/repositories/components/repository-forms/advanced-tls-form.tsx diff --git a/app/client/components/ui/collapsible.tsx b/app/client/components/ui/collapsible.tsx new file mode 100644 index 00000000..5e13272d --- /dev/null +++ b/app/client/components/ui/collapsible.tsx @@ -0,0 +1,98 @@ +import * as React from "react"; +import { ChevronDown } from "lucide-react"; +import { cn } from "~/client/lib/utils"; + +interface CollapsibleProps extends React.HTMLAttributes { + open?: boolean; + onOpenChange?: (open: boolean) => void; + defaultOpen?: boolean; +} + +const CollapsibleContext = React.createContext<{ + open: boolean; + setOpen: React.Dispatch>; +}>({ + open: false, + setOpen: () => {}, +}); + +const Collapsible = React.forwardRef( + ({ className, open: controlledOpen, onOpenChange, defaultOpen = false, children, ...props }, ref) => { + const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen); + + const isControlled = controlledOpen !== undefined; + const open = isControlled ? controlledOpen : uncontrolledOpen; + + const setOpen = React.useCallback( + (value: React.SetStateAction) => { + const newValue = typeof value === "function" ? value(open) : value; + if (!isControlled) { + setUncontrolledOpen(newValue); + } + onOpenChange?.(newValue); + }, + [isControlled, open, onOpenChange], + ); + + return ( + +
+ {children} +
+
+ ); + }, +); +Collapsible.displayName = "Collapsible"; + +interface CollapsibleTriggerProps extends React.ButtonHTMLAttributes {} + +const CollapsibleTrigger = React.forwardRef( + ({ className, children, ...props }, ref) => { + const { open, setOpen } = React.useContext(CollapsibleContext); + + return ( + + ); + }, +); +CollapsibleTrigger.displayName = "CollapsibleTrigger"; + +interface CollapsibleContentProps extends React.HTMLAttributes {} + +const CollapsibleContent = React.forwardRef( + ({ className, children, ...props }, ref) => { + const { open } = React.useContext(CollapsibleContext); + + return ( + + ); + }, +); +CollapsibleContent.displayName = "CollapsibleContent"; + +export { Collapsible, CollapsibleTrigger, CollapsibleContent }; diff --git a/app/client/modules/repositories/components/create-repository-form.tsx b/app/client/modules/repositories/components/create-repository-form.tsx index 08fa6e0b..827cb2cf 100644 --- a/app/client/modules/repositories/components/create-repository-form.tsx +++ b/app/client/modules/repositories/components/create-repository-form.tsx @@ -31,6 +31,7 @@ import { RcloneRepositoryForm, RestRepositoryForm, SftpRepositoryForm, + AdvancedForm, } from "./repository-forms"; export const formSchema = type({ @@ -268,6 +269,8 @@ export const CreateRepositoryForm = ({ {watchedBackend === "rest" && } {watchedBackend === "sftp" && } + + {mode === "update" && (