import { isDebug } from "core";
import { autoFormatString } from "core/utils";
import { type ChangeEvent, useState } from "react";
import {
TbAt,
TbBrandAppleFilled,
TbBrandDiscordFilled,
TbBrandFacebookFilled,
TbBrandGithubFilled,
TbBrandGoogleFilled,
TbBrandInstagram,
TbBrandOauth,
TbBrandX,
TbSettings,
} from "react-icons/tb";
import { twMerge } from "tailwind-merge";
import { useBknd } from "ui/client/bknd";
import { useBkndAuth } from "ui/client/schema/auth/use-bknd-auth";
import { Button } from "ui/components/buttons/Button";
import { IconButton } from "ui/components/buttons/IconButton";
import { Message } from "ui/components/display/Message";
import {
Field,
Form,
FormContextOverride,
FormDebug,
HiddenField,
ObjectField,
Subscribe,
useDerivedFieldContext,
useFormError,
useFormValue,
} from "ui/components/form/json-schema-form";
import { useBrowserTitle } from "ui/hooks/use-browser-title";
import * as AppShell from "../../layouts/AppShell/AppShell";
export function AuthStrategiesList(props) {
useBrowserTitle(["Auth", "Strategies"]);
const {
hasSecrets,
config: {
auth: { enabled },
},
} = useBknd({ withSecrets: true });
if (!hasSecrets) {
return ;
} else if (!enabled) {
return ;
}
return ;
}
const formOptions = {
keepEmpty: true,
debug: isDebug(),
};
function AuthStrategiesListInternal() {
const $auth = useBkndAuth();
const config = $auth.config.strategies;
const schema = $auth.schema.properties.strategies;
const schemas = Object.fromEntries(
// @ts-ignore
$auth.schema.properties.strategies.additionalProperties.anyOf.map((s) => [
s.properties.type.const,
s,
]),
);
async function handleSubmit(data: any) {
await $auth.actions.config.set({ strategies: data });
}
return (
);
}
type StrategyProps = {
type: "password" | "oauth" | "custom_oauth";
name: string;
unavailable?: boolean;
};
const Strategy = ({ type, name, unavailable }: StrategyProps) => {
const errors = useFormError(name, { strict: true });
const $auth = useBkndAuth();
const schemas = Object.fromEntries(
// @ts-ignore
$auth.schema.properties.strategies.additionalProperties.anyOf.map((s) => [
s.properties.type.const,
s,
]),
);
const schema = schemas[type];
const [open, setOpen] = useState(false);
if (!schema) return null;
return (
0 && "border-red-500",
)}
>
{autoFormatString(name)}
setOpen((o) => !o)}
/>
{open && (
)}
);
};
const StrategyToggle = ({ type }: { type: StrategyProps["type"] }) => {
const ctx = useDerivedFieldContext("");
const { value } = useFormValue("");
function handleToggleChange(e: ChangeEvent) {
const checked = e.target.value;
const value_keys = Object.keys(value ?? {});
const can_remove =
value_keys.length === 0 || (value_keys.length === 1 && value_keys[0] === "enabled");
if (!checked && can_remove) {
ctx.deleteValue(ctx.path);
} else {
ctx.setValue([ctx.path, "enabled"].join("."), checked);
}
}
return ;
};
const StrategyIcon = ({ type, provider }: { type: StrategyProps["type"]; provider?: string }) => {
if (type === "password") {
return ;
}
if (provider && provider in OAUTH_BRANDS) {
const BrandIcon = OAUTH_BRANDS[provider];
return ;
}
return ;
};
const OAUTH_BRANDS = {
google: TbBrandGoogleFilled,
github: TbBrandGithubFilled,
facebook: TbBrandFacebookFilled,
x: TbBrandX,
instagram: TbBrandInstagram,
apple: TbBrandAppleFilled,
discord: TbBrandDiscordFilled,
};
const StrategyForm = ({ type, name }: Pick) => {
let Component = (p: any) => (
);
switch (type) {
case "password":
Component = StrategyPasswordForm;
break;
case "oauth":
Component = StrategyOAuthForm;
break;
}
return (
<>
>
);
};
const StrategyPasswordForm = () => {
return ;
};
const StrategyOAuthForm = ({ type, name }: Pick) => {
return (
<>
>
);
};