Update vulnerable package dependencies
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / GroupBusinessLogicNew.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.impl;
23
24 import static org.openecomp.sdc.be.components.impl.BaseBusinessLogic.enumHasValueFilter;
25
26 import java.util.ArrayList;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.stream.Collectors;
32 import org.apache.commons.collections.CollectionUtils;
33 import org.apache.commons.collections.MapUtils;
34 import org.apache.commons.lang3.StringUtils;
35 import org.apache.commons.lang3.math.NumberUtils;
36 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
37 import org.openecomp.sdc.be.components.impl.lock.LockingTransactional;
38 import org.openecomp.sdc.be.components.validation.AccessValidations;
39 import org.openecomp.sdc.be.components.validation.ComponentValidations;
40 import org.openecomp.sdc.be.dao.api.ActionStatus;
41 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
42 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
43 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
44 import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
45 import org.openecomp.sdc.be.model.Component;
46 import org.openecomp.sdc.be.model.ComponentInstance;
47 import org.openecomp.sdc.be.model.GroupDefinition;
48 import org.openecomp.sdc.be.model.GroupProperty;
49 import org.openecomp.sdc.be.model.PropertyDefinition;
50 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
51 import org.openecomp.sdc.be.model.operations.StorageException;
52 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
53 import org.openecomp.sdc.be.model.operations.impl.GroupOperation;
54 import org.openecomp.sdc.common.util.ValidationUtils;
55 import org.springframework.transaction.annotation.Transactional;
56
57 @org.springframework.stereotype.Component
58 public class GroupBusinessLogicNew {
59
60     private final AccessValidations accessValidations;
61     private final ComponentValidations componentValidations;
62     private final GroupsOperation groupsOperation;
63     private final GroupOperation groupOperation;
64
65     public GroupBusinessLogicNew(AccessValidations accessValidations, ComponentValidations componentValidations, GroupsOperation groupsOperation,
66                                  GroupOperation groupOperation) {
67         this.accessValidations = accessValidations;
68         this.componentValidations = componentValidations;
69         this.groupsOperation = groupsOperation;
70         this.groupOperation = groupOperation;
71     }
72
73     @LockingTransactional
74     public List<String> updateMembers(String componentId, ComponentTypeEnum componentType, String userId, String groupUniqueId,
75                                       List<String> members) {
76         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP MEMBERS");
77         GroupDefinition groupDefinition = getGroup(component, groupUniqueId);
78         groupDefinition.setMembers(buildMembersMap(component, members));
79         groupsOperation.updateGroupOnComponent(componentId, groupDefinition, PromoteVersionEnum.MINOR);
80         return new ArrayList<>(groupDefinition.getMembers().values());
81     }
82
83     @LockingTransactional
84     public List<GroupProperty> updateProperties(String componentId, ComponentTypeEnum componentType, String userId, String groupUniqueId,
85                                                 List<GroupProperty> newProperties) {
86         Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP PROPERTIES");
87         GroupDefinition currentGroup = getGroup(component, groupUniqueId);
88         validateUpdatedPropertiesAndSetEmptyValues(currentGroup, newProperties);
89         return groupsOperation.updateGroupPropertiesOnComponent(componentId, currentGroup, newProperties, PromoteVersionEnum.MINOR).left()
90             .on(this::onUpdatePropertyError);
91     }
92
93     @Transactional
94     public List<PropertyDataDefinition> getProperties(String componentType, String userId, String componentId, String groupUniqueId) {
95         Component component = accessValidations.validateUserCanRetrieveComponentData(componentId, componentType, userId, "GET GROUP PROPERTIES");
96         GroupDefinition currentGroup = getGroup(component, groupUniqueId);
97         return currentGroup.getProperties();
98     }
99
100     private List<GroupProperty> onUpdatePropertyError(StorageOperationStatus storageOperationStatus) {
101         throw new StorageException(storageOperationStatus);
102     }
103
104     private Map<String, String> buildMembersMap(Component component, List<String> newMemberUniqueIds) {
105         Map<String, String> nameToUniqueId = new HashMap<>();
106         for (String memberUniqueId : newMemberUniqueIds) {
107             ComponentInstance componentInstance = getComponentInstance(component, memberUniqueId);
108             nameToUniqueId.put(componentInstance.getName(), componentInstance.getUniqueId());
109         }
110         return nameToUniqueId;
111     }
112
113     private ComponentInstance getComponentInstance(Component component, String memberUniqueId) {
114         return componentValidations.getComponentInstance(component, memberUniqueId).orElseThrow(
115             () -> new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, memberUniqueId, "",
116                 component.getActualComponentType(), component.getSystemName()));
117     }
118
119     private GroupDefinition getGroup(Component component, String groupUniqueId) {
120         return component.getGroupById(groupUniqueId).orElseThrow(
121             () -> new ByActionStatusComponentException(ActionStatus.GROUP_IS_MISSING, component.getSystemName(), component.getActualComponentType()));
122     }
123
124     private void validateUpdatedPropertiesAndSetEmptyValues(GroupDefinition originalGroup, List<GroupProperty> groupPropertiesToUpdate) {
125         if (CollectionUtils.isEmpty(groupPropertiesToUpdate)) {
126             throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, StringUtils.EMPTY);
127         }
128         if (CollectionUtils.isEmpty(originalGroup.getProperties())) {
129             throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND,
130                 groupPropertiesToUpdate.get(NumberUtils.INTEGER_ZERO).getName());
131         }
132         Map<String, GroupProperty> originalProperties = originalGroup.convertToGroupProperties().stream()
133             .collect(Collectors.toMap(PropertyDataDefinition::getName, p -> p));
134         for (GroupProperty gp : groupPropertiesToUpdate) {
135             String updatedPropertyName = gp.getName();
136             if (!originalProperties.containsKey(updatedPropertyName)) {
137                 throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, updatedPropertyName);
138             }
139             if (!isOnlyGroupPropertyValueChanged(gp, originalProperties.get(updatedPropertyName))) {
140                 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY, updatedPropertyName);
141             }
142             if (StringUtils.isEmpty(gp.getValue())) {
143                 gp.setValue(originalProperties.get(updatedPropertyName).getDefaultValue());
144             }
145             StorageOperationStatus sos = groupOperation.validateAndUpdatePropertyValue(gp);
146             if (StorageOperationStatus.OK != sos) {
147                 throw new StorageException(sos, updatedPropertyName);
148             }
149         }
150         validatePropertyBusinessLogic(groupPropertiesToUpdate, originalGroup);
151     }
152
153     private void validatePropertyBusinessLogic(List<GroupProperty> groupPropertiesToUpdate, GroupDefinition originalGroup) {
154         Map<PropertyDefinition.PropertyNames, String> enumValueMap = new EnumMap<>(PropertyDefinition.PropertyNames.class);
155         for (GroupProperty gp : groupPropertiesToUpdate) {
156             // Filter out non special properties which does not have Enum
157             final PropertyDefinition.PropertyNames gpEnum = PropertyDefinition.PropertyNames.findName(gp.getName());
158             if (gpEnum != null) {
159                 enumValueMap.put(gpEnum, gp.getValue());
160             }
161         }
162         if (MapUtils.isEmpty(enumValueMap)) {
163             return;
164         }
165         validateVFInstancesLogic(enumValueMap, prepareMapWithOriginalProperties(originalGroup));
166         if (enumValueMap.containsKey(PropertyDefinition.PropertyNames.VF_MODULE_DESCRIPTION) || enumValueMap
167             .containsKey(PropertyDefinition.PropertyNames.VF_MODULE_LABEL)) {
168             groupPropertiesToUpdate.stream().filter(e -> enumHasValueFilter(e.getName(), PropertyDefinition.PropertyNames::findName,
169                 PropertyDefinition.PropertyNames.VF_MODULE_DESCRIPTION, PropertyDefinition.PropertyNames.VF_MODULE_LABEL))
170                 .forEach(this::validateFreeText);
171         }
172     }
173
174     private Map<PropertyDefinition.PropertyNames, String> prepareMapWithOriginalProperties(GroupDefinition originalGroup) {
175         Map<PropertyDefinition.PropertyNames, String> oldValueMap = new EnumMap<>(PropertyDefinition.PropertyNames.class);
176         PropertyDefinition.PropertyNames[] propertiesToCheck = new PropertyDefinition.PropertyNames[]{PropertyDefinition.PropertyNames.INITIAL_COUNT,
177             PropertyDefinition.PropertyNames.MAX_INSTANCES, PropertyDefinition.PropertyNames.MIN_INSTANCES};
178         for (GroupProperty gp : originalGroup.convertToGroupProperties()) {
179             if (enumHasValueFilter(gp.getName(), PropertyDefinition.PropertyNames::findName, propertiesToCheck)) {
180                 oldValueMap.put(PropertyDefinition.PropertyNames.findName(gp.getName()), gp.getValue());
181             }
182         }
183         if (StringUtils.isEmpty(oldValueMap.get(PropertyDefinition.PropertyNames.MAX_INSTANCES))) {
184             oldValueMap.put(PropertyDefinition.PropertyNames.MAX_INSTANCES, String.valueOf(Integer.MAX_VALUE));
185         }
186         return oldValueMap;
187     }
188
189     private void validateVFInstancesLogic(Map<PropertyDefinition.PropertyNames, String> newValues,
190                                           Map<PropertyDefinition.PropertyNames, String> parentValues) {
191         if (!newValues.containsKey(PropertyDefinition.PropertyNames.INITIAL_COUNT) && !newValues
192             .containsKey(PropertyDefinition.PropertyNames.MAX_INSTANCES) && !newValues.containsKey(PropertyDefinition.PropertyNames.MIN_INSTANCES)) {
193             return;
194         }
195         int latestMaxInstances = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.MAX_INSTANCES);
196         int latestInitialCount = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.INITIAL_COUNT);
197         int latestMinInstances = getLatestIntProperty(newValues, parentValues, PropertyDefinition.PropertyNames.MIN_INSTANCES);
198         if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.INITIAL_COUNT) && (latestInitialCount > latestMaxInstances
199             || latestInitialCount < latestMinInstances)) {
200             throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE,
201                 PropertyDefinition.PropertyNames.INITIAL_COUNT.getPropertyName(), String.valueOf(latestMinInstances),
202                 String.valueOf(latestMaxInstances));
203         }
204         if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.MAX_INSTANCES) && latestMaxInstances < latestInitialCount) {
205             throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER,
206                 PropertyDefinition.PropertyNames.MAX_INSTANCES.getPropertyName(), "higher", String.valueOf(latestInitialCount));
207         }
208         if (isPropertyChanged(newValues, parentValues, PropertyDefinition.PropertyNames.MIN_INSTANCES) && latestMinInstances > latestInitialCount) {
209             throw new ByActionStatusComponentException(ActionStatus.INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER,
210                 PropertyDefinition.PropertyNames.MIN_INSTANCES.getPropertyName(), "lower", String.valueOf(latestInitialCount));
211         }
212     }
213
214     private boolean isPropertyChanged(Map<PropertyDefinition.PropertyNames, String> newValues,
215                                       Map<PropertyDefinition.PropertyNames, String> parentValues,
216                                       final PropertyDefinition.PropertyNames minInstances) {
217         return newValues.containsKey(minInstances) && !newValues.get(minInstances).equals(parentValues.get(minInstances));
218     }
219
220     private int getLatestIntProperty(Map<PropertyDefinition.PropertyNames, String> newValues,
221                                      Map<PropertyDefinition.PropertyNames, String> parentValues, PropertyDefinition.PropertyNames propertyKey) {
222         String value;
223         if (newValues.containsKey(propertyKey)) {
224             value = newValues.get(propertyKey);
225         } else {
226             value = parentValues.get(propertyKey);
227         }
228         return Integer.valueOf(value);
229     }
230
231     private boolean isOnlyGroupPropertyValueChanged(GroupProperty groupProperty1, GroupProperty groupProperty2) {
232         GroupProperty groupProperty1Duplicate = new GroupProperty(groupProperty1);
233         groupProperty1Duplicate.setValue(null);
234         groupProperty1Duplicate.setSchema(null);
235         groupProperty1Duplicate.setParentUniqueId(null);
236         GroupProperty groupProperty2Duplicate = new GroupProperty(groupProperty2);
237         groupProperty2Duplicate.setValue(null);
238         groupProperty2Duplicate.setSchema(null);
239         groupProperty2Duplicate.setParentUniqueId(null);
240         return StringUtils.equals(groupProperty1Duplicate.getValueUniqueUid(), groupProperty2Duplicate.getValueUniqueUid()) && groupProperty1Duplicate
241             .equals(groupProperty2Duplicate);
242     }
243
244     private void validateFreeText(GroupProperty groupPropertyToUpdate) {
245         final String groupTypeValue = groupPropertyToUpdate.getValue();
246         if (!org.apache.commons.lang3.StringUtils.isEmpty(groupTypeValue)) {
247             if (!ValidationUtils.validateDescriptionLength(groupTypeValue)) {
248                 throw new ByActionStatusComponentException(ActionStatus.COMPONENT_DESCRIPTION_EXCEEDS_LIMIT, NodeTypeEnum.Property.getName(),
249                     String.valueOf(ValidationUtils.COMPONENT_DESCRIPTION_MAX_LENGTH));
250             } else if (!ValidationUtils.validateIsEnglish(groupTypeValue)) {
251                 throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INVALID_DESCRIPTION, NodeTypeEnum.Property.getName());
252             }
253         }
254     }
255 }