From 86df29a2085662ed56e6041790f5c287ab5a9f13 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Tue, 3 Oct 2023 09:20:46 +0530 Subject: [PATCH 01/11] add rolev2 definitions --- .../core/extensions/RoleV2Manager.java | 136 ++++ .../org/wso2/charon3/core/objects/RoleV2.java | 609 ++++++++++++++++++ .../plainobjects/RolesV2GetResponse.java | 82 +++ .../protocol/endpoints/ResourceManager.java | 103 +++ .../endpoints/RoleResourceV2Manager.java | 209 ++++++ .../charon3/core/schema/SCIMConstants.java | 31 +- .../schema/SCIMResourceSchemaManager.java | 4 + .../core/schema/SCIMSchemaDefinitions.java | 99 +++ 8 files changed, 1272 insertions(+), 1 deletion(-) create mode 100644 modules/charon-core/src/main/java/org/wso2/charon3/core/extensions/RoleV2Manager.java create mode 100644 modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java create mode 100644 modules/charon-core/src/main/java/org/wso2/charon3/core/objects/plainobjects/RolesV2GetResponse.java create mode 100644 modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/extensions/RoleV2Manager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/extensions/RoleV2Manager.java new file mode 100644 index 000000000..ad2cb40c6 --- /dev/null +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/extensions/RoleV2Manager.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://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 + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.charon3.core.extensions; + +import org.wso2.charon3.core.exceptions.BadRequestException; +import org.wso2.charon3.core.exceptions.CharonException; +import org.wso2.charon3.core.exceptions.ConflictException; +import org.wso2.charon3.core.exceptions.ForbiddenException; +import org.wso2.charon3.core.exceptions.NotFoundException; +import org.wso2.charon3.core.exceptions.NotImplementedException; +import org.wso2.charon3.core.objects.RoleV2; +import org.wso2.charon3.core.objects.plainobjects.RolesV2GetResponse; +import org.wso2.charon3.core.utils.codeutils.Node; +import org.wso2.charon3.core.utils.codeutils.PatchOperation; +import org.wso2.charon3.core.utils.codeutils.SearchRequest; + +import java.util.List; +import java.util.Map; + +/** + * OSGi service interface which uses to manage roleV2. + */ +public interface RoleV2Manager { + + /** + * Create a role. + * + * @param role Role Object. + * @return Role. + * @throws CharonException CharonException. + * @throws ConflictException ConflictException. + * @throws NotImplementedException NotImplementedException. + * @throws BadRequestException BadRequestException. + */ + RoleV2 createRole(RoleV2 role) + throws CharonException, ConflictException, NotImplementedException, BadRequestException; + + /** + * Get the role for the given ID. + * + * @param id Role ID. + * @param requiredAttributes Required Attributes. + * @return Role. + * @throws NotImplementedException NotImplementedException. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + * @throws NotFoundException NotFoundException. + */ + RoleV2 getRole(String id, Map requiredAttributes) + throws NotImplementedException, BadRequestException, CharonException, NotFoundException; + + /** + * Delete the given role. + * + * @param id Role ID. + * @throws NotFoundException NotFoundException. + * @throws CharonException CharonException. + * @throws NotImplementedException NotImplementedException. + * @throws BadRequestException BadRequestException. + */ + void deleteRole(String id) throws NotFoundException, CharonException, NotImplementedException, BadRequestException; + + /** + * List roles with Get. + * + * @param node Node + * @param startIndex Start Index + * @param count Count + * @param sortBy Sort by + * @param sortOrder Sort order + * @return List of roles. + * @throws CharonException CharonException. + * @throws NotImplementedException NotImplementedException. + * @throws BadRequestException BadRequestException. + */ + RolesV2GetResponse listRolesWithGET(Node node, Integer startIndex, Integer count, String sortBy, String sortOrder) + throws CharonException, NotImplementedException, BadRequestException; + + /** + * Update the role. + * + * @param oldRole Old role. + * @param newRole new role. + * @return Updated role. + * @throws NotImplementedException NotImplementedException. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + * @throws ConflictException ConflictException. + * @throws NotFoundException NotFoundException. + */ + RoleV2 updateRole(RoleV2 oldRole, RoleV2 newRole) + throws NotImplementedException, BadRequestException, CharonException, ConflictException, NotFoundException; + + /** + * List roles with Post. + * + * @param searchRequest Search request. + * @return List of roles. + * @throws NotImplementedException NotImplementedException. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + */ + RolesV2GetResponse listRolesWithPost(SearchRequest searchRequest) + throws NotImplementedException, BadRequestException, CharonException; + + /** + * Updates the role via PATCH. + * + * @param roleId ID of the role. + * @param patchOperations A map of patch operations. + * @return Updated group. + * @throws CharonException Charon exception. + * @throws BadRequestException Bad request exception. + * @throws NotFoundException Not found exception. + * @throws NotImplementedException Functionality no implemented exception. + */ + RoleV2 patchRole(String roleId, Map> patchOperations) + throws NotImplementedException, BadRequestException, CharonException, ConflictException, NotFoundException, + ForbiddenException; +} diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java new file mode 100644 index 000000000..7b9ce637d --- /dev/null +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://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 + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.charon3.core.objects; + +import org.wso2.charon3.core.attributes.Attribute; +import org.wso2.charon3.core.attributes.ComplexAttribute; +import org.wso2.charon3.core.attributes.DefaultAttributeFactory; +import org.wso2.charon3.core.attributes.MultiValuedAttribute; +import org.wso2.charon3.core.attributes.SimpleAttribute; +import org.wso2.charon3.core.exceptions.BadRequestException; +import org.wso2.charon3.core.exceptions.CharonException; +import org.wso2.charon3.core.objects.plainobjects.MultiValuedComplexType; +import org.wso2.charon3.core.schema.SCIMAttributeSchema; +import org.wso2.charon3.core.schema.SCIMConstants; +import org.wso2.charon3.core.schema.SCIMResourceSchemaManager; +import org.wso2.charon3.core.schema.SCIMResourceTypeSchema; +import org.wso2.charon3.core.schema.SCIMSchemaDefinitions; +import org.wso2.charon3.core.utils.LambdaExceptionUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.wso2.charon3.core.utils.LambdaExceptionUtils.rethrowFunction; + +/** + * Represents the RoleV2 object which is a custom SCIM2 resource. + */ +public class RoleV2 extends AbstractSCIMObject { + + private static final long SERIAL_VERSION_UID = 6106269076155338045L; + + /** + * Get the display name of the role. + * + * @return Display name of the role. + */ + public String getDisplayName() { + + if (isAttributeExist(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME)) { + return LambdaExceptionUtils.rethrowSupplier( + () -> ((SimpleAttribute) attributeList.get(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME)) + .getStringValue()).get(); + } + return null; + } + + /** + * Set the display name of the role. + * + * @param displayName Display name. + * @throws CharonException CharonException. + * @throws BadRequestException BadRequestException. + */ + public void setDisplayName(String displayName) throws CharonException, BadRequestException { + + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME)) { + ((SimpleAttribute) this.attributeList.get(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME)). + updateValue(displayName); + } else { + SimpleAttribute displayAttribute = new SimpleAttribute(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME, + displayName); + displayAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.DISPLAY_NAME, displayAttribute); + this.attributeList.put(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME, displayAttribute); + } + } + + /** + * Deletes the current value of display name and rename it with the given value. + * + * @param displayName New display name. + */ + public void replaceDisplayName(String displayName) { + + replaceSimpleAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.DISPLAY_NAME, displayName); + } + + /** + * Get the users of the role. + * + * @return List of users. + */ + public List getUsers() { + + List userList = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { + MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.USERS); + List subValuesList = users.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + userList.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); + } + } + } + return userList; + } + + /** + * Get the users of the role with their display names. + * + * @return List of display names. + */ + public List getUsersWithDisplayName() { + + List displayNames = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { + MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.USERS); + List values = users.getAttributeValues(); + if (values != null) { + List subValuesList = users.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + displayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); + } + + } + return displayNames; + } + } + + return displayNames; + } + + /** + * Set a user to the role, where user will have three default attributes such as name, value and $ref. + * + * @param user User object. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + */ + public void setUser(User user) throws BadRequestException, CharonException { + + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { + MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.USERS); + ComplexAttribute complexAttribute = processUser(user); + users.setAttributeValue(complexAttribute); + } else { + MultiValuedAttribute users = new MultiValuedAttribute(SCIMConstants.RoleSchemaConstants.USERS); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.USERS, users); + ComplexAttribute complexAttribute = processUser(user); + users.setAttributeValue(complexAttribute); + this.setAttribute(users); + } + } + + /** + * Create user attribute with three default attributes such as name, value and $ref. + * + * @param user User object. + * @return User object as a complex attribute. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + */ + private ComplexAttribute processUser(User user) throws BadRequestException, CharonException { + + String userId = user.getId(); + String userName = user.getUserName(); + String reference = user.getLocation(); + + ComplexAttribute complexAttribute = new ComplexAttribute(); + complexAttribute.setName(SCIMConstants.RoleSchemaConstants.USERS + "_" + userId + SCIMConstants.DEFAULT); + + if (userId != null) { + SimpleAttribute valueSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, + userId); + DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.USERS_VALUE, valueSimpleAttribute); + complexAttribute.setSubAttribute(valueSimpleAttribute); + } + + if (userName != null) { + SimpleAttribute displaySimpleAttribute = new SimpleAttribute(SCIMConstants.RoleSchemaConstants.DISPLAY, + userName); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.USERS_DISPLAY, + displaySimpleAttribute); + complexAttribute.setSubAttribute(displaySimpleAttribute); + } + + if (reference != null) { + SimpleAttribute referenceSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, + reference); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.USERS_REF, + referenceSimpleAttribute); + complexAttribute.setSubAttribute(referenceSimpleAttribute); + } + + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.USERS, complexAttribute); + return complexAttribute; + } + + /** + * Get the groups of the role. + * + * @return List of groups. + */ + public List getGroups() { + + List groupList = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { + MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.GROUPS); + List subValuesList = groups.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + groupList.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); + } + } + } + return groupList; + } + + /** + * Get the groups of the role with their display names. + * + * @return List of display names. + */ + public List getGroupsWithDisplayName() { + + List displayNames = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { + MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.GROUPS); + List values = groups.getAttributeValues(); + if (values != null) { + List subValuesList = groups.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + displayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); + } + } + return displayNames; + } + } + + return displayNames; + } + + /** + * Set a group to the role, where group will have three default attributes such as name, value and $ref. + * + * @param group Group object. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + */ + public void setGroup(Group group) throws BadRequestException, CharonException { + + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { + MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.GROUPS); + ComplexAttribute complexAttribute = processGroup(group); + groups.setAttributeValue(complexAttribute); + } else { + MultiValuedAttribute groups = new MultiValuedAttribute(SCIMConstants.RoleSchemaConstants.GROUPS); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.GROUPS, groups); + ComplexAttribute complexAttribute = processGroup(group); + groups.setAttributeValue(complexAttribute); + this.setAttribute(groups); + } + } + + /** + * Create group attribute with three default attributes such as name, value and $ref. + * + * @param group Group object. + * @return Group object as a complex attribute. + * @throws BadRequestException BadRequestException. + * @throws CharonException CharonException. + */ + private ComplexAttribute processGroup(Group group) throws BadRequestException, CharonException { + + String groupID = group.getId(); + String groupName = group.getDisplayName(); + String reference = group.getLocation(); + + ComplexAttribute complexAttribute = new ComplexAttribute(); + complexAttribute.setName(SCIMConstants.RoleSchemaConstants.GROUPS + "_" + groupID + SCIMConstants.DEFAULT); + + if (groupID != null) { + SimpleAttribute valueSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, + groupID); + DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.GROUPS_VALUE, valueSimpleAttribute); + complexAttribute.setSubAttribute(valueSimpleAttribute); + } + + if (groupName != null) { + SimpleAttribute displaySimpleAttribute = new SimpleAttribute(SCIMConstants.RoleSchemaConstants.DISPLAY, + groupName); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.GROUPS_DISPLAY, + displaySimpleAttribute); + complexAttribute.setSubAttribute(displaySimpleAttribute); + } + + if (reference != null) { + SimpleAttribute referenceSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, + reference); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.GROUPS_REF, + referenceSimpleAttribute); + complexAttribute.setSubAttribute(referenceSimpleAttribute); + } + + DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.GROUPS, complexAttribute); + return complexAttribute; + } + + /** + * Set the schemas for SCIM role object. + */ + public void setSchemas() { + + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceSchema(); + List schemasList = schema.getSchemasList(); + for (String scheme : schemasList) { + setSchema(scheme); + } + } + + /** + * Get the permission values of SCIM role object. + */ + public List getPermissionValues() { + + List permissionValuesList = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { + MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); + List subValuesList = permissions.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + permissionValuesList.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); + } + } + } + return permissionValuesList; + } + + /** + * Get the display names of the permissions of the role. + * + * @return List of display names. + */ + public List getPermissionDisplayNames() { + + List permissionDisplayNames = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { + MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); + List values = permissions.getAttributeValues(); + if (values != null) { + List subValuesList = permissions.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + permissionDisplayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); + } + } + } + } + return permissionDisplayNames; + } + + /** + * Get the permissions of SCIM role object. + */ + public List getPermissions() { + + SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ROLE_V2_PERMISSIONS; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_DISPLAY; + return getMultivaluedComplexType(complexDefinition, valueDefinition, displayDefinition, null, null, + null).orElse(Collections.emptyList()); + } + + /** + * Set the permissions for SCIM role object. + */ + public void setPermissions(List permissionsList) { + + SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ROLE_V2_PERMISSIONS; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_DISPLAY; + addMultivaluedComplexAtribute(permissionsList, complexDefinition, valueDefinition, displayDefinition, + null, null, null); + } + + /** + * Get associated applications' value list of the role. + */ + public List getAssociatedApplicationValues() { + + List assocAppValuesList = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { + MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); + List subValuesList = permissions.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + assocAppValuesList.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); + } + } + } + return assocAppValuesList; + } + + /** + * Get associated applications' display names list of the role. + */ + public List getAssociatedApplicationDisplayNames() { + + List assocAppDisplayNames = new ArrayList<>(); + if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { + MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); + List subValuesList = permissions.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList != null && subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + assocAppDisplayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); + } + } + } + return assocAppDisplayNames; + } + + /** + * Get associated applications of the role. + */ + public List getAssociatedApplications() { + + SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASSOCIATED_APPLICATIONS; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_DISPLAY; + return getMultivaluedComplexType(complexDefinition, valueDefinition, displayDefinition, null, null, + null).orElse(Collections.emptyList()); + } + + /** + * Set associated applications of the role. + */ + public void setAssociatedApplications(List associatedApplicationsList) { + + SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASSOCIATED_APPLICATIONS; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_DISPLAY; + addMultivaluedComplexAtribute(associatedApplicationsList, complexDefinition, valueDefinition, + displayDefinition, null, null, null); + } + + /** + * Get the audience of the role. + */ + public ComplexAttribute getAudience() { + + if (isAudienceAttributeExist()) { + return (ComplexAttribute) attributeList.get(SCIMConstants.RoleSchemaConstants.AUDIENCE); + } else { + return null; + } + } + + /** + * Get the audience value of the role. + */ + public String getAudienceValue() { + + SCIMAttributeSchema audienceDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE; + SCIMAttributeSchema audienceValueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_VALUE; + return getComplexAttribute(audienceDefinition).map(aud -> getSimpleAttribute(audienceValueDefinition, aud) + .map(rethrowFunction(SimpleAttribute::getStringValue)) + .orElse(null)).orElse(null); + } + + /** + * Get the audience type of the role. + */ + public String getAudienceType() { + + SCIMAttributeSchema audienceDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE; + SCIMAttributeSchema audienceTypeDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_TYPE; + return getComplexAttribute(audienceDefinition).map(aud -> getSimpleAttribute(audienceTypeDefinition, aud) + .map(rethrowFunction(SimpleAttribute::getStringValue)) + .orElse(null)).orElse(null); + } + + /** + * Get the audience value of the role. + * + * @param audienceValue Unique ID of the audience. + * @param audienceDisplay Display name of the audience. + * @param audienceType Type of the audience. + * @throws BadRequestException If the audience attribute values are not accepted. + * @throws CharonException If error occurred while setting the audience attributes. + */ + public void setAudience(String audienceValue, String audienceDisplay, String audienceType) + throws BadRequestException, CharonException { + + ComplexAttribute audienceAttribute = + (ComplexAttribute) DefaultAttributeFactory.createAttribute( + SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE, + new ComplexAttribute(SCIMConstants.RoleSchemaConstants.AUDIENCE)); + if (!isAudienceAttributeExist()) { + attributeList.put(SCIMConstants.RoleSchemaConstants.AUDIENCE, audienceAttribute); + + SimpleAttribute audienceValueAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_VALUE, + new SimpleAttribute(SCIMConstants.RoleSchemaConstants.VALUE, audienceValue)); + SimpleAttribute audienceDisplayAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_DISPLAY, + new SimpleAttribute(SCIMConstants.RoleSchemaConstants.DISPLAY, audienceDisplay)); + SimpleAttribute audienceTypeAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_TYPE, + new SimpleAttribute(SCIMConstants.RoleSchemaConstants.TYPE, audienceType)); + + getAudience().setSubAttribute(audienceValueAttribute); + getAudience().setSubAttribute(audienceDisplayAttribute); + getAudience().setSubAttribute(audienceTypeAttribute); + } + } + + protected boolean isAudienceAttributeExist() { + + return attributeList.containsKey(SCIMConstants.RoleSchemaConstants.AUDIENCE); + } + + // TODO: having this kind of custom property in meta is a spec violation. Check whether we need to fix. + + /** + * Set the systemRole attribute of the meta attribute. + * + * @param isSystemRole Whether this is a read only system role. + * @throws CharonException CharonException. + * @throws BadRequestException BadRequestException. + */ + public void setSystemRole(boolean isSystemRole) throws CharonException, BadRequestException { + + // Create the systemRole attribute as defined in schema. + SimpleAttribute systemRoleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SYSTEM_ROLE, + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.SYSTEM_ROLE, isSystemRole)); + + // Check whether the meta complex attribute already exist. + if (getMetaAttribute() != null) { + ComplexAttribute metaAttribute = getMetaAttribute(); + // Check whether the systemRole attribute already exist. + if (metaAttribute.isSubAttributeExist(systemRoleAttribute.getName())) { + String error = "Tried to modify a read only attribute."; + throw new CharonException(error); + } else { + metaAttribute.setSubAttribute(systemRoleAttribute); + } + } else { + // Create the meta attribute and set the sub attribute. + createMetaAttribute(); + getMetaAttribute().setSubAttribute(systemRoleAttribute); + } + } +} diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/plainobjects/RolesV2GetResponse.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/plainobjects/RolesV2GetResponse.java new file mode 100644 index 000000000..013a900b3 --- /dev/null +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/plainobjects/RolesV2GetResponse.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://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 + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.charon3.core.objects.plainobjects; + +import org.wso2.charon3.core.objects.RoleV2; + +import java.util.List; + +/** + * This class representation can be used to create a RolesV2GetResponse type object which carries the total number of + * roles identified from the filter and the list of roles returned for this request. + */ +public class RolesV2GetResponse { + + private int totalRoles; + private List roles; + + /** + * Constructor used to build a response object. + */ + public RolesV2GetResponse(int totalRoles, List roles) { + + this.totalRoles = totalRoles; + this.roles = roles; + } + + /** + * Get total number of roles. + * + * @return Total number of roles. + */ + public int getTotalRoles() { + + return totalRoles; + } + + /** + * Set total number of roles. + * + * @param totalRoles Total number of roles. + */ + public void setTotalRoles(int totalRoles) { + + this.totalRoles = totalRoles; + } + + /** + * Get list of roles. + * + * @return List of roles. + */ + public List getRoles() { + + return roles; + } + + /** + * Set list of roles. + * + * @param filteredRoles List of roles. + */ + public void setRoles (List filteredRoles) { + + this.roles = filteredRoles; + } +} diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java index 507510641..2f0c549e5 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java @@ -16,6 +16,7 @@ package org.wso2.charon3.core.protocol.endpoints; import org.wso2.charon3.core.extensions.RoleManager; +import org.wso2.charon3.core.extensions.RoleV2Manager; import org.wso2.charon3.core.extensions.UserManager; import org.wso2.charon3.core.protocol.ResponseCodeConstants; import org.wso2.charon3.core.protocol.SCIMResponse; @@ -245,4 +246,106 @@ default SCIMResponse updateWithPATCHRole(String id, String patchRequest, RoleMan return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, Collections.emptyMap()); } + + // RoleV2 resource management operations. + + /** + * GET method to retrieve a specific role in roleV2 model. + * + * @param id Resource id. + * @param roleManager RoleV2 manager. + * @param attributes Attributes in the response. + * @param excludeAttributes Exclude attributes in the response. + * @return SCIMResponse. + */ + default SCIMResponse getRole(String id, RoleV2Manager roleManager, String attributes, String excludeAttributes) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + /** + * POST method to create a new role in roleV2 model. + * + * @param postRequest Post request. + * @param roleManager RoleV2 manager. + * @return SCIMResponse. + */ + default SCIMResponse createRole(String postRequest, RoleV2Manager roleManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + /** + * DELETE method to delete a specific role in roleV2 model. + * + * @param id Resource id. + * @param roleManager RoleV2 manager. + * @return SCIMResponse. + */ + default SCIMResponse deleteRole(String id, RoleV2Manager roleManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + /** + * GET method to list roles in roleV2 model. + * + * @param roleManager RoleV2 manager. + * @param filter Filter to be executed. + * @param startIndex Starting index value of the filter. + * @param count Number of required results. + * @param sortBy SortBy. + * @param sortOrder Sorting order. + * @return SCIMResponse. + */ + default SCIMResponse listWithGETRole(RoleV2Manager roleManager, String filter, Integer startIndex, Integer count, + String sortBy, String sortOrder) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + /** + * POST method to search roles in roleV2 model. + * + * @param searchRequest Search request. + * @param roleManager RoleV2 manager. + * @return SCIMResponse. + */ + default SCIMResponse listWithPOSTRole(String searchRequest, RoleV2Manager roleManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + /** + * PUT method To update a role by giving entire attributes set. + * + * @param id Resource id. + * @param putRequest Put request. + * @param roleManager RoleV2 manager. + * @return SCIMResponse. + */ + default SCIMResponse updateWithPUTRole(String id, String putRequest, RoleV2Manager roleManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + /** + * PATCH method to partially updates a role. + * + * @param id Resource id. + * @param patchRequest Patch request. + * @param roleManager RoleV2 manager. + * @return SCIMResponse. + */ + default SCIMResponse updateWithPATCHRole(String id, String patchRequest, RoleV2Manager roleManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java new file mode 100644 index 000000000..006973444 --- /dev/null +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://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 + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.charon3.core.protocol.endpoints; + +// TODO check the comment. possible to move this out from charon, since it's an extended resource + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.wso2.charon3.core.encoder.JSONDecoder; +import org.wso2.charon3.core.encoder.JSONEncoder; +import org.wso2.charon3.core.exceptions.BadRequestException; +import org.wso2.charon3.core.exceptions.CharonException; +import org.wso2.charon3.core.exceptions.ConflictException; +import org.wso2.charon3.core.exceptions.InternalErrorException; +import org.wso2.charon3.core.exceptions.NotFoundException; +import org.wso2.charon3.core.exceptions.NotImplementedException; +import org.wso2.charon3.core.extensions.RoleV2Manager; +import org.wso2.charon3.core.extensions.UserManager; +import org.wso2.charon3.core.objects.Role; +import org.wso2.charon3.core.objects.RoleV2; +import org.wso2.charon3.core.protocol.ResponseCodeConstants; +import org.wso2.charon3.core.protocol.SCIMResponse; +import org.wso2.charon3.core.schema.SCIMConstants; +import org.wso2.charon3.core.schema.SCIMResourceSchemaManager; +import org.wso2.charon3.core.schema.SCIMResourceTypeSchema; +import org.wso2.charon3.core.schema.SCIMSchemaDefinitions; +import org.wso2.charon3.core.schema.ServerSideValidator; +import org.wso2.charon3.core.utils.CopyUtil; +import org.wso2.charon3.core.utils.ResourceManagerUtil; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * REST API exposed by Charon-Core to perform operations on RoleResourceV2. + */ +public class RoleResourceV2Manager extends AbstractResourceManager { + + private static final Logger LOG = LoggerFactory.getLogger(RoleResourceV2Manager.class); + + @Override + public SCIMResponse getRole(String id, RoleV2Manager roleManager, String attributes, String excludeAttributes) { + + try { + if (roleManager == null) { + String error = "Provided role manager is null."; + throw new InternalErrorException(error); + } + JSONEncoder encoder = getEncoder(); + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceV2Schema(); + Map requiredAttributes = ResourceManagerUtil + .getOnlyRequiredAttributesURIs((SCIMResourceTypeSchema) CopyUtil.deepCopy(schema), attributes, + excludeAttributes); + + RoleV2 role = roleManager.getRole(id, requiredAttributes); + if (role == null) { + String message = "Role id: " + id + " not found in the system."; + throw new NotFoundException(message); + } + ServerSideValidator.validateRetrievedSCIMObject(role, schema, attributes, excludeAttributes); + // TODO +// ServerSideValidator.validateRetrievedSCIMRoleObject(role, attributes, excludeAttributes); + String encodedRole = encoder.encodeSCIMObject(role); + Map httpHeaders = new HashMap<>(); + httpHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); + return new SCIMResponse(ResponseCodeConstants.CODE_OK, encodedRole, httpHeaders); + } catch (NotFoundException | BadRequestException | CharonException | NotImplementedException | + InternalErrorException e) { + return encodeSCIMException(e); + } + } + + @Override + public SCIMResponse createRole(String postRequest, RoleV2Manager roleManager) { + + try { + if (roleManager == null) { + String error = "Provided role manager is null."; + throw new InternalErrorException(error); + } + JSONEncoder encoder = getEncoder(); + JSONDecoder decoder = getDecoder(); + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceV2Schema(); + + RoleV2 role = decoder.decodeResource(postRequest, schema, new RoleV2()); + ServerSideValidator.validateCreatedSCIMObject(role, SCIMSchemaDefinitions.SCIM_ROLE_V2_SCHEMA); + + RoleV2 createdRole = roleManager.createRole(role); + String encodedRole; + Map httpHeaders = new HashMap<>(); + if (createdRole != null) { + encodedRole = encoder.encodeSCIMObject(createdRole); + httpHeaders.put(SCIMConstants.LOCATION_HEADER, + getResourceEndpointURL(SCIMConstants.ROLE_ENDPOINT) + "/" + createdRole.getId()); + httpHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); + } else { + String message = "Newly created Role resource is null."; + throw new InternalErrorException(message); + } + return new SCIMResponse(ResponseCodeConstants.CODE_CREATED, encodedRole, httpHeaders); + + } catch (InternalErrorException | BadRequestException | ConflictException | CharonException | NotFoundException + | NotImplementedException e) { + return encodeSCIMException(e); + } + } + + @Override + public SCIMResponse deleteRole(String id, RoleV2Manager roleManager) { + + return null; + } + + @Override + public SCIMResponse listWithGETRole(RoleV2Manager roleManager, String filter, Integer startIndexInt, Integer countInt, + String sortBy, String sortOrder) { + + return null; + } + + @Override + public SCIMResponse listWithPOSTRole(String searchRequest, RoleV2Manager roleManager) { + + return null; + } + + @Override + public SCIMResponse updateWithPUTRole(String id, String putRequest, RoleV2Manager roleManager) { + + return null; + } + + @Override + public SCIMResponse updateWithPATCHRole(String id, String patchRequest, RoleV2Manager roleManager) { + + return null; + } + + @Override + public SCIMResponse get(String id, UserManager userManager, String attributes, String excludeAttributes) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + @Override + public SCIMResponse create(String scimObjectString, UserManager userManager, String attributes, + String excludeAttributes) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + @Override + public SCIMResponse delete(String id, UserManager userManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + @Override + public SCIMResponse listWithGET(UserManager userManager, String filter, int startIndex, int count, String sortBy, + String sortOrder, String domainName, String attributes, String excludeAttributes) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + @Override + public SCIMResponse listWithPOST(String resourceString, UserManager userManager) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + @Override + public SCIMResponse updateWithPUT(String existingId, String scimObjectString, UserManager userManager, + String attributes, String excludeAttributes) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + + @Override + public SCIMResponse updateWithPATCH(String existingId, String scimObjectString, UserManager userManager, + String attributes, String excludeAttributes) { + + return new SCIMResponse(ResponseCodeConstants.CODE_NOT_IMPLEMENTED, ResponseCodeConstants.DESC_NOT_IMPLEMENTED, + Collections.emptyMap()); + } + +} diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index 78c225eb7..9545360eb 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -524,7 +524,13 @@ public static class RoleSchemaConstants { public static final String GROUPS_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:groups"; public static final String PERMISSIONS = "permissions"; public static final String PERMISSIONS_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:permissions"; + public static final String ASC_APPLICATIONS = "associatedApplications"; + public static final String ASC_APPLICATIONS_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:associatedApplications"; + public static final String AUDIENCE = "audience"; + public static final String AUDIENCE_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:audience"; public static final String DISPLAY = "display"; + public static final String VALUE = "value"; public static final String TYPE = "type"; // Attributes descriptions of the attributes found in Role Schema. @@ -532,16 +538,26 @@ public static class RoleSchemaConstants { public static final String USERS_DESC = "A list of users of the role."; public static final String GROUPS_DESC = "A list of groups of the role."; public static final String PERMISSIONS_DESC = "A list of permissions of the role."; + public static final String ASC_APPLICATIONS_DESC = "A list of associated applications of the role."; + public static final String AUDIENCE_DESC = "The role usable scope."; public static final String USERS_VALUE_DESC = "Identifier of the user of this role."; public static final String GROUPS_VALUE_DESC = "Identifier of the group of this role."; - public static final String PERMISSIONS_VALUE_DESC = "List of the permissions of this role."; + public static final String PERMISSIONS_VALUE_DESC = "Identifier of the permissions of this role."; + public static final String ASC_APPLICATIONS_VALUE_DESC = + "Identifier of the associated applications of this role."; + public static final String AUDIENCE_VALUE_DESC = "Identifier of the role's usable audience."; public static final String USERS_REF_DESC = "The uri corresponding to a SCIM resource that is a user of this Role."; public static final String GROUPS_REF_DESC = "The uri corresponding to a SCIM resource that is a group of this Role."; public static final String USERS_DISPLAY_DESC = "A human-readable name for the user."; public static final String GROUPS_DISPLAY_DESC = "A human-readable name for the group."; + public static final String PERMISSIONS_DISPLAY_DESC = "A human-readable name for the permission."; + public static final String ASC_APPLICATIONS_DISPLAY_DESC = "A human-readable name for the application."; + public static final String AUDIENCE_DISPLAY_DESC = "A human-readable name of the role's usable audience."; public static final String TYPE_DESC = "A label indicating the type of resource, e.g. 'User' or 'Group'"; + public static final String AUDIENCE_TYPE_DESC = + "A label indicating the resource type of the role's usable audience."; // URIs of sub and multivalued attributes. public static final String USERS_VALUE_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:users.value"; @@ -554,6 +570,19 @@ public static class RoleSchemaConstants { public static final String GROUPS_DISPLAY_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:groups" + ".display"; public static final String GROUPS_TYPE_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:groups.type"; + public static final String PERMISSIONS_VALUE_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:permissions.value"; + public static final String PERMISSIONS_DISPLAY_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:permissions.display"; + public static final String ASC_APPLICATION_VALUE_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:associatedApplications.value"; + public static final String ASC_APPLICATION_DISPLAY_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:associatedApplications.display"; + public static final String AUDIENCE_VALUE_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:audience.value"; + public static final String AUDIENCE_DISPLAY_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:audience.display"; + public static final String AUDIENCE_TYPE_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:audience.type"; } /** diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java index 3ed8249a7..9dfd9128c 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java @@ -215,6 +215,10 @@ public SCIMResourceTypeSchema getRoleResourceSchema() { return SCIMSchemaDefinitions.SCIM_ROLE_SCHEMA; } + public SCIMResourceTypeSchema getRoleResourceV2Schema() { + + return SCIMSchemaDefinitions.SCIM_ROLE_V2_SCHEMA; + } public SCIMResourceTypeSchema getResourceTypeResourceSchema() { return SCIMSchemaDefinitions.SCIM_RESOURCE_TYPE_SCHEMA; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java index b6609655f..45c244910 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java @@ -1042,6 +1042,64 @@ public static class SCIMRoleSchemaDefinition { SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, null); + // Identifier of the permission of this Role. + public static final SCIMAttributeSchema PERMISSION_VALUE = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.PERMISSIONS_VALUE_URI, + SCIMConstants.RoleSchemaConstants.VALUE, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.PERMISSIONS_VALUE_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // A human-readable name of the permission of this Role. + public static final SCIMAttributeSchema PERMISSION_DISPLAY = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.PERMISSIONS_DISPLAY_URI, + SCIMConstants.RoleSchemaConstants.DISPLAY, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.PERMISSIONS_DISPLAY_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // Identifier of the associated application of this Role. + public static final SCIMAttributeSchema ASC_APPLICATION_VALUE = + SCIMAttributeSchema.createSCIMAttributeSchema( + SCIMConstants.RoleSchemaConstants.ASC_APPLICATION_VALUE_URI, + SCIMConstants.RoleSchemaConstants.VALUE, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_VALUE_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // A human-readable name of the associated application of this Role. + public static final SCIMAttributeSchema ASC_APPLICATION_DISPLAY = + SCIMAttributeSchema.createSCIMAttributeSchema( + SCIMConstants.RoleSchemaConstants.ASC_APPLICATION_DISPLAY_URI, + SCIMConstants.RoleSchemaConstants.DISPLAY, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_DISPLAY_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // Identifier of the role's audience. + public static final SCIMAttributeSchema AUDIENCE_VALUE = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.AUDIENCE_VALUE_URI, + SCIMConstants.RoleSchemaConstants.VALUE, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.AUDIENCE_VALUE_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // A human-readable name of role's audience. + public static final SCIMAttributeSchema AUDIENCE_DISPLAY = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.AUDIENCE_DISPLAY_URI, + SCIMConstants.RoleSchemaConstants.DISPLAY, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.AUDIENCE_DISPLAY_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // Type of the role's audience (eg: application, organization). + public static final SCIMAttributeSchema AUDIENCE_TYPE = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.AUDIENCE_TYPE_URI, + SCIMConstants.RoleSchemaConstants.TYPE, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.RoleSchemaConstants.AUDIENCE_TYPE_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, null); + // Attribute schemas of the attributes defined in role schema. // A human-readable name for the Role. REQUIRED. @@ -1053,6 +1111,15 @@ public static class SCIMRoleSchemaDefinition { SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, null); + // The audience of the role. + public static final SCIMAttributeSchema AUDIENCE = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.AUDIENCE_URI, + SCIMConstants.RoleSchemaConstants.AUDIENCE, SCIMDefinitions.DataType.COMPLEX, false, + SCIMConstants.RoleSchemaConstants.AUDIENCE_DESC, true, false, + SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, + new ArrayList<>(Arrays.asList(AUDIENCE_VALUE, AUDIENCE_DISPLAY, AUDIENCE_TYPE))); + // A list of users of the Role. public static final SCIMAttributeSchema USERS = SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.USERS_URI, @@ -1081,6 +1148,24 @@ public static class SCIMRoleSchemaDefinition { false, false, SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, null); + + // A list of permissions of the Role. + public static final SCIMAttributeSchema ROLE_V2_PERMISSIONS = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.PERMISSIONS_URI, + SCIMConstants.RoleSchemaConstants.PERMISSIONS, SCIMDefinitions.DataType.COMPLEX, true, + SCIMConstants.RoleSchemaConstants.PERMISSIONS_DESC, false, false, + SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, + new ArrayList<>(Arrays.asList(PERMISSION_VALUE, PERMISSION_DISPLAY))); + + // A list of associated applications of the Role. + public static final SCIMAttributeSchema ASSOCIATED_APPLICATIONS = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_URI, + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS, SCIMDefinitions.DataType.COMPLEX, true, + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_DESC, false, false, + SCIMDefinitions.Mutability.READ_ONLY, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, null, + new ArrayList<>(Arrays.asList(ASC_APPLICATION_VALUE, ASC_APPLICATION_DISPLAY))); } /** @@ -1476,6 +1561,20 @@ public static class SCIMResourceTypeSchemaDefinition { SCIMRoleSchemaDefinition.GROUPS, SCIMRoleSchemaDefinition.PERMISSIONS); + /** + * RoleV2 Resource Schema. + */ + public static final SCIMResourceTypeSchema SCIM_ROLE_V2_SCHEMA = + SCIMResourceTypeSchema.createSCIMResourceSchema( + new ArrayList<>(Collections.singletonList(SCIMConstants.ROLE_SCHEMA_URI)), + ID, + SCIMRoleSchemaDefinition.DISPLAY_NAME, + SCIMRoleSchemaDefinition.AUDIENCE, + SCIMRoleSchemaDefinition.USERS, + SCIMRoleSchemaDefinition.GROUPS, + SCIMRoleSchemaDefinition.ROLE_V2_PERMISSIONS, + SCIMRoleSchemaDefinition.ASSOCIATED_APPLICATIONS); + /* * **********SCIM defined Service Provider Config Resource Schema.**************************** */ From f7798882700734e8576390e7d906cbf330175d15 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Tue, 3 Oct 2023 12:56:06 +0530 Subject: [PATCH 02/11] fix check style and find bug issues --- .../src/main/java/org/wso2/charon3/core/objects/RoleV2.java | 2 +- .../core/protocol/endpoints/RoleResourceV2Manager.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java index 7b9ce637d..9df770333 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -45,7 +45,7 @@ */ public class RoleV2 extends AbstractSCIMObject { - private static final long SERIAL_VERSION_UID = 6106269076155338045L; + private static final long serialVersionUID = 6106269076155338045L; /** * Get the display name of the role. diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java index 006973444..5d35b3f9d 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java @@ -32,7 +32,6 @@ import org.wso2.charon3.core.exceptions.NotImplementedException; import org.wso2.charon3.core.extensions.RoleV2Manager; import org.wso2.charon3.core.extensions.UserManager; -import org.wso2.charon3.core.objects.Role; import org.wso2.charon3.core.objects.RoleV2; import org.wso2.charon3.core.protocol.ResponseCodeConstants; import org.wso2.charon3.core.protocol.SCIMResponse; @@ -129,8 +128,8 @@ public SCIMResponse deleteRole(String id, RoleV2Manager roleManager) { } @Override - public SCIMResponse listWithGETRole(RoleV2Manager roleManager, String filter, Integer startIndexInt, Integer countInt, - String sortBy, String sortOrder) { + public SCIMResponse listWithGETRole(RoleV2Manager roleManager, String filter, Integer startIndexInt, + Integer countInt, String sortBy, String sortOrder) { return null; } From ce0f24eae6c841faf2683308d81f5465d27ee783 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 7 Oct 2023 14:49:36 +0530 Subject: [PATCH 03/11] improve delete, list, update and change the schema --- .../endpoints/RoleResourceV2Manager.java | 596 +++++++++++++++++- .../charon3/core/schema/SCIMConstants.java | 5 + .../core/schema/SCIMSchemaDefinitions.java | 6 +- 3 files changed, 599 insertions(+), 8 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java index 5d35b3f9d..306856dc2 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java @@ -20,19 +20,32 @@ // TODO check the comment. possible to move this out from charon, since it's an extended resource +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.wso2.charon3.core.attributes.Attribute; +import org.wso2.charon3.core.attributes.ComplexAttribute; +import org.wso2.charon3.core.attributes.MultiValuedAttribute; +import org.wso2.charon3.core.attributes.SimpleAttribute; import org.wso2.charon3.core.encoder.JSONDecoder; import org.wso2.charon3.core.encoder.JSONEncoder; import org.wso2.charon3.core.exceptions.BadRequestException; import org.wso2.charon3.core.exceptions.CharonException; import org.wso2.charon3.core.exceptions.ConflictException; +import org.wso2.charon3.core.exceptions.ForbiddenException; import org.wso2.charon3.core.exceptions.InternalErrorException; import org.wso2.charon3.core.exceptions.NotFoundException; import org.wso2.charon3.core.exceptions.NotImplementedException; import org.wso2.charon3.core.extensions.RoleV2Manager; import org.wso2.charon3.core.extensions.UserManager; +import org.wso2.charon3.core.objects.AbstractSCIMObject; +import org.wso2.charon3.core.objects.ListedResource; import org.wso2.charon3.core.objects.RoleV2; +import org.wso2.charon3.core.objects.plainobjects.RolesV2GetResponse; import org.wso2.charon3.core.protocol.ResponseCodeConstants; import org.wso2.charon3.core.protocol.SCIMResponse; import org.wso2.charon3.core.schema.SCIMConstants; @@ -41,10 +54,18 @@ import org.wso2.charon3.core.schema.SCIMSchemaDefinitions; import org.wso2.charon3.core.schema.ServerSideValidator; import org.wso2.charon3.core.utils.CopyUtil; +import org.wso2.charon3.core.utils.PatchOperationUtil; import org.wso2.charon3.core.utils.ResourceManagerUtil; +import org.wso2.charon3.core.utils.codeutils.FilterTreeManager; +import org.wso2.charon3.core.utils.codeutils.Node; +import org.wso2.charon3.core.utils.codeutils.PatchOperation; +import org.wso2.charon3.core.utils.codeutils.SearchRequest; +import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -107,7 +128,7 @@ public SCIMResponse createRole(String postRequest, RoleV2Manager roleManager) { if (createdRole != null) { encodedRole = encoder.encodeSCIMObject(createdRole); httpHeaders.put(SCIMConstants.LOCATION_HEADER, - getResourceEndpointURL(SCIMConstants.ROLE_ENDPOINT) + "/" + createdRole.getId()); + getResourceEndpointURL(SCIMConstants.ROLE_V2_ENDPOINT) + "/" + createdRole.getId()); httpHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); } else { String message = "Newly created Role resource is null."; @@ -124,32 +145,170 @@ public SCIMResponse createRole(String postRequest, RoleV2Manager roleManager) { @Override public SCIMResponse deleteRole(String id, RoleV2Manager roleManager) { - return null; + try { + if (roleManager == null) { + String error = "Provided role manager is null."; + throw new InternalErrorException(error); + } + roleManager.deleteRole(id); + return new SCIMResponse(ResponseCodeConstants.CODE_NO_CONTENT, null, null); + } catch (InternalErrorException | CharonException | NotFoundException | NotImplementedException + | BadRequestException e) { + return encodeSCIMException(e); + } } @Override public SCIMResponse listWithGETRole(RoleV2Manager roleManager, String filter, Integer startIndexInt, Integer countInt, String sortBy, String sortOrder) { - return null; + try { + if (roleManager == null) { + String error = "Provided role manager is null."; + throw new InternalErrorException(error); + } + Integer count = ResourceManagerUtil.processCount(countInt); + Integer startIndex = ResourceManagerUtil.processStartIndex(startIndexInt); + sortOrder = resolveSortOrder(sortOrder, sortBy); + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceV2Schema(); + // Build node for filtering. + Node rootNode = buildNode(filter, schema); + JSONEncoder encoder = getEncoder(); + + RolesV2GetResponse rolesResponse = roleManager.listRolesWithGET(rootNode, startIndex, count, sortBy, + sortOrder); + return processRoleList(rolesResponse, encoder, startIndex); + } catch (CharonException | InternalErrorException | BadRequestException | NotImplementedException e) { + return encodeSCIMException(e); + } catch (IOException e) { + String error = "Error in tokenization of the input filter."; + CharonException charonException = new CharonException(error); + return AbstractResourceManager.encodeSCIMException(charonException); + } } @Override public SCIMResponse listWithPOSTRole(String searchRequest, RoleV2Manager roleManager) { - return null; + try { + if (roleManager == null) { + String error = "Provided role manager is null."; + throw new InternalErrorException(error); + } + JSONEncoder encoder = getEncoder(); + JSONDecoder decoder = getDecoder(); + + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceV2Schema(); + + // Create the search request object. + SearchRequest searchRequestObject = decoder.decodeSearchRequestBody(searchRequest, schema); + searchRequestObject.setCount(ResourceManagerUtil.processCount(searchRequestObject.getCountStr())); + searchRequestObject + .setStartIndex(ResourceManagerUtil.processStartIndex(searchRequestObject.getStartIndexStr())); + + if (searchRequestObject.getSchema() != null && !searchRequestObject.getSchema() + .equals(SCIMConstants.SEARCH_SCHEMA_URI)) { + throw new BadRequestException("Provided schema is invalid.", ResponseCodeConstants.INVALID_VALUE); + } + + // Check whether provided sortOrder is valid or not. + if (searchRequestObject.getSortOder() != null) { + if (!(searchRequestObject.getSortOder().equalsIgnoreCase(SCIMConstants.OperationalConstants.ASCENDING) + || searchRequestObject.getSortOder() + .equalsIgnoreCase(SCIMConstants.OperationalConstants.DESCENDING))) { + String error = " Invalid sortOrder value is specified"; + throw new BadRequestException(error, ResponseCodeConstants.INVALID_VALUE); + } + } + //If a value for "sortBy" is provided and no "sortOrder" is specified, "sortOrder" SHALL default to + // ascending. + if (searchRequestObject.getSortOder() == null && searchRequestObject.getSortBy() != null) { + searchRequestObject.setSortOder(SCIMConstants.OperationalConstants.ASCENDING); + } + + RolesV2GetResponse rolesResponse = roleManager.listRolesWithPost(searchRequestObject); + + for (RoleV2 role : rolesResponse.getRoles()) { + ServerSideValidator.validateRetrievedSCIMObjectInList(role, schema, + searchRequestObject.getAttributesAsString(), + searchRequestObject.getExcludedAttributesAsString()); + } + // Create a listed resource object out of the returned users list. + ListedResource listedResource = createListedResource(rolesResponse, searchRequestObject.getStartIndex()); + String encodedListedResource = encoder.encodeSCIMObject(listedResource); + Map responseHeaders = new HashMap<>(); + responseHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); + return new SCIMResponse(ResponseCodeConstants.CODE_OK, encodedListedResource, responseHeaders); + } catch (CharonException | InternalErrorException | BadRequestException | NotImplementedException e) { + return AbstractResourceManager.encodeSCIMException(e); + } } @Override public SCIMResponse updateWithPUTRole(String id, String putRequest, RoleV2Manager roleManager) { - return null; + try { + if (roleManager == null) { + String error = "Provided role manager is null."; + throw new InternalErrorException(error); + } + JSONEncoder encoder = getEncoder(); + JSONDecoder decoder = getDecoder(); + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceV2Schema(); + Map requestAttributes = ResourceManagerUtil.getAllAttributeURIs(schema); + RoleV2 role = decoder.decodeResource(putRequest, schema, new RoleV2()); + RoleV2 updatedRole; + + // Retrieve the old object. + RoleV2 oldRole = roleManager.getRole(id, requestAttributes); + if (oldRole != null) { + RoleV2 newRole = (RoleV2) ServerSideValidator.validateUpdatedSCIMObject(oldRole, role, schema); + updatedRole = roleManager.updateRole(oldRole, newRole); + } else { + String error = "No role exists with the given id: " + id; + throw new NotFoundException(error); + } + return getScimResponse(encoder, updatedRole); + } catch (NotFoundException | BadRequestException | CharonException | ConflictException | InternalErrorException + | NotImplementedException e) { + return encodeSCIMException(e); + } } @Override public SCIMResponse updateWithPATCHRole(String id, String patchRequest, RoleV2Manager roleManager) { - return null; + try { + if (roleManager == null) { + String error = "Provided role manager handler is null."; + throw new InternalErrorException(error); + } + JSONEncoder encoder = getEncoder(); + SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getRoleResourceV2Schema(); + Map requestAttributes = ResourceManagerUtil.getAllAttributeURIs(schema); + + List opList = getDecoder().decodeRequest(patchRequest); + + if (!isUpdateAllUsersOperationFound(opList)) { + return updateWithPatchOperations(id, opList, roleManager, schema, encoder); + } + + RoleV2 oldRole = roleManager.getRole(id, requestAttributes); + if (oldRole == null) { + throw new NotFoundException("No role with the id : " + id + " exists in the system."); + } + // Make a copy of original role. This will be used to restore to the original condition if failure occurs. + RoleV2 originalRole = (RoleV2) CopyUtil.deepCopy(oldRole); + RoleV2 patchedRole = doPatchRole(oldRole, schema, patchRequest); + RoleV2 updatedRole = roleManager.updateRole(originalRole, patchedRole); + return getScimResponse(encoder, updatedRole); + } catch (NotFoundException | BadRequestException | NotImplementedException | CharonException | ConflictException + | InternalErrorException e) { + return AbstractResourceManager.encodeSCIMException(e); + } catch (RuntimeException e) { + CharonException ex = new CharonException("Error in performing the patch operation on role resource.", e); + return AbstractResourceManager.encodeSCIMException(ex); + } } @Override @@ -205,4 +364,429 @@ public SCIMResponse updateWithPATCH(String existingId, String scimObjectString, Collections.emptyMap()); } + /** + * Resolves the sorting order of the filter. + * + * @param sortOrder Sort order in the request. + * @param sortBy SortBy in the request. + * @return Resolved sorting order. + * @throws BadRequestException BadRequestException. + */ + private String resolveSortOrder(String sortOrder, String sortBy) throws BadRequestException { + + // Check whether the provided sortOrder is valid or not. + if (sortOrder != null) { + if (!(SCIMConstants.OperationalConstants.ASCENDING.equalsIgnoreCase(sortOrder) + || SCIMConstants.OperationalConstants.DESCENDING.equalsIgnoreCase(sortOrder))) { + String error = "Invalid sortOrder value is specified."; + throw new BadRequestException(error, ResponseCodeConstants.INVALID_VALUE); + } + } else { + // If a value for "sortBy" is provided and no "sortOrder" is specified, "sortOrder" SHALL default to + // ascending. + if (sortBy != null) { + sortOrder = SCIMConstants.OperationalConstants.ASCENDING; + } + } + return sortOrder; + } + + /** + * Build Node for filtering. + * + * @param filter Filter in the request. + * @param schema Schema. + * @return Node. + * @throws BadRequestException BadRequestException. + * @throws IOException IOException. + */ + private Node buildNode(String filter, SCIMResourceTypeSchema schema) throws BadRequestException, IOException { + + if (filter != null) { + FilterTreeManager filterTreeManager = new FilterTreeManager(filter, schema); + return filterTreeManager.buildTree(); + } + return null; + } + + /** + * Method to process a list and return a SCIM response. + * + * @param rolesResponse Response made of the filtered role list and total number of users. + * @param encoder Json encoder. + * @param startIndex Starting index. + * @return SCIM response. + * @throws CharonException CharonException. + * @throws BadRequestException BadRequestException. + */ + private SCIMResponse processRoleList(RolesV2GetResponse rolesResponse, JSONEncoder encoder, int startIndex) + throws CharonException, BadRequestException { + + if (rolesResponse == null) { + rolesResponse = new RolesV2GetResponse(0, Collections.emptyList()); + } + if (rolesResponse.getRoles() == null) { + rolesResponse.setRoles(Collections.emptyList()); + } + for (RoleV2 role : rolesResponse.getRoles()) { + ServerSideValidator.validateSCIMObjectForRequiredAttributes(role, + SCIMSchemaDefinitions.SCIM_ROLE_V2_SCHEMA); + } + // Create a listed resource object out of the returned groups list. + ListedResource listedResource = createListedResource(rolesResponse, startIndex); + // Convert the listed resource into specific format. + String encodedListedResource = encoder.encodeSCIMObject(listedResource); + + Map responseHeaders = new HashMap<>(); + responseHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); + return new SCIMResponse(ResponseCodeConstants.CODE_OK, encodedListedResource, responseHeaders); + } + + protected ListedResource createListedResource(RolesV2GetResponse rolesResponse, int startIndex) { + + ListedResource listedResource = new ListedResource(); + listedResource.setSchema(SCIMConstants.LISTED_RESOURCE_CORE_SCHEMA_URI); + listedResource.setTotalResults(rolesResponse.getTotalRoles()); + listedResource.setStartIndex(startIndex); + listedResource.setItemsPerPage(rolesResponse.getRoles().size()); + for (RoleV2 role : rolesResponse.getRoles()) { + Map userAttributes = role.getAttributeList(); + listedResource.setResources(userAttributes); + } + return listedResource; + } + + private SCIMResponse getScimResponse(JSONEncoder encoder, RoleV2 updatedRole) + throws CharonException, NotFoundException, InternalErrorException { + + String encodedRole; + Map httpHeaders = new HashMap<>(); + if (updatedRole != null) { + // Create a deep copy of the user object since we are going to change it. + RoleV2 copiedRole = (RoleV2) CopyUtil.deepCopy(updatedRole); + encodedRole = encoder.encodeSCIMObject(copiedRole); + // Add location header + httpHeaders.put(SCIMConstants.LOCATION_HEADER, + getResourceEndpointURL(SCIMConstants.ROLE_V2_ENDPOINT) + "/" + updatedRole.getId()); + httpHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); + } else { + String error = "Updated Role resource is null."; + throw new InternalErrorException(error); + } + return new SCIMResponse(ResponseCodeConstants.CODE_OK, encodedRole, httpHeaders); + } + + /** + * Check whether it is required to update all users with the patch operation. + * + * @param patchOperations Patch operation. + * @return Whether it is required to update all users or not with the patch operation. + * @throws JSONException JSONException + */ + private boolean isUpdateAllUsersOperationFound(List patchOperations) throws JSONException { + + for (PatchOperation patchOperation : patchOperations) { + String operation = patchOperation.getOperation(); + String path = patchOperation.getPath(); + JSONObject valuesJson = null; + if (StringUtils.isBlank(path)) { + valuesJson = (JSONObject) patchOperation.getValues(); + } + if (SCIMConstants.OperationalConstants.REPLACE.equals(operation) && + (SCIMConstants.RoleSchemaConstants.USERS.equals(path) || + (valuesJson != null && valuesJson.has(SCIMConstants.RoleSchemaConstants.USERS)))) { + return true; + } else if (SCIMConstants.OperationalConstants.REMOVE.equals(operation) && + (SCIMConstants.RoleSchemaConstants.USERS).equals(path)) { + return true; + } + } + return false; + } + + /** + * Updates the role based on the operations defined in the patch request. The updated role information is sent + * back in the response. + * + * @param existingRoleId SCIM2 ID of the existing role. + * @param opList List of patch operations. + * @param roleManager Role Manager. + * @param schema SCIM resource schema. + * @return SCIM Response. + */ + private SCIMResponse updateWithPatchOperations(String existingRoleId, List opList, + RoleV2Manager roleManager, SCIMResourceTypeSchema schema, + JSONEncoder encoder) { + + try { + Map> patchOperations = new HashMap<>(); + patchOperations.put(SCIMConstants.OperationalConstants.ADD, new ArrayList<>()); + patchOperations.put(SCIMConstants.OperationalConstants.REMOVE, new ArrayList<>()); + patchOperations.put(SCIMConstants.OperationalConstants.REPLACE, new ArrayList<>()); + + for (PatchOperation patchOperation : opList) { + switch (patchOperation.getOperation()) { + case SCIMConstants.OperationalConstants.ADD: + patchOperations.get(SCIMConstants.OperationalConstants.ADD).add(patchOperation); + break; + case SCIMConstants.OperationalConstants.REMOVE: + patchOperations.get(SCIMConstants.OperationalConstants.REMOVE).add(patchOperation); + break; + case SCIMConstants.OperationalConstants.REPLACE: + patchOperations.get(SCIMConstants.OperationalConstants.REPLACE).add(patchOperation); + break; + default: + throw new BadRequestException("Unknown operation: " + patchOperation.getOperation(), + ResponseCodeConstants.INVALID_SYNTAX); + } + } + + // Process the Role patch operation and update the patch operation object with required values. + processRolePatchOperations(patchOperations, schema); + RoleV2 updatedRole = roleManager.patchRole(existingRoleId, patchOperations); + return getScimResponse(encoder, updatedRole); + } catch (NotFoundException | BadRequestException | NotImplementedException | ConflictException | + CharonException | InternalErrorException | ForbiddenException e) { + return AbstractResourceManager.encodeSCIMException(e); + } + } + + /** + * Process the Role patch operation and update the patch operation object with required values. + * + * @param patchOperations Patch operation. + * @param schema SCIM Resource Type Schema. + * @throws CharonException CharonException. + * @throws BadRequestException BadRequestException. + * @throws NotImplementedException NotImplementedException. + * @throws JSONException JSONException. + */ + private void processRolePatchOperations(Map> patchOperations, + SCIMResourceTypeSchema schema) + throws CharonException, BadRequestException, NotImplementedException, JSONException { + + for (PatchOperation patchOperation : patchOperations.get(SCIMConstants.OperationalConstants.REPLACE)) { + processPatchOperation(schema, patchOperation); + } + + for (PatchOperation patchOperation : patchOperations.get(SCIMConstants.OperationalConstants.ADD)) { + if (SCIMConstants.RoleSchemaConstants.PERMISSIONS.equalsIgnoreCase(patchOperation.getPath())) { + throw new NotImplementedException("Adding permissions not permitted."); + } + processPatchOperation(schema, patchOperation); + } + + for (PatchOperation patchOperation : patchOperations.get(SCIMConstants.OperationalConstants.REMOVE)) { + processRemovePatchOperation(patchOperation); + } + } + + private RoleV2 doPatchRole(RoleV2 oldRole, SCIMResourceTypeSchema roleSchema, String patchRequest) + throws CharonException, BadRequestException, NotImplementedException, InternalErrorException { + + // Make a copy of the original group. + RoleV2 originalRole = (RoleV2) CopyUtil.deepCopy(oldRole); + RoleV2 copyOfOldRole = (RoleV2) CopyUtil.deepCopy(oldRole); + + RoleV2 patchedRole = null; + List opList = getDecoder().decodeRequest(patchRequest); + for (PatchOperation operation : opList) { + switch (operation.getOperation()) { + case SCIMConstants.OperationalConstants.ADD: + if (patchedRole == null) { + patchedRole = (RoleV2) PatchOperationUtil + .doPatchAdd(operation, getDecoder(), oldRole, copyOfOldRole, roleSchema); + } else { + patchedRole = (RoleV2) PatchOperationUtil + .doPatchAdd(operation, getDecoder(), patchedRole, copyOfOldRole, roleSchema); + + } + copyOfOldRole = (RoleV2) CopyUtil.deepCopy(patchedRole); + break; + case SCIMConstants.OperationalConstants.REMOVE: + if (patchedRole == null) { + patchedRole = (RoleV2) PatchOperationUtil + .doPatchRemove(operation, oldRole, copyOfOldRole, roleSchema); + + } else { + patchedRole = (RoleV2) PatchOperationUtil + .doPatchRemove(operation, patchedRole, copyOfOldRole, roleSchema); + } + copyOfOldRole = (RoleV2) CopyUtil.deepCopy(patchedRole); + break; + case SCIMConstants.OperationalConstants.REPLACE: + if (patchedRole == null) { + patchedRole = (RoleV2) PatchOperationUtil + .doPatchReplace(operation, getDecoder(), oldRole, copyOfOldRole, roleSchema); + + } else { + patchedRole = (RoleV2) PatchOperationUtil + .doPatchReplace(operation, getDecoder(), patchedRole, copyOfOldRole, roleSchema); + } + copyOfOldRole = (RoleV2) CopyUtil.deepCopy(patchedRole); + break; + default: + throw new BadRequestException("Unknown operation.", ResponseCodeConstants.INVALID_SYNTAX); + } + } + return (RoleV2) ServerSideValidator.validateUpdatedSCIMObject(originalRole, patchedRole, roleSchema); + } + + private void processPatchOperation(SCIMResourceTypeSchema schema, PatchOperation patchOperation) + throws BadRequestException, CharonException { + + if (patchOperation.getValues() == null) { + throw new BadRequestException("The value is not provided to perform patch " + + patchOperation.getOperation() + " operation.", ResponseCodeConstants.INVALID_SYNTAX); + } + + if (patchOperation.getPath() != null) { + switch (patchOperation.getPath()) { + case SCIMConstants.RoleSchemaConstants.DISPLAY_NAME: { + String valuesProperty = (String) patchOperation.getValues(); + JSONObject attributePrefixedJson = new JSONObject(); + + attributePrefixedJson.put(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME, valuesProperty); + patchOperation.setValues(attributePrefixedJson); + break; + } + case SCIMConstants.RoleSchemaConstants.USERS: { + setPatchOperationValue(patchOperation, SCIMConstants.RoleSchemaConstants.USERS); + break; + } + case SCIMConstants.RoleSchemaConstants.GROUPS: { + setPatchOperationValue(patchOperation, SCIMConstants.RoleSchemaConstants.GROUPS); + break; + } + case SCIMConstants.RoleSchemaConstants.PERMISSIONS: { + setPatchOperationValue(patchOperation, SCIMConstants.RoleSchemaConstants.PERMISSIONS); + break; + } + default: + throw new BadRequestException("Not a valid attribute.", ResponseCodeConstants.INVALID_SYNTAX); + } + patchOperation.setPath(null); + } + processValueAttributeOfOperation(schema, patchOperation); + } + + private static void processRemovePatchOperation(PatchOperation patchOperation) + throws NotImplementedException, BadRequestException { + + if (SCIMConstants.RoleSchemaConstants.PERMISSIONS.equalsIgnoreCase(patchOperation.getPath())) { + throw new NotImplementedException("Removing permissions not permitted."); + } + + if (SCIMConstants.RoleSchemaConstants.DISPLAY_NAME.equalsIgnoreCase(patchOperation.getPath())) { + throw new BadRequestException("Can not remove a required attribute"); + } + + if (patchOperation.getPath() == null) { + throw new BadRequestException("No path value specified for remove operation", + ResponseCodeConstants.NO_TARGET); + } + + String path = patchOperation.getPath(); + // Split the path to extract the filter if present. + String[] parts = path.split("[\\[\\]]"); + + if (ArrayUtils.isEmpty(parts) || !(SCIMConstants.RoleSchemaConstants.USERS.equalsIgnoreCase(parts[0]) || + SCIMConstants.RoleSchemaConstants.GROUPS.equalsIgnoreCase(parts[0]))) { + throw new BadRequestException(parts[0] + " is not a valid attribute.", + ResponseCodeConstants.INVALID_SYNTAX); + } + + if (SCIMConstants.RoleSchemaConstants.USERS.equalsIgnoreCase(parts[0])) { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.USERS); + } else { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.GROUPS); + } + + if (parts.length != 1) { + Map patchObject = new HashMap<>(); + patchObject.put(SCIMConstants.RoleSchemaConstants.DISPLAY, null); + patchObject.put(SCIMConstants.CommonSchemaConstants.VALUE, null); + + // Currently we only support simple filters here. + String[] filterParts = parts[1].split(" "); + + if (filterParts.length != 3 || !patchObject.containsKey(filterParts[0])) { + throw new BadRequestException("Invalid filter", ResponseCodeConstants.INVALID_SYNTAX); + } + + if (!filterParts[1].equalsIgnoreCase((SCIMConstants.OperationalConstants.EQ).trim())) { + throw new NotImplementedException("Only Eq filter is supported"); + } + /* + According to the specification filter attribute value specified with quotation mark, so we need to + remove it if exists. + */ + filterParts[2] = filterParts[2].replaceAll("^\"|\"$", ""); + patchObject.put(filterParts[0], filterParts[2]); + patchOperation.setValues(patchObject); + } + } + + private static void setPatchOperationValue(PatchOperation patchOperation, String permissions) { + + JSONArray valuesPropertyJson = (JSONArray) patchOperation.getValues(); + JSONObject attributePrefixedJson = new JSONObject(); + attributePrefixedJson.put(permissions, valuesPropertyJson); + patchOperation.setValues(attributePrefixedJson); + } + + private void processValueAttributeOfOperation(SCIMResourceTypeSchema schema, PatchOperation patchOperation) + throws CharonException, BadRequestException { + + AbstractSCIMObject attributeHoldingSCIMObject = getDecoder().decode(patchOperation.getValues().toString(), + schema); + if (attributeHoldingSCIMObject == null) { + throw new BadRequestException("Not a valid attribute.", ResponseCodeConstants.INVALID_SYNTAX); + } + + Map attributeList = attributeHoldingSCIMObject.getAttributeList(); + + if (attributeList.containsKey(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME)) { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME); + patchOperation.setValues( + ((SimpleAttribute) attributeList.get(SCIMConstants.RoleSchemaConstants.DISPLAY_NAME)) + .getStringValue()); + } else if (attributeList.containsKey(SCIMConstants.RoleSchemaConstants.USERS)) { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.USERS); + patchOperation.setValues(transformAttributeToMap((MultiValuedAttribute) attributeList + .get(SCIMConstants.RoleSchemaConstants.USERS))); + } else if (attributeList.containsKey(SCIMConstants.RoleSchemaConstants.GROUPS)) { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.GROUPS); + patchOperation.setValues(transformAttributeToMap((MultiValuedAttribute) attributeList + .get(SCIMConstants.RoleSchemaConstants.GROUPS))); + } else if (attributeList.containsKey(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.PERMISSIONS); + patchOperation.setValues(((MultiValuedAttribute) attributeList. + get(SCIMConstants.RoleSchemaConstants.PERMISSIONS)).getAttributePrimitiveValues()); + } + } + + private List> transformAttributeToMap(MultiValuedAttribute multiValuedAttribute) + throws CharonException { + + List> memberList = new ArrayList<>(); + List subValuesList = multiValuedAttribute.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + + Map member = new HashMap<>(); + if (subAttributesList.get(SCIMConstants.CommonSchemaConstants.VALUE) != null) { + member.put(SCIMConstants.CommonSchemaConstants.VALUE, ((SimpleAttribute) + (subAttributesList.get(SCIMConstants.CommonSchemaConstants.VALUE))).getStringValue()); + } + + if (subAttributesList.get(SCIMConstants.CommonSchemaConstants.DISPLAY) != null) { + member.put(SCIMConstants.CommonSchemaConstants.DISPLAY, ((SimpleAttribute) + (subAttributesList.get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getStringValue()); + } + memberList.add(member); + } + return memberList; + } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index 9545360eb..ab810de10 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -58,6 +58,7 @@ public class SCIMConstants { public static final String USER_ENDPOINT = "/Users"; public static final String GROUP_ENDPOINT = "/Groups"; public static final String ROLE_ENDPOINT = "/Roles"; + public static final String ROLE_V2_ENDPOINT = "/v2/Roles"; public static final String SERVICE_PROVIDER_CONFIG_ENDPOINT = "/ServiceProviderConfig"; public static final String RESOURCE_TYPE_ENDPOINT = "/ResourceTypes"; public static final String SCHEMAS_ENDPOINT = "/Schemas"; @@ -533,6 +534,10 @@ public static class RoleSchemaConstants { public static final String VALUE = "value"; public static final String TYPE = "type"; + // Possible canonical values for audience type attribute. + public static final String APPLICATION = "application"; + public static final String ORGANIZATION = "organization"; + // Attributes descriptions of the attributes found in Role Schema. public static final String DISPLAY_NAME_DESC = "A human-readable name for the Role. REQUIRED."; public static final String USERS_DESC = "A list of users of the role."; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java index 45c244910..ed1b7ce7a 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java @@ -1098,7 +1098,9 @@ public static class SCIMRoleSchemaDefinition { SCIMConstants.RoleSchemaConstants.TYPE, SCIMDefinitions.DataType.STRING, false, SCIMConstants.RoleSchemaConstants.AUDIENCE_TYPE_DESC, false, false, SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, - SCIMDefinitions.Uniqueness.NONE, null, null, null); + SCIMDefinitions.Uniqueness.NONE, new ArrayList<>( + Arrays.asList(SCIMConstants.RoleSchemaConstants.APPLICATION, + SCIMConstants.RoleSchemaConstants.ORGANIZATION)), null, null); // Attribute schemas of the attributes defined in role schema. @@ -1115,7 +1117,7 @@ public static class SCIMRoleSchemaDefinition { public static final SCIMAttributeSchema AUDIENCE = SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.AUDIENCE_URI, SCIMConstants.RoleSchemaConstants.AUDIENCE, SCIMDefinitions.DataType.COMPLEX, false, - SCIMConstants.RoleSchemaConstants.AUDIENCE_DESC, true, false, + SCIMConstants.RoleSchemaConstants.AUDIENCE_DESC, false, false, SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, new ArrayList<>(Arrays.asList(AUDIENCE_VALUE, AUDIENCE_DISPLAY, AUDIENCE_TYPE))); From 4190c37e1a175f7ec05dafcaee05138050a8176e Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 7 Oct 2023 23:40:57 +0530 Subject: [PATCH 04/11] fix permission update and audience display retrieval --- .../org/wso2/charon3/core/objects/RoleV2.java | 12 ++++++++++++ .../endpoints/RoleResourceV2Manager.java | 18 +++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java index 9df770333..f9f418e98 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -522,6 +522,18 @@ public String getAudienceValue() { .orElse(null)).orElse(null); } + /** + * Get the audience display name of the role. + */ + public String getAudienceDisplayName() { + + SCIMAttributeSchema audienceDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE; + SCIMAttributeSchema audienceDisplayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_DISPLAY; + return getComplexAttribute(audienceDefinition).map(aud -> getSimpleAttribute(audienceDisplayDefinition, aud) + .map(rethrowFunction(SimpleAttribute::getStringValue)) + .orElse(null)).orElse(null); + } + /** * Get the audience type of the role. */ diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java index 306856dc2..2bf986f12 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java @@ -570,9 +570,6 @@ private void processRolePatchOperations(Map> patchO } for (PatchOperation patchOperation : patchOperations.get(SCIMConstants.OperationalConstants.ADD)) { - if (SCIMConstants.RoleSchemaConstants.PERMISSIONS.equalsIgnoreCase(patchOperation.getPath())) { - throw new NotImplementedException("Adding permissions not permitted."); - } processPatchOperation(schema, patchOperation); } @@ -673,10 +670,6 @@ private void processPatchOperation(SCIMResourceTypeSchema schema, PatchOperation private static void processRemovePatchOperation(PatchOperation patchOperation) throws NotImplementedException, BadRequestException { - if (SCIMConstants.RoleSchemaConstants.PERMISSIONS.equalsIgnoreCase(patchOperation.getPath())) { - throw new NotImplementedException("Removing permissions not permitted."); - } - if (SCIMConstants.RoleSchemaConstants.DISPLAY_NAME.equalsIgnoreCase(patchOperation.getPath())) { throw new BadRequestException("Can not remove a required attribute"); } @@ -691,15 +684,18 @@ private static void processRemovePatchOperation(PatchOperation patchOperation) String[] parts = path.split("[\\[\\]]"); if (ArrayUtils.isEmpty(parts) || !(SCIMConstants.RoleSchemaConstants.USERS.equalsIgnoreCase(parts[0]) || - SCIMConstants.RoleSchemaConstants.GROUPS.equalsIgnoreCase(parts[0]))) { + SCIMConstants.RoleSchemaConstants.GROUPS.equalsIgnoreCase(parts[0]) || + SCIMConstants.RoleSchemaConstants.PERMISSIONS.equalsIgnoreCase(parts[0]))) { throw new BadRequestException(parts[0] + " is not a valid attribute.", ResponseCodeConstants.INVALID_SYNTAX); } if (SCIMConstants.RoleSchemaConstants.USERS.equalsIgnoreCase(parts[0])) { patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.USERS); - } else { + } else if (SCIMConstants.RoleSchemaConstants.GROUPS.equalsIgnoreCase(parts[0])) { patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.GROUPS); + } else { + patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.PERMISSIONS); } if (parts.length != 1) { @@ -761,8 +757,8 @@ private void processValueAttributeOfOperation(SCIMResourceTypeSchema schema, Pat .get(SCIMConstants.RoleSchemaConstants.GROUPS))); } else if (attributeList.containsKey(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { patchOperation.setAttributeName(SCIMConstants.RoleSchemaConstants.PERMISSIONS); - patchOperation.setValues(((MultiValuedAttribute) attributeList. - get(SCIMConstants.RoleSchemaConstants.PERMISSIONS)).getAttributePrimitiveValues()); + patchOperation.setValues((transformAttributeToMap((MultiValuedAttribute) attributeList. + get(SCIMConstants.RoleSchemaConstants.PERMISSIONS)))); } } From 47f091dc4425961aaeddc4d7b71930219c4255e9 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Tue, 17 Oct 2023 11:20:57 +0530 Subject: [PATCH 05/11] set audience data to assigned role attribute of user and group resource --- .../org/wso2/charon3/core/objects/Group.java | 100 +++++++++++++++++ .../org/wso2/charon3/core/objects/User.java | 101 ++++++++++++++++++ .../charon3/core/schema/SCIMConstants.java | 16 ++- .../core/schema/SCIMSchemaDefinitions.java | 23 +++- 4 files changed, 238 insertions(+), 2 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java index 06837d6d6..d7ac69cfe 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java @@ -411,4 +411,104 @@ private void setRole(ComplexAttribute groupPropertiesAttribute) throws CharonExc } } + /** + * Set the assigned V2 roles of the group. + * + * @param role RoleV2 object. + * @throws CharonException CharonException. + * @throws BadRequestException BadRequestException. + */ + public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { + + SimpleAttribute valueSimpleAttribute = null; + SimpleAttribute displaySimpleAttribute; + SimpleAttribute referenceSimpleAttribute; + SimpleAttribute audienceValueSimpleAttribute; + SimpleAttribute audienceDisplaySimpleAttribute; + SimpleAttribute audienceTypeSimpleAttribute; + String reference = role.getLocation(); + String value = role.getId(); + String display = role.getDisplayName(); + String audienceValue = role.getAudienceValue(); + String audienceDisplay = role.getAudienceDisplayName(); + String audienceType = role.getAudienceType(); + ComplexAttribute complexAttribute = new ComplexAttribute(); + + if (StringUtils.isNotBlank(value)) { + valueSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, value); + valueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_VALUE, valueSimpleAttribute); + complexAttribute.setSubAttribute(valueSimpleAttribute); + } + + if (StringUtils.isNotBlank(reference)) { + referenceSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, reference); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_REF, + referenceSimpleAttribute); + complexAttribute.setSubAttribute(referenceSimpleAttribute); + } + + if (StringUtils.isNotBlank(display)) { + displaySimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.DISPLAY, display); + displaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_DISPLAY, + displaySimpleAttribute); + complexAttribute.setSubAttribute(displaySimpleAttribute); + } + + if (StringUtils.isNotBlank(audienceValue)) { + audienceValueSimpleAttribute = + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, audienceValue); + audienceValueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_VALUE, + audienceValueSimpleAttribute); + complexAttribute.setSubAttribute(audienceValueSimpleAttribute); + } + + if (StringUtils.isNotBlank(audienceDisplay)) { + audienceDisplaySimpleAttribute = + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, audienceDisplay); + audienceDisplaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_DISPLAY, + audienceDisplaySimpleAttribute); + complexAttribute.setSubAttribute(audienceDisplaySimpleAttribute); + } + + if (StringUtils.isNotBlank(audienceType)) { + audienceTypeSimpleAttribute = + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, audienceType); + audienceTypeSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_TYPE, + audienceTypeSimpleAttribute); + complexAttribute.setSubAttribute(audienceTypeSimpleAttribute); + } + + if (!complexAttribute.getSubAttributesList().isEmpty()) { + Object typeVal = SCIMConstants.DEFAULT; + Object valueVal = SCIMConstants.DEFAULT; + if (valueSimpleAttribute != null && valueSimpleAttribute.getValue() != null) { + valueVal = valueSimpleAttribute.getValue(); + } + String complexAttributeName = SCIMConstants.GroupSchemaConstants.ROLES + "_" + valueVal + "_" + typeVal; + complexAttribute.setName(complexAttributeName); + DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_SCHEMA, complexAttribute); + setRoleV2(complexAttribute); + } + } + + private void setRoleV2(ComplexAttribute groupPropertiesAttribute) throws CharonException, BadRequestException { + + MultiValuedAttribute groupsAttribute; + if (this.attributeList.containsKey(SCIMConstants.GroupSchemaConstants.ROLES)) { + groupsAttribute = (MultiValuedAttribute) this.attributeList.get(SCIMConstants.GroupSchemaConstants.ROLES); + groupsAttribute.setAttributeValue(groupPropertiesAttribute); + } else { + groupsAttribute = new MultiValuedAttribute(SCIMConstants.GroupSchemaConstants.ROLES); + groupsAttribute.setAttributeValue(groupPropertiesAttribute); + groupsAttribute = (MultiValuedAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_SCHEMA, groupsAttribute); + this.attributeList.put(SCIMConstants.GroupSchemaConstants.ROLES, groupsAttribute); + } + } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java index c59831e58..00792b3b7 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java @@ -915,6 +915,107 @@ private void setRole(ComplexAttribute groupPropertiesAttribute) throws CharonExc } } + /** + * Set the assigned V2 roles of the user. + * + * @param role RoleV2 object. + * @throws CharonException CharonException. + * @throws BadRequestException BadRequestException. + */ + public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { + + SimpleAttribute valueSimpleAttribute = null; + SimpleAttribute displaySimpleAttribute; + SimpleAttribute referenceSimpleAttribute; + SimpleAttribute audienceValueSimpleAttribute; + SimpleAttribute audienceDisplaySimpleAttribute; + SimpleAttribute audienceTypeSimpleAttribute; + String reference = role.getLocation(); + String value = role.getId(); + String display = role.getDisplayName(); + String audienceValue = role.getAudienceValue(); + String audienceDisplay = role.getAudienceDisplayName(); + String audienceType = role.getAudienceType(); + ComplexAttribute complexAttribute = new ComplexAttribute(); + + if (StringUtils.isNotBlank(value)) { + valueSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, value); + valueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_VALUE, valueSimpleAttribute); + complexAttribute.setSubAttribute(valueSimpleAttribute); + } + + if (StringUtils.isNotBlank(reference)) { + referenceSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, reference); + DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_REF, + referenceSimpleAttribute); + complexAttribute.setSubAttribute(referenceSimpleAttribute); + } + + if (StringUtils.isNotBlank(display)) { + displaySimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.DISPLAY, display); + displaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_DISPLAY, + displaySimpleAttribute); + complexAttribute.setSubAttribute(displaySimpleAttribute); + } + + if (StringUtils.isNotBlank(audienceValue)) { + audienceValueSimpleAttribute = + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, audienceValue); + audienceValueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_VALUE, + audienceValueSimpleAttribute); + complexAttribute.setSubAttribute(audienceValueSimpleAttribute); + } + + if (StringUtils.isNotBlank(audienceDisplay)) { + audienceDisplaySimpleAttribute = + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, audienceDisplay); + audienceDisplaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_DISPLAY, + audienceDisplaySimpleAttribute); + complexAttribute.setSubAttribute(audienceDisplaySimpleAttribute); + } + + if (StringUtils.isNotBlank(audienceType)) { + audienceTypeSimpleAttribute = + new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, audienceType); + audienceTypeSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_TYPE, + audienceTypeSimpleAttribute); + complexAttribute.setSubAttribute(audienceTypeSimpleAttribute); + } + + if (!complexAttribute.getSubAttributesList().isEmpty()) { + Object typeVal = SCIMConstants.DEFAULT; + Object valueVal = SCIMConstants.DEFAULT; + if (valueSimpleAttribute != null && valueSimpleAttribute.getValue() != null) { + valueVal = valueSimpleAttribute.getValue(); + } + String complexAttributeName = SCIMConstants.UserSchemaConstants.ROLES + "_" + valueVal + "_" + typeVal; + complexAttribute.setName(complexAttributeName); + DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_SCHEMA, complexAttribute); + setRoleV2(complexAttribute); + } + } + + private void setRoleV2(ComplexAttribute rolePropertiesAttribute) throws CharonException, BadRequestException { + + MultiValuedAttribute rolesAttribute; + if (this.attributeList.containsKey(SCIMConstants.UserSchemaConstants.ROLES)) { + rolesAttribute = (MultiValuedAttribute) this.attributeList.get(SCIMConstants.UserSchemaConstants.ROLES); + rolesAttribute.setAttributeValue(rolePropertiesAttribute); + } else { + rolesAttribute = new MultiValuedAttribute(SCIMConstants.UserSchemaConstants.ROLES); + rolesAttribute.setAttributeValue(rolePropertiesAttribute); + rolesAttribute = (MultiValuedAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_SCHEMA, rolesAttribute); + this.attributeList.put(SCIMConstants.UserSchemaConstants.ROLES, rolesAttribute); + } + } + /** * set the schemas of the user */ diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index ab810de10..722fc452b 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -103,6 +103,11 @@ public static class CommonSchemaConstants { public static final String REF = "$ref"; public static final String VALUE = "value"; + public static final String AUDIENCE_VALUE = "audienceValue"; + public static final String AUDIENCE_DISPLAY = "audienceDisplay"; + public static final String AUDIENCE_TYPE = "audienceType"; + + /*******Attributes descriptions of the attributes found in Common Schema.***************/ public static final String ID_DESC = "Unique identifier for the SCIM Resource as defined by the Service " + @@ -281,6 +286,12 @@ public static class UserSchemaConstants { public static final String ROLES_TYPE_URI = "urn:ietf:params:scim:schemas:core:2.0:User:roles.type"; public static final String ROLES_PRIMARY_URI = "urn:ietf:params:scim:schemas:core:2.0:User:roles.primary"; public static final String ROLES_REF_URI = "urn:ietf:params:scim:schemas:core:2.0:User:roles.$ref"; + public static final String ROLES_AUDIENCE_VALUE_URI = + "urn:ietf:params:scim:schemas:core:2.0:User:roles.audienceValue"; + public static final String ROLES_AUDIENCE_DISPLAY_URI = + "urn:ietf:params:scim:schemas:core:2.0:User:roles.audienceDisplay"; + public static final String ROLES_AUDIENCE_TYPE_URI = + "urn:ietf:params:scim:schemas:core:2.0:User:roles.audienceType"; public static final String ENTITLEMENTS_VALUE_URI = "urn:ietf:params:scim:schemas:core:2.0:User:entitlements" + ".value"; @@ -458,7 +469,10 @@ public static class UserSchemaConstants { "once."; public static final String ROLES_REF_DESC = "The uri of the corresponding 'Role' resource to which the user" + " belongs."; - + public static final String ROLES_AUDIENCE_VALUE_DESC = "The value of the role's usable audience."; + public static final String ROLES_AUDIENCE_DISPLAY_DESC = "A human-readable name of the role's usable audience."; + public static final String ROLES_AUDIENCE_TYPE_DESC = + "A label indicating the resource type of the role's usable audience."; public static final String X509CERTIFICATES_DESC = "A list of certificates issued to the User."; public static final String X509CERTIFICATES_VALUE_DESC = "The value of an X.509 certificate."; public static final String X509CERTIFICATES_DISPLAY_DESC = "A human-readable name, primarily used for display" + diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java index ed1b7ce7a..5bef7f196 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java @@ -513,6 +513,26 @@ public static class SCIMUserSchemaDefinition { SCIMDefinitions.Uniqueness.NONE, null, new ArrayList<> (Arrays.asList(SCIMDefinitions.ReferenceType.USER, SCIMDefinitions.ReferenceType .ROLE)), null); + public static final SCIMAttributeSchema ROLES_AUDIENCE_VALUE = SCIMAttributeSchema.createSCIMAttributeSchema( + SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_VALUE_URI, + SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_VALUE_DESC, false, false, + SCIMDefinitions.Mutability.READ_ONLY, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, + null, null, null); + + public static final SCIMAttributeSchema ROLES_AUDIENCE_DISPLAY = SCIMAttributeSchema.createSCIMAttributeSchema( + SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_DISPLAY_URI, + SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_DISPLAY_DESC, false, false, + SCIMDefinitions.Mutability.READ_ONLY, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, + null, null, null); + + public static final SCIMAttributeSchema ROLES_AUDIENCE_TYPE = SCIMAttributeSchema.createSCIMAttributeSchema( + SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_TYPE_URI, + SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, SCIMDefinitions.DataType.STRING, false, + SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_TYPE_DESC, false, false, + SCIMDefinitions.Mutability.READ_ONLY, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, + null, null, null); //sub attributes of x509certificates attribute @@ -807,7 +827,8 @@ public static class SCIMUserSchemaDefinition { SCIMConstants.UserSchemaConstants.ROLES_DESC, false, false, SCIMDefinitions.Mutability.READ_ONLY, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, - new ArrayList<>(Arrays.asList(ROLES_VALUE, ROLES_REF, ROLES_DISPLAY))); + new ArrayList<>(Arrays.asList(ROLES_VALUE, ROLES_REF, ROLES_DISPLAY, ROLES_AUDIENCE_VALUE, + ROLES_AUDIENCE_DISPLAY, ROLES_AUDIENCE_TYPE))); //A list of entitlements for the User that represent a thing the User has. public static final SCIMAttributeSchema ENTITLEMENTS = From c54cb8ec2168b6669042d921aa5e35519d10c7ec Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Tue, 17 Oct 2023 13:41:40 +0530 Subject: [PATCH 06/11] update copy rights year range in edited files --- .../org/wso2/charon3/core/objects/Group.java | 18 ++++++++++-------- .../org/wso2/charon3/core/objects/User.java | 18 ++++++++++-------- .../protocol/endpoints/ResourceManager.java | 18 ++++++++++-------- .../charon3/core/schema/SCIMConstants.java | 18 ++++++++++-------- .../charon3/core/schema/SCIMDefinitions.java | 18 ++++++++++-------- .../core/schema/SCIMResourceSchemaManager.java | 18 ++++++++++-------- 6 files changed, 60 insertions(+), 48 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java index d7ac69cfe..ecad52cf2 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java @@ -1,17 +1,19 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2023, WSO2 LLC. (http://www.wso2.com). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.charon3.core.objects; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java index 00792b3b7..7e4de6d86 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java @@ -1,17 +1,19 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2023, WSO2 LLC. (http://www.wso2.com). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.charon3.core.objects; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java index 2f0c549e5..c476e1742 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/ResourceManager.java @@ -1,17 +1,19 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2023, WSO2 LLC. (http://www.wso2.com). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.charon3.core.protocol.endpoints; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index 722fc452b..027d3a101 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -1,17 +1,19 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2023, WSO2 LLC. (http://www.wso2.com). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.charon3.core.schema; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMDefinitions.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMDefinitions.java index c5c480bc9..c208cf211 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMDefinitions.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMDefinitions.java @@ -1,17 +1,19 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2023, WSO2 LLC. (http://www.wso2.com). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.charon3.core.schema; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java index 9dfd9128c..5367b7c66 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java @@ -1,17 +1,19 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2023, WSO2 LLC. (http://www.wso2.com). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.charon3.core.schema; From ca64654c3f9c03eb95c521cc2f548d9206cbdb4e Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Wed, 18 Oct 2023 11:38:13 +0530 Subject: [PATCH 07/11] refactor code --- .../org/wso2/charon3/core/objects/Group.java | 61 ++-- .../org/wso2/charon3/core/objects/RoleV2.java | 289 ++++++++++-------- .../org/wso2/charon3/core/objects/User.java | 51 ++-- 3 files changed, 204 insertions(+), 197 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java index ecad52cf2..f134444e5 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java @@ -25,6 +25,7 @@ import org.wso2.charon3.core.attributes.SimpleAttribute; import org.wso2.charon3.core.exceptions.BadRequestException; import org.wso2.charon3.core.exceptions.CharonException; +import org.wso2.charon3.core.schema.SCIMAttributeSchema; import org.wso2.charon3.core.schema.SCIMConstants; import org.wso2.charon3.core.schema.SCIMResourceSchemaManager; import org.wso2.charon3.core.schema.SCIMResourceTypeSchema; @@ -47,6 +48,7 @@ public class Group extends AbstractSCIMObject { private static final long serialVersionUID = 6106269076155338045L; /** * get the display name of the group + * * @return * @throws CharonException */ @@ -61,6 +63,7 @@ public String getDisplayName() { /** * set the display name of the group + * * @param displayName * @throws CharonException * @throws BadRequestException @@ -87,6 +90,7 @@ public void replaceDisplayName(String displayname) { /** * get the members of the group + * * @return */ public List getMembers() { @@ -110,6 +114,7 @@ public List getMembers() { /** * get the members of the group with their display names + * * @return */ public List getMembersWithDisplayName() { @@ -171,6 +176,7 @@ public void setMember(String value, String display, String ref, String type) /** * set member to the group + * * @param userId * @param userName * @return @@ -423,11 +429,6 @@ private void setRole(ComplexAttribute groupPropertiesAttribute) throws CharonExc public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { SimpleAttribute valueSimpleAttribute = null; - SimpleAttribute displaySimpleAttribute; - SimpleAttribute referenceSimpleAttribute; - SimpleAttribute audienceValueSimpleAttribute; - SimpleAttribute audienceDisplaySimpleAttribute; - SimpleAttribute audienceTypeSimpleAttribute; String reference = role.getLocation(); String value = role.getId(); String display = role.getDisplayName(); @@ -437,52 +438,34 @@ public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { ComplexAttribute complexAttribute = new ComplexAttribute(); if (StringUtils.isNotBlank(value)) { - valueSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, value); - valueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_VALUE, valueSimpleAttribute); + valueSimpleAttribute = getSimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, value, + SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_VALUE); complexAttribute.setSubAttribute(valueSimpleAttribute); } if (StringUtils.isNotBlank(reference)) { - referenceSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, reference); - DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_REF, - referenceSimpleAttribute); - complexAttribute.setSubAttribute(referenceSimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, reference, + SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_REF)); } if (StringUtils.isNotBlank(display)) { - displaySimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.DISPLAY, display); - displaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_DISPLAY, - displaySimpleAttribute); - complexAttribute.setSubAttribute(displaySimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.DISPLAY, display, + SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_DISPLAY)); } if (StringUtils.isNotBlank(audienceValue)) { - audienceValueSimpleAttribute = - new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, audienceValue); - audienceValueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_VALUE, - audienceValueSimpleAttribute); - complexAttribute.setSubAttribute(audienceValueSimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, + audienceValue, SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_VALUE)); } if (StringUtils.isNotBlank(audienceDisplay)) { - audienceDisplaySimpleAttribute = - new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, audienceDisplay); - audienceDisplaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_DISPLAY, - audienceDisplaySimpleAttribute); - complexAttribute.setSubAttribute(audienceDisplaySimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, + audienceDisplay, SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_DISPLAY)); } if (StringUtils.isNotBlank(audienceType)) { - audienceTypeSimpleAttribute = - new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, audienceType); - audienceTypeSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_TYPE, - audienceTypeSimpleAttribute); - complexAttribute.setSubAttribute(audienceTypeSimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, + audienceType, SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_TYPE)); } if (!complexAttribute.getSubAttributesList().isEmpty()) { @@ -499,6 +482,14 @@ public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { } } + private SimpleAttribute getSimpleAttribute(String attributeName, String attributeValue, + SCIMAttributeSchema attributeSchema) + throws CharonException, BadRequestException { + + return (SimpleAttribute) DefaultAttributeFactory.createAttribute(attributeSchema, + new SimpleAttribute(attributeName, attributeValue)); + } + private void setRoleV2(ComplexAttribute groupPropertiesAttribute) throws CharonException, BadRequestException { MultiValuedAttribute groupsAttribute; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java index f9f418e98..75a706c17 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -100,20 +100,22 @@ public void replaceDisplayName(String displayName) { */ public List getUsers() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { + return Collections.emptyList(); + } List userList = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { - MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.USERS); - List subValuesList = users.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - userList.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } + MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.USERS); + List subValuesList = users.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || + !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + continue; } + userList.add((String) ((SimpleAttribute) (subAttributesList.get( + SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); } return userList; } @@ -125,27 +127,26 @@ public List getUsers() { */ public List getUsersWithDisplayName() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { + return Collections.emptyList(); + } + MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.USERS); + List subValuesList = users.getAttributeValues(); + if (subValuesList == null) { + return Collections.emptyList(); + } List displayNames = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { - MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.USERS); - List values = users.getAttributeValues(); - if (values != null) { - List subValuesList = users.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - displayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } - - } - return displayNames; + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || + !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + continue; } + displayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); } - return displayNames; } @@ -224,20 +225,25 @@ private ComplexAttribute processUser(User user) throws BadRequestException, Char */ public List getGroups() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { + return Collections.emptyList(); + } + MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.GROUPS); + List subValuesList = groups.getAttributeValues(); + if (subValuesList == null) { + return Collections.emptyList(); + } List groupList = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { - MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.GROUPS); - List subValuesList = groups.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - groupList.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || + !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + continue; } + groupList.add((String) ((SimpleAttribute) (subAttributesList.get( + SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); } return groupList; } @@ -249,26 +255,28 @@ public List getGroups() { */ public List getGroupsWithDisplayName() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { + return Collections.emptyList(); + } List displayNames = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { - MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.GROUPS); - List values = groups.getAttributeValues(); - if (values != null) { - List subValuesList = groups.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - displayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } - } - return displayNames; - } + MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.GROUPS); + List values = groups.getAttributeValues(); + if (values == null) { + return displayNames; } + List subValuesList = groups.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || !subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + continue; + } + displayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); + } return displayNames; } @@ -358,20 +366,26 @@ public void setSchemas() { */ public List getPermissionValues() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { + return Collections.emptyList(); + } + MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); + List subValuesList = permissions.getAttributeValues(); List permissionValuesList = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { - MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); - List subValuesList = permissions.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - permissionValuesList.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } + if (subValuesList == null) { + return Collections.emptyList(); + } + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || + !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + continue; } + permissionValuesList.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); + } return permissionValuesList; } @@ -383,23 +397,27 @@ public List getPermissionValues() { */ public List getPermissionDisplayNames() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { + return Collections.emptyList(); + } + MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); + List values = permissions.getAttributeValues(); List permissionDisplayNames = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { - MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); - List values = permissions.getAttributeValues(); - if (values != null) { - List subValuesList = permissions.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - permissionDisplayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } - } + if (values == null) { + return Collections.emptyList(); + + } + List subValuesList = permissions.getAttributeValues(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || !subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + continue; } + permissionDisplayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); } return permissionDisplayNames; } @@ -433,20 +451,25 @@ public void setPermissions(List permissionsList) { */ public List getAssociatedApplicationValues() { + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { + return Collections.emptyList(); + } + MultiValuedAttribute associatedApps = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); + List subValuesList = associatedApps.getAttributeValues(); List assocAppValuesList = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { - MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); - List subValuesList = permissions.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - assocAppValuesList.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } + if (subValuesList == null) { + return Collections.emptyList(); + } + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || + !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { + continue; } + assocAppValuesList.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); } return assocAppValuesList; } @@ -457,19 +480,24 @@ public List getAssociatedApplicationValues() { public List getAssociatedApplicationDisplayNames() { List assocAppDisplayNames = new ArrayList<>(); - if (this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { - MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); - List subValuesList = permissions.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList != null && subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - assocAppDisplayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } + if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { + return Collections.emptyList(); + } + MultiValuedAttribute associatedApps = (MultiValuedAttribute) this.attributeList + .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); + List subValuesList = associatedApps.getAttributeValues(); + if (subValuesList == null) { + return Collections.emptyList(); + } + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || !subAttributesList + .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { + continue; } + assocAppDisplayNames.add((String) ((SimpleAttribute) (subAttributesList + .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); } return assocAppDisplayNames; } @@ -503,11 +531,10 @@ public void setAssociatedApplications(List associatedApp */ public ComplexAttribute getAudience() { - if (isAudienceAttributeExist()) { - return (ComplexAttribute) attributeList.get(SCIMConstants.RoleSchemaConstants.AUDIENCE); - } else { + if (!isAudienceAttributeExist()) { return null; } + return (ComplexAttribute) attributeList.get(SCIMConstants.RoleSchemaConstants.AUDIENCE); } /** @@ -562,23 +589,24 @@ public void setAudience(String audienceValue, String audienceDisplay, String aud (ComplexAttribute) DefaultAttributeFactory.createAttribute( SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE, new ComplexAttribute(SCIMConstants.RoleSchemaConstants.AUDIENCE)); - if (!isAudienceAttributeExist()) { - attributeList.put(SCIMConstants.RoleSchemaConstants.AUDIENCE, audienceAttribute); - - SimpleAttribute audienceValueAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_VALUE, - new SimpleAttribute(SCIMConstants.RoleSchemaConstants.VALUE, audienceValue)); - SimpleAttribute audienceDisplayAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_DISPLAY, - new SimpleAttribute(SCIMConstants.RoleSchemaConstants.DISPLAY, audienceDisplay)); - SimpleAttribute audienceTypeAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_TYPE, - new SimpleAttribute(SCIMConstants.RoleSchemaConstants.TYPE, audienceType)); - - getAudience().setSubAttribute(audienceValueAttribute); - getAudience().setSubAttribute(audienceDisplayAttribute); - getAudience().setSubAttribute(audienceTypeAttribute); + if (isAudienceAttributeExist()) { + return; } + attributeList.put(SCIMConstants.RoleSchemaConstants.AUDIENCE, audienceAttribute); + + SimpleAttribute audienceValueAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_VALUE, + new SimpleAttribute(SCIMConstants.RoleSchemaConstants.VALUE, audienceValue)); + SimpleAttribute audienceDisplayAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_DISPLAY, + new SimpleAttribute(SCIMConstants.RoleSchemaConstants.DISPLAY, audienceDisplay)); + SimpleAttribute audienceTypeAttribute = (SimpleAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_TYPE, + new SimpleAttribute(SCIMConstants.RoleSchemaConstants.TYPE, audienceType)); + + getAudience().setSubAttribute(audienceValueAttribute); + getAudience().setSubAttribute(audienceDisplayAttribute); + getAudience().setSubAttribute(audienceTypeAttribute); } protected boolean isAudienceAttributeExist() { @@ -609,9 +637,8 @@ public void setSystemRole(boolean isSystemRole) throws CharonException, BadReque if (metaAttribute.isSubAttributeExist(systemRoleAttribute.getName())) { String error = "Tried to modify a read only attribute."; throw new CharonException(error); - } else { - metaAttribute.setSubAttribute(systemRoleAttribute); } + metaAttribute.setSubAttribute(systemRoleAttribute); } else { // Create the meta attribute and set the sub attribute. createMetaAttribute(); diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java index 7e4de6d86..71db9e652 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java @@ -928,7 +928,6 @@ public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { SimpleAttribute valueSimpleAttribute = null; SimpleAttribute displaySimpleAttribute; - SimpleAttribute referenceSimpleAttribute; SimpleAttribute audienceValueSimpleAttribute; SimpleAttribute audienceDisplaySimpleAttribute; SimpleAttribute audienceTypeSimpleAttribute; @@ -941,52 +940,34 @@ public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { ComplexAttribute complexAttribute = new ComplexAttribute(); if (StringUtils.isNotBlank(value)) { - valueSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, value); - valueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_VALUE, valueSimpleAttribute); + valueSimpleAttribute = getSimpleAttribute(SCIMConstants.CommonSchemaConstants.VALUE, value, + SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_VALUE); complexAttribute.setSubAttribute(valueSimpleAttribute); } if (StringUtils.isNotBlank(reference)) { - referenceSimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, reference); - DefaultAttributeFactory.createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_REF, - referenceSimpleAttribute); - complexAttribute.setSubAttribute(referenceSimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.REF, reference, + SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_REF)); } if (StringUtils.isNotBlank(display)) { - displaySimpleAttribute = new SimpleAttribute(SCIMConstants.CommonSchemaConstants.DISPLAY, display); - displaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_DISPLAY, - displaySimpleAttribute); - complexAttribute.setSubAttribute(displaySimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.DISPLAY, display, + SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_DISPLAY)); } if (StringUtils.isNotBlank(audienceValue)) { - audienceValueSimpleAttribute = - new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, audienceValue); - audienceValueSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_VALUE, - audienceValueSimpleAttribute); - complexAttribute.setSubAttribute(audienceValueSimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, + audienceValue, SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_VALUE)); } if (StringUtils.isNotBlank(audienceDisplay)) { - audienceDisplaySimpleAttribute = - new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, audienceDisplay); - audienceDisplaySimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_DISPLAY, - audienceDisplaySimpleAttribute); - complexAttribute.setSubAttribute(audienceDisplaySimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_DISPLAY, + audienceDisplay, SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_DISPLAY)); } if (StringUtils.isNotBlank(audienceType)) { - audienceTypeSimpleAttribute = - new SimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, audienceType); - audienceTypeSimpleAttribute = (SimpleAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_TYPE, - audienceTypeSimpleAttribute); - complexAttribute.setSubAttribute(audienceTypeSimpleAttribute); + complexAttribute.setSubAttribute(getSimpleAttribute(SCIMConstants.CommonSchemaConstants.AUDIENCE_TYPE, + audienceType, SCIMSchemaDefinitions.SCIMUserSchemaDefinition.ROLES_AUDIENCE_TYPE)); } if (!complexAttribute.getSubAttributesList().isEmpty()) { @@ -1003,6 +984,14 @@ public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { } } + private SimpleAttribute getSimpleAttribute(String attributeName, String attributeValue, + SCIMAttributeSchema attributeSchema) + throws CharonException, BadRequestException { + + return (SimpleAttribute) DefaultAttributeFactory.createAttribute(attributeSchema, + new SimpleAttribute(attributeName, attributeValue)); + } + private void setRoleV2(ComplexAttribute rolePropertiesAttribute) throws CharonException, BadRequestException { MultiValuedAttribute rolesAttribute; From 1d4873a8b036922d6e20c2155bee6e7c54f26592 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 21 Oct 2023 11:38:38 +0530 Subject: [PATCH 08/11] remove todo and fix review comments --- .../org/wso2/charon3/core/objects/Group.java | 18 +++++------ .../org/wso2/charon3/core/objects/RoleV2.java | 3 -- .../endpoints/RoleResourceV2Manager.java | 12 +++----- .../charon3/core/schema/SCIMConstants.java | 2 +- .../schema/SCIMResourceSchemaManager.java | 1 + .../core/schema/SCIMSchemaDefinitions.java | 1 + .../core/schema/ServerSideValidator.java | 30 +++++++++++++++++++ 7 files changed, 46 insertions(+), 21 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java index f134444e5..c9d06893d 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/Group.java @@ -490,18 +490,18 @@ private SimpleAttribute getSimpleAttribute(String attributeName, String attribut new SimpleAttribute(attributeName, attributeValue)); } - private void setRoleV2(ComplexAttribute groupPropertiesAttribute) throws CharonException, BadRequestException { + private void setRoleV2(ComplexAttribute rolePropertiesAttribute) throws CharonException, BadRequestException { - MultiValuedAttribute groupsAttribute; + MultiValuedAttribute rolesAttribute; if (this.attributeList.containsKey(SCIMConstants.GroupSchemaConstants.ROLES)) { - groupsAttribute = (MultiValuedAttribute) this.attributeList.get(SCIMConstants.GroupSchemaConstants.ROLES); - groupsAttribute.setAttributeValue(groupPropertiesAttribute); + rolesAttribute = (MultiValuedAttribute) this.attributeList.get(SCIMConstants.GroupSchemaConstants.ROLES); + rolesAttribute.setAttributeValue(rolePropertiesAttribute); } else { - groupsAttribute = new MultiValuedAttribute(SCIMConstants.GroupSchemaConstants.ROLES); - groupsAttribute.setAttributeValue(groupPropertiesAttribute); - groupsAttribute = (MultiValuedAttribute) DefaultAttributeFactory - .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_SCHEMA, groupsAttribute); - this.attributeList.put(SCIMConstants.GroupSchemaConstants.ROLES, groupsAttribute); + rolesAttribute = new MultiValuedAttribute(SCIMConstants.GroupSchemaConstants.ROLES); + rolesAttribute.setAttributeValue(rolePropertiesAttribute); + rolesAttribute = (MultiValuedAttribute) DefaultAttributeFactory + .createAttribute(SCIMSchemaDefinitions.SCIMGroupSchemaDefinition.ROLES_SCHEMA, rolesAttribute); + this.attributeList.put(SCIMConstants.GroupSchemaConstants.ROLES, rolesAttribute); } } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java index 75a706c17..41330bea9 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -385,7 +385,6 @@ public List getPermissionValues() { } permissionValuesList.add((String) ((SimpleAttribute) (subAttributesList .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } return permissionValuesList; } @@ -406,7 +405,6 @@ public List getPermissionDisplayNames() { List permissionDisplayNames = new ArrayList<>(); if (values == null) { return Collections.emptyList(); - } List subValuesList = permissions.getAttributeValues(); for (Attribute subValue : subValuesList) { @@ -614,7 +612,6 @@ protected boolean isAudienceAttributeExist() { return attributeList.containsKey(SCIMConstants.RoleSchemaConstants.AUDIENCE); } - // TODO: having this kind of custom property in meta is a spec violation. Check whether we need to fix. /** * Set the systemRole attribute of the meta attribute. diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java index 2bf986f12..4f15eefe5 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/protocol/endpoints/RoleResourceV2Manager.java @@ -18,8 +18,6 @@ package org.wso2.charon3.core.protocol.endpoints; -// TODO check the comment. possible to move this out from charon, since it's an extended resource - import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.json.JSONArray; @@ -95,8 +93,7 @@ public SCIMResponse getRole(String id, RoleV2Manager roleManager, String attribu throw new NotFoundException(message); } ServerSideValidator.validateRetrievedSCIMObject(role, schema, attributes, excludeAttributes); - // TODO -// ServerSideValidator.validateRetrievedSCIMRoleObject(role, attributes, excludeAttributes); + ServerSideValidator.validateRetrievedSCIMRoleV2Object(role, attributes, excludeAttributes); String encodedRole = encoder.encodeSCIMObject(role); Map httpHeaders = new HashMap<>(); httpHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON); @@ -261,13 +258,12 @@ public SCIMResponse updateWithPUTRole(String id, String putRequest, RoleV2Manage // Retrieve the old object. RoleV2 oldRole = roleManager.getRole(id, requestAttributes); - if (oldRole != null) { - RoleV2 newRole = (RoleV2) ServerSideValidator.validateUpdatedSCIMObject(oldRole, role, schema); - updatedRole = roleManager.updateRole(oldRole, newRole); - } else { + if (oldRole == null) { String error = "No role exists with the given id: " + id; throw new NotFoundException(error); } + RoleV2 newRole = (RoleV2) ServerSideValidator.validateUpdatedSCIMObject(oldRole, role, schema); + updatedRole = roleManager.updateRole(oldRole, newRole); return getScimResponse(encoder, updatedRole); } catch (NotFoundException | BadRequestException | CharonException | ConflictException | InternalErrorException | NotImplementedException e) { diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index 027d3a101..b118bdca4 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -560,7 +560,7 @@ public static class RoleSchemaConstants { public static final String GROUPS_DESC = "A list of groups of the role."; public static final String PERMISSIONS_DESC = "A list of permissions of the role."; public static final String ASC_APPLICATIONS_DESC = "A list of associated applications of the role."; - public static final String AUDIENCE_DESC = "The role usable scope."; + public static final String AUDIENCE_DESC = "The role usable audience."; public static final String USERS_VALUE_DESC = "Identifier of the user of this role."; public static final String GROUPS_VALUE_DESC = "Identifier of the group of this role."; public static final String PERMISSIONS_VALUE_DESC = "Identifier of the permissions of this role."; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java index 5367b7c66..209759bf5 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMResourceSchemaManager.java @@ -221,6 +221,7 @@ public SCIMResourceTypeSchema getRoleResourceV2Schema() { return SCIMSchemaDefinitions.SCIM_ROLE_V2_SCHEMA; } + public SCIMResourceTypeSchema getResourceTypeResourceSchema() { return SCIMSchemaDefinitions.SCIM_RESOURCE_TYPE_SCHEMA; diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java index 5bef7f196..18658bbe4 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java @@ -513,6 +513,7 @@ public static class SCIMUserSchemaDefinition { SCIMDefinitions.Uniqueness.NONE, null, new ArrayList<> (Arrays.asList(SCIMDefinitions.ReferenceType.USER, SCIMDefinitions.ReferenceType .ROLE)), null); + public static final SCIMAttributeSchema ROLES_AUDIENCE_VALUE = SCIMAttributeSchema.createSCIMAttributeSchema( SCIMConstants.UserSchemaConstants.ROLES_AUDIENCE_VALUE_URI, SCIMConstants.CommonSchemaConstants.AUDIENCE_VALUE, SCIMDefinitions.DataType.STRING, false, diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/ServerSideValidator.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/ServerSideValidator.java index c5922e27d..f9405dd8e 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/ServerSideValidator.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/ServerSideValidator.java @@ -21,6 +21,7 @@ import org.wso2.charon3.core.exceptions.NotFoundException; import org.wso2.charon3.core.objects.AbstractSCIMObject; import org.wso2.charon3.core.objects.Role; +import org.wso2.charon3.core.objects.RoleV2; import org.wso2.charon3.core.objects.User; import org.wso2.charon3.core.protocol.endpoints.AbstractResourceManager; import org.wso2.charon3.core.utils.AttributeUtil; @@ -161,6 +162,35 @@ public static void validateRetrievedSCIMRoleObject(Role scimObject, String reque } } + /** + * Validate Retrieved SCIM Role V2 Object. + * + * @param scimObject RoleV2 object. + * @param requestedAttributes RequestedAttributes. + * @param requestedExcludingAttributes RequestedExcludingAttributes. + */ + public static void validateRetrievedSCIMRoleV2Object(RoleV2 scimObject, String requestedAttributes, + String requestedExcludingAttributes) { + + List requestedExcludingAttributesList = null; + List requestedAttributesList = null; + if (requestedExcludingAttributes != null) { + // Make a list from the comma separated requestedExcludingAttributes. + requestedExcludingAttributesList = Arrays.asList(requestedExcludingAttributes.split(",")); + } + if (requestedAttributes != null) { + // Make a list from the comma separated requestedAttributes. + requestedAttributesList = Arrays.asList(requestedAttributes.split(",")); + } + if (requestedAttributesList != null && requestedAttributesList. + stream().noneMatch(SCIMConstants.RoleSchemaConstants.PERMISSIONS::equalsIgnoreCase)) { + scimObject.setPermissions(new ArrayList<>()); + } else if (requestedExcludingAttributesList != null && requestedExcludingAttributesList. + stream().anyMatch(SCIMConstants.RoleSchemaConstants.PERMISSIONS::equalsIgnoreCase)) { + scimObject.setPermissions(new ArrayList<>()); + } + } + /** * Perform validation on SCIM Object update on service provider side. * From c0b81268ca1c47a1287caf3660a11aa4778ea0f0 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 21 Oct 2023 13:04:36 +0530 Subject: [PATCH 09/11] support ref in permission and assoc applications --- .../org/wso2/charon3/core/objects/RoleV2.java | 28 ++++++++------- .../charon3/core/schema/SCIMConstants.java | 11 ++++-- .../core/schema/SCIMSchemaDefinitions.java | 35 ++++++++++++++----- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java index 41330bea9..cf5344b3c 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -426,10 +426,11 @@ public List getPermissionDisplayNames() { public List getPermissions() { SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ROLE_V2_PERMISSIONS; - SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_VALUE; - SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_DISPLAY; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSIONS_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSIONS_DISPLAY; + SCIMAttributeSchema refDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSIONS_REF; return getMultivaluedComplexType(complexDefinition, valueDefinition, displayDefinition, null, null, - null).orElse(Collections.emptyList()); + refDefinition).orElse(Collections.emptyList()); } /** @@ -438,10 +439,11 @@ public List getPermissions() { public void setPermissions(List permissionsList) { SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ROLE_V2_PERMISSIONS; - SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_VALUE; - SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSION_DISPLAY; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSIONS_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSIONS_DISPLAY; + SCIMAttributeSchema refDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.PERMISSIONS_REF; addMultivaluedComplexAtribute(permissionsList, complexDefinition, valueDefinition, displayDefinition, - null, null, null); + null, null, refDefinition); } /** @@ -506,10 +508,11 @@ public List getAssociatedApplicationDisplayNames() { public List getAssociatedApplications() { SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASSOCIATED_APPLICATIONS; - SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_VALUE; - SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_DISPLAY; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATIONS_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATIONS_DISPLAY; + SCIMAttributeSchema refDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATIONS_REF; return getMultivaluedComplexType(complexDefinition, valueDefinition, displayDefinition, null, null, - null).orElse(Collections.emptyList()); + refDefinition).orElse(Collections.emptyList()); } /** @@ -518,10 +521,11 @@ public List getAssociatedApplications() { public void setAssociatedApplications(List associatedApplicationsList) { SCIMAttributeSchema complexDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASSOCIATED_APPLICATIONS; - SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_VALUE; - SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATION_DISPLAY; + SCIMAttributeSchema valueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATIONS_VALUE; + SCIMAttributeSchema displayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATIONS_DISPLAY; + SCIMAttributeSchema refDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.ASC_APPLICATIONS_REF; addMultivaluedComplexAtribute(associatedApplicationsList, complexDefinition, valueDefinition, - displayDefinition, null, null, null); + displayDefinition, null, null, refDefinition); } /** diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index b118bdca4..0be25031e 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -571,6 +571,9 @@ public static class RoleSchemaConstants { "The uri corresponding to a SCIM resource that is a user of this Role."; public static final String GROUPS_REF_DESC = "The uri corresponding to a SCIM resource that is a group of this Role."; + public static final String PERMISSIONS_REF_DESC = "The uri corresponding to permission resource of this Role."; + public static final String ASC_APPLICATIONS_REF_DESC = + "The uri corresponding to associated application resource of this Role."; public static final String USERS_DISPLAY_DESC = "A human-readable name for the user."; public static final String GROUPS_DISPLAY_DESC = "A human-readable name for the group."; public static final String PERMISSIONS_DISPLAY_DESC = "A human-readable name for the permission."; @@ -595,10 +598,14 @@ public static class RoleSchemaConstants { "urn:ietf:params:scim:schemas:extension:2.0:Role:permissions.value"; public static final String PERMISSIONS_DISPLAY_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:permissions.display"; - public static final String ASC_APPLICATION_VALUE_URI = + public static final String PERMISSIONS_REF_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:permissions.$ref"; + public static final String ASC_APPLICATIONS_VALUE_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:associatedApplications.value"; - public static final String ASC_APPLICATION_DISPLAY_URI = + public static final String ASC_APPLICATIONS_DISPLAY_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:associatedApplications.display"; + public static final String ASC_APPLICATIONS_REF_URI = + "urn:ietf:params:scim:schemas:extension:2.0:Role:associatedApplications.$ref"; public static final String AUDIENCE_VALUE_URI = "urn:ietf:params:scim:schemas:extension:2.0:Role:audience.value"; public static final String AUDIENCE_DISPLAY_URI = diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java index 18658bbe4..b82e05e55 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMSchemaDefinitions.java @@ -1065,7 +1065,7 @@ public static class SCIMRoleSchemaDefinition { SCIMDefinitions.Uniqueness.NONE, null, null, null); // Identifier of the permission of this Role. - public static final SCIMAttributeSchema PERMISSION_VALUE = + public static final SCIMAttributeSchema PERMISSIONS_VALUE = SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.PERMISSIONS_VALUE_URI, SCIMConstants.RoleSchemaConstants.VALUE, SCIMDefinitions.DataType.STRING, false, SCIMConstants.RoleSchemaConstants.PERMISSIONS_VALUE_DESC, false, false, @@ -1073,31 +1073,48 @@ public static class SCIMRoleSchemaDefinition { SCIMDefinitions.Uniqueness.NONE, null, null, null); // A human-readable name of the permission of this Role. - public static final SCIMAttributeSchema PERMISSION_DISPLAY = + public static final SCIMAttributeSchema PERMISSIONS_DISPLAY = SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.PERMISSIONS_DISPLAY_URI, SCIMConstants.RoleSchemaConstants.DISPLAY, SCIMDefinitions.DataType.STRING, false, SCIMConstants.RoleSchemaConstants.PERMISSIONS_DISPLAY_DESC, false, false, SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, null); + // The uri corresponding to permission of a Role. + public static final SCIMAttributeSchema PERMISSIONS_REF = + SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.PERMISSIONS_REF_URI, + SCIMConstants.CommonSchemaConstants.REF, SCIMDefinitions.DataType.REFERENCE, false, + SCIMConstants.RoleSchemaConstants.PERMISSIONS_REF_DESC, false, false, + SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, + new ArrayList<>(Arrays.asList(SCIMDefinitions.ReferenceType.URI)), null); + // Identifier of the associated application of this Role. - public static final SCIMAttributeSchema ASC_APPLICATION_VALUE = + public static final SCIMAttributeSchema ASC_APPLICATIONS_VALUE = SCIMAttributeSchema.createSCIMAttributeSchema( - SCIMConstants.RoleSchemaConstants.ASC_APPLICATION_VALUE_URI, + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_VALUE_URI, SCIMConstants.RoleSchemaConstants.VALUE, SCIMDefinitions.DataType.STRING, false, SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_VALUE_DESC, false, false, SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, null); // A human-readable name of the associated application of this Role. - public static final SCIMAttributeSchema ASC_APPLICATION_DISPLAY = + public static final SCIMAttributeSchema ASC_APPLICATIONS_DISPLAY = SCIMAttributeSchema.createSCIMAttributeSchema( - SCIMConstants.RoleSchemaConstants.ASC_APPLICATION_DISPLAY_URI, + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_DISPLAY_URI, SCIMConstants.RoleSchemaConstants.DISPLAY, SCIMDefinitions.DataType.STRING, false, SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_DISPLAY_DESC, false, false, SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, null); + // The uri corresponding to an associated application of this Role. + public static final SCIMAttributeSchema ASC_APPLICATIONS_REF = SCIMAttributeSchema.createSCIMAttributeSchema( + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_REF_URI, SCIMConstants.CommonSchemaConstants.REF, + SCIMDefinitions.DataType.REFERENCE, false, SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_REF_DESC, + false, false, SCIMDefinitions.Mutability.IMMUTABLE, SCIMDefinitions.Returned.DEFAULT, + SCIMDefinitions.Uniqueness.NONE, null, + new ArrayList<>(Arrays.asList(SCIMDefinitions.ReferenceType.URI)), null); + // Identifier of the role's audience. public static final SCIMAttributeSchema AUDIENCE_VALUE = SCIMAttributeSchema.createSCIMAttributeSchema(SCIMConstants.RoleSchemaConstants.AUDIENCE_VALUE_URI, @@ -1180,7 +1197,7 @@ public static class SCIMRoleSchemaDefinition { SCIMConstants.RoleSchemaConstants.PERMISSIONS_DESC, false, false, SCIMDefinitions.Mutability.READ_WRITE, SCIMDefinitions.Returned.DEFAULT, SCIMDefinitions.Uniqueness.NONE, null, null, - new ArrayList<>(Arrays.asList(PERMISSION_VALUE, PERMISSION_DISPLAY))); + new ArrayList<>(Arrays.asList(PERMISSIONS_VALUE, PERMISSIONS_DISPLAY, PERMISSIONS_REF))); // A list of associated applications of the Role. public static final SCIMAttributeSchema ASSOCIATED_APPLICATIONS = @@ -1188,8 +1205,8 @@ public static class SCIMRoleSchemaDefinition { SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS, SCIMDefinitions.DataType.COMPLEX, true, SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS_DESC, false, false, SCIMDefinitions.Mutability.READ_ONLY, SCIMDefinitions.Returned.DEFAULT, - SCIMDefinitions.Uniqueness.NONE, null, null, - new ArrayList<>(Arrays.asList(ASC_APPLICATION_VALUE, ASC_APPLICATION_DISPLAY))); + SCIMDefinitions.Uniqueness.NONE, null, null, new ArrayList<>( + Arrays.asList(ASC_APPLICATIONS_VALUE, ASC_APPLICATIONS_DISPLAY, ASC_APPLICATIONS_REF))); } /** From ccf0c9f275f04a2dbdad5c6c04ba371b2f7c5aa7 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 21 Oct 2023 14:37:07 +0530 Subject: [PATCH 10/11] remove additional new line --- .../main/java/org/wso2/charon3/core/schema/SCIMConstants.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java index 0be25031e..7772c8b30 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/schema/SCIMConstants.java @@ -109,7 +109,6 @@ public static class CommonSchemaConstants { public static final String AUDIENCE_DISPLAY = "audienceDisplay"; public static final String AUDIENCE_TYPE = "audienceType"; - /*******Attributes descriptions of the attributes found in Common Schema.***************/ public static final String ID_DESC = "Unique identifier for the SCIM Resource as defined by the Service " + From 25b26c2228a54f30201b37c15e189987e55ccf32 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 21 Oct 2023 20:59:30 +0530 Subject: [PATCH 11/11] refactor code --- .../org/wso2/charon3/core/objects/RoleV2.java | 244 +++++------------- .../org/wso2/charon3/core/objects/User.java | 4 - 2 files changed, 61 insertions(+), 187 deletions(-) diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java index cf5344b3c..107d2e1ce 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/RoleV2.java @@ -100,24 +100,8 @@ public void replaceDisplayName(String displayName) { */ public List getUsers() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { - return Collections.emptyList(); - } - List userList = new ArrayList<>(); - MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.USERS); - List subValuesList = users.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || - !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - continue; - } - userList.add((String) ((SimpleAttribute) (subAttributesList.get( - SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } - return userList; + return getSubAttributeValuesListInMultiValuedComplexAttribute(SCIMConstants.RoleSchemaConstants.USERS, + SCIMConstants.CommonSchemaConstants.VALUE); } /** @@ -127,27 +111,8 @@ public List getUsers() { */ public List getUsersWithDisplayName() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.USERS)) { - return Collections.emptyList(); - } - MultiValuedAttribute users = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.USERS); - List subValuesList = users.getAttributeValues(); - if (subValuesList == null) { - return Collections.emptyList(); - } - List displayNames = new ArrayList<>(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || - !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - continue; - } - displayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } - return displayNames; + return getSubAttributeValuesListInMultiValuedComplexAttribute(SCIMConstants.RoleSchemaConstants.USERS, + SCIMConstants.CommonSchemaConstants.DISPLAY); } /** @@ -225,27 +190,8 @@ private ComplexAttribute processUser(User user) throws BadRequestException, Char */ public List getGroups() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { - return Collections.emptyList(); - } - MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.GROUPS); - List subValuesList = groups.getAttributeValues(); - if (subValuesList == null) { - return Collections.emptyList(); - } - List groupList = new ArrayList<>(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || - !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - continue; - } - groupList.add((String) ((SimpleAttribute) (subAttributesList.get( - SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } - return groupList; + return getSubAttributeValuesListInMultiValuedComplexAttribute(SCIMConstants.RoleSchemaConstants.GROUPS, + SCIMConstants.CommonSchemaConstants.VALUE); } /** @@ -255,29 +201,8 @@ public List getGroups() { */ public List getGroupsWithDisplayName() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.GROUPS)) { - return Collections.emptyList(); - } - List displayNames = new ArrayList<>(); - MultiValuedAttribute groups = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.GROUPS); - List values = groups.getAttributeValues(); - if (values == null) { - return displayNames; - } - List subValuesList = groups.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || !subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - continue; - } - displayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - - } - return displayNames; + return getSubAttributeValuesListInMultiValuedComplexAttribute(SCIMConstants.RoleSchemaConstants.GROUPS, + SCIMConstants.CommonSchemaConstants.DISPLAY); } /** @@ -366,27 +291,8 @@ public void setSchemas() { */ public List getPermissionValues() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { - return Collections.emptyList(); - } - MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); - List subValuesList = permissions.getAttributeValues(); - List permissionValuesList = new ArrayList<>(); - if (subValuesList == null) { - return Collections.emptyList(); - } - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || - !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - continue; - } - permissionValuesList.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } - return permissionValuesList; + return getSubAttributeValuesListInMultiValuedComplexAttribute(SCIMConstants.RoleSchemaConstants.PERMISSIONS, + SCIMConstants.CommonSchemaConstants.VALUE); } /** @@ -396,28 +302,8 @@ public List getPermissionValues() { */ public List getPermissionDisplayNames() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.PERMISSIONS)) { - return Collections.emptyList(); - } - MultiValuedAttribute permissions = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.PERMISSIONS); - List values = permissions.getAttributeValues(); - List permissionDisplayNames = new ArrayList<>(); - if (values == null) { - return Collections.emptyList(); - } - List subValuesList = permissions.getAttributeValues(); - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || !subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - continue; - } - permissionDisplayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } - return permissionDisplayNames; + return getSubAttributeValuesListInMultiValuedComplexAttribute(SCIMConstants.RoleSchemaConstants.PERMISSIONS, + SCIMConstants.CommonSchemaConstants.DISPLAY); } /** @@ -451,27 +337,9 @@ public void setPermissions(List permissionsList) { */ public List getAssociatedApplicationValues() { - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { - return Collections.emptyList(); - } - MultiValuedAttribute associatedApps = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); - List subValuesList = associatedApps.getAttributeValues(); - List assocAppValuesList = new ArrayList<>(); - if (subValuesList == null) { - return Collections.emptyList(); - } - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || - !subAttributesList.containsKey(SCIMConstants.CommonSchemaConstants.VALUE)) { - continue; - } - assocAppValuesList.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.VALUE))).getValue()); - } - return assocAppValuesList; + return getSubAttributeValuesListInMultiValuedComplexAttribute( + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS, + SCIMConstants.CommonSchemaConstants.VALUE); } /** @@ -479,27 +347,8 @@ public List getAssociatedApplicationValues() { */ public List getAssociatedApplicationDisplayNames() { - List assocAppDisplayNames = new ArrayList<>(); - if (!this.isAttributeExist(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS)) { - return Collections.emptyList(); - } - MultiValuedAttribute associatedApps = (MultiValuedAttribute) this.attributeList - .get(SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS); - List subValuesList = associatedApps.getAttributeValues(); - if (subValuesList == null) { - return Collections.emptyList(); - } - for (Attribute subValue : subValuesList) { - ComplexAttribute complexAttribute = (ComplexAttribute) subValue; - Map subAttributesList = complexAttribute.getSubAttributesList(); - if (subAttributesList == null || !subAttributesList - .containsKey(SCIMConstants.CommonSchemaConstants.DISPLAY)) { - continue; - } - assocAppDisplayNames.add((String) ((SimpleAttribute) (subAttributesList - .get(SCIMConstants.CommonSchemaConstants.DISPLAY))).getValue()); - } - return assocAppDisplayNames; + return getSubAttributeValuesListInMultiValuedComplexAttribute( + SCIMConstants.RoleSchemaConstants.ASC_APPLICATIONS, SCIMConstants.CommonSchemaConstants.DISPLAY); } /** @@ -544,11 +393,8 @@ public ComplexAttribute getAudience() { */ public String getAudienceValue() { - SCIMAttributeSchema audienceDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE; - SCIMAttributeSchema audienceValueDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_VALUE; - return getComplexAttribute(audienceDefinition).map(aud -> getSimpleAttribute(audienceValueDefinition, aud) - .map(rethrowFunction(SimpleAttribute::getStringValue)) - .orElse(null)).orElse(null); + return getSubAttributeOfComplexAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE, + SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_VALUE); } /** @@ -556,11 +402,8 @@ public String getAudienceValue() { */ public String getAudienceDisplayName() { - SCIMAttributeSchema audienceDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE; - SCIMAttributeSchema audienceDisplayDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_DISPLAY; - return getComplexAttribute(audienceDefinition).map(aud -> getSimpleAttribute(audienceDisplayDefinition, aud) - .map(rethrowFunction(SimpleAttribute::getStringValue)) - .orElse(null)).orElse(null); + return getSubAttributeOfComplexAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE, + SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_DISPLAY); } /** @@ -568,11 +411,8 @@ public String getAudienceDisplayName() { */ public String getAudienceType() { - SCIMAttributeSchema audienceDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE; - SCIMAttributeSchema audienceTypeDefinition = SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_TYPE; - return getComplexAttribute(audienceDefinition).map(aud -> getSimpleAttribute(audienceTypeDefinition, aud) - .map(rethrowFunction(SimpleAttribute::getStringValue)) - .orElse(null)).orElse(null); + return getSubAttributeOfComplexAttribute(SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE, + SCIMSchemaDefinitions.SCIMRoleSchemaDefinition.AUDIENCE_TYPE); } /** @@ -646,4 +486,42 @@ public void setSystemRole(boolean isSystemRole) throws CharonException, BadReque getMetaAttribute().setSubAttribute(systemRoleAttribute); } } + + private List getSubAttributeValuesListInMultiValuedComplexAttribute(String multiValuedAttributeName, + String subAttributeName) { + + if (!this.isAttributeExist(multiValuedAttributeName)) { + return Collections.emptyList(); + } + MultiValuedAttribute multiValuedAttribute = + (MultiValuedAttribute) this.attributeList.get(multiValuedAttributeName); + List subValuesList = multiValuedAttribute.getAttributeValues(); + if (subValuesList == null) { + return Collections.emptyList(); + } + return getSubAttributeValues(subAttributeName, subValuesList); + } + + private List getSubAttributeValues(String subAttributeName, List subValuesList) { + + List subAttributeValues = new ArrayList<>(); + for (Attribute subValue : subValuesList) { + ComplexAttribute complexAttribute = (ComplexAttribute) subValue; + Map subAttributesList = complexAttribute.getSubAttributesList(); + if (subAttributesList == null || !subAttributesList.containsKey(subAttributeName)) { + continue; + } + subAttributeValues.add((String) ((SimpleAttribute) (subAttributesList.get(subAttributeName))).getValue()); + } + return subAttributeValues; + } + + private String getSubAttributeOfComplexAttribute(SCIMAttributeSchema complexAttributeSchema, + SCIMAttributeSchema subAttributeSchema) { + + return getComplexAttribute(complexAttributeSchema).map( + complexAttribute -> getSimpleAttribute(subAttributeSchema, complexAttribute) + .map(rethrowFunction(SimpleAttribute::getStringValue)) + .orElse(null)).orElse(null); + } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java index 71db9e652..d4dc5ab32 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/objects/User.java @@ -927,10 +927,6 @@ private void setRole(ComplexAttribute groupPropertiesAttribute) throws CharonExc public void setRoleV2(RoleV2 role) throws CharonException, BadRequestException { SimpleAttribute valueSimpleAttribute = null; - SimpleAttribute displaySimpleAttribute; - SimpleAttribute audienceValueSimpleAttribute; - SimpleAttribute audienceDisplaySimpleAttribute; - SimpleAttribute audienceTypeSimpleAttribute; String reference = role.getLocation(); String value = role.getId(); String display = role.getDisplayName();