Upgrade SDC from Titan to Janus Graph
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / UserAdminOperation.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  */
20
21 package org.openecomp.sdc.be.model.operations.impl;
22
23 import org.janusgraph.core.JanusGraphVertex;
24 import fj.data.Either;
25 import org.apache.commons.lang3.BooleanUtils;
26 import org.apache.tinkerpop.gremlin.structure.Direction;
27 import org.apache.tinkerpop.gremlin.structure.Edge;
28 import org.apache.tinkerpop.gremlin.structure.Vertex;
29 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
30 import org.openecomp.sdc.be.dao.api.ActionStatus;
31 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
32 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
33 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
34 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
35 import org.openecomp.sdc.be.dao.utils.UserStatusEnum;
36 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
37 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
38 import org.openecomp.sdc.be.model.User;
39 import org.openecomp.sdc.be.model.operations.api.IUserAdminOperation;
40 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
41 import org.openecomp.sdc.be.resources.data.UserData;
42 import org.openecomp.sdc.common.datastructure.Wrapper;
43 import org.openecomp.sdc.common.log.wrappers.Logger;
44 import org.openecomp.sdc.common.util.MethodActivationStatusEnum;
45 import org.springframework.beans.factory.annotation.Qualifier;
46 import org.springframework.stereotype.Component;
47
48 import java.util.*;
49
50 import static org.apache.commons.collections.CollectionUtils.isEmpty;
51
52 @Component("user-operation")
53 public class UserAdminOperation implements IUserAdminOperation {
54
55     private JanusGraphGenericDao janusGraphGenericDao;
56
57     public UserAdminOperation(@Qualifier("janusgraph-generic-dao")
58                                   JanusGraphGenericDao janusGraphGenericDao) {
59         super();
60         this.janusGraphGenericDao = janusGraphGenericDao;
61
62     }
63
64     private static final Logger log = Logger.getLogger(UserAdminOperation.class.getName());
65
66     @Override
67     public Either<User, ActionStatus> getUserData(String id, boolean inTransaction) {
68         return getUserData(id, true, inTransaction);
69     }
70
71     private Either<User, ActionStatus> getUserData(String id, boolean isActive, boolean inTransaction) {
72         log.debug("getUserData - start");
73         Wrapper<Either<User, ActionStatus>> resultWrapper = new Wrapper<>();
74         Wrapper<UserData> userWrapper = new Wrapper<>();
75         try {
76             validateUserExists(resultWrapper, userWrapper, id);
77
78             if (resultWrapper.isEmpty()) {
79                 validateUserData(resultWrapper, userWrapper.getInnerElement(), id);
80
81             }
82             if (resultWrapper.isEmpty()) {
83                 if (isActive) {
84                     validateActiveUser(resultWrapper, userWrapper.getInnerElement());
85                 } else {
86                     validateInActiveUser(resultWrapper, userWrapper.getInnerElement());
87                 }
88             }
89
90             if (resultWrapper.isEmpty()) {
91                 resultWrapper.setInnerElement(Either.left(convertToUser(userWrapper.getInnerElement())));
92             }
93
94             return resultWrapper.getInnerElement();
95         } finally {
96             if (!inTransaction) {
97                 janusGraphGenericDao.commit();
98             }
99             log.debug("getUserData - end");
100         }
101     }
102
103     private void validateInActiveUser(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
104         User user = convertToUser(userData);
105         if (user.getStatus() == UserStatusEnum.ACTIVE) {
106             resultWrapper.setInnerElement(Either.right(ActionStatus.USER_NOT_FOUND));
107         }
108     }
109
110     private void validateActiveUser(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
111         User user = convertToUser(userData);
112         if (user.getStatus() == UserStatusEnum.INACTIVE) {
113             resultWrapper.setInnerElement(Either.right(ActionStatus.USER_INACTIVE));
114         }
115     }
116
117     private void validateUserData(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData, String id) {
118         if (userData == null) {
119             log.debug("Problem get User with userId {}. Reason -  either.left().value() = null", id);
120             resultWrapper.setInnerElement(Either.right(ActionStatus.GENERAL_ERROR));
121         }
122     }
123
124     private void validateUserExists(Wrapper<Either<User, ActionStatus>> resultWrapper, Wrapper<UserData> userWrapper, String id) {
125         if (id == null) {
126             log.info("User userId  is empty");
127             resultWrapper.setInnerElement(Either.right(ActionStatus.MISSING_INFORMATION));
128             return;
129         }
130         id = id.toLowerCase();
131         Either<UserData, JanusGraphOperationStatus> either = janusGraphGenericDao
132             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), id, UserData.class);
133
134         if (either.isRight()) {
135             resultWrapper.setInnerElement(getUserNotFoundError(id, either.right().value()));
136         } else {
137             userWrapper.setInnerElement(either.left().value());
138         }
139     }
140
141     @Override
142     public Either<User, StorageOperationStatus> saveUserData(User user) {
143         Either<UserData, JanusGraphOperationStatus> result = null;
144         try {
145             UserData userData = convertToUserData(user);
146             result = janusGraphGenericDao.createNode(userData, UserData.class);
147             if (result.isRight()) {
148                 log.debug("Problem while saving User  {}. Reason - {}", userData.getUserId(), result.right().value());
149                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
150             }
151             log.debug("User {} saved successfully", userData.getUserId());
152             return Either.left(convertToUser(result.left().value()));
153
154         } finally {
155
156             if (result == null || result.isRight()) {
157                 log.error("saveUserData - Failed");
158                 janusGraphGenericDao.rollback();
159             } else {
160                 log.debug("saveUserData - end");
161                 janusGraphGenericDao.commit();
162             }
163         }
164     }
165
166     @Override
167     public Either<User, StorageOperationStatus> updateUserData(User user) {
168         Either<UserData, JanusGraphOperationStatus> result = null;
169         try {
170             log.debug("updateUserData - start");
171             UserData userData = convertToUserData(user);
172             result = janusGraphGenericDao.updateNode(userData, UserData.class);
173             if (result.isRight()) {
174                 if (log.isDebugEnabled()) {
175                     log.debug("Problem while updating User {}. Reason - {}", userData.toString(), result.right().value());
176                 }
177                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
178             }
179             log.debug("User {} updated successfully",userData.getUserId());
180             return Either.left(convertToUser(result.left().value()));
181
182         } finally {
183
184             if (result == null || result.isRight()) {
185                 log.error("updateUserData - Failed");
186                 janusGraphGenericDao.rollback();
187             } else {
188                 log.debug("updateUserData - end");
189                 janusGraphGenericDao.commit();
190             }
191
192         }
193     }
194
195     @Override
196     public Either<User, StorageOperationStatus> deActivateUser(User user) {
197         Either<User, StorageOperationStatus> result;
198         user.setStatus(UserStatusEnum.INACTIVE);
199         Either<User, StorageOperationStatus> status = updateUserData(user);
200         if (status.isRight()) {
201             result = Either.right(status.right().value());
202         } else {
203             result = Either.left(user);
204         }
205         return result;
206     }
207
208     @Override
209     public Either<User, ActionStatus> deleteUserData(String id) {
210         Either<User, ActionStatus> result;
211         Either<UserData, JanusGraphOperationStatus> eitherGet = janusGraphGenericDao
212             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), id, UserData.class);
213         if (eitherGet.isRight()) {
214             log.debug("Problem while retriving user with userId {}",id);
215             if (eitherGet.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
216                 result = Either.right(ActionStatus.USER_NOT_FOUND);
217             } else {
218                 result = Either.right(ActionStatus.GENERAL_ERROR);
219             }
220         } else {
221             result = deleteUserLogic(eitherGet.left().value());
222         }
223         return result;
224     }
225
226     private Either<User, ActionStatus> deleteUserLogic(UserData userData) {
227         Wrapper<Either<User, ActionStatus>> resultWrapper = new Wrapper<>();
228         try {
229             validateUserHasNoConnections(resultWrapper, userData);
230             if (resultWrapper.isEmpty()) {
231                 deleteUser(resultWrapper, userData);
232             }
233         } finally {
234             janusGraphGenericDao.commit();
235         }
236         return resultWrapper.getInnerElement();
237     }
238
239     private void deleteUser(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
240         Either<UserData, JanusGraphOperationStatus> eitherDelete = janusGraphGenericDao
241             .deleteNode(userData, UserData.class);
242         if (eitherDelete.isRight()) {
243             if (log.isDebugEnabled()) {
244                 log.debug("Problem while deleting User {}. Reason - {}", userData.toString(), eitherDelete.right().value());
245             }
246             resultWrapper.setInnerElement(Either.right(ActionStatus.GENERAL_ERROR));
247         } else {
248             log.debug("User {} deleted successfully",userData.getUserId());
249             resultWrapper.setInnerElement(Either.left(convertToUser(eitherDelete.left().value())));
250         }
251     }
252
253     private void validateUserHasNoConnections(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
254         if (resultWrapper.isEmpty()) {
255
256             Either<List<Edge>, JanusGraphOperationStatus> edgesForNode = janusGraphGenericDao
257                 .getEdgesForNode(userData, Direction.BOTH);
258             if (edgesForNode.isRight()) {
259                 if (log.isDebugEnabled()) {
260                     log.debug("Problem while deleting User {}. Reason - {}", userData.getUserId(), edgesForNode.right().value());
261                 }
262                 resultWrapper.setInnerElement(Either.right(ActionStatus.GENERAL_ERROR));
263             } else {
264                 List<Edge> vertexEdges = edgesForNode.left().value();
265                 if (!isEmpty(vertexEdges)) {
266                     resultWrapper.setInnerElement(Either.right(ActionStatus.USER_HAS_ACTIVE_ELEMENTS));
267                 }
268             }
269         }
270     }
271
272     public Either<List<Edge>, StorageOperationStatus> getUserPendingTasksList(User user, Map<String, Object> properties) {
273
274         Either<JanusGraphVertex, JanusGraphOperationStatus> vertexUser = janusGraphGenericDao
275             .getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), user.getUserId());
276         if (vertexUser.isRight()) {
277             JanusGraphOperationStatus tos = vertexUser.right().value();
278             log.debug("Failed to get User {} from graph while retrieving pending tasks. Reason - {}", user.getUserId(), tos);
279             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(tos));
280         }
281         List<Edge> pendingTasks = new ArrayList<>();
282         Either<List<Edge>, JanusGraphOperationStatus> edges = janusGraphGenericDao
283             .getOutgoingEdgesByCriteria(vertexUser.left().value(), GraphEdgeLabels.STATE, properties);
284         if (edges.isRight() || edges.left().value() == null) {
285             JanusGraphOperationStatus tos = edges.right().value();
286             if (tos == JanusGraphOperationStatus.NOT_FOUND) {
287                 return Either.left(pendingTasks);
288             } else {
289                 log.debug("Failed while retrieving pending tasks for user {} . Reason - {}", user.getUserId(), tos);
290                 return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(tos));
291             }
292         }
293         for (Edge edge : edges.left().value()) {
294             if (!isComponentDeleted(edge.inVertex())) {
295                 pendingTasks.add(edge);
296             }
297         }
298         logPendingTasks(user, pendingTasks);
299         return Either.left(pendingTasks);
300     }
301
302     private boolean isComponentDeleted(Vertex componentVertex) {
303         VertexProperty<Object> property = componentVertex.property(GraphPropertiesDictionary.IS_DELETED.getProperty());
304         if (property.isPresent()) {
305             return BooleanUtils.isTrue((Boolean) property.value());
306         }
307         return false;
308     }
309
310     private void logPendingTasks(User user, List<Edge> pendingTasks) {
311         if (log.isDebugEnabled()) {
312             for (Edge edge : pendingTasks) {
313                 Object resourceUuid = edge.inVertex().property(GraphPropertyEnum.UNIQUE_ID.getProperty()).value();
314                 Object componentName = edge.inVertex().property(GraphPropertyEnum.NAME.getProperty()).value();
315                 Object componentState = edge.inVertex().property(GraphPropertyEnum.STATE.getProperty()).value();
316                 log.debug("The user userId = {} is working on the component name = {} uid = {} in state {}", user.getUserId(), componentName, resourceUuid, componentState);
317             }
318         }
319     }
320
321     @Override
322     public Either<List<User>, ActionStatus> getAllUsersWithRole(String role, String status) {
323         try {
324             Map<String, Object> propertiesToMatch = new HashMap<>();
325             if (role != null && !role.trim().isEmpty()) {
326                 propertiesToMatch.put(GraphPropertiesDictionary.ROLE.getProperty(), role);
327             }
328             if (status != null && !status.isEmpty()) {
329                 propertiesToMatch.put(GraphPropertiesDictionary.USER_STATUS.getProperty(), status);
330             }
331
332             Either<List<UserData>, JanusGraphOperationStatus> userNodes = janusGraphGenericDao
333                 .getByCriteria(NodeTypeEnum.User, propertiesToMatch, UserData.class);
334
335             janusGraphGenericDao.commit();
336             return convertToUsers(role, userNodes);
337         } finally {
338             janusGraphGenericDao.commit();
339         }
340     }
341
342     private Either<List<User>, ActionStatus> convertToUsers(String role, Either<List<UserData>, JanusGraphOperationStatus> userNodes) {
343
344         if (userNodes.isRight()) {
345             // in case of NOT_FOUND from JanusGraph return empty list
346             JanusGraphOperationStatus tos = userNodes.right().value();
347             if (tos.equals(JanusGraphOperationStatus.NOT_FOUND)) {
348                 return Either.left(Collections.emptyList());
349             } else {
350                 log.error("Problem while getting all users with role {}. Reason - {}", role, tos);
351                 return Either.right(ActionStatus.GENERAL_ERROR);
352             }
353         } else {
354             List<UserData> userDataList = userNodes.left().value();
355             if (userDataList != null) {
356                 return Either.left(convertToUsers(userDataList));
357             }
358             log.debug("No users were found with role {}", role);
359             return Either.left(Collections.emptyList());
360         }
361     }
362
363     private List<User> convertToUsers(List<UserData> usersData) {
364         List<User> result = new ArrayList<>();
365         for (UserData userData : usersData) {
366             User user = convertToUser(userData);
367             result.add(user);
368         }
369         return result;
370     }
371
372     private Either<User, ActionStatus> getUserNotFoundError(String uid, JanusGraphOperationStatus status) {
373         if (status == JanusGraphOperationStatus.NOT_FOUND) {
374             log.debug("User with userId {} not found", uid);
375             return Either.right(ActionStatus.USER_NOT_FOUND);
376         } else {
377             log.debug("Problem get User with userId {}. Reason - {}", uid, status);
378             return  Either.right(ActionStatus.GENERAL_ERROR);
379         }
380     }
381
382     protected User convertToUser(UserData userData) {
383         User user = new User();
384         user.setUserId(userData.getUserId());
385         user.setEmail(userData.getEmail());
386         user.setFirstName(userData.getFirstName());
387         user.setLastName(userData.getLastName());
388         user.setRole(userData.getRole());
389         user.setLastLoginTime(userData.getLastLoginTime());
390         // Support backward compatibility - user status may not exist in old
391         // users
392         Either<UserStatusEnum, MethodActivationStatusEnum> either = UserStatusEnum.findByName(userData.getStatus());
393         user.setStatus(either.isLeft() ? either.left().value() : UserStatusEnum.ACTIVE);
394         return user;
395     }
396
397     protected UserData convertToUserData(User user) {
398         UserData userData = new UserData();
399         userData.setUserId(user.getUserId().toLowerCase());
400         userData.setEmail(user.getEmail());
401         userData.setFirstName(user.getFirstName());
402         userData.setLastName(user.getLastName());
403         userData.setRole(user.getRole());
404         userData.setStatus(user.getStatus().name());
405         userData.setLastLoginTime(user.getLastLoginTime());
406         return userData;
407     }
408
409 }