Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove delete option from default claims and dialects #7069

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -183,6 +194,8 @@ export class ClaimManagementConstants {

public static readonly EMPTY_STRING: string = "";

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
Loading