Search in sources :

Example 21 with JSONDecoder

use of org.wso2.charon3.core.encoder.JSONDecoder in project charon by wso2.

the class UserResourceManager method updateWithPATCH.

/**
 * Update the user resource by sequence of operations.
 *
 * @param existingId
 * @param scimObjectString
 * @param userManager
 * @param attributes
 * @param excludeAttributes
 * @return
 */
public SCIMResponse updateWithPATCH(String existingId, String scimObjectString, UserManager userManager, String attributes, String excludeAttributes) {
    try {
        if (userManager == null) {
            String error = "Provided user manager handler is null.";
            throw new InternalErrorException(error);
        }
        // obtain the json decoder.
        JSONDecoder decoder = getDecoder();
        // decode the SCIM User object, encoded in the submitted payload.
        List<PatchOperation> opList = decoder.decodeRequest(scimObjectString);
        SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getUserResourceSchema();
        // get the user from the user core
        User oldUser = userManager.getUser(existingId, ResourceManagerUtil.getAllAttributeURIs(schema));
        if (oldUser == null) {
            throw new NotFoundException("No user with the id : " + existingId + " in the user store.");
        }
        // make a copy of the original user
        User copyOfOldUser = (User) CopyUtil.deepCopy(oldUser);
        // make another copy of original user.
        // this will be used to restore to the original condition if failure occurs.
        User originalUser = (User) CopyUtil.deepCopy(copyOfOldUser);
        User newUser = null;
        for (PatchOperation operation : opList) {
            if (operation.getOperation().equals(SCIMConstants.OperationalConstants.ADD)) {
                if (newUser == null) {
                    newUser = (User) PatchOperationUtil.doPatchAdd(operation, getDecoder(), oldUser, copyOfOldUser, schema);
                    copyOfOldUser = (User) CopyUtil.deepCopy(newUser);
                } else {
                    newUser = (User) PatchOperationUtil.doPatchAdd(operation, getDecoder(), newUser, copyOfOldUser, schema);
                    copyOfOldUser = (User) CopyUtil.deepCopy(newUser);
                }
            } else if (operation.getOperation().equals(SCIMConstants.OperationalConstants.REMOVE)) {
                if (newUser == null) {
                    newUser = (User) PatchOperationUtil.doPatchRemove(operation, oldUser, copyOfOldUser, schema);
                    copyOfOldUser = (User) CopyUtil.deepCopy(newUser);
                } else {
                    newUser = (User) PatchOperationUtil.doPatchRemove(operation, newUser, copyOfOldUser, schema);
                    copyOfOldUser = (User) CopyUtil.deepCopy(newUser);
                }
            } else if (operation.getOperation().equals(SCIMConstants.OperationalConstants.REPLACE)) {
                if (newUser == null) {
                    newUser = (User) PatchOperationUtil.doPatchReplace(operation, getDecoder(), oldUser, copyOfOldUser, schema);
                    copyOfOldUser = (User) CopyUtil.deepCopy(newUser);
                } else {
                    newUser = (User) PatchOperationUtil.doPatchReplace(operation, getDecoder(), newUser, copyOfOldUser, schema);
                    copyOfOldUser = (User) CopyUtil.deepCopy(newUser);
                }
            } else {
                throw new BadRequestException("Unknown operation.", ResponseCodeConstants.INVALID_SYNTAX);
            }
        }
        // get the URIs of required attributes which must be given a value
        Map<String, Boolean> requiredAttributes = ResourceManagerUtil.getOnlyRequiredAttributesURIs((SCIMResourceTypeSchema) CopyUtil.deepCopy(schema), attributes, excludeAttributes);
        User validatedUser = (User) ServerSideValidator.validateUpdatedSCIMObject(originalUser, newUser, schema);
        newUser = userManager.updateUser(validatedUser, requiredAttributes);
        // encode the newly created SCIM user object and add id attribute to Location header.
        String encodedUser;
        Map<String, String> httpHeaders = new HashMap<String, String>();
        if (newUser != null) {
            // create a deep copy of the user object since we are going to change it.
            User copiedUser = (User) CopyUtil.deepCopy(newUser);
            // need to remove password before returning
            ServerSideValidator.validateReturnedAttributes(copiedUser, attributes, excludeAttributes);
            encodedUser = getEncoder().encodeSCIMObject(copiedUser);
            // add location header
            httpHeaders.put(SCIMConstants.LOCATION_HEADER, getResourceEndpointURL(SCIMConstants.USER_ENDPOINT) + "/" + newUser.getId());
            httpHeaders.put(SCIMConstants.CONTENT_TYPE_HEADER, SCIMConstants.APPLICATION_JSON);
        } else {
            String error = "Updated User resource is null.";
            throw new CharonException(error);
        }
        // put the URI of the User object in the response header parameter.
        return new SCIMResponse(ResponseCodeConstants.CODE_OK, encodedUser, httpHeaders);
    } catch (NotFoundException e) {
        return AbstractResourceManager.encodeSCIMException(e);
    } catch (BadRequestException e) {
        return AbstractResourceManager.encodeSCIMException(e);
    } catch (NotImplementedException e) {
        return AbstractResourceManager.encodeSCIMException(e);
    } catch (CharonException e) {
        return AbstractResourceManager.encodeSCIMException(e);
    } catch (InternalErrorException e) {
        return AbstractResourceManager.encodeSCIMException(e);
    } catch (RuntimeException e) {
        CharonException e1 = new CharonException("Error in performing the patch operation on user resource.", e);
        return AbstractResourceManager.encodeSCIMException(e1);
    }
}
Also used : User(org.wso2.charon3.core.objects.User) HashMap(java.util.HashMap) NotImplementedException(org.wso2.charon3.core.exceptions.NotImplementedException) NotFoundException(org.wso2.charon3.core.exceptions.NotFoundException) InternalErrorException(org.wso2.charon3.core.exceptions.InternalErrorException) JSONDecoder(org.wso2.charon3.core.encoder.JSONDecoder) PatchOperation(org.wso2.charon3.core.utils.codeutils.PatchOperation) BadRequestException(org.wso2.charon3.core.exceptions.BadRequestException) SCIMResourceTypeSchema(org.wso2.charon3.core.schema.SCIMResourceTypeSchema) CharonException(org.wso2.charon3.core.exceptions.CharonException) SCIMResponse(org.wso2.charon3.core.protocol.SCIMResponse)

Example 22 with JSONDecoder

use of org.wso2.charon3.core.encoder.JSONDecoder in project charon by wso2.

the class PatchOperationUtil method doPatchReplaceOnPathWithFilters.

/*
     * This method is to do patch replace for level three attributes with a filter and path value present.
     * @param oldResource
     * @param copyOfOldResource
     * @param schema
     * @param decoder
     * @param operation
     * @param parts
     * @throws NotImplementedException
     * @throws BadRequestException
     * @throws CharonException
     * @throws JSONException
     * @throws InternalErrorException
     */
private static void doPatchReplaceOnPathWithFilters(AbstractSCIMObject oldResource, SCIMResourceTypeSchema schema, JSONDecoder decoder, PatchOperation operation, String[] parts) throws NotImplementedException, BadRequestException, CharonException, JSONException, InternalErrorException {
    if (parts.length != 1) {
        // currently we only support simple filters here.
        String[] filterParts = parts[1].split(" ");
        ExpressionNode expressionNode = new ExpressionNode();
        expressionNode.setAttributeValue(filterParts[0]);
        expressionNode.setOperation(filterParts[1]);
        expressionNode.setValue(filterParts[2]);
        if (expressionNode.getOperation().equalsIgnoreCase((SCIMConstants.OperationalConstants.EQ).trim())) {
            if (parts.length == 3) {
                parts[0] = parts[0] + parts[2];
            }
            String[] attributeParts = parts[0].split("[\\.]");
            if (attributeParts.length == 1) {
                doPatchReplaceWithFiltersForLevelOne(oldResource, attributeParts, expressionNode, operation, schema, decoder);
            } else if (attributeParts.length == 2) {
                doPatchReplaceWithFiltersForLevelTwo(oldResource, attributeParts, expressionNode, operation, schema, decoder);
            } else if (attributeParts.length == 3) {
                doPatchReplaceWithFiltersForLevelThree(oldResource, attributeParts, expressionNode, operation, schema, decoder);
            }
        } else {
            throw new NotImplementedException("Only Eq filter is supported");
        }
    }
}
Also used : ExpressionNode(org.wso2.charon3.core.utils.codeutils.ExpressionNode) NotImplementedException(org.wso2.charon3.core.exceptions.NotImplementedException)

Example 23 with JSONDecoder

use of org.wso2.charon3.core.encoder.JSONDecoder in project charon by wso2.

the class PatchOperationUtil method doPatchReplaceOnResource.

/*
     *
     * @param oldResource
     * @param copyOfOldResource
     * @param schema
     * @param decoder
     * @param operation
     * @return
     * @throws CharonException
     */
private static AbstractSCIMObject doPatchReplaceOnResource(AbstractSCIMObject oldResource, AbstractSCIMObject copyOfOldResource, SCIMResourceTypeSchema schema, JSONDecoder decoder, PatchOperation operation) throws CharonException {
    try {
        AbstractSCIMObject attributeHoldingSCIMObject = decoder.decode(operation.getValues().toString(), schema);
        if (oldResource != null) {
            for (String attributeName : attributeHoldingSCIMObject.getAttributeList().keySet()) {
                Attribute oldAttribute = oldResource.getAttribute(attributeName);
                if (oldAttribute != null) {
                    // if the attribute is there, append it.
                    if (oldAttribute.getMultiValued()) {
                        // this is multivalued complex case.
                        MultiValuedAttribute attributeValue = (MultiValuedAttribute) attributeHoldingSCIMObject.getAttribute(attributeName);
                        if (oldAttribute.getMutability().equals(SCIMDefinitions.Mutability.IMMUTABLE) || oldAttribute.getMutability().equals(SCIMDefinitions.Mutability.READ_ONLY)) {
                            throw new BadRequestException("Immutable or Read-Only attributes can not be modified.", ResponseCodeConstants.MUTABILITY);
                        } else {
                            // delete the old attribute
                            oldResource.deleteAttribute(attributeName);
                            // replace with new attribute
                            oldResource.setAttribute(attributeValue);
                        }
                    } else if (oldAttribute.getType().equals(SCIMDefinitions.DataType.COMPLEX)) {
                        // this is the complex attribute case.
                        Map<String, Attribute> subAttributeList = ((ComplexAttribute) attributeHoldingSCIMObject.getAttribute(attributeName)).getSubAttributesList();
                        for (Map.Entry<String, Attribute> subAttrib : subAttributeList.entrySet()) {
                            Attribute subAttribute = oldAttribute.getSubAttribute(subAttrib.getKey());
                            if (subAttribute != null) {
                                if (subAttribute.getType().equals(SCIMDefinitions.DataType.COMPLEX)) {
                                    if (subAttribute.getMultiValued()) {
                                        // extension schema is the only one who reaches here.
                                        MultiValuedAttribute attributeSubValue = (MultiValuedAttribute) ((ComplexAttribute) attributeHoldingSCIMObject.getAttribute(attributeName)).getSubAttribute(subAttrib.getKey());
                                        if (subAttribute.getMutability().equals(SCIMDefinitions.Mutability.IMMUTABLE) || subAttribute.getMutability().equals(SCIMDefinitions.Mutability.READ_ONLY)) {
                                            throw new BadRequestException("Immutable or Read-Only attributes can not be modified.", ResponseCodeConstants.MUTABILITY);
                                        } else {
                                            // delete the old attribute
                                            ((ComplexAttribute) (oldAttribute)).removeSubAttribute(subAttribute.getName());
                                            // replace with new attribute
                                            ((ComplexAttribute) (oldAttribute)).setSubAttribute(attributeSubValue);
                                        }
                                    } else {
                                        // extension schema is the only one who reaches here.
                                        Map<String, Attribute> subSubAttributeList = ((ComplexAttribute) (attributeHoldingSCIMObject.getAttribute(attributeName).getSubAttribute(subAttrib.getKey()))).getSubAttributesList();
                                        for (Map.Entry<String, Attribute> subSubAttrb : subSubAttributeList.entrySet()) {
                                            Attribute subSubAttribute = oldAttribute.getSubAttribute(subAttrib.getKey()).getSubAttribute(subSubAttrb.getKey());
                                            if (subSubAttribute != null) {
                                                if (subSubAttribute.getMultiValued()) {
                                                    if (subSubAttribute.getMutability().equals(SCIMDefinitions.Mutability.IMMUTABLE) || subSubAttribute.getMutability().equals(SCIMDefinitions.Mutability.READ_ONLY)) {
                                                        throw new BadRequestException("Immutable or Read-Only attributes " + "can not be modified.", ResponseCodeConstants.MUTABILITY);
                                                    } else {
                                                        // delete the old attribute
                                                        ((ComplexAttribute) (oldAttribute.getSubAttribute(subAttrib.getKey()))).removeSubAttribute(subSubAttribute.getName());
                                                        // replace with new attribute
                                                        ((ComplexAttribute) (oldAttribute.getSubAttribute(subAttrib.getKey()))).setSubAttribute(subSubAttribute);
                                                    }
                                                } else {
                                                    ((SimpleAttribute) subSubAttribute).setValue(((SimpleAttribute) subSubAttrb.getValue()));
                                                }
                                            } else {
                                                ((ComplexAttribute) (subAttribute)).setSubAttribute(subSubAttrb.getValue());
                                            }
                                        }
                                    }
                                } else {
                                    if (subAttribute.getMutability().equals(SCIMDefinitions.Mutability.IMMUTABLE) || subAttribute.getMutability().equals(SCIMDefinitions.Mutability.READ_ONLY)) {
                                        throw new BadRequestException("Immutable or Read-Only " + "attributes can not be modified.", ResponseCodeConstants.MUTABILITY);
                                    } else {
                                        // delete the old attribute
                                        ((ComplexAttribute) (oldAttribute)).removeSubAttribute(subAttribute.getName());
                                        // replace with new attribute
                                        ((ComplexAttribute) (oldAttribute)).setSubAttribute(subAttributeList.get(subAttribute.getName()));
                                    }
                                }
                            } else {
                                // add the attribute
                                ((ComplexAttribute) oldAttribute).setSubAttribute(subAttrib.getValue());
                            }
                        }
                    } else {
                        if (oldAttribute.getMutability().equals(SCIMDefinitions.Mutability.IMMUTABLE) || oldAttribute.getMutability().equals(SCIMDefinitions.Mutability.READ_ONLY)) {
                            throw new BadRequestException("Immutable or Read-Only attributes can not be modified.", ResponseCodeConstants.MUTABILITY);
                        } else {
                            // this is the simple attribute case.replace the value
                            ((SimpleAttribute) oldAttribute).setValue(((SimpleAttribute) attributeHoldingSCIMObject.getAttribute(oldAttribute.getName())).getValue());
                        }
                    }
                } else {
                    // add the attribute
                    oldResource.setAttribute(attributeHoldingSCIMObject.getAttributeList().get(attributeName));
                }
            }
            AbstractSCIMObject validatedResource = ServerSideValidator.validateUpdatedSCIMObject(copyOfOldResource, oldResource, schema);
            return validatedResource;
        } else {
            throw new CharonException("Error in getting the old resource.");
        }
    } catch (BadRequestException | CharonException e) {
        throw new CharonException("Error in performing the add operation", e);
    }
}
Also used : AbstractSCIMObject(org.wso2.charon3.core.objects.AbstractSCIMObject) MultiValuedAttribute(org.wso2.charon3.core.attributes.MultiValuedAttribute) SimpleAttribute(org.wso2.charon3.core.attributes.SimpleAttribute) ComplexAttribute(org.wso2.charon3.core.attributes.ComplexAttribute) Attribute(org.wso2.charon3.core.attributes.Attribute) SimpleAttribute(org.wso2.charon3.core.attributes.SimpleAttribute) ComplexAttribute(org.wso2.charon3.core.attributes.ComplexAttribute) BadRequestException(org.wso2.charon3.core.exceptions.BadRequestException) CharonException(org.wso2.charon3.core.exceptions.CharonException) Map(java.util.Map) MultiValuedAttribute(org.wso2.charon3.core.attributes.MultiValuedAttribute)

Aggregations

BadRequestException (org.wso2.charon3.core.exceptions.BadRequestException)22 CharonException (org.wso2.charon3.core.exceptions.CharonException)15 JSONDecoder (org.wso2.charon3.core.encoder.JSONDecoder)14 InternalErrorException (org.wso2.charon3.core.exceptions.InternalErrorException)14 SCIMResourceTypeSchema (org.wso2.charon3.core.schema.SCIMResourceTypeSchema)14 HashMap (java.util.HashMap)13 NotFoundException (org.wso2.charon3.core.exceptions.NotFoundException)13 SCIMResponse (org.wso2.charon3.core.protocol.SCIMResponse)13 JSONEncoder (org.wso2.charon3.core.encoder.JSONEncoder)10 NotImplementedException (org.wso2.charon3.core.exceptions.NotImplementedException)10 Attribute (org.wso2.charon3.core.attributes.Attribute)7 ComplexAttribute (org.wso2.charon3.core.attributes.ComplexAttribute)7 MultiValuedAttribute (org.wso2.charon3.core.attributes.MultiValuedAttribute)7 SimpleAttribute (org.wso2.charon3.core.attributes.SimpleAttribute)7 User (org.wso2.charon3.core.objects.User)7 JSONException (org.json.JSONException)6 AttributeSchema (org.wso2.charon3.core.schema.AttributeSchema)6 JSONArray (org.json.JSONArray)5 AbstractSCIMObject (org.wso2.charon3.core.objects.AbstractSCIMObject)5 JSONObject (org.json.JSONObject)4