mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-31 06:56:39 +00:00
add learn more link
This commit is contained in:
@@ -45,6 +45,7 @@ import { useTranslations } from "next-intl";
|
|||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { ListRolesResponse } from "@server/routers/role";
|
import { ListRolesResponse } from "@server/routers/role";
|
||||||
import AutoProvisionConfigWidget from "@app/components/AutoProvisionConfigWidget";
|
import AutoProvisionConfigWidget from "@app/components/AutoProvisionConfigWidget";
|
||||||
|
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
|
||||||
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
import {
|
import {
|
||||||
@@ -493,7 +494,7 @@ export default function GeneralPage() {
|
|||||||
{t("idpAutoProvisionUsers")}
|
{t("idpAutoProvisionUsers")}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
{t("idpAutoProvisionUsersDescription")}
|
<IdpAutoProvisionUsersDescription />
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import AutoProvisionConfigWidget from "@app/components/AutoProvisionConfigWidget";
|
import AutoProvisionConfigWidget from "@app/components/AutoProvisionConfigWidget";
|
||||||
|
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
|
||||||
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
||||||
import {
|
import {
|
||||||
SettingsContainer,
|
SettingsContainer,
|
||||||
@@ -296,7 +297,7 @@ export default function Page() {
|
|||||||
{t("idpAutoProvisionUsers")}
|
{t("idpAutoProvisionUsers")}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
{t("idpAutoProvisionUsersDescription")}
|
<IdpAutoProvisionUsersDescription />
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { formatAxiosError } from "@app/lib/api";
|
|||||||
import { createApiClient } from "@app/lib/api";
|
import { createApiClient } from "@app/lib/api";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
|
||||||
import { SwitchInput } from "@app/components/SwitchInput";
|
import { SwitchInput } from "@app/components/SwitchInput";
|
||||||
import {
|
import {
|
||||||
InfoSection,
|
InfoSection,
|
||||||
@@ -349,7 +350,7 @@ export default function GeneralPage() {
|
|||||||
{t("idpAutoProvisionUsers")}
|
{t("idpAutoProvisionUsers")}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
{t("idpAutoProvisionUsersDescription")}
|
<IdpAutoProvisionUsersDescription />
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
@@ -375,9 +376,6 @@ export default function GeneralPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{t("idpAutoProvisionUsersDescription")}
|
|
||||||
</span>
|
|
||||||
{form.watch("autoProvision") && (
|
{form.watch("autoProvision") && (
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
{t.rich(
|
{t.rich(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
FormMessage
|
FormMessage
|
||||||
} from "@app/components/ui/form";
|
} from "@app/components/ui/form";
|
||||||
import HeaderTitle from "@app/components/SettingsSectionTitle";
|
import HeaderTitle from "@app/components/SettingsSectionTitle";
|
||||||
|
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
|
||||||
import { SwitchInput } from "@app/components/SwitchInput";
|
import { SwitchInput } from "@app/components/SwitchInput";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
||||||
import { Button } from "@app/components/ui/button";
|
import { Button } from "@app/components/ui/button";
|
||||||
@@ -94,8 +95,7 @@ export default function Page() {
|
|||||||
|
|
||||||
const watchedType = form.watch("type");
|
const watchedType = form.watch("type");
|
||||||
const templatesLocked =
|
const templatesLocked =
|
||||||
!templatesPaid &&
|
!templatesPaid && (watchedType === "google" || watchedType === "azure");
|
||||||
(watchedType === "google" || watchedType === "azure");
|
|
||||||
|
|
||||||
async function onSubmit(data: CreateIdpFormValues) {
|
async function onSubmit(data: CreateIdpFormValues) {
|
||||||
if (
|
if (
|
||||||
@@ -223,7 +223,9 @@ export default function Page() {
|
|||||||
<div className="flex items-start mb-0">
|
<div className="flex items-start mb-0">
|
||||||
<SwitchInput
|
<SwitchInput
|
||||||
id="auto-provision-toggle"
|
id="auto-provision-toggle"
|
||||||
label={t("idpAutoProvisionUsers")}
|
label={t(
|
||||||
|
"idpAutoProvisionUsers"
|
||||||
|
)}
|
||||||
defaultChecked={form.getValues(
|
defaultChecked={form.getValues(
|
||||||
"autoProvision"
|
"autoProvision"
|
||||||
)}
|
)}
|
||||||
@@ -235,11 +237,6 @@ export default function Page() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{t(
|
|
||||||
"idpAutoProvisionUsersDescription"
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
@@ -251,391 +248,409 @@ export default function Page() {
|
|||||||
disabled={templatesLocked}
|
disabled={templatesLocked}
|
||||||
className="min-w-0 border-0 p-0 m-0 disabled:pointer-events-none disabled:opacity-60"
|
className="min-w-0 border-0 p-0 m-0 disabled:pointer-events-none disabled:opacity-60"
|
||||||
>
|
>
|
||||||
{watchedType === "google" && (
|
{watchedType === "google" && (
|
||||||
<SettingsSection>
|
|
||||||
<SettingsSectionHeader>
|
|
||||||
<SettingsSectionTitle>
|
|
||||||
{t("idpGoogleConfigurationTitle")}
|
|
||||||
</SettingsSectionTitle>
|
|
||||||
<SettingsSectionDescription>
|
|
||||||
{t("idpGoogleConfigurationDescription")}
|
|
||||||
</SettingsSectionDescription>
|
|
||||||
</SettingsSectionHeader>
|
|
||||||
<SettingsSectionBody>
|
|
||||||
<SettingsSectionForm>
|
|
||||||
<Form {...form}>
|
|
||||||
<form
|
|
||||||
className="space-y-4"
|
|
||||||
id="create-idp-form"
|
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
|
||||||
>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="clientId"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpClientId")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpGoogleClientIdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="clientSecret"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpClientSecret")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpGoogleClientSecretDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
</SettingsSectionForm>
|
|
||||||
</SettingsSectionBody>
|
|
||||||
</SettingsSection>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{watchedType === "azure" && (
|
|
||||||
<SettingsSection>
|
|
||||||
<SettingsSectionHeader>
|
|
||||||
<SettingsSectionTitle>
|
|
||||||
{t("idpAzureConfigurationTitle")}
|
|
||||||
</SettingsSectionTitle>
|
|
||||||
<SettingsSectionDescription>
|
|
||||||
{t("idpAzureConfigurationDescription")}
|
|
||||||
</SettingsSectionDescription>
|
|
||||||
</SettingsSectionHeader>
|
|
||||||
<SettingsSectionBody>
|
|
||||||
<SettingsSectionForm>
|
|
||||||
<Form {...form}>
|
|
||||||
<form
|
|
||||||
className="space-y-4"
|
|
||||||
id="create-idp-form"
|
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
|
||||||
>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="tenantId"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpTenantIdLabel")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpAzureTenantIdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="clientId"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpClientId")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpAzureClientIdDescription2"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="clientSecret"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpClientSecret")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpAzureClientSecretDescription2"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
</SettingsSectionForm>
|
|
||||||
</SettingsSectionBody>
|
|
||||||
</SettingsSection>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{watchedType === "oidc" && (
|
|
||||||
<SettingsSectionGrid cols={2}>
|
|
||||||
<SettingsSection>
|
<SettingsSection>
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
{t("idpOidcConfigure")}
|
{t("idpGoogleConfigurationTitle")}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
{t("idpOidcConfigureDescription")}
|
{t("idpGoogleConfigurationDescription")}
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
<Form {...form}>
|
<SettingsSectionForm>
|
||||||
<form
|
<Form {...form}>
|
||||||
className="space-y-4"
|
<form
|
||||||
id="create-idp-form"
|
className="space-y-4"
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
id="create-idp-form"
|
||||||
>
|
onSubmit={form.handleSubmit(
|
||||||
<FormField
|
onSubmit
|
||||||
control={form.control}
|
|
||||||
name="clientId"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpClientId")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpClientIdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
)}
|
||||||
/>
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="clientId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t("idpClientId")}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpGoogleClientIdDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="clientSecret"
|
name="clientSecret"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
{t("idpClientSecret")}
|
{t(
|
||||||
</FormLabel>
|
"idpClientSecret"
|
||||||
<FormControl>
|
)}
|
||||||
<Input
|
</FormLabel>
|
||||||
type="password"
|
<FormControl>
|
||||||
{...field}
|
<Input
|
||||||
/>
|
type="password"
|
||||||
</FormControl>
|
{...field}
|
||||||
<FormDescription>
|
/>
|
||||||
{t(
|
</FormControl>
|
||||||
"idpClientSecretDescription"
|
<FormDescription>
|
||||||
)}
|
{t(
|
||||||
</FormDescription>
|
"idpGoogleClientSecretDescription"
|
||||||
<FormMessage />
|
)}
|
||||||
</FormItem>
|
</FormDescription>
|
||||||
)}
|
<FormMessage />
|
||||||
/>
|
</FormItem>
|
||||||
|
)}
|
||||||
<FormField
|
/>
|
||||||
control={form.control}
|
</form>
|
||||||
name="authUrl"
|
</Form>
|
||||||
render={({ field }) => (
|
</SettingsSectionForm>
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpAuthUrl")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
placeholder="https://your-idp.com/oauth2/authorize"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpAuthUrlDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="tokenUrl"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpTokenUrl")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
placeholder="https://your-idp.com/oauth2/token"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpTokenUrlDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{watchedType === "azure" && (
|
||||||
<SettingsSection>
|
<SettingsSection>
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
{t("idpToken")}
|
{t("idpAzureConfigurationTitle")}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
{t("idpTokenDescription")}
|
{t("idpAzureConfigurationDescription")}
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
<Form {...form}>
|
<SettingsSectionForm>
|
||||||
<form
|
<Form {...form}>
|
||||||
className="space-y-4"
|
<form
|
||||||
id="create-idp-form"
|
className="space-y-4"
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
id="create-idp-form"
|
||||||
>
|
onSubmit={form.handleSubmit(
|
||||||
<FormField
|
onSubmit
|
||||||
control={form.control}
|
|
||||||
name="identifierPath"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("idpJmespathLabel")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpJmespathLabelDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
)}
|
||||||
/>
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="tenantId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"idpTenantIdLabel"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpAzureTenantIdDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="emailPath"
|
name="clientId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
{t(
|
{t("idpClientId")}
|
||||||
"idpJmespathEmailPathOptional"
|
</FormLabel>
|
||||||
)}
|
<FormControl>
|
||||||
</FormLabel>
|
<Input {...field} />
|
||||||
<FormControl>
|
</FormControl>
|
||||||
<Input {...field} />
|
<FormDescription>
|
||||||
</FormControl>
|
{t(
|
||||||
<FormDescription>
|
"idpAzureClientIdDescription2"
|
||||||
{t(
|
)}
|
||||||
"idpJmespathEmailPathOptionalDescription"
|
</FormDescription>
|
||||||
)}
|
<FormMessage />
|
||||||
</FormDescription>
|
</FormItem>
|
||||||
<FormMessage />
|
)}
|
||||||
</FormItem>
|
/>
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="namePath"
|
name="clientSecret"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
{t(
|
{t(
|
||||||
"idpJmespathNamePathOptional"
|
"idpClientSecret"
|
||||||
)}
|
)}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input
|
||||||
</FormControl>
|
type="password"
|
||||||
<FormDescription>
|
{...field}
|
||||||
{t(
|
/>
|
||||||
"idpJmespathNamePathOptionalDescription"
|
</FormControl>
|
||||||
)}
|
<FormDescription>
|
||||||
</FormDescription>
|
{t(
|
||||||
<FormMessage />
|
"idpAzureClientSecretDescription2"
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
</FormDescription>
|
||||||
/>
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
<FormField
|
)}
|
||||||
control={form.control}
|
/>
|
||||||
name="scopes"
|
</form>
|
||||||
render={({ field }) => (
|
</Form>
|
||||||
<FormItem>
|
</SettingsSectionForm>
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"idpOidcConfigureScopes"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"idpOidcConfigureScopesDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
</SettingsSectionGrid>
|
)}
|
||||||
)}
|
|
||||||
|
{watchedType === "oidc" && (
|
||||||
|
<SettingsSectionGrid cols={2}>
|
||||||
|
<SettingsSection>
|
||||||
|
<SettingsSectionHeader>
|
||||||
|
<SettingsSectionTitle>
|
||||||
|
{t("idpOidcConfigure")}
|
||||||
|
</SettingsSectionTitle>
|
||||||
|
<SettingsSectionDescription>
|
||||||
|
{t("idpOidcConfigureDescription")}
|
||||||
|
</SettingsSectionDescription>
|
||||||
|
</SettingsSectionHeader>
|
||||||
|
<SettingsSectionBody>
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
className="space-y-4"
|
||||||
|
id="create-idp-form"
|
||||||
|
onSubmit={form.handleSubmit(
|
||||||
|
onSubmit
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="clientId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t("idpClientId")}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpClientIdDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="clientSecret"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"idpClientSecret"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpClientSecretDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="authUrl"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t("idpAuthUrl")}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder="https://your-idp.com/oauth2/authorize"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpAuthUrlDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="tokenUrl"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t("idpTokenUrl")}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder="https://your-idp.com/oauth2/token"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpTokenUrlDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</SettingsSectionBody>
|
||||||
|
</SettingsSection>
|
||||||
|
|
||||||
|
<SettingsSection>
|
||||||
|
<SettingsSectionHeader>
|
||||||
|
<SettingsSectionTitle>
|
||||||
|
{t("idpToken")}
|
||||||
|
</SettingsSectionTitle>
|
||||||
|
<SettingsSectionDescription>
|
||||||
|
{t("idpTokenDescription")}
|
||||||
|
</SettingsSectionDescription>
|
||||||
|
</SettingsSectionHeader>
|
||||||
|
<SettingsSectionBody>
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
className="space-y-4"
|
||||||
|
id="create-idp-form"
|
||||||
|
onSubmit={form.handleSubmit(
|
||||||
|
onSubmit
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="identifierPath"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"idpJmespathLabel"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpJmespathLabelDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="emailPath"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"idpJmespathEmailPathOptional"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpJmespathEmailPathOptionalDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="namePath"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"idpJmespathNamePathOptional"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpJmespathNamePathOptionalDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="scopes"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"idpOidcConfigureScopes"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"idpOidcConfigureScopesDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</SettingsSectionBody>
|
||||||
|
</SettingsSection>
|
||||||
|
</SettingsSectionGrid>
|
||||||
|
)}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</SettingsContainer>
|
</SettingsContainer>
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
|
||||||
import { FormDescription } from "@app/components/ui/form";
|
import { FormDescription } from "@app/components/ui/form";
|
||||||
import { SwitchInput } from "@app/components/SwitchInput";
|
import { SwitchInput } from "@app/components/SwitchInput";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
import {
|
import { MappingBuilderRule, RoleMappingMode } from "@app/lib/idpRoleMapping";
|
||||||
MappingBuilderRule,
|
|
||||||
RoleMappingMode
|
|
||||||
} from "@app/lib/idpRoleMapping";
|
|
||||||
import RoleMappingConfigFields from "@app/components/RoleMappingConfigFields";
|
import RoleMappingConfigFields from "@app/components/RoleMappingConfigFields";
|
||||||
|
|
||||||
type Role = {
|
type Role = {
|
||||||
@@ -60,9 +58,6 @@ export default function AutoProvisionConfigWidget({
|
|||||||
onCheckedChange={onAutoProvisionChange}
|
onCheckedChange={onAutoProvisionChange}
|
||||||
disabled={!isPaidUser(tierMatrix.autoProvisioning)}
|
disabled={!isPaidUser(tierMatrix.autoProvisioning)}
|
||||||
/>
|
/>
|
||||||
<FormDescription className="text-sm text-muted-foreground">
|
|
||||||
{t("idpAutoProvisionUsersDescription")}
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{autoProvision && (
|
{autoProvision && (
|
||||||
|
|||||||
29
src/components/IdpAutoProvisionUsersDescription.tsx
Normal file
29
src/components/IdpAutoProvisionUsersDescription.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
|
const AUTO_PROVISION_DOCS_URL =
|
||||||
|
"https://docs.pangolin.net/manage/identity-providers/auto-provisioning";
|
||||||
|
|
||||||
|
type IdpAutoProvisionUsersDescriptionProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function IdpAutoProvisionUsersDescription({
|
||||||
|
className
|
||||||
|
}: IdpAutoProvisionUsersDescriptionProps) {
|
||||||
|
const t = useTranslations();
|
||||||
|
return (
|
||||||
|
<span className={className}>
|
||||||
|
{t("idpAutoProvisionUsersDescription")}{" "}
|
||||||
|
<a
|
||||||
|
href={AUTO_PROVISION_DOCS_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-primary hover:underline"
|
||||||
|
>
|
||||||
|
{t("learnMore")}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import { Checkbox } from "@app/components/ui/checkbox";
|
|||||||
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
||||||
import { InfoIcon, ExternalLink } from "lucide-react";
|
import { InfoIcon, ExternalLink } from "lucide-react";
|
||||||
import { StrategySelect } from "@app/components/StrategySelect";
|
import { StrategySelect } from "@app/components/StrategySelect";
|
||||||
|
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
|
||||||
import { SwitchInput } from "@app/components/SwitchInput";
|
import { SwitchInput } from "@app/components/SwitchInput";
|
||||||
import { Badge } from "@app/components/ui/badge";
|
import { Badge } from "@app/components/ui/badge";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
@@ -163,9 +164,6 @@ export function IdpCreateWizard({
|
|||||||
disabled={loading}
|
disabled={loading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{t("idpAutoProvisionUsersDescription")}
|
|
||||||
</span>
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
|
|||||||
Reference in New Issue
Block a user