fix: PR suggestions
This commit is contained in:
parent
1a12436195
commit
08a19ed38d
4 changed files with 25 additions and 119 deletions
|
|
@ -72,7 +72,6 @@ export const CreateRepositoryForm = ({
|
|||
const form = useForm<RepositoryFormValues>({
|
||||
resolver: arktypeResolver(cleanSchema as unknown as typeof formSchema),
|
||||
defaultValues: initialValues,
|
||||
mode: "onTouched",
|
||||
resetOptions: {
|
||||
keepDefaultValues: true,
|
||||
keepDirtyValues: false,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { useState, useRef } from "react";
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
import {
|
||||
FormControl,
|
||||
|
|
@ -22,10 +21,6 @@ type Props = {
|
|||
export const RestRepositoryForm = ({ form }: Props) => {
|
||||
const insecureTls = form.watch("insecureTls");
|
||||
const cacert = form.watch("cacert");
|
||||
const [showCertTooltip, setShowCertTooltip] = useState(false);
|
||||
const [tooltipPos, setTooltipPos] = useState({ x: 0, y: 0 });
|
||||
const tooltipTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const tooltipHideTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -91,81 +86,33 @@ export const RestRepositoryForm = ({ form }: Props) => {
|
|||
<FormItem>
|
||||
<FormLabel>CA Certificate (Optional)</FormLabel>
|
||||
<FormControl>
|
||||
<div className="relative">
|
||||
<Textarea
|
||||
placeholder="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----"
|
||||
rows={6}
|
||||
disabled={insecureTls}
|
||||
{...field}
|
||||
value={insecureTls ? "" : field.value}
|
||||
onChange={(e) => {
|
||||
field.onChange(e);
|
||||
if (e.target.value) {
|
||||
form.setValue("insecureTls", false);
|
||||
}
|
||||
}}
|
||||
onPointerEnter={(e) => {
|
||||
if (insecureTls && !showCertTooltip) {
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
setTooltipPos({
|
||||
x: e.clientX - rect.left,
|
||||
y: e.clientY - rect.top,
|
||||
});
|
||||
|
||||
// Clear any existing timeout
|
||||
if (tooltipTimeoutRef.current) {
|
||||
clearTimeout(tooltipTimeoutRef.current);
|
||||
}
|
||||
|
||||
// Set new timeout to show tooltip after 500ms
|
||||
tooltipTimeoutRef.current = setTimeout(() => {
|
||||
setShowCertTooltip(true);
|
||||
}, 500);
|
||||
}
|
||||
}}
|
||||
onPointerMove={(e) => {
|
||||
if (insecureTls && !showCertTooltip) {
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
setTooltipPos({
|
||||
x: e.clientX - rect.left,
|
||||
y: e.clientY - rect.top,
|
||||
});
|
||||
}
|
||||
}}
|
||||
onPointerLeave={() => {
|
||||
// Clear show timeout if still waiting
|
||||
if (tooltipTimeoutRef.current) {
|
||||
clearTimeout(tooltipTimeoutRef.current);
|
||||
tooltipTimeoutRef.current = null;
|
||||
}
|
||||
|
||||
// Clear any existing hide timeout
|
||||
if (tooltipHideTimeoutRef.current) {
|
||||
clearTimeout(tooltipHideTimeoutRef.current);
|
||||
}
|
||||
|
||||
// Set timeout to hide tooltip after 500ms
|
||||
tooltipHideTimeoutRef.current = setTimeout(() => {
|
||||
setShowCertTooltip(false);
|
||||
}, 500);
|
||||
}}
|
||||
/>
|
||||
{insecureTls && showCertTooltip && (
|
||||
<div
|
||||
className="pointer-events-none absolute z-50 rounded-md bg-foreground px-3 py-1.5 text-xs text-background shadow-md"
|
||||
style={{
|
||||
left: `${tooltipPos.x}px`,
|
||||
top: `${tooltipPos.y - 40}px`,
|
||||
transform: "translateX(-50%)",
|
||||
}}
|
||||
>
|
||||
<p className="max-w-xs text-balance">
|
||||
<Tooltip delayDuration={500}>
|
||||
<TooltipTrigger asChild>
|
||||
<div>
|
||||
<Textarea
|
||||
placeholder="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----"
|
||||
rows={6}
|
||||
disabled={insecureTls}
|
||||
{...field}
|
||||
value={insecureTls ? "" : field.value}
|
||||
onChange={(e) => {
|
||||
field.onChange(e);
|
||||
if (e.target.value) {
|
||||
form.setValue("insecureTls", false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
{insecureTls && (
|
||||
<TooltipContent>
|
||||
<p className="max-w-xs">
|
||||
CA certificate is disabled because TLS validation is being skipped. Uncheck "Skip TLS Certificate
|
||||
Verification" to provide a custom CA certificate.
|
||||
</p>
|
||||
</div>
|
||||
</TooltipContent>
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Custom CA certificate for self-signed certificates (PEM format).{" "}
|
||||
|
|
|
|||
|
|
@ -62,53 +62,13 @@ export const rcloneRepositoryConfigSchema = type({
|
|||
path: "string",
|
||||
}).and(baseRepositoryConfigSchema);
|
||||
|
||||
const pemCertificateType = type("string").narrow((value, ctx) => {
|
||||
if (!value || value.trim() === "") {
|
||||
return true;
|
||||
}
|
||||
|
||||
const trimmed = value.trim();
|
||||
|
||||
// Check for BEGIN and END markers
|
||||
if (!trimmed.includes("-----BEGIN CERTIFICATE-----") || !trimmed.includes("-----END CERTIFICATE-----")) {
|
||||
return ctx.error("Certificate must be in PEM format with BEGIN and END markers");
|
||||
}
|
||||
|
||||
// Extract content between markers
|
||||
const beginMarker = "-----BEGIN CERTIFICATE-----";
|
||||
const endMarker = "-----END CERTIFICATE-----";
|
||||
const beginIndex = trimmed.indexOf(beginMarker);
|
||||
const endIndex = trimmed.indexOf(endMarker);
|
||||
|
||||
if (beginIndex === -1 || endIndex === -1 || endIndex <= beginIndex) {
|
||||
return ctx.error("Invalid PEM certificate structure");
|
||||
}
|
||||
|
||||
// Extract base64 content
|
||||
const base64Content = trimmed.substring(beginIndex + beginMarker.length, endIndex).replace(/\s/g, "");
|
||||
|
||||
// Validate base64 format
|
||||
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
||||
if (!base64Regex.test(base64Content)) {
|
||||
return ctx.error("Certificate contains invalid base64 characters");
|
||||
}
|
||||
|
||||
if (base64Content.length === 0) {
|
||||
return ctx.error("Certificate content is empty");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
const optionalPemCertificate = pemCertificateType.optional();
|
||||
|
||||
export const restRepositoryConfigSchema = type({
|
||||
backend: "'rest'",
|
||||
url: "string",
|
||||
username: "string?",
|
||||
password: "string?",
|
||||
path: "string?",
|
||||
cacert: optionalPemCertificate as any,
|
||||
cacert: "string?",
|
||||
insecureTls: "boolean?",
|
||||
}).and(baseRepositoryConfigSchema);
|
||||
|
||||
|
|
|
|||
|
|
@ -886,7 +886,7 @@ export const cleanupTemporaryKeys = async (config: RepositoryConfig, env: Record
|
|||
await fs.unlink(env.GOOGLE_APPLICATION_CREDENTIALS).catch(() => {});
|
||||
}
|
||||
|
||||
if (config.backend === "rest" && env.RESTIC_CACERT) {
|
||||
if (env.RESTIC_CACERT) {
|
||||
await fs.unlink(env.RESTIC_CACERT).catch(() => {});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue