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