mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-13 08:26:40 +00:00
Merge branch 'dev' into feat/login-page-customization
This commit is contained in:
@@ -34,14 +34,16 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
title: t('apiKeysPermissionsTitle'),
|
||||
title: t("apiKeysPermissionsTitle"),
|
||||
href: "/admin/api-keys/{apiKeyId}/permissions"
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsSectionTitle title={t('apiKeysSettings', {apiKeyName: apiKey?.name})} />
|
||||
<SettingsSectionTitle
|
||||
title={t("apiKeysSettings", { apiKeyName: apiKey?.name })}
|
||||
/>
|
||||
|
||||
<ApiKeyProvider apiKey={apiKey}>
|
||||
<HorizontalTabs items={navItems}>{children}</HorizontalTabs>
|
||||
|
||||
@@ -45,10 +45,10 @@ export default function Page() {
|
||||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('apiKeysPermissionsErrorLoadingActions'),
|
||||
title: t("apiKeysPermissionsErrorLoadingActions"),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
t('apiKeysPermissionsErrorLoadingActions')
|
||||
t("apiKeysPermissionsErrorLoadingActions")
|
||||
)
|
||||
});
|
||||
});
|
||||
@@ -79,18 +79,18 @@ export default function Page() {
|
||||
)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(t('apiKeysErrorSetPermission'), e);
|
||||
console.error(t("apiKeysErrorSetPermission"), e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('apiKeysErrorSetPermission'),
|
||||
title: t("apiKeysErrorSetPermission"),
|
||||
description: formatAxiosError(e)
|
||||
});
|
||||
});
|
||||
|
||||
if (actionsRes && actionsRes.status === 200) {
|
||||
toast({
|
||||
title: t('apiKeysPermissionsUpdated'),
|
||||
description: t('apiKeysPermissionsUpdatedDescription')
|
||||
title: t("apiKeysPermissionsUpdated"),
|
||||
description: t("apiKeysPermissionsUpdatedDescription")
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,10 +104,12 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('apiKeysPermissionsTitle')}
|
||||
{t("apiKeysPermissionsTitle")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('apiKeysPermissionsGeneralSettingsDescription')}
|
||||
{t(
|
||||
"apiKeysPermissionsGeneralSettingsDescription"
|
||||
)}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -125,7 +127,7 @@ export default function Page() {
|
||||
loading={loadingSavePermissions}
|
||||
disabled={loadingSavePermissions}
|
||||
>
|
||||
{t('apiKeysPermissionsSave')}
|
||||
{t("apiKeysPermissionsSave")}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSectionBody>
|
||||
|
||||
@@ -30,7 +30,7 @@ import { createApiClient, formatAxiosError } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { toast } from "@app/hooks/useToast";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
CreateOrgApiKeyBody,
|
||||
CreateOrgApiKeyResponse
|
||||
@@ -64,10 +64,10 @@ export default function Page() {
|
||||
name: z
|
||||
.string()
|
||||
.min(2, {
|
||||
message: t('nameMin', {len: 2})
|
||||
message: t("nameMin", { len: 2 })
|
||||
})
|
||||
.max(255, {
|
||||
message: t('nameMax', {len: 255})
|
||||
message: t("nameMax", { len: 255 })
|
||||
})
|
||||
});
|
||||
|
||||
@@ -82,7 +82,7 @@ export default function Page() {
|
||||
return data.copied;
|
||||
},
|
||||
{
|
||||
message: t('apiKeysConfirmCopy2'),
|
||||
message: t("apiKeysConfirmCopy2"),
|
||||
path: ["copied"]
|
||||
}
|
||||
);
|
||||
@@ -115,7 +115,7 @@ export default function Page() {
|
||||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('apiKeysErrorCreate'),
|
||||
title: t("apiKeysErrorCreate"),
|
||||
description: formatAxiosError(e)
|
||||
});
|
||||
});
|
||||
@@ -136,10 +136,10 @@ export default function Page() {
|
||||
)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(t('apiKeysErrorSetPermission'), e);
|
||||
console.error(t("apiKeysErrorSetPermission"), e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('apiKeysErrorSetPermission'),
|
||||
title: t("apiKeysErrorSetPermission"),
|
||||
description: formatAxiosError(e)
|
||||
});
|
||||
});
|
||||
@@ -172,8 +172,8 @@ export default function Page() {
|
||||
<>
|
||||
<div className="flex justify-between">
|
||||
<HeaderTitle
|
||||
title={t('apiKeysCreate')}
|
||||
description={t('apiKeysCreateDescription')}
|
||||
title={t("apiKeysCreate")}
|
||||
description={t("apiKeysCreateDescription")}
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -181,7 +181,7 @@ export default function Page() {
|
||||
router.push(`/admin/api-keys`);
|
||||
}}
|
||||
>
|
||||
{t('apiKeysSeeAll')}
|
||||
{t("apiKeysSeeAll")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -193,7 +193,7 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('apiKeysTitle')}
|
||||
{t("apiKeysTitle")}
|
||||
</SettingsSectionTitle>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -214,7 +214,7 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('name')}
|
||||
{t("name")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -235,10 +235,12 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('apiKeysGeneralSettings')}
|
||||
{t("apiKeysGeneralSettings")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('apiKeysGeneralSettingsDescription')}
|
||||
{t(
|
||||
"apiKeysGeneralSettingsDescription"
|
||||
)}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -258,14 +260,14 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('apiKeysList')}
|
||||
{t("apiKeysList")}
|
||||
</SettingsSectionTitle>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<InfoSections cols={2}>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
{t('name')}
|
||||
{t("name")}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<CopyToClipboard
|
||||
@@ -275,7 +277,7 @@ export default function Page() {
|
||||
</InfoSection>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
{t('created')}
|
||||
{t("created")}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
{moment(
|
||||
@@ -288,10 +290,10 @@ export default function Page() {
|
||||
<Alert variant="neutral">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
{t('apiKeysSave')}
|
||||
{t("apiKeysSave")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('apiKeysSaveDescription')}
|
||||
{t("apiKeysSaveDescription")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
@@ -358,7 +360,7 @@ export default function Page() {
|
||||
router.push(`/admin/api-keys`);
|
||||
}}
|
||||
>
|
||||
{t('cancel')}
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
)}
|
||||
{!apiKey && (
|
||||
@@ -370,7 +372,7 @@ export default function Page() {
|
||||
form.handleSubmit(onSubmit)();
|
||||
}}
|
||||
>
|
||||
{t('generate')}
|
||||
{t("generate")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -381,7 +383,7 @@ export default function Page() {
|
||||
copiedForm.handleSubmit(onCopiedSubmit)();
|
||||
}}
|
||||
>
|
||||
{t('done')}
|
||||
{t("done")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -34,8 +34,8 @@ export default async function ApiKeysPage(props: ApiKeyPageProps) {
|
||||
return (
|
||||
<>
|
||||
<SettingsSectionTitle
|
||||
title={t('apiKeysManage')}
|
||||
description={t('apiKeysDescription')}
|
||||
title={t("apiKeysManage")}
|
||||
description={t("apiKeysDescription")}
|
||||
/>
|
||||
|
||||
<ApiKeysTable apiKeys={rows} />
|
||||
|
||||
@@ -58,17 +58,17 @@ export default function GeneralPage() {
|
||||
const t = useTranslations();
|
||||
|
||||
const GeneralFormSchema = z.object({
|
||||
name: z.string().min(2, { message: t('nameMin', {len: 2}) }),
|
||||
clientId: z.string().min(1, { message: t('idpClientIdRequired') }),
|
||||
clientSecret: z.string().min(1, { message: t('idpClientSecretRequired') }),
|
||||
authUrl: z.url({ message: t('idpErrorAuthUrlInvalid') }),
|
||||
tokenUrl: z.url({ message: t('idpErrorTokenUrlInvalid') }),
|
||||
identifierPath: z
|
||||
name: z.string().min(2, { message: t("nameMin", { len: 2 }) }),
|
||||
clientId: z.string().min(1, { message: t("idpClientIdRequired") }),
|
||||
clientSecret: z
|
||||
.string()
|
||||
.min(1, { message: t('idpPathRequired') }),
|
||||
.min(1, { message: t("idpClientSecretRequired") }),
|
||||
authUrl: z.url({ message: t("idpErrorAuthUrlInvalid") }),
|
||||
tokenUrl: z.url({ message: t("idpErrorTokenUrlInvalid") }),
|
||||
identifierPath: z.string().min(1, { message: t("idpPathRequired") }),
|
||||
emailPath: z.string().optional(),
|
||||
namePath: z.string().optional(),
|
||||
scopes: z.string().min(1, { message: t('idpScopeRequired') }),
|
||||
scopes: z.string().min(1, { message: t("idpScopeRequired") }),
|
||||
autoProvision: z.boolean().default(false)
|
||||
});
|
||||
|
||||
@@ -111,7 +111,7 @@ export default function GeneralPage() {
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -145,14 +145,14 @@ export default function GeneralPage() {
|
||||
|
||||
if (res.status === 200) {
|
||||
toast({
|
||||
title: t('success'),
|
||||
description: t('idpUpdatedDescription')
|
||||
title: t("success"),
|
||||
description: t("idpUpdatedDescription")
|
||||
});
|
||||
router.refresh();
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -171,17 +171,17 @@ export default function GeneralPage() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpTitle')}
|
||||
{t("idpTitle")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpSettingsDescription')}
|
||||
{t("idpSettingsDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<InfoSections cols={3}>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
{t('redirectUrl')}
|
||||
{t("redirectUrl")}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<CopyToClipboard text={redirectUrl} />
|
||||
@@ -192,10 +192,10 @@ export default function GeneralPage() {
|
||||
<Alert variant="neutral" className="">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
{t('redirectUrlAbout')}
|
||||
{t("redirectUrlAbout")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('redirectUrlAboutDescription')}
|
||||
{t("redirectUrlAboutDescription")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
<SettingsSectionForm>
|
||||
@@ -210,12 +210,14 @@ export default function GeneralPage() {
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('name')}</FormLabel>
|
||||
<FormLabel>
|
||||
{t("name")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpDisplayName')}
|
||||
{t("idpDisplayName")}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -225,7 +227,7 @@ export default function GeneralPage() {
|
||||
<div className="flex items-start mb-0">
|
||||
<SwitchInput
|
||||
id="auto-provision-toggle"
|
||||
label={t('idpAutoProvisionUsers')}
|
||||
label={t("idpAutoProvisionUsers")}
|
||||
defaultChecked={form.getValues(
|
||||
"autoProvision"
|
||||
)}
|
||||
@@ -238,7 +240,7 @@ export default function GeneralPage() {
|
||||
/>
|
||||
</div>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{t('idpAutoProvisionUsersDescription')}
|
||||
{t("idpAutoProvisionUsersDescription")}
|
||||
</span>
|
||||
</form>
|
||||
</Form>
|
||||
@@ -250,10 +252,10 @@ export default function GeneralPage() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpOidcConfigure')}
|
||||
{t("idpOidcConfigure")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpOidcConfigureDescription')}
|
||||
{t("idpOidcConfigureDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -270,13 +272,15 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpClientId')}
|
||||
{t("idpClientId")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpClientIdDescription')}
|
||||
{t(
|
||||
"idpClientIdDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -289,7 +293,7 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpClientSecret')}
|
||||
{t("idpClientSecret")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -298,7 +302,9 @@ export default function GeneralPage() {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpClientSecretDescription')}
|
||||
{t(
|
||||
"idpClientSecretDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -311,13 +317,15 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpAuthUrl')}
|
||||
{t("idpAuthUrl")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpAuthUrlDescription')}
|
||||
{t(
|
||||
"idpAuthUrlDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -330,13 +338,15 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpTokenUrl')}
|
||||
{t("idpTokenUrl")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpTokenUrlDescription')}
|
||||
{t(
|
||||
"idpTokenUrlDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -351,10 +361,10 @@ export default function GeneralPage() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpToken')}
|
||||
{t("idpToken")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpTokenDescription')}
|
||||
{t("idpTokenDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -368,17 +378,21 @@ export default function GeneralPage() {
|
||||
<Alert variant="neutral">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
{t('idpJmespathAbout')}
|
||||
{t("idpJmespathAbout")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('idpJmespathAboutDescription')}
|
||||
{t(
|
||||
"idpJmespathAboutDescription"
|
||||
)}
|
||||
<a
|
||||
href="https://jmespath.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline inline-flex items-center"
|
||||
>
|
||||
{t('idpJmespathAboutDescriptionLink')}{" "}
|
||||
{t(
|
||||
"idpJmespathAboutDescriptionLink"
|
||||
)}{" "}
|
||||
<ExternalLink className="ml-1 h-4 w-4" />
|
||||
</a>
|
||||
</AlertDescription>
|
||||
@@ -390,13 +404,15 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpJmespathLabel')}
|
||||
{t("idpJmespathLabel")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpJmespathLabelDescription')}
|
||||
{t(
|
||||
"idpJmespathLabelDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -409,13 +425,17 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpJmespathEmailPathOptional')}
|
||||
{t(
|
||||
"idpJmespathEmailPathOptional"
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpJmespathEmailPathOptionalDescription')}
|
||||
{t(
|
||||
"idpJmespathEmailPathOptionalDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -428,13 +448,17 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpJmespathNamePathOptional')}
|
||||
{t(
|
||||
"idpJmespathNamePathOptional"
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpJmespathNamePathOptionalDescription')}
|
||||
{t(
|
||||
"idpJmespathNamePathOptionalDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -447,13 +471,17 @@ export default function GeneralPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpOidcConfigureScopes')}
|
||||
{t(
|
||||
"idpOidcConfigureScopes"
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpOidcConfigureScopesDescription')}
|
||||
{t(
|
||||
"idpOidcConfigureScopesDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -474,7 +502,7 @@ export default function GeneralPage() {
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
{t('saveGeneralSettings')}
|
||||
{t("saveGeneralSettings")}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -89,7 +89,7 @@ export default function PoliciesPage() {
|
||||
const [editingPolicy, setEditingPolicy] = useState<PolicyRow | null>(null);
|
||||
|
||||
const policyFormSchema = z.object({
|
||||
orgId: z.string().min(1, { message: t('orgRequired') }),
|
||||
orgId: z.string().min(1, { message: t("orgRequired") }),
|
||||
roleMapping: z.string().optional(),
|
||||
orgMapping: z.string().optional()
|
||||
});
|
||||
@@ -133,7 +133,7 @@ export default function PoliciesPage() {
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -148,7 +148,7 @@ export default function PoliciesPage() {
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -167,7 +167,7 @@ export default function PoliciesPage() {
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -202,15 +202,15 @@ export default function PoliciesPage() {
|
||||
};
|
||||
setPolicies([...policies, newPolicy]);
|
||||
toast({
|
||||
title: t('success'),
|
||||
description: t('orgPolicyAddedDescription')
|
||||
title: t("success"),
|
||||
description: t("orgPolicyAddedDescription")
|
||||
});
|
||||
setShowAddDialog(false);
|
||||
form.reset();
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -244,8 +244,8 @@ export default function PoliciesPage() {
|
||||
)
|
||||
);
|
||||
toast({
|
||||
title: t('success'),
|
||||
description: t('orgPolicyUpdatedDescription')
|
||||
title: t("success"),
|
||||
description: t("orgPolicyUpdatedDescription")
|
||||
});
|
||||
setShowAddDialog(false);
|
||||
setEditingPolicy(null);
|
||||
@@ -253,7 +253,7 @@ export default function PoliciesPage() {
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -271,13 +271,13 @@ export default function PoliciesPage() {
|
||||
policies.filter((policy) => policy.orgId !== orgId)
|
||||
);
|
||||
toast({
|
||||
title: t('success'),
|
||||
description: t('orgPolicyDeletedDescription')
|
||||
title: t("success"),
|
||||
description: t("orgPolicyDeletedDescription")
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -295,13 +295,13 @@ export default function PoliciesPage() {
|
||||
});
|
||||
if (res.status === 200) {
|
||||
toast({
|
||||
title: t('success'),
|
||||
description: t('defaultMappingsUpdatedDescription')
|
||||
title: t("success"),
|
||||
description: t("defaultMappingsUpdatedDescription")
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -320,18 +320,18 @@ export default function PoliciesPage() {
|
||||
<Alert variant="neutral" className="mb-6">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
{t('orgPoliciesAbout')}
|
||||
{t("orgPoliciesAbout")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{/*TODO(vlalx): Validate replacing */}
|
||||
{t('orgPoliciesAboutDescription')}{" "}
|
||||
{t("orgPoliciesAboutDescription")}{" "}
|
||||
<Link
|
||||
href="https://docs.pangolin.net/manage/identity-providers/auto-provisioning"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{t('orgPoliciesAboutDescriptionLink')}
|
||||
{t("orgPoliciesAboutDescriptionLink")}
|
||||
<ExternalLink className="ml-1 h-4 w-4 inline" />
|
||||
</Link>
|
||||
</AlertDescription>
|
||||
@@ -340,10 +340,10 @@ export default function PoliciesPage() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('defaultMappingsOptional')}
|
||||
{t("defaultMappingsOptional")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('defaultMappingsOptionalDescription')}
|
||||
{t("defaultMappingsOptionalDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -362,13 +362,15 @@ export default function PoliciesPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('defaultMappingsRole')}
|
||||
{t("defaultMappingsRole")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('defaultMappingsRoleDescription')}
|
||||
{t(
|
||||
"defaultMappingsRoleDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -381,13 +383,15 @@ export default function PoliciesPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('defaultMappingsOrg')}
|
||||
{t("defaultMappingsOrg")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('defaultMappingsOrgDescription')}
|
||||
{t(
|
||||
"defaultMappingsOrgDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -402,7 +406,7 @@ export default function PoliciesPage() {
|
||||
form="policy-default-mappings-form"
|
||||
loading={updateDefaultMappingsLoading}
|
||||
>
|
||||
{t('defaultMappingsSubmit')}
|
||||
{t("defaultMappingsSubmit")}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSectionBody>
|
||||
@@ -445,11 +449,11 @@ export default function PoliciesPage() {
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>
|
||||
{editingPolicy
|
||||
? t('orgPoliciesEdit')
|
||||
: t('orgPoliciesAdd')}
|
||||
? t("orgPoliciesEdit")
|
||||
: t("orgPoliciesAdd")}
|
||||
</CredenzaTitle>
|
||||
<CredenzaDescription>
|
||||
{t('orgPolicyConfig')}
|
||||
{t("orgPolicyConfig")}
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody>
|
||||
@@ -466,7 +470,7 @@ export default function PoliciesPage() {
|
||||
name="orgId"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormLabel>{t('org')}</FormLabel>
|
||||
<FormLabel>{t("org")}</FormLabel>
|
||||
{editingPolicy ? (
|
||||
<Input {...field} disabled />
|
||||
) : (
|
||||
@@ -490,17 +494,25 @@ export default function PoliciesPage() {
|
||||
org.orgId ===
|
||||
field.value
|
||||
)?.name
|
||||
: t('orgSelect')}
|
||||
: t(
|
||||
"orgSelect"
|
||||
)}
|
||||
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder={t('orgSearch')} />
|
||||
<CommandInput
|
||||
placeholder={t(
|
||||
"orgSearch"
|
||||
)}
|
||||
/>
|
||||
<CommandList>
|
||||
<CommandEmpty>
|
||||
{t('orgNotFound')}
|
||||
{t(
|
||||
"orgNotFound"
|
||||
)}
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{organizations.map(
|
||||
@@ -551,13 +563,15 @@ export default function PoliciesPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('roleMappingPathOptional')}
|
||||
{t("roleMappingPathOptional")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('defaultMappingsRoleDescription')}
|
||||
{t(
|
||||
"defaultMappingsRoleDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -570,13 +584,15 @@ export default function PoliciesPage() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('orgMappingPathOptional')}
|
||||
{t("orgMappingPathOptional")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('defaultMappingsOrgDescription')}
|
||||
{t(
|
||||
"defaultMappingsOrgDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -603,7 +619,9 @@ export default function PoliciesPage() {
|
||||
: addPolicyLoading
|
||||
}
|
||||
>
|
||||
{editingPolicy ? t('orgPolicyUpdate') : t('orgPolicyAdd')}
|
||||
{editingPolicy
|
||||
? t("orgPolicyUpdate")
|
||||
: t("orgPolicyAdd")}
|
||||
</Button>
|
||||
</CredenzaFooter>
|
||||
</CredenzaContent>
|
||||
|
||||
@@ -48,18 +48,18 @@ export default function Page() {
|
||||
const t = useTranslations();
|
||||
|
||||
const createIdpFormSchema = z.object({
|
||||
name: z.string().min(2, { message: t('nameMin', {len: 2}) }),
|
||||
name: z.string().min(2, { message: t("nameMin", { len: 2 }) }),
|
||||
type: z.enum(["oidc"]),
|
||||
clientId: z.string().min(1, { message: t('idpClientIdRequired') }),
|
||||
clientSecret: z.string().min(1, { message: t('idpClientSecretRequired') }),
|
||||
authUrl: z.url({ message: t('idpErrorAuthUrlInvalid') }),
|
||||
tokenUrl: z.url({ message: t('idpErrorTokenUrlInvalid') }),
|
||||
identifierPath: z
|
||||
clientId: z.string().min(1, { message: t("idpClientIdRequired") }),
|
||||
clientSecret: z
|
||||
.string()
|
||||
.min(1, { message: t('idpPathRequired') }),
|
||||
.min(1, { message: t("idpClientSecretRequired") }),
|
||||
authUrl: z.url({ message: t("idpErrorAuthUrlInvalid") }),
|
||||
tokenUrl: z.url({ message: t("idpErrorTokenUrlInvalid") }),
|
||||
identifierPath: z.string().min(1, { message: t("idpPathRequired") }),
|
||||
emailPath: z.string().optional(),
|
||||
namePath: z.string().optional(),
|
||||
scopes: z.string().min(1, { message: t('idpScopeRequired') }),
|
||||
scopes: z.string().min(1, { message: t("idpScopeRequired") }),
|
||||
autoProvision: z.boolean().default(false)
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ export default function Page() {
|
||||
{
|
||||
id: "oidc",
|
||||
title: "OAuth2/OIDC",
|
||||
description: t('idpOidcDescription')
|
||||
description: t("idpOidcDescription")
|
||||
}
|
||||
];
|
||||
|
||||
@@ -117,14 +117,14 @@ export default function Page() {
|
||||
|
||||
if (res.status === 201) {
|
||||
toast({
|
||||
title: t('success'),
|
||||
description: t('idpCreatedDescription')
|
||||
title: t("success"),
|
||||
description: t("idpCreatedDescription")
|
||||
});
|
||||
router.push(`/admin/idp/${res.data.data.idpId}`);
|
||||
}
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t('error'),
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
@@ -137,8 +137,8 @@ export default function Page() {
|
||||
<>
|
||||
<div className="flex justify-between">
|
||||
<HeaderTitle
|
||||
title={t('idpCreate')}
|
||||
description={t('idpCreateDescription')}
|
||||
title={t("idpCreate")}
|
||||
description={t("idpCreateDescription")}
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -146,7 +146,7 @@ export default function Page() {
|
||||
router.push("/admin/idp");
|
||||
}}
|
||||
>
|
||||
{t('idpSeeAll')}
|
||||
{t("idpSeeAll")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -154,10 +154,10 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpTitle')}
|
||||
{t("idpTitle")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpCreateSettingsDescription')}
|
||||
{t("idpCreateSettingsDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -173,12 +173,14 @@ export default function Page() {
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('name')}</FormLabel>
|
||||
<FormLabel>
|
||||
{t("name")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpDisplayName')}
|
||||
{t("idpDisplayName")}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -188,7 +190,7 @@ export default function Page() {
|
||||
<div className="flex items-start mb-0">
|
||||
<SwitchInput
|
||||
id="auto-provision-toggle"
|
||||
label={t('idpAutoProvisionUsers')}
|
||||
label={t("idpAutoProvisionUsers")}
|
||||
defaultChecked={form.getValues(
|
||||
"autoProvision"
|
||||
)}
|
||||
@@ -201,7 +203,7 @@ export default function Page() {
|
||||
/>
|
||||
</div>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{t('idpAutoProvisionUsersDescription')}
|
||||
{t("idpAutoProvisionUsersDescription")}
|
||||
</span>
|
||||
</form>
|
||||
</Form>
|
||||
@@ -212,10 +214,10 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpType')}
|
||||
{t("idpType")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpTypeDescription')}
|
||||
{t("idpTypeDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -235,10 +237,10 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpOidcConfigure')}
|
||||
{t("idpOidcConfigure")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpOidcConfigureDescription')}
|
||||
{t("idpOidcConfigureDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -254,13 +256,15 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpClientId')}
|
||||
{t("idpClientId")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpClientIdDescription')}
|
||||
{t(
|
||||
"idpClientIdDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -273,7 +277,7 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpClientSecret')}
|
||||
{t("idpClientSecret")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -282,7 +286,9 @@ export default function Page() {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpClientSecretDescription')}
|
||||
{t(
|
||||
"idpClientSecretDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -295,7 +301,7 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpAuthUrl')}
|
||||
{t("idpAuthUrl")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -304,7 +310,9 @@ export default function Page() {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpAuthUrlDescription')}
|
||||
{t(
|
||||
"idpAuthUrlDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -317,7 +325,7 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpTokenUrl')}
|
||||
{t("idpTokenUrl")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -326,7 +334,9 @@ export default function Page() {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpTokenUrlDescription')}
|
||||
{t(
|
||||
"idpTokenUrlDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -338,10 +348,10 @@ export default function Page() {
|
||||
<Alert variant="neutral">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
{t('idpOidcConfigureAlert')}
|
||||
{t("idpOidcConfigureAlert")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('idpOidcConfigureAlertDescription')}
|
||||
{t("idpOidcConfigureAlertDescription")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</SettingsSectionBody>
|
||||
@@ -350,10 +360,10 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t('idpToken')}
|
||||
{t("idpToken")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t('idpTokenDescription')}
|
||||
{t("idpTokenDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
@@ -366,17 +376,21 @@ export default function Page() {
|
||||
<Alert variant="neutral">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
{t('idpJmespathAbout')}
|
||||
{t("idpJmespathAbout")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('idpJmespathAboutDescription')}{" "}
|
||||
{t(
|
||||
"idpJmespathAboutDescription"
|
||||
)}{" "}
|
||||
<a
|
||||
href="https://jmespath.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline inline-flex items-center"
|
||||
>
|
||||
{t('idpJmespathAboutDescriptionLink')}{" "}
|
||||
{t(
|
||||
"idpJmespathAboutDescriptionLink"
|
||||
)}{" "}
|
||||
<ExternalLink className="ml-1 h-4 w-4" />
|
||||
</a>
|
||||
</AlertDescription>
|
||||
@@ -388,13 +402,15 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpJmespathLabel')}
|
||||
{t("idpJmespathLabel")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpJmespathLabelDescription')}
|
||||
{t(
|
||||
"idpJmespathLabelDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -407,13 +423,17 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpJmespathEmailPathOptional')}
|
||||
{t(
|
||||
"idpJmespathEmailPathOptional"
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpJmespathEmailPathOptionalDescription')}
|
||||
{t(
|
||||
"idpJmespathEmailPathOptionalDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -426,13 +446,17 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpJmespathNamePathOptional')}
|
||||
{t(
|
||||
"idpJmespathNamePathOptional"
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpJmespathNamePathOptionalDescription')}
|
||||
{t(
|
||||
"idpJmespathNamePathOptionalDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -445,13 +469,17 @@ export default function Page() {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t('idpOidcConfigureScopes')}
|
||||
{t(
|
||||
"idpOidcConfigureScopes"
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('idpOidcConfigureScopesDescription')}
|
||||
{t(
|
||||
"idpOidcConfigureScopesDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -473,7 +501,7 @@ export default function Page() {
|
||||
router.push("/admin/idp");
|
||||
}}
|
||||
>
|
||||
{t('cancel')}
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
@@ -481,7 +509,7 @@ export default function Page() {
|
||||
loading={createLoading}
|
||||
onClick={form.handleSubmit(onSubmit)}
|
||||
>
|
||||
{t('idpSubmit')}
|
||||
{t("idpSubmit")}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -22,8 +22,8 @@ export default async function IdpPage() {
|
||||
return (
|
||||
<>
|
||||
<SettingsSectionTitle
|
||||
title={t('idpManage')}
|
||||
description={t('idpManageDescription')}
|
||||
title={t("idpManage")}
|
||||
description={t("idpManageDescription")}
|
||||
/>
|
||||
<IdpTable idps={idps} />
|
||||
</>
|
||||
|
||||
@@ -14,4 +14,3 @@ export default async function AdminLicenseLayout(props: LayoutProps) {
|
||||
|
||||
return props.children;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,10 +315,8 @@ export default function LicensePage() {
|
||||
setSelectedLicenseKey(null);
|
||||
}}
|
||||
dialog={
|
||||
<div>
|
||||
<p>
|
||||
{t("licenseQuestionRemove")}
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
<p>{t("licenseQuestionRemove")}</p>
|
||||
<p>
|
||||
<b>{t("licenseMessageRemove")}</b>
|
||||
</p>
|
||||
@@ -362,7 +360,8 @@ export default function LicensePage() {
|
||||
<div className="space-y-2 text-green-500">
|
||||
<div className="text-2xl flex items-center gap-2">
|
||||
<Check />
|
||||
{t("licensed")}
|
||||
{t("licensed") +
|
||||
`${licenseStatus?.tier === "personal" ? ` (${t("personalUseOnly")})` : ""}`}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -188,7 +188,7 @@ export default function UsersTable({ users }: Props) {
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: () => (<span className="p-3">{t("actions")}</span>),
|
||||
header: () => <span className="p-3">{t("actions")}</span>,
|
||||
cell: ({ row }) => {
|
||||
const r = row.original;
|
||||
return (
|
||||
@@ -243,7 +243,7 @@ export default function UsersTable({ users }: Props) {
|
||||
setSelected(null);
|
||||
}}
|
||||
dialog={
|
||||
<div>
|
||||
<div className="space-y-2">
|
||||
<p>{t("userQuestionRemove")}</p>
|
||||
|
||||
<p>{t("userMessageRemove")}</p>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { AdminGetUserResponse } from "@server/routers/user/adminGetUser";
|
||||
import { HorizontalTabs } from "@app/components/HorizontalTabs";
|
||||
import { cache } from "react";
|
||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { getTranslations } from "next-intl/server";
|
||||
|
||||
interface UserLayoutProps {
|
||||
children: React.ReactNode;
|
||||
@@ -36,7 +36,7 @@ export default async function UserLayoutProps(props: UserLayoutProps) {
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
title: t('general'),
|
||||
title: t("general"),
|
||||
href: "/admin/users/{userId}/general"
|
||||
}
|
||||
];
|
||||
@@ -45,11 +45,9 @@ export default async function UserLayoutProps(props: UserLayoutProps) {
|
||||
<>
|
||||
<SettingsSectionTitle
|
||||
title={`${user?.email || user?.name || user?.username}`}
|
||||
description={t('userDescription2')}
|
||||
description={t("userDescription2")}
|
||||
/>
|
||||
<HorizontalTabs items={navItems}>
|
||||
{children}
|
||||
</HorizontalTabs>
|
||||
<HorizontalTabs items={navItems}>{children}</HorizontalTabs>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ export default async function UserPage(props: {
|
||||
}) {
|
||||
const { userId } = await props.params;
|
||||
redirect(`/admin/users/${userId}/general`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export default async function UsersPage(props: PageProps) {
|
||||
username: row.username,
|
||||
type: row.type,
|
||||
idpId: row.idpId,
|
||||
idpName: row.idpName || t('idpNameInternal'),
|
||||
idpName: row.idpName || t("idpNameInternal"),
|
||||
dateCreated: row.dateCreated,
|
||||
serverAdmin: row.serverAdmin,
|
||||
twoFactorEnabled: row.twoFactorEnabled,
|
||||
@@ -47,14 +47,16 @@ export default async function UsersPage(props: PageProps) {
|
||||
return (
|
||||
<>
|
||||
<SettingsSectionTitle
|
||||
title={t('userTitle')}
|
||||
description={t('userDescription')}
|
||||
title={t("userTitle")}
|
||||
description={t("userDescription")}
|
||||
/>
|
||||
<Alert variant="neutral" className="mb-6">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">{t('userAbount')}</AlertTitle>
|
||||
<AlertTitle className="font-semibold">
|
||||
{t("userAbount")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('userAbountDescription')}
|
||||
{t("userAbountDescription")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
<UsersTable users={userRows} />
|
||||
|
||||
Reference in New Issue
Block a user