Sync Application Users Roles during login process
[portal.git] / ecomp-portal-BE-os / src / main / java / org / onap / portalapp / controller / LoginController.java
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed  
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License. 
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * 
37  */
38 package org.onap.portalapp.controller;
39
40 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
41
42 import java.io.IOException;
43 import java.net.MalformedURLException;
44 import java.net.URL;
45 import java.net.URLDecoder;
46 import java.util.Enumeration;
47 import java.util.HashMap;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.UUID;
51
52 import javax.servlet.http.Cookie;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.servlet.http.HttpServletResponse;
55
56 import org.apache.commons.lang.StringUtils;
57 import org.json.JSONObject;
58 import org.onap.portalapp.command.EPLoginBean;
59 import org.onap.portalapp.portal.domain.SharedContext;
60 import org.onap.portalapp.portal.service.EPLoginService;
61 import org.onap.portalapp.portal.service.EPRoleFunctionService;
62 import org.onap.portalapp.portal.service.ExternalAccessRolesService;
63 import org.onap.portalapp.portal.service.SharedContextService;
64 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
65 import org.onap.portalapp.portal.utils.EPSystemProperties;
66 import org.onap.portalapp.portal.utils.EcompPortalUtils;
67 import org.onap.portalapp.util.EPUserUtils;
68 import org.onap.portalapp.util.SessionCookieUtil;
69 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
70 import org.onap.portalsdk.core.menu.MenuProperties;
71 import org.onap.portalsdk.core.util.SystemProperties;
72 import org.slf4j.MDC;
73 import org.springframework.beans.factory.annotation.Autowired;
74 import org.springframework.http.HttpStatus;
75 import org.springframework.stereotype.Controller;
76 import org.springframework.util.StopWatch;
77 import org.springframework.web.bind.annotation.ExceptionHandler;
78 import org.springframework.web.bind.annotation.RequestMapping;
79 import org.springframework.web.bind.annotation.GetMapping;
80 import org.springframework.web.bind.annotation.PostMapping;
81 import org.springframework.web.bind.annotation.RequestMethod;
82 import org.springframework.web.bind.annotation.ResponseBody;
83 import org.springframework.web.servlet.ModelAndView;
84 import org.springframework.web.util.WebUtils;
85
86 import com.fasterxml.jackson.databind.DeserializationFeature;
87 import com.fasterxml.jackson.databind.JsonNode;
88 import com.fasterxml.jackson.databind.ObjectMapper;
89
90 @Controller
91 @RequestMapping("/")
92 public class LoginController extends EPUnRestrictedBaseController implements LoginService {
93
94         private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LoginController.class);
95
96         public static final String DEFAULT_SUCCESS_VIEW = "applicationsHome";
97         public static final String DEFAULT_FAILURE_VIEW = "login";
98         public static final String ERROR_MESSAGE_KEY = "error";
99         public static final String REDIRECT_URL = "redirectUrl";
100         public static final String REDIRECT_COLON = "redirect:";
101
102         @Autowired
103         private EPLoginService loginService;
104         @Autowired
105         private SharedContextService sharedContextService;
106         @Autowired
107         private EPRoleFunctionService ePRoleFunctionService;
108         @Autowired
109         private ExternalAccessRolesService externalAccessRolesService ;
110
111         private String viewName = "login";
112
113         private String welcomeView;
114
115         @GetMapping(value = { "/login.htm" })
116         public ModelAndView login(HttpServletRequest request) {
117                 Map<String, Object> model = new HashMap<String, Object>();
118                 String authentication = SystemProperties.getProperty(SystemProperties.AUTHENTICATION_MECHANISM);
119                 String loginPage;
120                 if (authentication == null || "".equals(authentication) || "OICD".equals(authentication.trim()))
121                         loginPage = "openIdLogin";
122                 else
123                         loginPage = getViewName();
124                 return new ModelAndView(loginPage, "model", model);
125         }
126
127         @SuppressWarnings("rawtypes")
128         @PostMapping(value = { "/open_source/login" })
129         @ResponseBody
130         public String loginValidate(HttpServletRequest request, HttpServletResponse response) throws Exception {
131
132                 String orgUserId = "";
133                 ObjectMapper mapper = new ObjectMapper();
134                 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
135                 JsonNode root = mapper.readTree(request.getReader());
136
137                 EPLoginBean commandBean = new EPLoginBean();
138                 String loginId = root.get("loginId").textValue();
139                 String password = root.get("password").textValue();
140                 commandBean.setLoginId(loginId);
141                 commandBean.setLoginPwd(password);
142                 
143                 HashMap additionalParamsMap = new HashMap();
144                 StringBuilder sbAdditionalInfo = new StringBuilder();
145
146                 commandBean = getLoginService().findUser(commandBean,
147                                 (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), additionalParamsMap);
148                 String fullURL = getFullURL(request);
149                 if (commandBean.getUser() == null) {
150                         String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage()
151                                         : "login.error.external.invalid";
152                         logger.info(EELFLoggerDelegate.debugLogger, "loginId {} does not exist in the the DB.", loginId);
153                         sbAdditionalInfo.append(String.format("But the Login-Id: %s doesn't exist in the Database. Request-URL: %s",
154                                         loginId, fullURL));
155                         return loginErrorMessage;
156                 } else {
157                         // store the currently logged in user's information in the session
158                         EPUserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
159                                         commandBean.getBusinessDirectMenu(), ePRoleFunctionService);
160
161                         try {
162                                 logger.info(EELFLoggerDelegate.debugLogger, "loginValidate: store user info into share context begins");
163                                 String sessionId = request.getSession().getId();
164                                 List<SharedContext> existingSC = getSharedContextService().getSharedContexts(sessionId);
165                                 if (existingSC == null || existingSC.isEmpty()) {
166                                         getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_FIRST_NAME,
167                                                         commandBean.getUser().getFirstName());
168                                         getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_LAST_NAME,
169                                                         commandBean.getUser().getLastName());
170                                         getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_EMAIL,
171                                                         commandBean.getUser().getEmail());
172                                         getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_ORG_USERID,
173                                                         commandBean.getLoginId());
174                                 }
175
176                         } catch (Exception e) {
177                                 logger.info(EELFLoggerDelegate.errorLogger, "loginValidate: failed the shared context adding process ",
178                                                 e);
179                         }
180                         logger.info(EELFLoggerDelegate.debugLogger,
181                                         "loginValidate: PresetUp the EP service cookie and intial sessionManagement");
182
183                         SessionCookieUtil.preSetUp(request, response);
184                         SessionCookieUtil.setUpUserIdCookie(request, response, loginId);
185
186                         JSONObject j = new JSONObject("{success: success}");
187                         
188                         try {
189                                 //if app is centralized then sync user roles from the external auth system
190                                 orgUserId = commandBean.getUser().getOrgUserId();
191                                 if(EcompPortalUtils.checkIfRemoteCentralAccessAllowed()) {
192                                         externalAccessRolesService.syncApplicationUserRolesFromExtAuthSystem(orgUserId);
193                                         logger.info(EELFLoggerDelegate.errorLogger, "Sync: Sync Application UserRoles From ExtAuthSystem is done..");
194                                 }
195                         } catch (Exception e) {
196                                 logger.info(EELFLoggerDelegate.errorLogger, "Sync: Sync Application UserRoles From ExtAuthSystem Faild..",
197                                                 e);
198                         }
199
200                         return j.toString();
201                 }
202         }
203
204         /*
205          * Work around a bug in ecompsdkos version 1.1.0 which hard-codes this endpoint.
206          */
207         @RequestMapping(value = { "/process_csp" }, method = RequestMethod.GET)
208         public ModelAndView processCsp(HttpServletRequest request, HttpServletResponse response) throws Exception {
209                 return processSingleSignOn(request, response);
210         }
211         /*
212          * Remove this method after epsdk-app-common/.../SingleSignOnController.java is
213          * repaired.
214          */
215
216         @GetMapping(value = { "/processSingleSignOn" })
217         public ModelAndView processSingleSignOn(HttpServletRequest request, HttpServletResponse response) throws Exception {
218
219                 Map<Object, Object> model = new HashMap<Object, Object>();
220                 HashMap<Object, Object> additionalParamsMap = new HashMap<Object, Object>();
221                 EPLoginBean commandBean = new EPLoginBean();
222                 MDC.put(MDC_KEY_REQUEST_ID, (getRequestId(request)==null || getRequestId(request).isEmpty()) ? UUID.randomUUID().toString():getRequestId(request));
223                 // get userId from cookie
224                 String orgUserId = SessionCookieUtil.getUserIdFromCookie(request, response);
225                 logger.info(EELFLoggerDelegate.debugLogger, "processSingleSignOn: begins with orgUserId {}", orgUserId);
226
227                 StringBuilder sbAdditionalInfo = new StringBuilder();
228                 validateDomain(request);
229                 if (orgUserId == null || orgUserId.length() == 0) {
230                         model.put(ERROR_MESSAGE_KEY, SystemProperties.MESSAGE_KEY_LOGIN_ERROR_COOKIE_EMPTY);
231                         if (request.getParameter(REDIRECT_URL) != null && request.getParameter(REDIRECT_URL).length() != 0) {
232                                 return new ModelAndView(REDIRECT_COLON + DEFAULT_FAILURE_VIEW + ".htm" + "?redirectUrl="
233                                                 + request.getParameter(REDIRECT_URL));
234                         } else {
235                                 return new ModelAndView(REDIRECT_COLON + DEFAULT_FAILURE_VIEW + ".htm");
236                         }
237                 } else {
238
239                         StopWatch stopWatch = new StopWatch("LoginController.Login");
240                         stopWatch.start();
241
242                         try {
243                                 logger.info(EELFLoggerDelegate.debugLogger,
244                                                 "Operation findUser is started to locate user {}  in the database.", orgUserId);
245                                 commandBean.setLoginId(orgUserId);
246                                 commandBean.setOrgUserId(orgUserId);
247                                 commandBean = getLoginService().findUser(commandBean,
248                                                 (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY),
249                                                 additionalParamsMap);
250
251                                 stopWatch.stop();
252                                 MDC.put(EPSystemProperties.MDC_TIMER, String.valueOf(stopWatch.getTotalTimeMillis()));
253                                 logger.info(EELFLoggerDelegate.debugLogger, "Operation findUser is completed.");
254                         } catch (Exception e) {
255                                 stopWatch.stop();
256                                 MDC.put(EPSystemProperties.MDC_TIMER, String.valueOf(stopWatch.getTotalTimeMillis()));
257                                 logger.info(EELFLoggerDelegate.errorLogger, "processSingleSignOn failed on user " + orgUserId, e);
258                         } finally {
259                                 MDC.remove(EPSystemProperties.MDC_TIMER);
260                         }
261
262                         sbAdditionalInfo.append("Login attempt is succeeded. ");
263                         String fullURL = getFullURL(request);
264                         if (commandBean.getUser() == null) {
265                                 logger.info(EELFLoggerDelegate.debugLogger,
266                                                 "processSingleSignOn: loginId {} does not exist in the the DB.", orgUserId);
267
268                                 sbAdditionalInfo.append(String.format(
269                                                 "But the Login-Id: %s doesn't exist in the Database. Created a Guest Session. Request-URL: %s",
270                                                 orgUserId, fullURL));
271                                 validateDomain(request);
272                                 if (request.getParameter(REDIRECT_URL) != null && request.getParameter(REDIRECT_URL).length() != 0) {
273                                         return new ModelAndView(REDIRECT_COLON + DEFAULT_FAILURE_VIEW + ".htm" + "?redirectUrl="
274                                                         + request.getParameter(REDIRECT_URL));
275                                 } else {
276                                         return new ModelAndView(REDIRECT_COLON + DEFAULT_FAILURE_VIEW + ".htm");
277                                 }
278                         } else {
279
280                                 sbAdditionalInfo.append(
281                                                 String.format("Login-Id: %s, Login-Method: %s, Request-URL: %s", orgUserId, "", fullURL));
282                                 logger.info(EELFLoggerDelegate.debugLogger, "processSingleSignOn: now set up user session for {}",
283                                                 orgUserId);
284
285                                 EPUserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
286                                                 commandBean.getBusinessDirectMenu(), ePRoleFunctionService);
287                                 logger.info(EELFLoggerDelegate.debugLogger,
288                                                 "processSingleSignOn: now set up user session for {} finished", orgUserId);
289
290                                 // Store user's information into share context
291                                 try {
292                                         logger.info(EELFLoggerDelegate.debugLogger,
293                                                         "processSingleSignOn: store user info into share context begins");
294                                         String sessionId = request.getSession().getId();
295                                         List<SharedContext> existingSC = getSharedContextService().getSharedContexts(sessionId);
296                                         if (existingSC == null || existingSC.isEmpty()) {
297                                                 getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_FIRST_NAME,
298                                                                 commandBean.getUser().getFirstName());
299                                                 getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_LAST_NAME,
300                                                                 commandBean.getUser().getLastName());
301                                                 getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_EMAIL,
302                                                                 commandBean.getUser().getEmail());
303                                                 getSharedContextService().addSharedContext(sessionId, EPSystemProperties.USER_ORG_USERID,
304                                                                 commandBean.getLoginId());
305                                         }
306                                 } catch (Exception e) {
307                                         logger.info(EELFLoggerDelegate.errorLogger,
308                                                         "processSingleSignOn: failed the shared context adding process", e);
309                                 }
310
311                                 logger.info(EELFLoggerDelegate.debugLogger,
312                                                 "processSingleSignOn: PresetUp the EP service cookie and intial sessionManagement");
313                                 SessionCookieUtil.preSetUp(request, response);
314                                 SessionCookieUtil.setUpUserIdCookie(request, response, orgUserId);
315                                 logger.info(EELFLoggerDelegate.debugLogger,
316                                                 "processSingleSignOn: PresetUp the EP service cookie and intial sessionManagement completed");
317                                 logger.info(EELFLoggerDelegate.debugLogger,
318                                                 commandBean.getUser().getOrgUserId() + " exists in the the system.");
319
320                                 // get redirectUrl from URL parameter
321                                 validateDomain(request);
322                                 if (request.getParameter(REDIRECT_URL) != null && request.getParameter(REDIRECT_URL).length() != 0) {
323                                         String forwardUrl = URLDecoder.decode(request.getParameter(REDIRECT_URL), "UTF-8");
324                                         // clean cookie
325                                         Cookie cookie2 = new Cookie(REDIRECT_URL, "");
326                                         // ONAP does not use https
327                                         cookie2.setSecure(false);
328                                         cookie2.setMaxAge(0);
329                                         cookie2.setDomain(EPSystemProperties.getProperty(EPSystemProperties.COOKIE_DOMAIN));
330                                         cookie2.setPath("/");
331                                         response.addCookie(cookie2);
332                                         return new ModelAndView(REDIRECT_COLON + forwardUrl);
333                                 }
334
335                                 // first check if redirectUrl exists or not
336                                 if (WebUtils.getCookie(request, REDIRECT_URL) != null) {
337                                         String forwardUrl = WebUtils.getCookie(request, REDIRECT_URL).getValue();
338                                         // clean cookie
339                                         Cookie cookie2 = new Cookie(REDIRECT_URL, "");
340                                         // ONAP does not use https
341                                         cookie2.setSecure(false);
342                                         cookie2.setMaxAge(0);
343                                         cookie2.setDomain(EPSystemProperties.getProperty(EPSystemProperties.COOKIE_DOMAIN));
344                                         cookie2.setPath("/");
345                                         response.addCookie(cookie2);
346
347                                         return new ModelAndView(REDIRECT_COLON + forwardUrl);
348                                 }
349                         }
350                 }
351
352                 // if user has been authenticated, now take them to the welcome page.
353                 logger.info(EELFLoggerDelegate.debugLogger, "processSingleSignOn: Now return to application home page");
354                 return new ModelAndView(REDIRECT_COLON + SystemProperties.getProperty(EPSystemProperties.FE_URL));
355         }
356
357         private void validateDomain(HttpServletRequest request) throws MalformedURLException {
358                 final String returnToAppUrl = request.getParameter(REDIRECT_URL);
359                 if (StringUtils.isNotBlank(returnToAppUrl)) {
360                         String hostName = new URL(returnToAppUrl).getHost();
361                         if (StringUtils.isNotBlank(hostName)
362                                         && !hostName.endsWith(EPSystemProperties.getProperty(EPCommonSystemProperties.COOKIE_DOMAIN))) {
363                                 logger.debug(EELFLoggerDelegate.debugLogger,
364                                                 "processSingleSignOn ()  accessing Unauthorized url  :" + hostName);
365                                 throw new SecurityException("accessing Unauthorized url : " + hostName);
366                         }
367                 }
368         }
369
370         private String getFullURL(HttpServletRequest request) {
371                 if (request != null) {
372                         String requestURL = request.getRequestURL().toString();
373                         String queryString = request.getQueryString();
374                         if (queryString == null) {
375                                 return requestURL;
376                         } else {
377                                 return requestURL + "?" + queryString;
378                         }
379                 }
380                 return "";
381         }
382
383         private String getRequestId(HttpServletRequest request) {
384                 Enumeration<String> headerNames = request.getHeaderNames();
385                 String requestId = "";
386                 while (headerNames.hasMoreElements()) {
387                         String headerName = headerNames.nextElement();
388                         logger.debug(EELFLoggerDelegate.debugLogger, "getRequestId: header {} has value {}", headerName,
389                                         request.getHeader(headerName));
390                         if (headerName.equalsIgnoreCase(SystemProperties.ECOMP_REQUEST_ID)) {
391                                 requestId = request.getHeader(headerName);
392                                 break;
393                         }
394                 }
395                 return requestId.isEmpty() ? UUID.randomUUID().toString() : requestId;
396         }
397
398         public String getWelcomeView() {
399                 return welcomeView;
400         }
401
402         public void setWelcomeView(String welcomeView) {
403                 this.welcomeView = welcomeView;
404         }
405
406         @Override
407         public String getViewName() {
408                 return viewName;
409         }
410
411         @Override
412         public void setViewName(String viewName) {
413                 this.viewName = viewName;
414         }
415
416         public EPLoginService getLoginService() {
417                 return loginService;
418         }
419
420         public void setLoginService(EPLoginService loginService) {
421                 this.loginService = loginService;
422         }
423
424         public SharedContextService getSharedContextService() {
425                 return sharedContextService;
426         }
427
428         public void setSharedContextService(SharedContextService sharedContextService) {
429                 this.sharedContextService = sharedContextService;
430         }
431
432         @ExceptionHandler(Exception.class)
433         protected void handleBadRequests(Exception e, HttpServletResponse response) throws IOException {
434                 logger.warn(EELFLoggerDelegate.errorLogger, "Handling bad request", e);
435                 response.sendError(HttpStatus.BAD_REQUEST.value());
436         }
437 }