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.user;
23 import fj.data.Either;
24 import org.apache.commons.collections.CollectionUtils;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.tinkerpop.gremlin.structure.Edge;
27 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
28 import org.openecomp.sdc.be.dao.api.ActionStatus;
29 import org.openecomp.sdc.be.dao.utils.UserStatusEnum;
30 import org.openecomp.sdc.be.facade.operations.UserOperation;
31 import org.openecomp.sdc.be.impl.ComponentsUtils;
32 import org.openecomp.sdc.be.model.LifecycleStateEnum;
33 import org.openecomp.sdc.be.model.User;
34 import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
35 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
36 import org.openecomp.sdc.common.api.UserRoleEnum;
37 import org.openecomp.sdc.common.datastructure.UserContext;
38 import org.openecomp.sdc.common.kpi.api.ASDCKpiApi;
39 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
40 import org.openecomp.sdc.common.log.wrappers.Logger;
41 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
42 import org.openecomp.sdc.exception.ResponseFormat;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.HashSet;
47 import java.util.List;
48 import java.util.Objects;
49 import java.util.stream.Collectors;
51 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.ADD_USER;
52 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.GET_USERS_LIST;
53 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_USER;
55 @org.springframework.stereotype.Component
56 public class UserBusinessLogic {
58 private static final Logger log = Logger.getLogger(UserBusinessLogic.class);
59 private static final String IN_CERTIFICATION_CHECKED_OUT = "in-certification/checked-out";
60 private static final String UNKNOWN = "UNKNOWN";
61 private static UserAdminValidator userAdminValidator = UserAdminValidator.getInstance();
63 private final UserAdminOperation userAdminOperation;
64 private final ComponentsUtils componentsUtils;
65 private final UserOperation facadeUserOperation;
67 public UserBusinessLogic(UserAdminOperation userAdminOperation, ComponentsUtils componentsUtils, UserOperation facadeUserOperation) {
68 this.userAdminOperation = userAdminOperation;
69 this.componentsUtils = componentsUtils;
70 this.facadeUserOperation = facadeUserOperation;
73 public User getUser(String userId, boolean inTransaction) {
74 Either<User, ActionStatus> result = userAdminOperation.getUserData(userId, inTransaction);
75 if (result.isRight()) {
76 handleUserAccessAuditing(userId, result.right().value());
77 throw new ByActionStatusComponentException(result.right().value(), userId);
79 User user = result.left().value();
81 handleUserAccessAuditing(userId, ActionStatus.GENERAL_ERROR);
82 throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
87 public User getUser(String userId) {
88 UserContext userContext = ThreadLocalsHolder.getUserContext();
89 if (Objects.isNull(userContext) || Objects.isNull(userContext.getUserId())) {
90 log.info("USER_NOT_FOUND, user=" + userId);
91 handleUserAccessAuditing(userId, ActionStatus.USER_NOT_FOUND);
92 throw new ByActionStatusComponentException(ActionStatus.USER_NOT_FOUND, userId);
94 if (Objects.isNull(userContext.getUserRoles())){
95 userContext.setUserRoles(new HashSet<>());
97 return convertUserContextToUser(userContext);
100 protected User convertUserContextToUser(UserContext userContext) {
101 User user = new User();
102 user.setUserId(userContext.getUserId());
103 user.setFirstName(userContext.getFirstName());
104 user.setLastName(userContext.getLastName());
105 boolean userHasRoles = userContext.getUserRoles().iterator().hasNext();
106 user.setRole(!userHasRoles ? null : userContext.getUserRoles().iterator().next());
107 user.setStatus(userHasRoles ? UserStatusEnum.ACTIVE : UserStatusEnum.INACTIVE);
111 public boolean hasActiveUser(String userId) {
112 UserContext userContext = ThreadLocalsHolder.getUserContext();
113 if (Objects.isNull(userContext) || Objects.isNull(userContext.getUserId()) ) {
114 handleUserAccessAuditing(userId, ActionStatus.USER_NOT_FOUND);
117 if (Objects.isNull(userContext.getUserRoles()) || userContext.getUserRoles().isEmpty()){
118 handleUserAccessAuditing(userId, ActionStatus.USER_INACTIVE);
124 public User createUser(String modifierUserId, User newUser) {
126 User modifier = getValidModifier(modifierUserId, newUser.getUserId(), AuditingActionEnum.ADD_USER);
128 // verify user not exist
129 String newUserId = newUser.getUserId();
130 Either<User, ActionStatus> eitherUserInDB = verifyNewUser(newUserId);
131 newUser.setStatus(UserStatusEnum.ACTIVE);
133 validateEmail(newUser);
135 validateRole(newUser);
137 // handle last login if user is import
138 if (newUser.getLastLoginTime() == null) {
139 newUser.setLastLoginTime(0L);
143 if (ActionStatus.USER_INACTIVE.equals(eitherUserInDB.right().value())) { // user inactive - update state // exist
144 newUser.setLastLoginTime(0L);
145 createdUser = userAdminOperation.updateUserData(newUser);
146 } else { // user does not exist - create new user
147 if (!userAdminValidator.validateUserId(newUserId)) {
148 log.debug("createUser method - user has invalid userId = {}", newUser.getUserId());
149 throw new ByActionStatusComponentException(ActionStatus.INVALID_USER_ID, newUserId);
151 createdUser = userAdminOperation.saveUserData(newUser);
153 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
154 handleAuditing(modifier, null, createdUser, responseFormat, AuditingActionEnum.ADD_USER);
155 getFacadeUserOperation().updateUserCache(UserOperationEnum.CREATE, createdUser.getUserId(), createdUser.getRole());
159 private void validateRole(User newUser) {
160 if (newUser.getRole() == null || newUser.getRole().length() == 0) {
161 newUser.setRole(Role.DESIGNER.name());
163 if (!userAdminValidator.validateRole(newUser.getRole())) {
164 log.debug("createUser method - user has invalid role = {}", newUser.getUserId());
165 throw new ByActionStatusComponentException(ActionStatus.INVALID_ROLE, newUser.getRole());
170 private void validateEmail(User newUser) {
171 if (newUser.getEmail() != null && !userAdminValidator.validateEmail(newUser.getEmail())) {
172 log.debug("createUser method - user has invalid email = {}", newUser.getUserId());
173 throw new ByActionStatusComponentException(ActionStatus.INVALID_EMAIL_ADDRESS, newUser.getEmail());
177 private Either<User, ActionStatus> verifyNewUser(String newUserId) {
178 Either<User, ActionStatus> eitherUserInDB = getUserData(newUserId);
179 if (eitherUserInDB.isRight()) {
180 ActionStatus status = eitherUserInDB.right().value();
181 if (!ActionStatus.USER_NOT_FOUND.equals(status) && !ActionStatus.USER_INACTIVE.equals(status)) {
182 componentsUtils.auditAdminUserActionAndThrowException(ADD_USER, null, null, null, status, newUserId);
184 } else {// User exist in DB
185 User userFromDb = eitherUserInDB.left().value();
186 if (userFromDb.getStatus() == UserStatusEnum.ACTIVE) {
187 log.debug("createUser method - user with id {} already exist with id: {}", newUserId, userFromDb.getUserId());
188 componentsUtils.auditAdminUserActionAndThrowException(ADD_USER, null, null, null, ActionStatus.USER_ALREADY_EXIST, newUserId);
191 return eitherUserInDB;
194 public Either<User, ActionStatus> verifyNewUserForPortal(String newUserId) {
195 Either<User, ActionStatus> eitherUserInDB = getUserData(newUserId);
196 if (eitherUserInDB.isRight()) {
197 ActionStatus status = eitherUserInDB.right().value();
198 if (!ActionStatus.USER_NOT_FOUND.equals(status) && !ActionStatus.USER_INACTIVE.equals(status)) {
199 componentsUtils.auditAdminUserActionAndThrowException(ADD_USER, null, null, null, status, newUserId);
203 return eitherUserInDB;
206 private Either<User, ActionStatus> getUserData(String newUserId) {
207 if (newUserId == null) {
208 log.error(EcompLoggerErrorCode.DATA_ERROR, "", "","Create user - new user id is missing");
209 throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
212 return userAdminOperation.getUserData(newUserId, false);
215 public User updateUserRole(String modifierUserId, String userIdToUpdate, String userRole) {
217 User modifier = getValidModifier(modifierUserId, userIdToUpdate, UPDATE_USER);
218 User userToUpdate = getUser(userIdToUpdate, false);
219 validateChangeRoleToAllowedRoles(userRole);
221 List<Edge> userPendingTasks = userAdminOperation.getUserPendingTasksList(userToUpdate, getChangeRoleStateLimitations(userToUpdate));
222 if (!userPendingTasks.isEmpty()) {
223 log.debug("updateUserRole method - User cannot be updated, user have pending projects userId {}", userIdToUpdate);
224 String userInfo = userToUpdate.getFirstName() + " " + userToUpdate.getLastName() + '(' + userToUpdate.getUserId() + ')';
225 componentsUtils.auditAdminUserActionAndThrowException(UPDATE_USER, modifier, userToUpdate, null, ActionStatus.CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS, userInfo, IN_CERTIFICATION_CHECKED_OUT);
228 Role newRole = Role.valueOf(userRole);
229 User newUser = new User();
230 newUser.setRole(newRole.name());
231 newUser.setUserId(userIdToUpdate);
233 User updatedUser = userAdminOperation.updateUserData(newUser);
234 handleAuditing(modifier, userToUpdate, updatedUser, componentsUtils.getResponseFormat(ActionStatus.OK), UPDATE_USER);
235 getFacadeUserOperation().updateUserCache(UserOperationEnum.CHANGE_ROLE, updatedUser.getUserId(), updatedUser.getRole());
239 private void validateChangeRoleToAllowedRoles(String userRole) {
240 List<String> allowedRoles = Arrays.asList(UserRoleEnum.DESIGNER.getName(), UserRoleEnum.ADMIN.getName());
241 if (!allowedRoles.contains(userRole)){
242 throw new ByActionStatusComponentException(ActionStatus.INVALID_ROLE, userRole);
246 User getValidModifier(String modifierUserId, String userIdHandle, AuditingActionEnum actionEnum) {
247 if (modifierUserId == null) {
248 log.error(EcompLoggerErrorCode.DATA_ERROR, "", "", "user modifier is missing");
249 throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
252 User modifier = getUser(modifierUserId, false);
253 if (!modifier.getRole().equals(UserRoleEnum.ADMIN.getName())) {
254 log.debug("user is not admin. Id = {}", modifier.getUserId());
255 componentsUtils.auditAdminUserActionAndThrowException(actionEnum, modifier, null, null, ActionStatus.RESTRICTED_OPERATION);
258 if (modifier.getUserId().equals(userIdHandle)) {
259 log.debug("admin user cannot act on self. Id = {}", modifier.getUserId());
260 componentsUtils.auditAdminUserActionAndThrowException(actionEnum, modifier, null, null, ActionStatus.UPDATE_USER_ADMIN_CONFLICT);
265 public List<User> getAllAdminUsers() {
266 Either<List<User>, ActionStatus> response = userAdminOperation.getAllUsersWithRole(Role.ADMIN.name(), null);
267 if (response.isRight()) {
268 throw new ByActionStatusComponentException(response.right().value());
270 return response.left().value();
273 public List<User> getUsersList(String modifierAttId, List<String> roles, String rolesStr) {
274 if (modifierAttId == null) {
275 throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
277 User user = getUser(modifierAttId, false);
278 Either<List<User>, ResponseFormat> getResponse;
279 List<User> userList = new ArrayList<>();
280 if (!CollectionUtils.isEmpty(roles)) {
281 for (String role : roles) {
282 if (!userAdminValidator.validateRole(role)) {
283 componentsUtils.auditAdminUserActionAndThrowException(GET_USERS_LIST, user, null, null, ActionStatus.INVALID_ROLE, role);
285 getResponse = getUsersPerRole(role, user, rolesStr);
286 userList.addAll(getResponse.left().value());
290 getResponse = getUsersPerRole(null, user, rolesStr);
291 userList.addAll(getResponse.left().value());
293 handleGetUsersListAuditing(user, componentsUtils.getResponseFormat(ActionStatus.OK), rolesStr);
297 Either<List<User>, ResponseFormat> getUsersPerRole(String role, User user, String rolesStr) {
298 ResponseFormat responseFormat;
299 Either<List<User>, ActionStatus> response = userAdminOperation.getAllUsersWithRole(role, UserStatusEnum.ACTIVE.name());
300 if (response.isRight()) {
301 responseFormat = componentsUtils.getResponseFormat(response.right().value());
302 handleGetUsersListAuditing(user, responseFormat, rolesStr);
303 return Either.right(responseFormat);
305 List<User> users = response.left().value()
307 .filter(u-> StringUtils.isNotEmpty(u.getUserId()))
308 .collect(Collectors.toList());
309 return Either.left(users);
312 private void handleGetUsersListAuditing(User user, ResponseFormat responseFormat, String details) {
313 componentsUtils.auditGetUsersList(user, details, responseFormat);
316 private void handleAuditing(User modifier, User userBefore, User userAfter, ResponseFormat responseFormat, AuditingActionEnum actionName) {
317 componentsUtils.auditAdminUserAction(actionName, modifier, userBefore, userAfter, responseFormat);
320 private void handleUserAccessAuditing(User user, ResponseFormat responseFormat) {
321 componentsUtils.auditUserAccess(user, responseFormat);
324 private void handleUserAccessAuditing(String userId, ActionStatus status, String... params) {
325 componentsUtils.auditUserAccess(new User(userId), status, params);
328 public User authorize(User authUser) {
329 String userId = authUser.getUserId();
330 if (userId == null) {
331 log.debug("authorize method - user id is missing");
332 throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
335 User user = getUser(userId, false);
337 String firstName = authUser.getFirstName();
338 if (firstName != null && !firstName.isEmpty() && !firstName.equals(user.getFirstName())) {
339 user.setFirstName(firstName);
342 String lastName = authUser.getLastName();
343 if (lastName != null && !lastName.isEmpty() && !lastName.equals(user.getLastName())) {
344 user.setLastName(lastName);
347 String email = authUser.getEmail();
348 if (email != null && !email.isEmpty() && !email.equals(user.getEmail())) {
349 user.setEmail(email);
352 // last login time stamp handle
353 user.setLastLoginTime();
355 User updatedUser = userAdminOperation.updateUserData(user);
356 Long lastLoginTime = user.getLastLoginTime();
357 if (lastLoginTime != null) {
358 updatedUser.setLastLoginTime(lastLoginTime);
360 updatedUser.setLastLoginTime(0L);
363 handleUserAccessAuditing(updatedUser.getUserId(), ActionStatus.OK);
364 ASDCKpiApi.countUsersAuthorizations();
369 * The method updates user credentials only, the role is neglected The role updated through updateRole method
371 public Either<User, ResponseFormat> updateUserCredentials(User updatedUserCred) {
373 ResponseFormat responseFormat;
375 String userId = updatedUserCred.getUserId();
377 if (userId == null) {
378 updatedUserCred.setUserId(UNKNOWN);
379 log.debug("updateUserCredentials method - user header is missing");
380 responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
381 handleUserAccessAuditing(updatedUserCred, responseFormat);
382 return Either.right(responseFormat);
385 User user = getUser(userId, false);
386 String firstName = updatedUserCred.getFirstName();
387 if (firstName != null && !firstName.isEmpty() && !firstName.equals(user.getFirstName())) {
388 user.setFirstName(firstName);
391 String lastName = updatedUserCred.getLastName();
392 if (lastName != null && !lastName.isEmpty() && !lastName.equals(user.getLastName())) {
393 user.setLastName(lastName);
396 String email = updatedUserCred.getEmail();
397 if (email != null && !email.isEmpty() && !email.equals(user.getEmail())) {
398 user.setEmail(email);
401 if (updatedUserCred.getLastLoginTime() != null && user.getLastLoginTime() != null) {
402 if (updatedUserCred.getLastLoginTime() > user.getLastLoginTime()) {
403 user.setLastLoginTime(updatedUserCred.getLastLoginTime());
405 } else if (updatedUserCred.getLastLoginTime() != null && user.getLastLoginTime() == null) {
406 user.setLastLoginTime(updatedUserCred.getLastLoginTime());
409 User updatedUser = userAdminOperation.updateUserData(user);
410 responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
411 handleUserAccessAuditing(updatedUser, responseFormat);
412 return Either.left(updatedUser);
415 private List<Object> getChangeRoleStateLimitations(User user) {
416 UserRoleEnum role = UserRoleEnum.valueOf(user.getRole());
417 List<Object> properties = new ArrayList<>();
420 case PRODUCT_STRATEGIST:
421 case PRODUCT_MANAGER:
423 properties.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name());
426 // For tester we allow change role even if there are pending task (per US468155 in 1810)
432 public UserOperation getFacadeUserOperation() {
433 return facadeUserOperation;