[SDC-29] rebase continue work to align source
[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 com.thinkaurelius.titan.core.TitanVertex;
24 import fj.data.Either;
25 import org.apache.commons.lang3.tuple.ImmutablePair;
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.neo4j.GraphEdgeLabels;
32 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
33 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
34 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
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.FunctionalMenuInfo;
39 import org.openecomp.sdc.be.model.User;
40 import org.openecomp.sdc.be.model.operations.api.IUserAdminOperation;
41 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
42 import org.openecomp.sdc.be.resources.data.UserData;
43 import org.openecomp.sdc.be.resources.data.UserFunctionalMenuData;
44 import org.openecomp.sdc.common.datastructure.Wrapper;
45 import org.openecomp.sdc.common.util.MethodActivationStatusEnum;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Qualifier;
49 import org.springframework.stereotype.Component;
50
51 import java.util.ArrayList;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.List;
55 import java.util.Map;
56
57 @Component("user-operation")
58 public class UserAdminOperation implements IUserAdminOperation {
59
60         private TitanGenericDao titanGenericDao;
61
62         public UserAdminOperation(@Qualifier("titan-generic-dao") TitanGenericDao titanGenericDao) {
63                 super();
64                 this.titanGenericDao = titanGenericDao;
65
66         }
67
68         private static Logger log = LoggerFactory.getLogger(UserAdminOperation.class.getName());
69
70         @Override
71         public Either<User, ActionStatus> getInactiveUserData(String id) {
72                 return getUserData(id, false, false);
73         }
74
75         @Override
76         public Either<User, ActionStatus> getUserData(String id, boolean inTransaction) {
77                 return getUserData(id, true, inTransaction);
78         }
79
80         private Either<User, ActionStatus> getUserData(String id, boolean isActive, boolean inTransaction) {
81                 log.debug("getUserData - start");
82                 Wrapper<Either<User, ActionStatus>> resultWrapper = new Wrapper<>();
83                 Wrapper<UserData> userWrapper = new Wrapper<>();
84                 try {
85                         validateUserExists(resultWrapper, userWrapper, id);
86
87                         if (resultWrapper.isEmpty()) {
88                                 validateUserData(resultWrapper, userWrapper.getInnerElement(), id);
89
90                         }
91                         if (resultWrapper.isEmpty()) {
92                                 if (isActive) {
93                                         validateActiveUser(resultWrapper, userWrapper.getInnerElement());
94                                 } else {
95                                         validateInActiveUser(resultWrapper, userWrapper.getInnerElement());
96                                 }
97                         }
98
99                         if (resultWrapper.isEmpty()) {
100                                 Either<User, ActionStatus> result = Either.left(convertToUser(userWrapper.getInnerElement()));
101                                 resultWrapper.setInnerElement(result);
102                         }
103
104                         return resultWrapper.getInnerElement();
105                 } finally {
106                         if (false == inTransaction) {
107                                 titanGenericDao.commit();
108                         }
109                         log.debug("getUserData - end");
110                 }
111         }
112
113         private void validateInActiveUser(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
114                 User user = convertToUser(userData);
115                 if (user.getStatus() == UserStatusEnum.ACTIVE) {
116                         Either<User, ActionStatus> result = Either.right(ActionStatus.USER_NOT_FOUND);
117                         resultWrapper.setInnerElement(result);
118                 }
119         }
120
121         private void validateActiveUser(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
122                 User user = convertToUser(userData);
123                 if (user.getStatus() == UserStatusEnum.INACTIVE) {
124                         Either<User, ActionStatus> result = Either.right(ActionStatus.USER_INACTIVE);
125                         resultWrapper.setInnerElement(result);
126                 }
127         }
128
129         private void validateUserData(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData, String id) {
130                 if (userData == null) {
131                         log.debug("Problem get User with userId {}. Reason -  either.left().value() = null", id);
132                         Either<User, ActionStatus> result = Either.right(ActionStatus.GENERAL_ERROR);
133                         resultWrapper.setInnerElement(result);
134                 }
135         }
136
137         private void validateUserExists(Wrapper<Either<User, ActionStatus>> resultWrapper, Wrapper<UserData> userWrapper, String id) {
138                 Either<User, ActionStatus> result;
139                 if (id == null) {
140                         log.info("User userId  is empty");
141                         result = Either.right(ActionStatus.MISSING_INFORMATION);
142                         resultWrapper.setInnerElement(result);
143                         return;
144                 }
145                 id = id.toLowerCase();
146                 Either<UserData, TitanOperationStatus> either = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), id, UserData.class);
147
148                 if (either.isRight()) {
149                         resultWrapper.setInnerElement(getUserNotFoundError(id, either.right().value()));
150                 } else {
151                         userWrapper.setInnerElement(either.left().value());
152                 }
153         }
154
155         @Override
156         public Either<User, StorageOperationStatus> saveUserData(User user) {
157
158                 Either<UserData, TitanOperationStatus> result = null;
159                 try {
160                         UserData userData = convertToUserData(user);
161                         result = titanGenericDao.createNode(userData, UserData.class);
162                         if (result.isRight()) {
163                                 log.debug("Problem while saving User  {}. Reason - {}",userData.toString(),result.right().value().name());
164                                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
165                         }
166                         log.debug("User {} saved successfully",userData.toString());
167                         return Either.left(convertToUser(result.left().value()));
168
169                 } finally {
170
171                         if (result == null || result.isRight()) {
172                                 log.error("saveUserData - Failed");
173                                 titanGenericDao.rollback();
174                         } else {
175                                 log.debug("saveUserData - end");
176                                 titanGenericDao.commit();
177                         }
178                 }
179         }
180
181         @Override
182         public Either<User, StorageOperationStatus> updateUserData(User user) {
183                 Either<UserData, TitanOperationStatus> result = null;
184                 try {
185                         log.debug("updateUserData - start");
186                         UserData userData = convertToUserData(user);
187                         result = titanGenericDao.updateNode(userData, UserData.class);
188                         if (result.isRight()) {
189                                 log.debug("Problem while updating User {}. Reason - {}",userData.toString(),result.right().value().name());
190                                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
191                         }
192                         log.debug("User {} updated successfully",userData.toString());
193                         return Either.left(convertToUser(result.left().value()));
194
195                 } finally {
196
197                         if (result == null || result.isRight()) {
198                                 log.error("updateUserData - Failed");
199                                 titanGenericDao.rollback();
200                         } else {
201                                 log.debug("updateUserData - end");
202                                 titanGenericDao.commit();
203                         }
204
205                 }
206         }
207
208         @Override
209         public Either<User, StorageOperationStatus> deActivateUser(User user) {
210                 Either<User, StorageOperationStatus> result;
211                 user.setStatus(UserStatusEnum.INACTIVE);
212                 Either<User, StorageOperationStatus> status = updateUserData(user);
213                 if (status.isRight()) {
214                         result = Either.right(status.right().value());
215                 } else {
216                         result = Either.left(user);
217                 }
218                 return result;
219         }
220
221         @Override
222         public Either<User, ActionStatus> deleteUserData(String id) {
223                 Either<User, ActionStatus> result;
224                 Either<UserData, TitanOperationStatus> eitherGet = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), id, UserData.class);
225                 if (eitherGet.isRight()) {
226                         log.debug("Problem while retriving user with userId {}",id);
227                         if (eitherGet.right().value() == TitanOperationStatus.NOT_FOUND) {
228                                 result = Either.right(ActionStatus.USER_NOT_FOUND);
229                         } else {
230                                 result = Either.right(ActionStatus.GENERAL_ERROR);
231                         }
232
233                 } else {
234                         result = deleteUserLogic(eitherGet.left().value());
235                 }
236                 return result;
237         }
238
239         private Either<User, ActionStatus> deleteUserLogic(UserData userData) {
240                 Wrapper<Either<User, ActionStatus>> resultWrapper = new Wrapper<>();
241                 try {
242                         validateUserHasNoConnections(resultWrapper, userData);
243
244                         if (resultWrapper.isEmpty()) {
245                                 deleteUser(resultWrapper, userData);
246                         }
247
248                 } finally {
249                         titanGenericDao.commit();
250                 }
251
252                 return resultWrapper.getInnerElement();
253         }
254
255         private void deleteUser(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
256                 Either<UserData, TitanOperationStatus> eitherDelete = titanGenericDao.deleteNode(userData, UserData.class);
257                 if (eitherDelete.isRight()) {
258                         log.debug("Problem while deleting User {}. Reason - {}",userData.toString(),eitherDelete.right().value().name());
259                         Either<User, ActionStatus> result = Either.right(ActionStatus.GENERAL_ERROR);
260                         resultWrapper.setInnerElement(result);
261                 } else {
262                         log.debug("User {} deleted successfully",userData.toString());
263                         Either<User, ActionStatus> result = Either.left(convertToUser(eitherDelete.left().value()));
264                         resultWrapper.setInnerElement(result);
265                 }
266         }
267
268         private void validateUserHasNoConnections(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
269                 if (resultWrapper.isEmpty()) {
270
271                         Either<List<Edge>, TitanOperationStatus> edgesForNode = titanGenericDao.getEdgesForNode(userData, Direction.BOTH);
272                         if (edgesForNode.isRight()) {
273                                 log.debug("Problem while deleting User {}. Reason - {}",userData.toString(),edgesForNode.right().value().name());
274                                 Either<User, ActionStatus> result = Either.right(ActionStatus.GENERAL_ERROR);
275                                 resultWrapper.setInnerElement(result);
276                         } else {
277                                 List<Edge> vertexEdges = edgesForNode.left().value();
278                                 if (vertexEdges.size() > 0) {
279                                         Either<User, ActionStatus> result = Either.right(ActionStatus.USER_HAS_ACTIVE_ELEMENTS);
280                                         resultWrapper.setInnerElement(result);
281                                 }
282                         }
283                 }
284         }
285
286         public Either<List<Edge>, StorageOperationStatus> getUserPendingTasksList(User user, Map<String, Object> properties) {
287
288                 UserData userData = convertToUserData(user);
289
290                 Either<TitanVertex, TitanOperationStatus> vertexUser = titanGenericDao.getVertexByProperty(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), user.getUserId());
291                 if (vertexUser.isRight()) {
292                         log.debug("Problem while deleting User {}. Reason - {}",userData.toString(),vertexUser.right().value().name());
293                         return Either.right(StorageOperationStatus.GENERAL_ERROR);
294                 }
295
296                 List<Edge> pandingTasks = new ArrayList<>();
297                 Either<List<Edge>, TitanOperationStatus> edges = titanGenericDao.getOutgoingEdgesByCriteria(vertexUser.left().value(), GraphEdgeLabels.STATE, properties);
298
299                 if (edges.isRight() || edges.left().value() == null) {
300                         if (edges.right().value() == TitanOperationStatus.NOT_FOUND) {
301                                 return Either.left(pandingTasks);
302                         } else {
303                                 log.debug("Problem while deleting User {}. Reason - ",userData.toString(),edges.right().value().name());
304                                 return Either.right(StorageOperationStatus.GENERAL_ERROR);
305                         }
306                 }
307
308                 for (Edge edge : edges.left().value()) {
309                         Vertex componentVertex = edge.inVertex();
310                         VertexProperty<Object> property = componentVertex.property(GraphPropertiesDictionary.IS_DELETED.getProperty());
311                         if (!property.isPresent()) {
312                                 pandingTasks.add(edge);
313                         } else {
314                                 Boolean isDeletedValue = (java.lang.Boolean) property.value();
315                                 if (isDeletedValue == null || isDeletedValue == false) {
316                                         pandingTasks.add(edge);
317                                 }
318                         }
319                 }
320                 
321                 if(log.isDebugEnabled()) {
322                         for (Edge edge : pandingTasks) {
323                                 Object resourceUuid = edge.inVertex().property(GraphPropertyEnum.UNIQUE_ID.getProperty()).value();
324                                 Object componentName = edge.inVertex().property(GraphPropertyEnum.NAME.getProperty()).value();
325                                 Object componentState = edge.inVertex().property(GraphPropertyEnum.STATE.getProperty()).value();
326                                 log.debug("The user userId = {} is working on the component name = {} uid = {} in state {}", user.getUserId(), componentName, resourceUuid, componentState);                                    
327                         }
328                 }
329                 
330                 return Either.left(pandingTasks);
331         }
332
333         @Override
334         public Either<List<User>, ActionStatus> getAllUsersWithRole(String role, String status) {
335                 try {
336                         List<User> result = new ArrayList<>();
337                         Map<String, Object> propertiesToMatch = new HashMap<>();
338                         if (role != null && !role.trim().isEmpty()) {
339                                 propertiesToMatch.put(GraphPropertiesDictionary.ROLE.getProperty(), role);
340                         }
341                         if (status != null && !status.isEmpty()) {
342                                 propertiesToMatch.put(GraphPropertiesDictionary.USER_STATUS.getProperty(), status);
343                         }
344
345                         Either<List<UserData>, TitanOperationStatus> userNodes = titanGenericDao.getByCriteria(NodeTypeEnum.User, propertiesToMatch, UserData.class);
346
347                         titanGenericDao.commit();
348                         return convertToUsers(role, userNodes);
349                 } finally {
350                         titanGenericDao.commit();
351                 }
352         }
353
354         private Either<List<User>, ActionStatus> convertToUsers(String role, Either<List<UserData>, TitanOperationStatus> userNodes) {
355
356                 if (userNodes.isRight()) {
357             // in case of NOT_FOUND from Titan return empty list
358             if (userNodes.right().value().equals(TitanOperationStatus.NOT_FOUND)) {
359                 return Either.left(Collections.emptyList());
360             } else {
361                 log.error("Problem while getting all users with role {}. Reason - {}", role, userNodes.right().value().name());
362                 return Either.right(ActionStatus.GENERAL_ERROR);
363             }
364         } else {
365                         List<UserData> userDataList = userNodes.left().value();
366             if (userDataList != null) {
367                 return Either.left(convertToUsers(userDataList));
368             }
369             log.debug("No users were found with role {}", role);
370             return Either.left(Collections.emptyList());
371         }
372         }
373
374         private List<User> convertToUsers(List<UserData> usersData) {
375                 List<User> result = new ArrayList<>();
376                 for (UserData userData : usersData) {
377                         User user = convertToUser(userData);
378                         result.add(user);
379                 }
380                 return result;
381         }
382
383         @Override
384         public Either<List<User>, ActionStatus> getAllUsers() {
385                 try {
386                         Either<List<UserData>, TitanOperationStatus> userNodes = titanGenericDao.getAll(NodeTypeEnum.User, UserData.class);
387                         return convertToUsers("", userNodes);
388                 } finally {
389                         titanGenericDao.commit();
390                 }
391         }
392
393         private Either<User, ActionStatus> getUserNotFoundError(String uid, TitanOperationStatus status) {
394                 if (status == TitanOperationStatus.NOT_FOUND) {
395             log.debug("User with userId {} not found", uid);
396             return Either.right(ActionStatus.USER_NOT_FOUND);
397         } else {
398             log.debug("Problem get User with userId {}. Reason - {}", uid, status.name());
399             return  Either.right(ActionStatus.GENERAL_ERROR);
400         }
401         }
402
403         protected User convertToUser(UserData userData) {
404                 User user = new User();
405                 user.setUserId(userData.getUserId());
406                 user.setEmail(userData.getEmail());
407                 user.setFirstName(userData.getFirstName());
408                 user.setLastName(userData.getLastName());
409                 user.setRole(userData.getRole());
410                 user.setLastLoginTime(userData.getLastLoginTime());
411                 // Support backward compatibility - user status may not exist in old
412                 // users
413                 Either<UserStatusEnum, MethodActivationStatusEnum> either = UserStatusEnum.findByName(userData.getStatus());
414                 user.setStatus(either.isLeft() ? either.left().value() : UserStatusEnum.ACTIVE);
415                 return user;
416         }
417
418         protected UserData convertToUserData(User user) {
419                 UserData userData = new UserData();
420                 userData.setUserId(user.getUserId().toLowerCase());
421                 userData.setEmail(user.getEmail());
422                 userData.setFirstName(user.getFirstName());
423                 userData.setLastName(user.getLastName());
424                 userData.setRole(user.getRole());
425                 userData.setStatus(user.getStatus().name());
426                 userData.setLastLoginTime(user.getLastLoginTime());
427                 return userData;
428         }
429
430         @Override
431         public Either<ImmutablePair<User, FunctionalMenuInfo>, ActionStatus> getUserDataWithFunctionalMenu(String userId) {
432
433                 Either<User, ActionStatus> userData = getUserData(userId, true, true);
434
435                 if (userData.isRight()) {
436                         return Either.right(userData.right().value());
437                 }
438                 User user = userData.left().value();
439                 Either<UserFunctionalMenuData, TitanOperationStatus> functionalMenu = getFunctionalMenu(userId);
440
441                 FunctionalMenuInfo functionalMenuInfo = new FunctionalMenuInfo();
442                 if (functionalMenu.isRight()) {
443                         TitanOperationStatus status = functionalMenu.right().value();
444                         if (status != TitanOperationStatus.NOT_FOUND) {
445                                 return Either.right(ActionStatus.GENERAL_ERROR);
446                         }
447                 } else {
448                         UserFunctionalMenuData userFunctionalMenuData = functionalMenu.left().value();
449                         functionalMenuInfo.setFunctionalMenu(userFunctionalMenuData.getFunctionalMenu());
450                 }
451
452                 ImmutablePair<User, FunctionalMenuInfo> result = new ImmutablePair<User, FunctionalMenuInfo>(user, functionalMenuInfo);
453
454                 return Either.left(result);
455         }
456
457         public Either<UserFunctionalMenuData, TitanOperationStatus> getFunctionalMenu(String userId) {
458
459                 Either<UserFunctionalMenuData, TitanOperationStatus> result;
460                 if (userId == null) {
461                         log.info("User userId  is empty");
462                         result = Either.right(TitanOperationStatus.NOT_FOUND);
463                         return result;
464                 }
465                 userId = userId.toLowerCase();
466                 String uid = UniqueIdBuilder.buildUserFunctionalMenuUid(userId);
467
468                 Either<UserFunctionalMenuData, TitanOperationStatus> either = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.UserFunctionalMenu), uid, UserFunctionalMenuData.class);
469
470                 return either;
471         }
472
473         public Either<FunctionalMenuInfo, TitanOperationStatus> createOrUpdateFunctionalMenu(String userId, String newFunctionalMenu) {
474
475                 Either<UserFunctionalMenuData, TitanOperationStatus> functionalMenu = getFunctionalMenu(userId);
476
477                 if (functionalMenu.isRight()) {
478                         TitanOperationStatus status = functionalMenu.right().value();
479                         if (status == TitanOperationStatus.NOT_FOUND) {
480                                 String uid = UniqueIdBuilder.buildUserFunctionalMenuUid(userId);
481                                 UserFunctionalMenuData functionalMenuData = new UserFunctionalMenuData(newFunctionalMenu, uid);
482
483                                 Either<UserFunctionalMenuData, TitanOperationStatus> createNode = titanGenericDao.createNode(functionalMenuData, UserFunctionalMenuData.class);
484
485                                 if (createNode.isRight()) {
486                                         return Either.right(createNode.right().value());
487                                 } else {
488                                         return Either.left(convert(createNode.left().value()));
489                                 }
490
491                         } else {
492                                 return Either.right(status);
493                         }
494
495                 } else {
496                         UserFunctionalMenuData userFunctionalMenuData = functionalMenu.left().value();
497                         userFunctionalMenuData.setFunctionalMenu(newFunctionalMenu);
498                         Either<UserFunctionalMenuData, TitanOperationStatus> updateNode = titanGenericDao.updateNode(userFunctionalMenuData, UserFunctionalMenuData.class);
499
500                         if (updateNode.isRight()) {
501                                 return Either.right(updateNode.right().value());
502                         } else {
503                                 return Either.left(convert(updateNode.left().value()));
504                         }
505                 }
506
507         }
508
509         private FunctionalMenuInfo convert(UserFunctionalMenuData functionalMenuData) {
510
511                 if (functionalMenuData == null) {
512                         return null;
513                 }
514
515                 FunctionalMenuInfo functionalMenuInfo = new FunctionalMenuInfo();
516                 functionalMenuInfo.setFunctionalMenu(functionalMenuData.getFunctionalMenu());
517
518                 return functionalMenuInfo;
519
520         }
521
522 }