2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.model.operations.impl;
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;
51 import java.util.ArrayList;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.List;
57 @Component("user-operation")
58 public class UserAdminOperation implements IUserAdminOperation {
60 private TitanGenericDao titanGenericDao;
62 public UserAdminOperation(@Qualifier("titan-generic-dao") TitanGenericDao titanGenericDao) {
64 this.titanGenericDao = titanGenericDao;
68 private static Logger log = LoggerFactory.getLogger(UserAdminOperation.class.getName());
71 public Either<User, ActionStatus> getInactiveUserData(String id) {
72 return getUserData(id, false, false);
76 public Either<User, ActionStatus> getUserData(String id, boolean inTransaction) {
77 return getUserData(id, true, inTransaction);
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<>();
85 validateUserExists(resultWrapper, userWrapper, id);
87 if (resultWrapper.isEmpty()) {
88 validateUserData(resultWrapper, userWrapper.getInnerElement(), id);
91 if (resultWrapper.isEmpty()) {
93 validateActiveUser(resultWrapper, userWrapper.getInnerElement());
95 validateInActiveUser(resultWrapper, userWrapper.getInnerElement());
99 if (resultWrapper.isEmpty()) {
100 Either<User, ActionStatus> result = Either.left(convertToUser(userWrapper.getInnerElement()));
101 resultWrapper.setInnerElement(result);
104 return resultWrapper.getInnerElement();
106 if (false == inTransaction) {
107 titanGenericDao.commit();
109 log.debug("getUserData - end");
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);
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);
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);
137 private void validateUserExists(Wrapper<Either<User, ActionStatus>> resultWrapper, Wrapper<UserData> userWrapper, String id) {
138 Either<User, ActionStatus> result;
140 log.info("User userId is empty");
141 result = Either.right(ActionStatus.MISSING_INFORMATION);
142 resultWrapper.setInnerElement(result);
145 id = id.toLowerCase();
146 Either<UserData, TitanOperationStatus> either = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.User), id, UserData.class);
148 if (either.isRight()) {
149 resultWrapper.setInnerElement(getUserNotFoundError(id, either.right().value()));
151 userWrapper.setInnerElement(either.left().value());
156 public Either<User, StorageOperationStatus> saveUserData(User user) {
158 Either<UserData, TitanOperationStatus> result = null;
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);
166 log.debug("User {} saved successfully",userData.toString());
167 return Either.left(convertToUser(result.left().value()));
171 if (result == null || result.isRight()) {
172 log.error("saveUserData - Failed");
173 titanGenericDao.rollback();
175 log.debug("saveUserData - end");
176 titanGenericDao.commit();
182 public Either<User, StorageOperationStatus> updateUserData(User user) {
183 Either<UserData, TitanOperationStatus> result = null;
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);
192 log.debug("User {} updated successfully",userData.toString());
193 return Either.left(convertToUser(result.left().value()));
197 if (result == null || result.isRight()) {
198 log.error("updateUserData - Failed");
199 titanGenericDao.rollback();
201 log.debug("updateUserData - end");
202 titanGenericDao.commit();
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());
216 result = Either.left(user);
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);
230 result = Either.right(ActionStatus.GENERAL_ERROR);
234 result = deleteUserLogic(eitherGet.left().value());
239 private Either<User, ActionStatus> deleteUserLogic(UserData userData) {
240 Wrapper<Either<User, ActionStatus>> resultWrapper = new Wrapper<>();
242 validateUserHasNoConnections(resultWrapper, userData);
244 if (resultWrapper.isEmpty()) {
245 deleteUser(resultWrapper, userData);
249 titanGenericDao.commit();
252 return resultWrapper.getInnerElement();
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);
262 log.debug("User {} deleted successfully",userData.toString());
263 Either<User, ActionStatus> result = Either.left(convertToUser(eitherDelete.left().value()));
264 resultWrapper.setInnerElement(result);
268 private void validateUserHasNoConnections(Wrapper<Either<User, ActionStatus>> resultWrapper, UserData userData) {
269 if (resultWrapper.isEmpty()) {
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);
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);
286 public Either<List<Edge>, StorageOperationStatus> getUserPendingTasksList(User user, Map<String, Object> properties) {
288 UserData userData = convertToUserData(user);
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);
296 List<Edge> pandingTasks = new ArrayList<>();
297 Either<List<Edge>, TitanOperationStatus> edges = titanGenericDao.getOutgoingEdgesByCriteria(vertexUser.left().value(), GraphEdgeLabels.STATE, properties);
299 if (edges.isRight() || edges.left().value() == null) {
300 if (edges.right().value() == TitanOperationStatus.NOT_FOUND) {
301 return Either.left(pandingTasks);
303 log.debug("Problem while deleting User {}. Reason - ",userData.toString(),edges.right().value().name());
304 return Either.right(StorageOperationStatus.GENERAL_ERROR);
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);
314 Boolean isDeletedValue = (java.lang.Boolean) property.value();
315 if (isDeletedValue == null || isDeletedValue == false) {
316 pandingTasks.add(edge);
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);
330 return Either.left(pandingTasks);
334 public Either<List<User>, ActionStatus> getAllUsersWithRole(String role, String status) {
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);
341 if (status != null && !status.isEmpty()) {
342 propertiesToMatch.put(GraphPropertiesDictionary.USER_STATUS.getProperty(), status);
345 Either<List<UserData>, TitanOperationStatus> userNodes = titanGenericDao.getByCriteria(NodeTypeEnum.User, propertiesToMatch, UserData.class);
347 titanGenericDao.commit();
348 return convertToUsers(role, userNodes);
350 titanGenericDao.commit();
354 private Either<List<User>, ActionStatus> convertToUsers(String role, Either<List<UserData>, TitanOperationStatus> userNodes) {
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());
361 log.error("Problem while getting all users with role {}. Reason - {}", role, userNodes.right().value().name());
362 return Either.right(ActionStatus.GENERAL_ERROR);
365 List<UserData> userDataList = userNodes.left().value();
366 if (userDataList != null) {
367 return Either.left(convertToUsers(userDataList));
369 log.debug("No users were found with role {}", role);
370 return Either.left(Collections.emptyList());
374 private List<User> convertToUsers(List<UserData> usersData) {
375 List<User> result = new ArrayList<>();
376 for (UserData userData : usersData) {
377 User user = convertToUser(userData);
384 public Either<List<User>, ActionStatus> getAllUsers() {
386 Either<List<UserData>, TitanOperationStatus> userNodes = titanGenericDao.getAll(NodeTypeEnum.User, UserData.class);
387 return convertToUsers("", userNodes);
389 titanGenericDao.commit();
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);
398 log.debug("Problem get User with userId {}. Reason - {}", uid, status.name());
399 return Either.right(ActionStatus.GENERAL_ERROR);
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
413 Either<UserStatusEnum, MethodActivationStatusEnum> either = UserStatusEnum.findByName(userData.getStatus());
414 user.setStatus(either.isLeft() ? either.left().value() : UserStatusEnum.ACTIVE);
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());
431 public Either<ImmutablePair<User, FunctionalMenuInfo>, ActionStatus> getUserDataWithFunctionalMenu(String userId) {
433 Either<User, ActionStatus> userData = getUserData(userId, true, true);
435 if (userData.isRight()) {
436 return Either.right(userData.right().value());
438 User user = userData.left().value();
439 Either<UserFunctionalMenuData, TitanOperationStatus> functionalMenu = getFunctionalMenu(userId);
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);
448 UserFunctionalMenuData userFunctionalMenuData = functionalMenu.left().value();
449 functionalMenuInfo.setFunctionalMenu(userFunctionalMenuData.getFunctionalMenu());
452 ImmutablePair<User, FunctionalMenuInfo> result = new ImmutablePair<User, FunctionalMenuInfo>(user, functionalMenuInfo);
454 return Either.left(result);
457 public Either<UserFunctionalMenuData, TitanOperationStatus> getFunctionalMenu(String userId) {
459 Either<UserFunctionalMenuData, TitanOperationStatus> result;
460 if (userId == null) {
461 log.info("User userId is empty");
462 result = Either.right(TitanOperationStatus.NOT_FOUND);
465 userId = userId.toLowerCase();
466 String uid = UniqueIdBuilder.buildUserFunctionalMenuUid(userId);
468 Either<UserFunctionalMenuData, TitanOperationStatus> either = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.UserFunctionalMenu), uid, UserFunctionalMenuData.class);
473 public Either<FunctionalMenuInfo, TitanOperationStatus> createOrUpdateFunctionalMenu(String userId, String newFunctionalMenu) {
475 Either<UserFunctionalMenuData, TitanOperationStatus> functionalMenu = getFunctionalMenu(userId);
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);
483 Either<UserFunctionalMenuData, TitanOperationStatus> createNode = titanGenericDao.createNode(functionalMenuData, UserFunctionalMenuData.class);
485 if (createNode.isRight()) {
486 return Either.right(createNode.right().value());
488 return Either.left(convert(createNode.left().value()));
492 return Either.right(status);
496 UserFunctionalMenuData userFunctionalMenuData = functionalMenu.left().value();
497 userFunctionalMenuData.setFunctionalMenu(newFunctionalMenu);
498 Either<UserFunctionalMenuData, TitanOperationStatus> updateNode = titanGenericDao.updateNode(userFunctionalMenuData, UserFunctionalMenuData.class);
500 if (updateNode.isRight()) {
501 return Either.right(updateNode.right().value());
503 return Either.left(convert(updateNode.left().value()));
509 private FunctionalMenuInfo convert(UserFunctionalMenuData functionalMenuData) {
511 if (functionalMenuData == null) {
515 FunctionalMenuInfo functionalMenuInfo = new FunctionalMenuInfo();
516 functionalMenuInfo.setFunctionalMenu(functionalMenuData.getFunctionalMenu());
518 return functionalMenuInfo;