Skip to content

Commit

Permalink
feat: web admin supports combined auth plugin config
Browse files Browse the repository at this point in the history
  • Loading branch information
vicanso committed Sep 22, 2024
1 parent 4c4b8b6 commit 8ec0960
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 26 deletions.
179 changes: 179 additions & 0 deletions web/src/components/combined-auths.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import * as React from "react";
import { cn } from "@/lib/utils";
import { Input } from "@/components/ui/input";
import { random } from "@/helpers/util";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { useI18n } from "@/i18n";
import { Button } from "./ui/button";

interface CombinedAuth {
app_id: string;
ip_list: string[];
secret: string;
deviation: number;
}

interface CombinedAuthsProps {
defaultValue?: CombinedAuth[];
onValueChange: (values: CombinedAuth[]) => void;
className?: string;
}

export const CombinedAuths = React.forwardRef<
HTMLInputElement,
CombinedAuthsProps
>(({ defaultValue = [], className, onValueChange, ...props }, ref) => {
const pluginI18n = useI18n("plugin");
const arr = defaultValue.map((item) => {
return {
id: random(),
app_id: item.app_id,
ip_list: item.ip_list,
secret: item.secret,
deviation: item.deviation,
};
});
if (arr.length === 0) {
arr.push({
id: random(),
app_id: "",
ip_list: [],
secret: "",
deviation: 10,
});
}
const [inputs, setInputs] = React.useState(arr);
const setUpdate = (
values: {
id: string;
app_id: string;
ip_list: string[];
secret: string;
deviation: number;
}[],
) => {
setInputs(values);
const arr: CombinedAuth[] = [];

values.forEach((item) => {
if (!item.app_id || !item.secret) {
return;
}
arr.push({
app_id: item.app_id,
ip_list: item.ip_list,
secret: item.secret,
deviation: item.deviation,
});
});
onValueChange(arr);
};

const items = inputs.map((item, index) => {
const last = index === inputs.length - 1;
const mb = last ? "" : "mb-4";
return (
<Card key={item.id} className={cn(mb)}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium ">
{pluginI18n("combinedAuthAuthParameters")}
</CardTitle>
</CardHeader>
<CardContent>
<Input
className="mb-4"
defaultValue={item.app_id || ""}
placeholder={pluginI18n("combinedAuthAuthAppIdPlaceholder")}
onInput={(e) => {
const value = (e.target as HTMLInputElement).value || "";
const arr = inputs.slice(0);
arr[index].app_id = value.trim();
setUpdate(arr);
}}
/>
<Input
className="mb-4"
defaultValue={(item.ip_list || []).join(",")}
placeholder={pluginI18n("combinedAuthAuthIpListPlaceholder")}
onInput={(e) => {
const value = (e.target as HTMLInputElement).value || "";
const arr = inputs.slice(0);
const ipList: string[] = [];
value.split(",").forEach((item) => {
const ip = item.trim();
if (ip) {
ipList.push(ip);
}
});
arr[index].ip_list = ipList;
setUpdate(arr);
}}
/>
<Input
className="mb-4"
defaultValue={item.secret || ""}
placeholder={pluginI18n("combinedAuthAuthSecretPlaceholder")}
onInput={(e) => {
const value = (e.target as HTMLInputElement).value || "";
const arr = inputs.slice(0);
arr[index].secret = value.trim();
setUpdate(arr);
}}
/>
<Input
className="mb-4"
type="number"
defaultValue={item.deviation}
placeholder={pluginI18n("combinedAuthAuthDeviationPlaceholder")}
onInput={(e) => {
const value = (e.target as HTMLInputElement).value || "";
const arr = inputs.slice(0);
arr[index].deviation = Number(value.trim());
setUpdate(arr);
}}
/>
{!last && (
<Button
className="w-full"
onClick={(e) => {
const arr = inputs.slice(0);
arr.splice(index, 1);
setUpdate(arr);
e.preventDefault();
}}
>
{pluginI18n("combinedAuthAuthRemove")}
</Button>
)}
{last && (
<Button
className="w-full"
onClick={(e) => {
const arr = inputs.slice(0);
arr.push({
id: random(),
app_id: "",
ip_list: [],
secret: "",
deviation: 10,
});
setUpdate(arr);
e.preventDefault();
}}
>
{pluginI18n("combinedAuthAuthAdd")}
</Button>
)}
</CardContent>
</Card>
);
});

return (
<div className={cn(className)} ref={ref} {...props}>
{items}
</div>
);
});

CombinedAuths.displayName = "CombinedAuths";
17 changes: 17 additions & 0 deletions web/src/components/ex-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { KvInputs } from "@/components/kv-inputs";
import { SortCheckboxs } from "@/components/sort-checkboxs";
import { ExFormOption, ExFormItemCategory } from "@/constants";
import { Inputs } from "@/components/inputs";
import { CombinedAuths } from "@/components/combined-auths";

function getOption(
value: string | number | boolean | null | undefined,
Expand Down Expand Up @@ -409,6 +410,22 @@ export function ExForm({
</FormItem>
);
}
case ExFormItemCategory.COMBINED_AUTHS: {
return (
<FormItem>
<FormLabel>{item.label}</FormLabel>
<FormControl>
<CombinedAuths
defaultValue={item.defaultValue as []}
onValueChange={(value) => {
setUpdated(item.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
);
}
default: {
return (
<FormItem>
Expand Down
76 changes: 76 additions & 0 deletions web/src/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import * as React from "react"

import { cn } from "@/lib/utils"

const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-xl border bg-card text-card-foreground shadow",
className
)}
{...props}
/>
))
Card.displayName = "Card"

const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
))
CardHeader.displayName = "CardHeader"

const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn("font-semibold leading-none tracking-tight", className)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"

const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"

const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"

const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"

export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
1 change: 1 addition & 0 deletions web/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export enum ExFormItemCategory {
JSON = "json",
KV_LIST = "kvList",
SORT_CHECKBOXS = "sortCheckboxs",
COMBINED_AUTHS = "combinedAuths",
}

export enum PluginCategory {
Expand Down
9 changes: 9 additions & 0 deletions web/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,5 +342,14 @@ export default {
"Input the header name : Input the header value",
responseHeadersRemoveHeader: "Remove Header",
responseHeadersRemoveHeaderPlaceholder: "Input the header name",
combinedAuthAuthorizations: "Authorizations",
combinedAuthAuthParameters: "Parameters",
combinedAuthAuthAppIdPlaceholder: "Input the app id",
combinedAuthAuthIpListPlaceholder: "Input the ip list",
combinedAuthAuthSecretPlaceholder: "Input the secret",
combinedAuthAuthDeviationPlaceholder: "Input the deviation(e.g. 10)",
combinedAuthAuthAdd: "Add",
combinedAuthAuthRemove: "Remove",
remark: "Remark",
},
};
9 changes: 9 additions & 0 deletions web/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,5 +323,14 @@ export default {
"输入设置响应头的名称 : 输入设置响应头的值",
responseHeadersRemoveHeader: "删除响应头",
responseHeadersRemoveHeaderPlaceholder: "输入响应头名称",
combinedAuthAuthorizations: "认证配置列表",
combinedAuthAuthParameters: "认证参数",
combinedAuthAuthAppIdPlaceholder: "输入应用id",
combinedAuthAuthIpListPlaceholder: "输入ip列表",
combinedAuthAuthSecretPlaceholder: "输入密钥",
combinedAuthAuthDeviationPlaceholder: "输入允许时间偏移量(e.g. 10)",
combinedAuthAuthAdd: "添加",
combinedAuthAuthRemove: "删除",
remark: "备注",
},
};
Loading

0 comments on commit 8ec0960

Please sign in to comment.