Skip to content

Commit

Permalink
Merge pull request #7069 from amanda-ariyaratne/issue-26702
Browse files Browse the repository at this point in the history
Remove delete option from default claims and dialects
  • Loading branch information
amanda-ariyaratne authored Nov 20, 2024
2 parents 7e43f80 + 2b32068 commit 056ebc9
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 118 deletions.
7 changes: 7 additions & 0 deletions .changeset/little-eagles-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@wso2is/admin.extensions.v1": patch
"@wso2is/admin.claims.v1": patch
"@wso2is/core": patch
---

remove delete option from default claims and dialects
63 changes: 23 additions & 40 deletions features/admin.claims.v1/components/claims-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Show } from "@wso2is/access-control";
import { Show, useRequiredScopes } from "@wso2is/access-control";
import {
AppConstants,
AppState,
Expand All @@ -29,7 +29,6 @@ import { getProfileSchemas } from "@wso2is/admin.users.v1/api";
import { getUserStores } from "@wso2is/admin.userstores.v1/api/user-stores";
import { UserStoreListItem } from "@wso2is/admin.userstores.v1/models/user-stores";
import { IdentityAppsApiException } from "@wso2is/core/exceptions";
import { hasRequiredScopes } from "@wso2is/core/helpers";
import {
AlertLevels,
AttributeMapping,
Expand All @@ -38,6 +37,7 @@ import {
ExternalClaim,
LoadableComponentInterface,
ProfileSchemaInterface,
Property,
SBACInterface,
TestableComponentInterface
} from "@wso2is/core/models";
Expand Down Expand Up @@ -70,7 +70,7 @@ import React,{
useState
} from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { ThunkDispatch } from "redux-thunk";
import { Header, Icon, ItemHeader, SemanticICONS } from "semantic-ui-react";
import { EditExternalClaim } from "./edit";
Expand Down Expand Up @@ -225,7 +225,9 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
const [ editClaim, setEditClaim ] = useState("");
const [ editExternalClaim, setEditExternalClaim ] = useState<AddExternalClaim>(undefined);

const allowedScopes: string = useSelector((state: AppState) => state?.auth?.allowedScopes);
const hasAttributeCreatePermissions: boolean = useRequiredScopes(featureConfig?.attributeDialects?.scopes?.create);
const hasAttributeUpdatePermissions: boolean = useRequiredScopes(featureConfig?.attributeDialects?.scopes?.update);
const hasAttributeDeletePermissions: boolean = useRequiredScopes(featureConfig?.attributeDialects?.scopes?.delete);

const dispatch: ThunkDispatch<AppState, any, any> = useDispatch();

Expand Down Expand Up @@ -818,18 +820,10 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
const showEditAction: boolean =
attributeConfig.externalAttributes.showActions(dialectID) &&
attributeConfig.externalAttributes.isAttributeEditable &&
hasRequiredScopes(
featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.create,
allowedScopes
);
hasAttributeCreatePermissions;
const showDeleteAction: boolean =
attributeConfig.externalAttributes.showDeleteIcon(dialectID, list) &&
hasRequiredScopes(
featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.delete,
allowedScopes
);
hasAttributeDeletePermissions;

return showEditAction || showDeleteAction;
};
Expand Down Expand Up @@ -1014,22 +1008,19 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
if (isLocalClaim(list)) {
return [
{
icon: (): SemanticICONS => !hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.update, allowedScopes)
icon: (): SemanticICONS => !hasAttributeUpdatePermissions
? "eye"
: "pencil alternate",
onClick: (e: SyntheticEvent, claim: Claim | ExternalClaim | ClaimDialect): void => {
history.push(AppConstants.getPaths().get("LOCAL_CLAIMS_EDIT").replace(":id", claim?.id));
},
popupText: (): string => hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.update, allowedScopes)
popupText: (): string => hasAttributeUpdatePermissions
? t("common:edit")
: t("common:view"),
renderer: "semantic-icon"
},
attributeConfig.attributes.deleteAction && {
hidden: (): boolean => !hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.delete, allowedScopes),
hidden: (): boolean => !hasAttributeDeletePermissions,
icon: (): SemanticICONS => "trash alternate",
onClick: (e: SyntheticEvent, claim: Claim | ExternalClaim | ClaimDialect): void =>
initDelete(ListType.LOCAL, claim),
Expand All @@ -1042,8 +1033,7 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
if (isDialect(list)) {
return [
{
hidden: (): boolean => !hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.create, allowedScopes),
hidden: (): boolean => !hasAttributeCreatePermissions,
icon: (): SemanticICONS => "pencil alternate",
onClick: (e: SyntheticEvent, dialect: ClaimDialect): void => {
history.push(AppConstants.getPaths().get("EXTERNAL_DIALECT_EDIT").replace(":id", dialect.id));
Expand All @@ -1052,8 +1042,7 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
renderer: "semantic-icon"
},
attributeConfig.attributeMappings.deleteAction && {
hidden: (): boolean => !hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.delete, allowedScopes),
hidden: (): boolean => !hasAttributeDeletePermissions,
icon: (): SemanticICONS => "trash alternate",
onClick: (e: SyntheticEvent, dialect: ClaimDialect): void => initDelete(ListType.DIALECT, dialect),
popupText: (): string => t("common:delete"),
Expand All @@ -1074,8 +1063,7 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
attributeConfig.externalAttributes.showActions(dialectID) && {
hidden: (): boolean => {
if (attributeConfig.externalAttributes.isAttributeEditable) {
return !hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.create, allowedScopes);
return !hasAttributeCreatePermissions;
} else {
return !attributeConfig.externalAttributes.isAttributeEditable;
}
Expand All @@ -1094,22 +1082,18 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
},
attributeConfig.externalAttributes.showDeleteIcon(dialectID, list) && {
hidden: (claim: ExternalClaim): boolean => {
if (!hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.delete, allowedScopes)
if (!hasAttributeDeletePermissions
|| attributeConfig.externalAttributes.hideDeleteIcon(claim)) {
return true;
}

if (attributeConfig.defaultScimMapping
&& Object.keys(attributeConfig.defaultScimMapping).length > 0) {
const defaultSCIMClaims: Map<string, string> = attributeConfig
.defaultScimMapping[claim.claimDialectURI];

if (defaultSCIMClaims && defaultSCIMClaims.get(claim.claimURI)) {
return true;
} else {
return false;
}
if (claim?.properties?.some((property: Property) =>
property.key === ClaimManagementConstants.SYSTEM_CLAIM_PROPERTY_NAME
&& property.value === "true"
)) {
return true;
} else {
return false;
}
},
icon: (): SemanticICONS => "trash alternate",
Expand Down Expand Up @@ -1158,8 +1142,7 @@ export const ClaimsList: FunctionComponent<ClaimsListPropsInterface> = (
const resolveTableRowClick = (e: SyntheticEvent, item: Claim | ExternalClaim | ClaimDialect | any): void => {

//Disables inline edit if create scope is not available
if (!hasRequiredScopes(featureConfig?.attributeDialects,
featureConfig?.attributeDialects?.scopes?.create, allowedScopes)) {
if (!hasAttributeCreatePermissions) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2023-2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
Expand All @@ -16,7 +16,7 @@
* under the License.
*/

import { Show } from "@wso2is/access-control";
import { Show, useRequiredScopes } from "@wso2is/access-control";
import { AppConstants, AppState, FeatureConfigInterface, history } from "@wso2is/admin.core.v1";
import { attributeConfig } from "@wso2is/admin.extensions.v1";
import { SCIMConfigs } from "@wso2is/admin.extensions.v1/configs/scim";
Expand All @@ -31,7 +31,6 @@ import { useValidationConfigData } from "@wso2is/admin.validation.v1/api";
import { ValidationFormInterface } from "@wso2is/admin.validation.v1/models";
import { IdentityAppsError } from "@wso2is/core/errors";
import { IdentityAppsApiException } from "@wso2is/core/exceptions";
import { hasRequiredScopes } from "@wso2is/core/helpers";
import {
AlertInterface,
AlertLevels,
Expand All @@ -40,6 +39,7 @@ import {
ProfileSchemaInterface,
TestableComponentInterface
} from "@wso2is/core/models";
import { Property } from "@wso2is/core/src/models";
import { addAlert, setProfileSchemaRequestLoadingStatus, setSCIMSchemas } from "@wso2is/core/store";
import { Field, Form } from "@wso2is/form";
import {
Expand Down Expand Up @@ -125,11 +125,13 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca

const allowedScopes: string = useSelector((state: AppState) => state?.auth?.allowedScopes);
const featureConfig: FeatureConfigInterface = useSelector((state: AppState) => state.config.ui.features);
const hasAttributeUpdatePermissions: boolean = useRequiredScopes(featureConfig?.attributeDialects?.scopes?.update);
const [ hideSpecialClaims, setHideSpecialClaims ] = useState<boolean>(true);
const [ usernameConfig, setUsernameConfig ] = useState<ValidationFormInterface>(undefined);
const [ connector, setConnector ] = useState<GovernanceConnectorInterface>(undefined);
const [ accountVerificationEnabled, setAccountVerificationEnabled ] = useState<boolean>(false);
const [ selfRegistrationEnabled, setSelfRegistrationEnabledEnabled ] = useState<boolean>(false);
const [ isSystemClaim, setIsSystemClaim ] = useState<boolean>(false);

const { t } = useTranslation();

Expand Down Expand Up @@ -184,6 +186,13 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca
else {
setHideSpecialClaims(true);
}

setIsSystemClaim(
claim?.properties?.some((property: Property) =>
property.key === ClaimManagementConstants.SYSTEM_CLAIM_PROPERTY_NAME
&& property.value === "true"
)
);
}, [ claim, usernameConfig ]);

useEffect(() => {
Expand Down Expand Up @@ -318,8 +327,7 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca
if (hideSpecialClaims) {
return true;
} else {
return !hasRequiredScopes(
featureConfig?.attributeDialects, featureConfig?.attributeDialects?.scopes?.update, allowedScopes);
return !hasAttributeUpdatePermissions;
}
}, [ featureConfig, allowedScopes, hideSpecialClaims ]);

Expand Down Expand Up @@ -758,6 +766,7 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca
&& !READONLY_CLAIM_CONFIGS.includes(claim?.claimURI)
&& !hideSpecialClaims
&& claim.claimURI !== ClaimManagementConstants.EMAIL_CLAIM_URI
&& !isSystemClaim
&& (
<Show
when={ featureConfig?.attributeDialects?.scopes?.delete }
Expand Down
13 changes: 13 additions & 0 deletions features/admin.claims.v1/constants/claim-management-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ export class ClaimManagementConstants {
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("SCIM_SCHEMAS_CORE")
];

public static readonly SYSTEM_DIALECTS: string[] = [
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("OPENID_NET"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("LOCAL"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("OIDC"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("SCIM2_SCHEMAS_CORE"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("SCIM2_SCHEMAS_CORE_USER"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("SCIM2_SCHEMAS_EXT_ENT_USER"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("SCIM_SCHEMAS_CORE"),
ClaimManagementConstants.ATTRIBUTE_DIALECT_IDS.get("XML_SOAP")
];

public static readonly CUSTOM_MAPPING: string = SCIMConfigs.custom;

public static readonly OIDC_MAPPING: string[] = [
Expand Down Expand Up @@ -195,6 +206,8 @@ export class ClaimManagementConstants {
ClaimManagementConstants.VERIFIED_MOBILE_NUMBERS_CLAIM_URI
];

public static readonly SYSTEM_CLAIM_PROPERTY_NAME: string = "isSystemClaim";

/**
* The error code that is returned when there is no item in the list
*/
Expand Down
63 changes: 33 additions & 30 deletions features/admin.claims.v1/pages/external-dialect-edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,37 +349,40 @@ const ExternalDialectEditPage: FunctionComponent<ExternalDialectEditPageInterfac

<Divider hidden />

{ attributeConfig.attributeMappings.showDangerZone && (
<Grid>
<Grid.Row columns={ 1 }>
<Grid.Column width={ 16 }>
<Show
when={ featureConfig?.oidcScopes?.scopes?.delete }
>
<DangerZoneGroup
sectionHeader={ t("common:dangerZone") }
data-testid={ `${ testId }-danger-zone-group` }
{
attributeConfig.attributeMappings.showDangerZone
&& !ClaimManagementConstants.SYSTEM_DIALECTS.includes(dialect?.id)
&& (
<Grid>
<Grid.Row columns={ 1 }>
<Grid.Column width={ 16 }>
<Show
when={ featureConfig?.oidcScopes?.scopes?.delete }
>
<DangerZone
actionTitle={ t("claims:dialects." +
"dangerZone.actionTitle", {
type: resolveType(attributeType, true, true)
}) }
header={ t("claims:dialects.dangerZone.header", {
type: resolveType(attributeType, true)
}) }
subheader={ t("claims:dialects.dangerZone.subheader", {
type: resolveType(attributeType)
}) }
onActionClick={ () => setConfirmDelete(true) }
data-testid={ `${ testId }-dialect-delete-danger-zone` }
/>
</DangerZoneGroup>
</Show>
</Grid.Column>
</Grid.Row>
</Grid>
) }
<DangerZoneGroup
sectionHeader={ t("common:dangerZone") }
data-testid={ `${ testId }-danger-zone-group` }
>
<DangerZone
actionTitle={ t("claims:dialects." +
"dangerZone.actionTitle", {
type: resolveType(attributeType, true, true)
}) }
header={ t("claims:dialects.dangerZone.header", {
type: resolveType(attributeType, true)
}) }
subheader={ t("claims:dialects.dangerZone.subheader", {
type: resolveType(attributeType)
}) }
onActionClick={ () => setConfirmDelete(true) }
data-testid={ `${ testId }-dialect-delete-danger-zone` }
/>
</DangerZoneGroup>
</Show>
</Grid.Column>
</Grid.Row>
</Grid>
) }
{ attributeConfig.attributeMappings.showDangerZone && confirmDelete && deleteConfirmation() }
</>
);
Expand Down
Loading

0 comments on commit 056ebc9

Please sign in to comment.