Skip to content

Commit

Permalink
Merge pull request #7362 from amanda-ariyaratne/scim-system-schema-fe…
Browse files Browse the repository at this point in the history
…ature-2

Add SCIM system schema
  • Loading branch information
amanda-ariyaratne authored Jan 23, 2025
2 parents a99d84e + 31b4e92 commit 71ee1c0
Show file tree
Hide file tree
Showing 33 changed files with 353 additions and 185 deletions.
11 changes: 11 additions & 0 deletions .changeset/selfish-hairs-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@wso2is/admin.extensions.v1": patch
"@wso2is/admin.claims.v1": patch
"@wso2is/admin.users.v1": patch
"@wso2is/admin.core.v1": patch
"@wso2is/myaccount": patch
"@wso2is/console": patch
"@wso2is/core": patch
---

Add system schema
Original file line number Diff line number Diff line change
Expand Up @@ -1984,6 +1984,9 @@
{% if console.enable_identity_claims is defined %}
"enableIdentityClaims": {{ console.enable_identity_claims }},
{% endif %}
{% if scim2.custom_user_schema_uri is defined %}
"customUserSchemaURI": "{{ scim2.custom_user_schema_uri }}",
{% endif %}
{% if tenant_mgt.enable_email_domain is defined %}
"enableEmailDomain": {{ tenant_mgt.enable_email_domain }},
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@
{% endfor %}
{% endif %}
},
{% if scim2.custom_user_schema_uri is defined %}
"customUserSchemaURI": "{{ scim2.custom_user_schema_uri }}",
{% endif %}
"privacyPolicyConfigs": {
{% if myaccount.privacy_policy_configs.items() is defined %}
{% for key, value in myaccount.privacy_policy_configs.items() %}
Expand Down
6 changes: 3 additions & 3 deletions apps/myaccount/src/api/profile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2024, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2019-2025, 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 Down Expand Up @@ -146,8 +146,8 @@ export const getProfileInfo = (): Promise<BasicProfileInterface> => {
const profileResponse: BasicProfileInterface = {
emails: response.data.emails || "",
name: response.data.name || { familyName: "", givenName: "" },
pendingEmails: response.data[ProfileConstants.SCIM2_ENT_USER_SCHEMA]
? response.data[ProfileConstants.SCIM2_ENT_USER_SCHEMA].pendingEmails
pendingEmails: response.data[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA]
? response.data[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA].pendingEmails
: [],
phoneNumbers: response.data.phoneNumbers || [],
profileUrl: response.data.profileUrl || "",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2019-2025, 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 Down Expand Up @@ -135,7 +135,7 @@ export const EmailRecovery: React.FunctionComponent<EmailRecoveryProps> = (
}
]
: [ emailAddress ],
[ProfileConstants.SCIM2_ENT_USER_SCHEMA]: {
[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA]: {
"verifyEmail": true
}
};
Expand Down
103 changes: 49 additions & 54 deletions apps/myaccount/src/components/profile/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export const Profile: FunctionComponent<ProfileProps> = (props: ProfileProps): R
state.authenticationInformation.profileInfo.isReadOnly);
const hasLocalAccount: boolean = useSelector((state: AppState) => state.authenticationInformation.hasLocalAccount);
const config: ConfigReducerStateInterface = useSelector((state: AppState) => state.config);
const userSchemaURI: string = useSelector((state: AppState) => state?.config?.ui?.userSchemaURI);

const activeForm: string = useSelector((state: AppState) => state.global.activeForm);
const supportedI18nLanguages: SupportedLanguagesMeta = useSelector(
Expand Down Expand Up @@ -431,58 +432,46 @@ export const Profile: FunctionComponent<ProfileProps> = (props: ProfileProps): R
tempProfileInfo.set(schema.name, primaryEmail);
}
} else {
if (schema.extended
&& profileDetails?.profileInfo[ProfileConstants.SCIM2_ENT_USER_SCHEMA]
&& profileDetails?.profileInfo[ProfileConstants.SCIM2_ENT_USER_SCHEMA][schemaNames[0]]) {
tempProfileInfo.set(
schema.name,
profileDetails?.profileInfo[ProfileConstants.SCIM2_ENT_USER_SCHEMA]
? profileDetails?.profileInfo[
ProfileConstants.SCIM2_ENT_USER_SCHEMA][schemaNames[0]
]
: ""
);

return;
}

if (schema.extended
&& profileDetails?.profileInfo[ProfileConstants.SCIM2_WSO2_CUSTOM_SCHEMA]
&& profileDetails?.profileInfo[ProfileConstants.SCIM2_WSO2_CUSTOM_SCHEMA][schemaNames[0]]) {

const multiValuedAttributes: string[] = [
EMAIL_ADDRESSES_ATTRIBUTE,
MOBILE_NUMBERS_ATTRIBUTE,
VERIFIED_EMAIL_ADDRESSES_ATTRIBUTE,
VERIFIED_MOBILE_NUMBERS_ATTRIBUTE
if (schema.extended) {
const schemaURIs: string[] = [
ProfileConstants.SCIM2_ENT_USER_SCHEMA,
ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA,
userSchemaURI
];

if (multiValuedAttributes.includes(schemaNames[0])) {
for (const schemaURI of schemaURIs) {
if (profileDetails?.profileInfo[schemaURI]?.[schemaNames[0]]) {

const multiValuedAttributes: string[] = [
EMAIL_ADDRESSES_ATTRIBUTE,
MOBILE_NUMBERS_ATTRIBUTE,
VERIFIED_EMAIL_ADDRESSES_ATTRIBUTE,
VERIFIED_MOBILE_NUMBERS_ATTRIBUTE
];

if (schemaURI === ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA
&& multiValuedAttributes.includes(schemaNames[0])) {
const attributeValue: string | string[] =
profileDetails?.profileInfo[schemaURI]?.[schemaNames[0]];

const attributeValue: string | string[] =
profileDetails?.profileInfo[
ProfileConstants.SCIM2_WSO2_CUSTOM_SCHEMA]?.[schemaNames[0]];
const formattedValue: string = Array.isArray(attributeValue)
? attributeValue.join(",")
: "";

const formattedValue: string = Array.isArray(attributeValue)
? attributeValue.join(",")
: "";
tempProfileInfo.set(schema.name, formattedValue);

return;
}

tempProfileInfo.set(schema.name, formattedValue);
tempProfileInfo.set(
schema.name,
profileDetails?.profileInfo[schemaURI]?.[schemaNames[0]] ?? ""
);

return;
return;
}
}
tempProfileInfo.set(
schema.name,
profileDetails?.profileInfo[ProfileConstants.SCIM2_WSO2_CUSTOM_SCHEMA]
? profileDetails?.profileInfo[
ProfileConstants.SCIM2_WSO2_CUSTOM_SCHEMA
][schemaNames[0]]
: ""
);

return;
}

tempProfileInfo.set(schema.name, profileDetails.profileInfo[schemaNames[0]]);
}
} else {
Expand Down Expand Up @@ -512,14 +501,20 @@ export const Profile: FunctionComponent<ProfileProps> = (props: ProfileProps): R
}
}
} else {
if (schema.extended) {
tempProfileInfo.set(schema.name,
profileDetails?.profileInfo[ProfileConstants.SCIM2_ENT_USER_SCHEMA]?.[schemaNames[0]]
? profileDetails
?.profileInfo[
ProfileConstants.SCIM2_ENT_USER_SCHEMA
][schemaNames[0]][schemaNames[1]]
: "");
if (schema.extended
&& profileDetails?.profileInfo[ProfileConstants.SCIM2_ENT_USER_SCHEMA]?.[schemaNames[0]]) {
tempProfileInfo.set(
schema.name,
profileDetails.profileInfo[ProfileConstants.SCIM2_ENT_USER_SCHEMA][schemaNames[0]][
schemaNames[1]]
?? "");
} else if (schema.extended &&
profileDetails?.profileInfo[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA]?.[schemaNames[0]]) {
tempProfileInfo.set(
schema.name,
profileDetails.profileInfo[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA][schemaNames[0]][
schemaNames[1]]
?? "");
} else {
const subValue: BasicProfileInterface = profileDetails.profileInfo[schemaNames[0]]
&& profileDetails.profileInfo[schemaNames[0]].find(
Expand Down Expand Up @@ -705,7 +700,7 @@ export const Profile: FunctionComponent<ProfileProps> = (props: ProfileProps): R
if (values.get(formName)) {
value = {
...value,
[ProfileConstants.SCIM2_ENT_USER_SCHEMA]: {
[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA]: {
"verifyEmail": true
}
};
Expand Down Expand Up @@ -747,7 +742,7 @@ export const Profile: FunctionComponent<ProfileProps> = (props: ProfileProps): R
if (primaryValue) {
value = {
...value,
[ProfileConstants.SCIM2_ENT_USER_SCHEMA]: {
[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA]: {
"verifyEmail": true
}
};
Expand Down
10 changes: 5 additions & 5 deletions apps/myaccount/src/components/shared/mobile-update-wizard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2020-2025, 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 Down Expand Up @@ -93,9 +93,9 @@ export const MobileUpdateWizard: React.FunctionComponent<MobileUpdateWizardProps
const isMobileVerificationPending = (updatedMobileNumber: string, userData: Record<string, string>): boolean => {
const PENDING_MOBILE_CLAIM: string = "pendingMobileNumber";

return userData && userData[ProfileConstants.SCIM2_ENT_USER_SCHEMA] &&
userData[ProfileConstants.SCIM2_ENT_USER_SCHEMA][PENDING_MOBILE_CLAIM] &&
userData[ProfileConstants.SCIM2_ENT_USER_SCHEMA][PENDING_MOBILE_CLAIM] === updatedMobileNumber;
return userData && userData[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA] &&
userData[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA][PENDING_MOBILE_CLAIM] &&
userData[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA][PENDING_MOBILE_CLAIM] === updatedMobileNumber;

};

Expand Down Expand Up @@ -127,7 +127,7 @@ export const MobileUpdateWizard: React.FunctionComponent<MobileUpdateWizardProps
value: mobileNumber
}
],
[ProfileConstants.SCIM2_ENT_USER_SCHEMA]: { "verifyMobile": true }
[ProfileConstants.SCIM2_SYSTEM_USER_SCHEMA]: { "verifyMobile": true }
};
updateProfileInfo(data).then((response: AxiosResponse) => {
if (response.status === 200) {
Expand Down
8 changes: 5 additions & 3 deletions apps/myaccount/src/configs/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import { I18nModuleInitOptions, I18nModuleOptionsInterface, MetaI18N, generateBackendPaths } from "@wso2is/i18n";
import { I18nConstants } from "../constants";
import { AppConstants } from "../constants/app-constants";
import { UserManagementConstants } from "../constants/user-management-constants";
// Keep statement as this to avoid cyclic dependency. Do not import from config index.
import { SCIMConfigs } from "../extensions/configs/scim";
import { AppUtils } from "../init/app-utils";
Expand Down Expand Up @@ -109,8 +110,7 @@ export class Config {
this.getDeploymentConfig()?.serverHost
}/api/server/v1/configs/home-realm-identifiers`,
isReadOnlyUser: `${this.getDeploymentConfig()?.serverHost}/scim2/Me?attributes=${
SCIMConfigs.scimEnterpriseUserClaimUri.isReadOnlyUser
}`,
SCIMConfigs.scim.systemSchema}:isReadOnlyUser`,
issuer: `${this.getDeploymentConfig()?.serverHost}/oauth2/token`,
jwks: `${this.getDeploymentConfig()?.serverHost}/oauth2/jwks`,
logout: `${this.getDeploymentConfig()?.serverHost}/oidc/logout`,
Expand Down Expand Up @@ -170,7 +170,9 @@ export class Config {
productName: window["AppUtils"]?.getConfig()?.ui?.productName,
productVersionConfig: window["AppUtils"]?.getConfig()?.ui?.productVersionConfig,
showAppSwitchButton: window["AppUtils"]?.getConfig()?.ui?.showAppSwitchButton,
theme: window["AppUtils"]?.getConfig()?.ui?.theme
theme: window["AppUtils"]?.getConfig()?.ui?.theme,
userSchemaURI: window[ "AppUtils" ]?.getConfig()?.ui?.customUserSchemaURI
?? UserManagementConstants.DEFAULT_SCIM2_CUSTOM_USER_SCHEMA_URI
};
}

Expand Down
7 changes: 6 additions & 1 deletion apps/myaccount/src/constants/user-management-constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022-2024, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2022-2025, 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 Down Expand Up @@ -39,4 +39,9 @@ export class UserManagementConstants {
.set("USERNAME", "userName")
.set("NAME", "name")
.set("DISPLAY_NAME", "displayName");

/**
* Default scim2 custom user schema URI.
*/
public static readonly DEFAULT_SCIM2_CUSTOM_USER_SCHEMA_URI: string = "urn:scim:schemas:extension:custom:User";
}
3 changes: 2 additions & 1 deletion apps/myaccount/src/extensions/configs/models/scim.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2021-2025, 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 @@ -25,6 +25,7 @@ export interface SCIMConfigInterface {
coreSchema: string,
enterpriseSchema: string,
userSchema: string,
systemSchema: string,
customEnterpriseSchema:string
};

Expand Down
3 changes: 2 additions & 1 deletion apps/myaccount/src/extensions/configs/scim.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021-2024, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2021-2025, 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 Down Expand Up @@ -31,6 +31,7 @@ export const SCIMConfigs: SCIMConfigInterface = {
coreSchema: "urn:ietf:params:scim:schemas:core:2.0",
customEnterpriseSchema: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
enterpriseSchema: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
systemSchema: "urn:scim:wso2:schema",
userSchema: "urn:ietf:params:scim:schemas:core:2.0:User"
},

Expand Down
11 changes: 8 additions & 3 deletions apps/myaccount/src/models/app-config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2020-2025, 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 Down Expand Up @@ -158,7 +158,7 @@ export interface UIConfigInterface extends CommonUIConfigInterface {
* Config for enable MFA user wise.
*/
enableMFAUserWise?: boolean;
/**
/**
* Config for disable MFA for federated users.
*/
disableMFAForFederatedUsers?: boolean;
Expand All @@ -174,7 +174,12 @@ export interface UIConfigInterface extends CommonUIConfigInterface {
* Config to check whether the multiple emails and mobile numbers per user feature is enabled.
*/
isMultipleEmailsAndMobileNumbersEnabled?: boolean;
}
/**
* Overridden Scim2 user schema URI.
* If the value is not overridden, the default SCIM2 user schema URI is returned.
*/
userSchemaURI?: string;
}

/**
* Interface for defining settings and configs of an external app.
Expand Down
Loading

0 comments on commit 71ee1c0

Please sign in to comment.