f90440011da4ef6caecc9c04e48a6a2adc5e0fb3
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / user / UserBusinessLogic.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 package org.openecomp.sdc.be.user;
21
22 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.ADD_USER;
23 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.GET_USERS_LIST;
24 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_USER;
25
26 import fj.data.Either;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.stream.Collectors;
33 import org.apache.commons.collections.CollectionUtils;
34 import org.apache.commons.lang3.StringUtils;
35 import org.apache.tinkerpop.gremlin.structure.Edge;
36 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.dao.utils.UserStatusEnum;
39 import org.openecomp.sdc.be.facade.operations.UserOperation;
40 import org.openecomp.sdc.be.impl.ComponentsUtils;
41 import org.openecomp.sdc.be.model.LifecycleStateEnum;
42 import org.openecomp.sdc.be.model.User;
43 import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
44 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
45 import org.openecomp.sdc.common.api.UserRoleEnum;
46 import org.openecomp.sdc.common.datastructure.UserContext;
47 import org.openecomp.sdc.common.kpi.api.ASDCKpiApi;
48 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
49 import org.openecomp.sdc.common.log.wrappers.Logger;
50 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
51 import org.openecomp.sdc.exception.ResponseFormat;
52
53 @org.springframework.stereotype.Component
54 public class UserBusinessLogic {
55
56     private static final Logger log = Logger.getLogger(UserBusinessLogic.class);
57     private static final String IN_CERTIFICATION_CHECKED_OUT = "in-certification/checked-out";
58     private static final String UNKNOWN = "UNKNOWN";
59     private static UserAdminValidator userAdminValidator = UserAdminValidator.getInstance();
60     private final UserAdminOperation userAdminOperation;
61     private final ComponentsUtils componentsUtils;
62     private final UserOperation facadeUserOperation;
63
64     public UserBusinessLogic(UserAdminOperation userAdminOperation, ComponentsUtils componentsUtils, UserOperation facadeUserOperation) {
65         this.userAdminOperation = userAdminOperation;
66         this.componentsUtils = componentsUtils;
67         this.facadeUserOperation = facadeUserOperation;
68     }
69
70     public User getUser(String userId, boolean inTransaction) {
71         Either<User, ActionStatus> result = userAdminOperation.getUserData(userId, inTransaction);
72         if (result.isRight()) {
73             handleUserAccessAuditing(userId, result.right().value());
74             throw new ByActionStatusComponentException(result.right().value(), userId);
75         }
76         User user = result.left().value();
77         if (user == null) {
78             handleUserAccessAuditing(userId, ActionStatus.GENERAL_ERROR);
79             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
80         }
81         return user;
82     }
83
84     public User getUser(String userId) {
85         UserContext userContext = ThreadLocalsHolder.getUserContext();
86         if (Objects.isNull(userContext) || Objects.isNull(userContext.getUserId())) {
87             log.info("USER_NOT_FOUND, user=" + userId);
88             handleUserAccessAuditing(userId, ActionStatus.USER_NOT_FOUND);
89             throw new ByActionStatusComponentException(ActionStatus.USER_NOT_FOUND, userId);
90         }
91         if (Objects.isNull(userContext.getUserRoles())) {
92             userContext.setUserRoles(new HashSet<>());
93         }
94         return convertUserContextToUser(userContext);
95     }
96
97     protected User convertUserContextToUser(UserContext userContext) {
98         User user = new User();
99         user.setUserId(userContext.getUserId());
100         user.setFirstName(userContext.getFirstName());
101         user.setLastName(userContext.getLastName());
102         boolean userHasRoles = userContext.getUserRoles().iterator().hasNext();
103         user.setRole(!userHasRoles ? null : userContext.getUserRoles().iterator().next());
104         user.setStatus(userHasRoles ? UserStatusEnum.ACTIVE : UserStatusEnum.INACTIVE);
105         return user;
106     }
107
108     public boolean hasActiveUser(String userId) {
109         UserContext userContext = ThreadLocalsHolder.getUserContext();
110         if (Objects.isNull(userContext) || Objects.isNull(userContext.getUserId())) {
111             handleUserAccessAuditing(userId, ActionStatus.USER_NOT_FOUND);
112             return false;
113         }
114         if (Objects.isNull(userContext.getUserRoles()) || userContext.getUserRoles().isEmpty()) {
115             handleUserAccessAuditing(userId, ActionStatus.USER_INACTIVE);
116             return false;
117         }
118         return true;
119     }
120
121     public User createUser(String modifierUserId, User newUser) {
122         User modifier = getValidModifier(modifierUserId, newUser.getUserId(), AuditingActionEnum.ADD_USER);
123         // verify user not exist
124         String newUserId = newUser.getUserId();
125         Either<User, ActionStatus> eitherUserInDB = verifyNewUser(newUserId);
126         newUser.setStatus(UserStatusEnum.ACTIVE);
127         validateEmail(newUser);
128         validateRole(newUser);
129         // handle last login if user is import
130         if (newUser.getLastLoginTime() == null) {
131             newUser.setLastLoginTime(0L);
132         }
133         User createdUser;
134         if (ActionStatus.USER_INACTIVE.equals(eitherUserInDB.right()
135             .value())) { // user inactive - update state                                                                                  // exist
136             newUser.setLastLoginTime(0L);
137             createdUser = userAdminOperation.updateUserData(newUser);
138         } else { // user does not exist - create new user
139             if (!userAdminValidator.validateUserId(newUserId)) {
140                 log.debug("createUser method - user has invalid userId = {}", newUser.getUserId());
141                 throw new ByActionStatusComponentException(ActionStatus.INVALID_USER_ID, newUserId);
142             }
143             createdUser = userAdminOperation.saveUserData(newUser);
144         }
145         ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
146         handleAuditing(modifier, null, createdUser, responseFormat, AuditingActionEnum.ADD_USER);
147         getFacadeUserOperation().updateUserCache(UserOperationEnum.CREATE, createdUser.getUserId(), createdUser.getRole());
148         return createdUser;
149     }
150
151     private void validateRole(User newUser) {
152         if (newUser.getRole() == null || newUser.getRole().length() == 0) {
153             newUser.setRole(Role.DESIGNER.name());
154         } else {
155             if (!userAdminValidator.validateRole(newUser.getRole())) {
156                 log.debug("createUser method - user has invalid role = {}", newUser.getUserId());
157                 throw new ByActionStatusComponentException(ActionStatus.INVALID_ROLE, newUser.getRole());
158             }
159         }
160     }
161
162     private void validateEmail(User newUser) {
163         if (newUser.getEmail() != null && !userAdminValidator.validateEmail(newUser.getEmail())) {
164             log.debug("createUser method - user has invalid email = {}", newUser.getUserId());
165             throw new ByActionStatusComponentException(ActionStatus.INVALID_EMAIL_ADDRESS, newUser.getEmail());
166         }
167     }
168
169     private Either<User, ActionStatus> verifyNewUser(String newUserId) {
170         Either<User, ActionStatus> eitherUserInDB = getUserData(newUserId);
171         if (eitherUserInDB.isRight()) {
172             ActionStatus status = eitherUserInDB.right().value();
173             if (!ActionStatus.USER_NOT_FOUND.equals(status) && !ActionStatus.USER_INACTIVE.equals(status)) {
174                 componentsUtils.auditAdminUserActionAndThrowException(ADD_USER, null, null, null, status, newUserId);
175             }
176         } else {// User exist in DB
177             User userFromDb = eitherUserInDB.left().value();
178             if (userFromDb.getStatus() == UserStatusEnum.ACTIVE) {
179                 log.debug("createUser method - user with id {} already exist with id: {}", newUserId, userFromDb.getUserId());
180                 componentsUtils.auditAdminUserActionAndThrowException(ADD_USER, null, null, null, ActionStatus.USER_ALREADY_EXIST, newUserId);
181             }
182         }
183         return eitherUserInDB;
184     }
185
186     public Either<User, ActionStatus> verifyNewUserForPortal(String newUserId) {
187         Either<User, ActionStatus> eitherUserInDB = getUserData(newUserId);
188         if (eitherUserInDB.isRight()) {
189             ActionStatus status = eitherUserInDB.right().value();
190             if (!ActionStatus.USER_NOT_FOUND.equals(status) && !ActionStatus.USER_INACTIVE.equals(status)) {
191                 componentsUtils.auditAdminUserActionAndThrowException(ADD_USER, null, null, null, status, newUserId);
192             }
193         }
194         return eitherUserInDB;
195     }
196
197     private Either<User, ActionStatus> getUserData(String newUserId) {
198         if (newUserId == null) {
199             log.error(EcompLoggerErrorCode.DATA_ERROR, "", "", "Create user - new user id is missing");
200             throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
201         }
202         return userAdminOperation.getUserData(newUserId, false);
203     }
204
205     public User updateUserRole(String modifierUserId, String userIdToUpdate, String userRole) {
206         User modifier = getValidModifier(modifierUserId, userIdToUpdate, UPDATE_USER);
207         User userToUpdate = getUser(userIdToUpdate, false);
208         validateChangeRoleToAllowedRoles(userRole);
209         List<Edge> userPendingTasks = userAdminOperation.getUserPendingTasksList(userToUpdate, getChangeRoleStateLimitations(userToUpdate));
210         if (!userPendingTasks.isEmpty()) {
211             log.debug("updateUserRole method - User cannot be updated, user have pending projects userId {}", userIdToUpdate);
212             String userInfo = userToUpdate.getFirstName() + " " + userToUpdate.getLastName() + '(' + userToUpdate.getUserId() + ')';
213             componentsUtils.auditAdminUserActionAndThrowException(UPDATE_USER, modifier, userToUpdate, null,
214                 ActionStatus.CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS, userInfo, IN_CERTIFICATION_CHECKED_OUT);
215         }
216         Role newRole = Role.valueOf(userRole);
217         User newUser = new User();
218         newUser.setRole(newRole.name());
219         newUser.setUserId(userIdToUpdate);
220         User updatedUser = userAdminOperation.updateUserData(newUser);
221         handleAuditing(modifier, userToUpdate, updatedUser, componentsUtils.getResponseFormat(ActionStatus.OK), UPDATE_USER);
222         getFacadeUserOperation().updateUserCache(UserOperationEnum.CHANGE_ROLE, updatedUser.getUserId(), updatedUser.getRole());
223         return updatedUser;
224     }
225
226     private void validateChangeRoleToAllowedRoles(String userRole) {
227         List<String> allowedRoles = Arrays.asList(UserRoleEnum.DESIGNER.getName(), UserRoleEnum.ADMIN.getName());
228         if (!allowedRoles.contains(userRole)) {
229             throw new ByActionStatusComponentException(ActionStatus.INVALID_ROLE, userRole);
230         }
231     }
232
233     User getValidModifier(String modifierUserId, String userIdHandle, AuditingActionEnum actionEnum) {
234         if (modifierUserId == null) {
235             log.error(EcompLoggerErrorCode.DATA_ERROR, "", "", "user modifier is missing");
236             throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
237         }
238         User modifier = getUser(modifierUserId, false);
239         if (!modifier.getRole().equals(UserRoleEnum.ADMIN.getName())) {
240             log.debug("user is not admin. Id = {}", modifier.getUserId());
241             componentsUtils.auditAdminUserActionAndThrowException(actionEnum, modifier, null, null, ActionStatus.RESTRICTED_OPERATION);
242         }
243         if (modifier.getUserId().equals(userIdHandle)) {
244             log.debug("admin user cannot act on self. Id = {}", modifier.getUserId());
245             componentsUtils.auditAdminUserActionAndThrowException(actionEnum, modifier, null, null, ActionStatus.UPDATE_USER_ADMIN_CONFLICT);
246         }
247         return modifier;
248     }
249
250     public List<User> getAllAdminUsers() {
251         Either<List<User>, ActionStatus> response = userAdminOperation.getAllUsersWithRole(Role.ADMIN.name(), null);
252         if (response.isRight()) {
253             throw new ByActionStatusComponentException(response.right().value());
254         }
255         return response.left().value();
256     }
257
258     public List<User> getUsersList(String modifierAttId, List<String> roles, String rolesStr) {
259         if (modifierAttId == null) {
260             throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
261         }
262         User user = getUser(modifierAttId, false);
263         Either<List<User>, ResponseFormat> getResponse;
264         List<User> userList = new ArrayList<>();
265         if (!CollectionUtils.isEmpty(roles)) {
266             for (String role : roles) {
267                 if (!userAdminValidator.validateRole(role)) {
268                     componentsUtils.auditAdminUserActionAndThrowException(GET_USERS_LIST, user, null, null, ActionStatus.INVALID_ROLE, role);
269                 }
270                 getResponse = getUsersPerRole(role, user, rolesStr);
271                 userList.addAll(getResponse.left().value());
272             }
273         } else {
274             rolesStr = "All";
275             getResponse = getUsersPerRole(null, user, rolesStr);
276             userList.addAll(getResponse.left().value());
277         }
278         handleGetUsersListAuditing(user, componentsUtils.getResponseFormat(ActionStatus.OK), rolesStr);
279         return userList;
280     }
281
282     Either<List<User>, ResponseFormat> getUsersPerRole(String role, User user, String rolesStr) {
283         ResponseFormat responseFormat;
284         Either<List<User>, ActionStatus> response = userAdminOperation.getAllUsersWithRole(role, UserStatusEnum.ACTIVE.name());
285         if (response.isRight()) {
286             responseFormat = componentsUtils.getResponseFormat(response.right().value());
287             handleGetUsersListAuditing(user, responseFormat, rolesStr);
288             return Either.right(responseFormat);
289         }
290         List<User> users = response.left().value().stream().filter(u -> StringUtils.isNotEmpty(u.getUserId())).collect(Collectors.toList());
291         return Either.left(users);
292     }
293
294     private void handleGetUsersListAuditing(User user, ResponseFormat responseFormat, String details) {
295         componentsUtils.auditGetUsersList(user, details, responseFormat);
296     }
297
298     private void handleAuditing(User modifier, User userBefore, User userAfter, ResponseFormat responseFormat, AuditingActionEnum actionName) {
299         componentsUtils.auditAdminUserAction(actionName, modifier, userBefore, userAfter, responseFormat);
300     }
301
302     private void handleUserAccessAuditing(User user, ResponseFormat responseFormat) {
303         componentsUtils.auditUserAccess(user, responseFormat);
304     }
305
306     private void handleUserAccessAuditing(String userId, ActionStatus status, String... params) {
307         componentsUtils.auditUserAccess(new User(userId), status, params);
308     }
309
310     public User authorize(User authUser) {
311         String userId = authUser.getUserId();
312         if (userId == null) {
313             log.debug("authorize method -  user id is missing");
314             throw new ByActionStatusComponentException(ActionStatus.MISSING_INFORMATION);
315         }
316         User user = getUser(userId, false);
317         String firstName = authUser.getFirstName();
318         if (firstName != null && !firstName.isEmpty() && !firstName.equals(user.getFirstName())) {
319             user.setFirstName(firstName);
320         }
321         String lastName = authUser.getLastName();
322         if (lastName != null && !lastName.isEmpty() && !lastName.equals(user.getLastName())) {
323             user.setLastName(lastName);
324         }
325         String email = authUser.getEmail();
326         if (email != null && !email.isEmpty() && !email.equals(user.getEmail())) {
327             user.setEmail(email);
328         }
329         // last login time stamp handle
330         user.setLastLoginTime();
331         User updatedUser = userAdminOperation.updateUserData(user);
332         Long lastLoginTime = user.getLastLoginTime();
333         if (lastLoginTime != null) {
334             updatedUser.setLastLoginTime(lastLoginTime);
335         } else {
336             updatedUser.setLastLoginTime(0L);
337         }
338         handleUserAccessAuditing(updatedUser.getUserId(), ActionStatus.OK);
339         ASDCKpiApi.countUsersAuthorizations();
340         return updatedUser;
341     }
342
343     /*
344      * The method updates user credentials only, the role is neglected The role updated through updateRole method
345      */
346     public Either<User, ResponseFormat> updateUserCredentials(User updatedUserCred) {
347         ResponseFormat responseFormat;
348         String userId = updatedUserCred.getUserId();
349         if (userId == null) {
350             updatedUserCred.setUserId(UNKNOWN);
351             log.debug("updateUserCredentials method - user header is missing");
352             responseFormat = componentsUtils.getResponseFormat(ActionStatus.MISSING_INFORMATION);
353             handleUserAccessAuditing(updatedUserCred, responseFormat);
354             return Either.right(responseFormat);
355         }
356         User user = getUser(userId, false);
357         String firstName = updatedUserCred.getFirstName();
358         if (firstName != null && !firstName.isEmpty() && !firstName.equals(user.getFirstName())) {
359             user.setFirstName(firstName);
360         }
361         String lastName = updatedUserCred.getLastName();
362         if (lastName != null && !lastName.isEmpty() && !lastName.equals(user.getLastName())) {
363             user.setLastName(lastName);
364         }
365         String email = updatedUserCred.getEmail();
366         if (email != null && !email.isEmpty() && !email.equals(user.getEmail())) {
367             user.setEmail(email);
368         }
369         if (updatedUserCred.getLastLoginTime() != null && user.getLastLoginTime() != null) {
370             if (updatedUserCred.getLastLoginTime() > user.getLastLoginTime()) {
371                 user.setLastLoginTime(updatedUserCred.getLastLoginTime());
372             }
373         } else if (updatedUserCred.getLastLoginTime() != null && user.getLastLoginTime() == null) {
374             user.setLastLoginTime(updatedUserCred.getLastLoginTime());
375         }
376         User updatedUser = userAdminOperation.updateUserData(user);
377         responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK);
378         handleUserAccessAuditing(updatedUser, responseFormat);
379         return Either.left(updatedUser);
380     }
381
382     private List<Object> getChangeRoleStateLimitations(User user) {
383         UserRoleEnum role = UserRoleEnum.valueOf(user.getRole());
384         List<Object> properties = new ArrayList<>();
385         switch (role) {
386             case DESIGNER:
387             case PRODUCT_STRATEGIST:
388             case PRODUCT_MANAGER:
389             case ADMIN:
390                 properties.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name());
391                 break;
392             case TESTER:
393                 // For tester we allow change role even if there are pending task (per US468155 in 1810)
394             default:
395         }
396         return properties;
397     }
398
399     public UserOperation getFacadeUserOperation() {
400         return facadeUserOperation;
401     }
402 }