mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-14 08:56:39 +00:00
add idp auto provision override on user
This commit is contained in:
@@ -20,12 +20,14 @@ import {
|
||||
} from "@app/components/ui/dropdown-menu";
|
||||
import Link from "next/link";
|
||||
import { useTranslations } from "next-intl";
|
||||
import IdpTypeBadge from "./IdpTypeBadge";
|
||||
|
||||
export type IdpRow = {
|
||||
idpId: number;
|
||||
name: string;
|
||||
type: string;
|
||||
orgCount: number;
|
||||
variant?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
@@ -57,15 +59,6 @@ export default function IdpTable({ idps }: Props) {
|
||||
}
|
||||
};
|
||||
|
||||
const getTypeDisplay = (type: string) => {
|
||||
switch (type) {
|
||||
case "oidc":
|
||||
return "OAuth2/OIDC";
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
const columns: ColumnDef<IdpRow>[] = [
|
||||
{
|
||||
accessorKey: "idpId",
|
||||
@@ -116,9 +109,8 @@ export default function IdpTable({ idps }: Props) {
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const type = row.original.type;
|
||||
return (
|
||||
<Badge variant="secondary">{getTypeDisplay(type)}</Badge>
|
||||
);
|
||||
const variant = row.original.variant;
|
||||
return <IdpTypeBadge type={type} variant={variant} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
62
src/components/IdpTypeBadge.tsx
Normal file
62
src/components/IdpTypeBadge.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import { Badge } from "@app/components/ui/badge";
|
||||
import Image from "next/image";
|
||||
|
||||
type IdpTypeBadgeProps = {
|
||||
type: string;
|
||||
variant?: string;
|
||||
name?: string;
|
||||
};
|
||||
|
||||
export default function IdpTypeBadge({
|
||||
type,
|
||||
variant,
|
||||
name
|
||||
}: IdpTypeBadgeProps) {
|
||||
const effectiveType = variant || type;
|
||||
const effectiveName = name || formatType(effectiveType);
|
||||
|
||||
function formatType(type: string) {
|
||||
if (type === "google") return "Google";
|
||||
if (type === "azure") return "Azure";
|
||||
if (type === "oidc") return "OAuth2/OIDC";
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="inline-flex items-center space-x-1 w-fit"
|
||||
>
|
||||
{effectiveType === "google" && (
|
||||
<>
|
||||
<Image
|
||||
src="/idp/google.png"
|
||||
alt="Google"
|
||||
width={16}
|
||||
height={16}
|
||||
className="rounded"
|
||||
/>
|
||||
<span>{effectiveName}</span>
|
||||
</>
|
||||
)}
|
||||
{effectiveType === "azure" && (
|
||||
<>
|
||||
<Image
|
||||
src="/idp/azure.png"
|
||||
alt="Azure"
|
||||
width={16}
|
||||
height={16}
|
||||
className="rounded"
|
||||
/>
|
||||
<span>{effectiveName}</span>
|
||||
</>
|
||||
)}
|
||||
{effectiveType === "oidc" && <span>{effectiveName}</span>}
|
||||
{!["google", "azure", "oidc"].includes(effectiveType) && (
|
||||
<span>{effectiveName}</span>
|
||||
)}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import { startAuthentication } from "@simplewebauthn/browser";
|
||||
export type LoginFormIDP = {
|
||||
idpId: number;
|
||||
name: string;
|
||||
variant?: string;
|
||||
};
|
||||
|
||||
type LoginFormProps = {
|
||||
@@ -496,19 +497,41 @@ export default function LoginForm({ redirect, onLogin, idps }: LoginFormProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{idps.map((idp) => (
|
||||
<Button
|
||||
key={idp.idpId}
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
loginWithIdp(idp.idpId);
|
||||
}}
|
||||
>
|
||||
{idp.name}
|
||||
</Button>
|
||||
))}
|
||||
{idps.map((idp) => {
|
||||
const effectiveType = idp.variant || idp.name.toLowerCase();
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={idp.idpId}
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="w-full inline-flex items-center space-x-2"
|
||||
onClick={() => {
|
||||
loginWithIdp(idp.idpId);
|
||||
}}
|
||||
>
|
||||
{effectiveType === "google" && (
|
||||
<Image
|
||||
src="/idp/google.png"
|
||||
alt="Google"
|
||||
width={16}
|
||||
height={16}
|
||||
className="rounded"
|
||||
/>
|
||||
)}
|
||||
{effectiveType === "azure" && (
|
||||
<Image
|
||||
src="/idp/azure.png"
|
||||
alt="Azure"
|
||||
width={16}
|
||||
height={16}
|
||||
className="rounded"
|
||||
/>
|
||||
)}
|
||||
<span>{idp.name}</span>
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -27,7 +27,9 @@ function getActionsCategories(root: boolean) {
|
||||
[t('actionListInvitations')]: "listInvitations",
|
||||
[t('actionRemoveUser')]: "removeUser",
|
||||
[t('actionListUsers')]: "listUsers",
|
||||
[t('actionListOrgDomains')]: "listOrgDomains"
|
||||
[t('actionListOrgDomains')]: "listOrgDomains",
|
||||
[t('updateOrgUser')]: "updateOrgUser",
|
||||
[t('createOrgUser')]: "createOrgUser"
|
||||
},
|
||||
|
||||
Site: {
|
||||
|
||||
@@ -21,6 +21,7 @@ import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useUserContext } from "@app/hooks/useUserContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
import IdpTypeBadge from "./IdpTypeBadge";
|
||||
|
||||
export type UserRow = {
|
||||
id: string;
|
||||
@@ -31,6 +32,7 @@ export type UserRow = {
|
||||
idpId: number | null;
|
||||
idpName: string;
|
||||
type: string;
|
||||
idpVariant: string | null;
|
||||
status: string;
|
||||
role: string;
|
||||
isOwner: boolean;
|
||||
@@ -81,6 +83,16 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const userRow = row.original;
|
||||
return (
|
||||
<IdpTypeBadge
|
||||
type={userRow.type}
|
||||
name={userRow.idpName}
|
||||
variant={userRow.idpVariant || undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user