Fix saml config + org form permissions handling
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { Button, Card, IconTrashCan } from "@probo/ui";
|
||||
import { use } from "react";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import { graphql } from "relay-runtime";
|
||||
@@ -18,6 +16,7 @@ export const generalSettingsPageQuery = graphql`
|
||||
... on Organization {
|
||||
id
|
||||
name @required(action: THROW)
|
||||
canDelete: permission(action: "iam:organization:delete")
|
||||
...OrganizationFormFragment
|
||||
}
|
||||
}
|
||||
@@ -42,9 +41,6 @@ export function GeneralSettingsPage(props: {
|
||||
const { __ } = useTranslate();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const canDelete = isAuthorized("Organization", "deleteOrganization");
|
||||
|
||||
const { organization } = usePreloadedQuery<GeneralSettingsPageQuery>(
|
||||
generalSettingsPageQuery,
|
||||
queryRef,
|
||||
@@ -80,7 +76,7 @@ export function GeneralSettingsPage(props: {
|
||||
<div className="space-y-6">
|
||||
<OrganizationForm fKey={organization} />
|
||||
|
||||
{canDelete && (
|
||||
{organization.canDelete && (
|
||||
<div className="space-y-4 mt-12">
|
||||
<h2 className="text-base font-medium text-red-600">
|
||||
{__("Danger Zone")}
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
type PreloadedQuery,
|
||||
} from "react-relay";
|
||||
import type { SAMLSettingsPageQuery } from "/__generated__/iam/SAMLSettingsPageQuery.graphql";
|
||||
import { Suspense, use, useState } from "react";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
import { Suspense, useState } from "react";
|
||||
import { Breadcrumb, Button, Dialog, useDialogRef } from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { SAMLConfigurationList } from "./_components/SAMLConfigurationList";
|
||||
@@ -21,7 +20,13 @@ import { SAMLDomainVerifyDialog } from "./_components/SAMLDomainVerifyDialog";
|
||||
export const samlSettingsPageQuery = graphql`
|
||||
query SAMLSettingsPageQuery($organizationId: ID!) {
|
||||
organization: node(id: $organizationId) @required(action: THROW) {
|
||||
...SAMLConfigurationListFragment
|
||||
__typename
|
||||
... on Organization {
|
||||
canCreateSAMLConfiguration: permission(
|
||||
action: "iam:saml-configuration:create"
|
||||
)
|
||||
...SAMLConfigurationListFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -38,9 +43,11 @@ export function SAMLSettingsPage(props: {
|
||||
useState<string>();
|
||||
|
||||
const { __ } = useTranslate();
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
|
||||
const { organization } = usePreloadedQuery(samlSettingsPageQuery, queryRef);
|
||||
if (organization.__typename !== "Organization") {
|
||||
throw new Error("invalid node type");
|
||||
}
|
||||
const [formQueryRef, loadFormQuery] =
|
||||
useQueryLoader<EditSAMLConfigurationFormQuery>(samlConfigurationFormQuery);
|
||||
|
||||
@@ -70,7 +77,7 @@ export function SAMLSettingsPage(props: {
|
||||
<div className="space-y-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-base font-medium">{__("SAML Single Sign-On")}</h2>
|
||||
{isAuthorized("Organization", "createSAMLConfiguration") && (
|
||||
{organization.canCreateSAMLConfiguration && (
|
||||
<Button onClick={() => handleOpenFormDialog()}>
|
||||
{__("Add Configuration")}
|
||||
</Button>
|
||||
|
||||
@@ -44,6 +44,7 @@ const inviteMutation = graphql`
|
||||
expiresAt
|
||||
acceptedAt
|
||||
createdAt
|
||||
canDelete: permission(action: "iam:invitation:delete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
Textarea,
|
||||
useDialogRef,
|
||||
} from "@probo/ui";
|
||||
import { use, useState, type ChangeEventHandler } from "react";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
import { useState, type ChangeEventHandler } from "react";
|
||||
import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import { graphql } from "relay-runtime";
|
||||
@@ -33,6 +32,7 @@ const fragment = graphql`
|
||||
websiteUrl
|
||||
email
|
||||
headquarterAddress
|
||||
canUpdate: permission(action: "iam:organization:update")
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -83,18 +83,13 @@ export function OrganizationForm(props: {
|
||||
const { __ } = useTranslate();
|
||||
const deleteDialogRef = useDialogRef();
|
||||
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const canUpdate = isAuthorized("Organization", "updateOrganization");
|
||||
|
||||
const [logoPreview, setLogoPreview] = useState<string | null>(null);
|
||||
const [horizontalLogoPreview, setHorizontalLogoPreview] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
|
||||
const organization = useFragment<OrganizationFormFragment$key>(
|
||||
fragment,
|
||||
fKey,
|
||||
);
|
||||
const { canUpdate, ...organization } =
|
||||
useFragment<OrganizationFormFragment$key>(fragment, fKey);
|
||||
|
||||
const [updateOrganization, isUpdatingOrganization] = useMutationWithToasts(
|
||||
updateOrganizationMutation,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { use } from "react";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
@@ -37,6 +35,8 @@ const fragment = graphql`
|
||||
domainVerificationToken
|
||||
domainVerifiedAt
|
||||
testLoginUrl
|
||||
canUpdate: permission(action: "iam:saml-configuration:update")
|
||||
canDelete: permission(action: "iam:saml-configuration:delete")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,6 @@ export function SAMLConfigurationList(props: {
|
||||
|
||||
const organizationId = useOrganizationId();
|
||||
const { __ } = useTranslate();
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
|
||||
const confirm = useConfirm();
|
||||
const [isCopied, copy] = useCopy();
|
||||
@@ -197,10 +196,7 @@ export function SAMLConfigurationList(props: {
|
||||
<div className="flex gap-2 justify-end">
|
||||
{config.domainVerifiedAt ? (
|
||||
<>
|
||||
{isAuthorized(
|
||||
"SAMLConfiguration",
|
||||
"updateSAMLConfiguration",
|
||||
) && (
|
||||
{config.canUpdate && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => onEdit(config.id)}
|
||||
@@ -208,7 +204,7 @@ export function SAMLConfigurationList(props: {
|
||||
{__("Edit")}
|
||||
</Button>
|
||||
)}
|
||||
{isAuthorized("Organization", "deleteOrganization") && (
|
||||
{config.canDelete && (
|
||||
<Button
|
||||
variant="danger"
|
||||
onClick={() => handleDelete(config)}
|
||||
@@ -219,18 +215,17 @@ export function SAMLConfigurationList(props: {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{isAuthorized("Organization", "verifyDomain") &&
|
||||
!!config.domainVerificationToken && (
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() =>
|
||||
onVerifyDomain(config.domainVerificationToken!)
|
||||
}
|
||||
>
|
||||
{__("Verify Domain")}
|
||||
</Button>
|
||||
)}
|
||||
{isAuthorized("Organization", "deleteOrganization") && (
|
||||
{config.canUpdate && !!config.domainVerificationToken && (
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() =>
|
||||
onVerifyDomain(config.domainVerificationToken!)
|
||||
}
|
||||
>
|
||||
{__("Verify Domain")}
|
||||
</Button>
|
||||
)}
|
||||
{config.canDelete && (
|
||||
<Button
|
||||
variant="danger"
|
||||
onClick={() => handleDelete(config)}
|
||||
|
||||
Reference in New Issue
Block a user