Skip to content

Commit

Permalink
Add support for claim-wise uniqueness validation
Browse files Browse the repository at this point in the history
  • Loading branch information
AfraHussaindeen committed Nov 11, 2024
1 parent 163f073 commit 8a293ef
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1909,5 +1909,8 @@
"theme": {
"name": "{{ console.theme }}"
}
{% if identity_mgt.user_claim_update.uniqueness.enable is defined %}
"isClaimUniquenessValidationEnabled": "{{ identity_mgt.user_claim_update.uniqueness.enable }}",
{% endif %}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import { Show } from "@wso2is/access-control";
import { AppConstants, AppState, FeatureConfigInterface, history } from "@wso2is/admin.core.v1";
import useUIConfig from "@wso2is/admin.core.v1/hooks/use-ui-configs";
import { attributeConfig } from "@wso2is/admin.extensions.v1";
import { SCIMConfigs } from "@wso2is/admin.extensions.v1/configs/scim";
import {
Expand Down Expand Up @@ -135,6 +136,8 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca

const { data: validationData } = useValidationConfigData();

const { UIConfig } = useUIConfig();

/**
* Get username configuration.
*/
Expand Down Expand Up @@ -418,14 +421,28 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca
};

const onSubmit = (values: Record<string, unknown>) => {
const updatedProperties: { key: string; value: string }[] = [ ...(claim.properties || []) ];
const uniquenessScopeIndex: number = updatedProperties.findIndex((prop: { key: string; value: string }) =>
prop.key === "UniquenessScope"
);

if (uniquenessScopeIndex !== -1) {
updatedProperties[uniquenessScopeIndex].value = values.uniquenessScope?.toString() || "NONE";
} else {
updatedProperties.push({
key: "UniquenessScope",
value: values.uniquenessScope?.toString() || "NONE"
});
}

const data: Claim = {
attributeMapping: claim.attributeMapping,
claimURI: claim.claimURI,
description: values?.description !== undefined ? values.description?.toString() : claim?.description,
displayName: values?.name !== undefined ? values.name?.toString() : claim?.displayName,
displayOrder: attributeConfig.editAttributes.getDisplayOrder(
claim.displayOrder, values.displayOrder?.toString()),
properties: claim.properties,
properties: updatedProperties,
readOnly: values?.readOnly !== undefined ? !!values.readOnly : claim?.readOnly,
regEx: values?.regularExpression !== undefined ? values.regularExpression?.toString() : claim?.regEx,
required: values?.required !== undefined && !values?.readOnly ? !!values.required : false,
Expand Down Expand Up @@ -555,6 +572,39 @@ export const EditBasicDetailsLocalClaims: FunctionComponent<EditBasicDetailsLoca
/>
)
}
{
claim && !READONLY_CLAIM_CONFIGS.includes(claim?.claimURI)
&& !hideSpecialClaims && mappingChecked
&& UIConfig?.isClaimUniquenessValidationEnabled && (
<Field.Dropdown
ariaLabel="uniqueness-scope-dropdown"
name="uniquenessScope"
label={ t("claims:local.forms.uniquenessScope.label") }
data-testid={ `${ testId }-form-uniqueness-scope-dropdown` }
disabled={ !hasMapping }
hint={ t("claims:local.forms.uniquenessScopeHint") }
options={ [
{
text: t("claims:local.forms.uniquenessScope.options.none"),
value: "NONE"
},
{
text: t("claims:local.forms.uniquenessScope.options.withinUserstore"),
value: "WITHIN_USERSTORE"
},
{
text: t("claims:local.forms.uniquenessScope.options.acrossUserstores"),
value: "ACROSS_USERSTORES"
}
] }
value={
(claim?.properties?.find(
(prop: { key: string; value: string }) => prop.key === "UniquenessScope"
)?.value as string) || "NONE"
}
/>
)
}
{ !READONLY_CLAIM_CONFIGS.includes(claim?.claimURI) && mappingChecked
? (
!hideSpecialClaims &&
Expand Down
2 changes: 2 additions & 0 deletions features/admin.core.v1/configs/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ export class Config {
hiddenUserStores: window[ "AppUtils" ]?.getConfig()?.ui?.hiddenUserStores,
i18nConfigs: window[ "AppUtils" ]?.getConfig()?.ui?.i18nConfigs,
identityProviderTemplates: window[ "AppUtils" ]?.getConfig()?.ui?.identityProviderTemplates,
isClaimUniquenessValidationEnabled:
window[ "AppUtils" ]?.getConfig()?.ui?.isClaimUniquenessValidationEnabled,
isClientSecretHashEnabled: window[ "AppUtils" ]?.getConfig()?.ui?.isClientSecretHashEnabled,
isCookieConsentBannerEnabled: window[ "AppUtils" ]?.getConfig()?.ui?.isCookieConsentBannerEnabled,
isCustomClaimMappingEnabled: window[ "AppUtils" ]?.getConfig()?.ui?.isCustomClaimMappingEnabled,
Expand Down
4 changes: 4 additions & 0 deletions features/admin.core.v1/models/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ export interface UIConfigInterface extends CommonUIConfigInterface<FeatureConfig
* Should dialects addition be allowed.
*/
isDialectAddingEnabled?: boolean;
/**
* Flag to check if the claims uniqueness validation is enabled.
*/
isClaimUniquenessValidationEnabled?: boolean;
/**
* Flag to check if the `OAuth.EnableClientSecretHash` is enabled in the `identity.xml`.
*/
Expand Down
1 change: 1 addition & 0 deletions features/admin.core.v1/store/reducers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ export const commonConfigReducerInitialState: CommonConfigReducerStateInterface<
enabled: false
}
},
isClaimUniquenessValidationEnabled: undefined,
isClientSecretHashEnabled: undefined,
isCookieConsentBannerEnabled: undefined,
isCustomClaimMappingEnabled: undefined,
Expand Down
9 changes: 9 additions & 0 deletions modules/i18n/src/models/namespaces/claims-ns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,15 @@ export interface ClaimsNS {
invalidName: string;
};
};
uniquenessScope: {
label: string;
options: {
none: string;
withinUserstore: string;
acrossUserstores: string;
};
};
uniquenessScopeHint: string;
nameHint: string;
description: {
label: string;
Expand Down
9 changes: 9 additions & 0 deletions modules/i18n/src/models/namespaces/console-ns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4186,6 +4186,15 @@ export interface ConsoleNS {
disabledConfigInfo: string;
configApplicabilityInfo: string;
};
uniquenessScope: {
label: string;
options: {
none: string;
withinUserstore: string;
acrossUserstores: string;
}
};
uniquenessScopeHint: string;
};
dangerZone: {
actionTitle: string;
Expand Down
11 changes: 10 additions & 1 deletion modules/i18n/src/translations/en-US/portals/claims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,16 @@ export const claims: ClaimsNS = {
"you need to disable account verification for your organization.",
supportedByDefault: {
label: "Display this attribute on the user's profile"
}
},
uniquenessScope: {
label: "Uniqueness Validation",
options: {
none: "None",
withinUserstore: "Within User Store",
acrossUserstores: "Across User Stores"

Check warning on line 503 in modules/i18n/src/translations/en-US/portals/claims.ts

View workflow job for this annotation

GitHub Actions / ⬣ ESLint (STATIC ANALYSIS) (lts/*, 8.7.4)

Expected object keys to be in ascending order. 'acrossUserstores' should be before 'withinUserstore'
}
},
uniquenessScopeHint: "Select the scope to validate the uniqueness of the attribute value."
},
mappedAttributes: {
hint: "Enter the attribute from each user store that you want to map to this attribute."
Expand Down
11 changes: 10 additions & 1 deletion modules/i18n/src/translations/en-US/portals/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3501,7 +3501,16 @@ export const console: ConsoleNS = {
"you need to disable account verification for your organization.",
supportedByDefault: {
label: "Display this attribute on the user's profile"
}
},
uniquenessScope: {
label: "Uniqueness Validation",
options: {
none: "None",
withinUserstore: "Within User Store",
acrossUserstores: "Across User Stores"
}
},
uniquenessScopeHint: "Select the scope to validate the uniqueness of the attribute value."
},
mappedAttributes: {
hint: "Enter the attribute from each user store that you want to map to this attribute."
Expand Down

0 comments on commit 8a293ef

Please sign in to comment.