Merge "Fix sql injection vulnerability"
[portal.git] / ecomp-portal-BE-common / src / main / java / org / onap / portalapp / portal / controller / AppsControllerExternalRequest.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.portal.controller;
39
40 import java.util.List;
41
42 import java.util.Set;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpServletResponse;
45
46 import javax.validation.ConstraintViolation;
47 import javax.validation.Valid;
48 import javax.validation.Validation;
49 import javax.validation.Validator;
50 import javax.validation.ValidatorFactory;
51 import org.onap.portalapp.portal.domain.EPApp;
52 import org.onap.portalapp.portal.domain.EPUser;
53 import org.onap.portalapp.portal.ecomp.model.PortalRestResponse;
54 import org.onap.portalapp.portal.ecomp.model.PortalRestStatusEnum;
55 import org.onap.portalapp.portal.logging.aop.EPAuditLog;
56 import org.onap.portalapp.portal.service.AdminRolesService;
57 import org.onap.portalapp.portal.service.EPAppService;
58 import org.onap.portalapp.portal.service.PortalAdminService;
59 import org.onap.portalapp.portal.service.UserService;
60 import org.onap.portalapp.portal.transport.FieldsValidator;
61 import org.onap.portalapp.portal.transport.OnboardingApp;
62 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
63 import org.onap.portalapp.portal.utils.EcompPortalUtils;
64 import org.onap.portalapp.portal.utils.PortalConstants;
65 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
66 import org.springframework.beans.factory.annotation.Autowired;
67 import org.springframework.context.annotation.Configuration;
68 import org.springframework.context.annotation.EnableAspectJAutoProxy;
69 import org.springframework.web.bind.annotation.PathVariable;
70 import org.springframework.web.bind.annotation.RequestBody;
71 import org.springframework.web.bind.annotation.RequestMapping;
72 import org.springframework.web.bind.annotation.RequestMethod;
73 import org.springframework.web.bind.annotation.ResponseBody;
74 import org.springframework.web.bind.annotation.RestController;
75
76 import io.swagger.annotations.ApiOperation;
77
78 /**
79  * Processes requests from external systems (i.e., not the front-end web UI).
80  * First use case is ONAP Controller, which has to create an admin and onboard
81  * itself upon launch of a fresh Portal.
82  * 
83  * Listens on the "auxapi" path prefix. Provides alternate implementations of
84  * methods in several existing controllers because an EPUser object is not
85  * available in the session for these requests.
86  * 
87  * Checks credentials sent via HTTP Basic Authentication. The Portal's basic
88  * HTTP authentication system requires that the user names and endpoints are
89  * registered together.
90  */
91 @RestController
92 @RequestMapping(PortalConstants.REST_AUX_API)
93 @Configuration
94 @EnableAspectJAutoProxy
95 @EPAuditLog
96 public class AppsControllerExternalRequest implements BasicAuthenticationController {
97         private static final ValidatorFactory VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory();
98
99         private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AppsControllerExternalRequest.class);
100
101         private static final String ONBOARD_APP = "/onboardApp";
102
103         /**
104          * For testing whether a user is a superadmin.
105          */
106         @Autowired
107         private AdminRolesService adminRolesService;
108
109         /**
110          * For onboarding or updating an app
111          */
112         @Autowired
113         private EPAppService appService;
114
115         /**
116          * For promoting a user to Portal admin
117          */
118         @Autowired
119         private PortalAdminService portalAdminService;
120
121         /**
122          * For creating a new user
123          */
124         @Autowired
125         private UserService userService;
126
127         /**
128          * Creates a new user as a Portal administrator.
129          * 
130          * <PRE>
131          { 
132                 "loginId" : "abc123",
133                 "loginPwd": "",
134                 "email":"ecomp@controller" 
135          }
136          * </PRE>
137          * 
138          * @param request
139          *            HttpServletRequest
140          * @param epUser
141          *            User details; the email and orgUserId fields are mandatory
142          * @param response
143          *            HttpServletResponse
144          * @return PortalRestResponse with success or failure
145          */
146         @ApiOperation(value = "Creates a new user as a Portal administrator.", response = PortalRestResponse.class)
147         @RequestMapping(value = "/portalAdmin", method = RequestMethod.POST, produces = "application/json")
148         @ResponseBody
149         public PortalRestResponse<String> postPortalAdmin(HttpServletRequest request, HttpServletResponse response,
150                         @Valid @RequestBody EPUser epUser) {
151                 EcompPortalUtils.logAndSerializeObject(logger, "postPortalAdmin", "request", epUser);
152                 PortalRestResponse<String> portalResponse = new PortalRestResponse<>();
153
154                 if (epUser!=null){
155                         Validator validator = VALIDATOR_FACTORY.getValidator();
156                         Set<ConstraintViolation<EPUser>> constraintViolations = validator.validate(epUser);
157                         if (!constraintViolations.isEmpty()){
158                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
159                                 portalResponse.setMessage("Data is not valid");
160                                 return portalResponse;
161                         }
162                 }
163
164                 // Check mandatory fields.
165                 if (epUser.getEmail() == null || epUser.getEmail().trim().length() == 0 //
166                                 || epUser.getLoginId() == null || epUser.getLoginId().trim().length() == 0 //
167                                 || epUser.getLoginPwd() == null) {
168                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
169                         portalResponse.setMessage("Missing required field: email, loginId, or loginPwd");
170                         return portalResponse;
171                 }
172
173                 try {
174                         // Check for existing user; create if not found.
175                         List<EPUser> userList = userService.getUserByUserId(epUser.getOrgUserId());
176                         if (userList == null || userList.size() == 0) {
177                                 // Create user with first, last names etc.; do check for
178                                 // duplicates.
179                                 String userCreateResult = userService.saveNewUser(epUser, "Yes");
180                                 if (!"success".equals(userCreateResult)) {
181                                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
182                                         portalResponse.setMessage(userCreateResult);
183                                         return portalResponse;
184                                 }
185                         }
186
187                         // Check for Portal admin status; promote if not.
188                         if (adminRolesService.isSuperAdmin(epUser)) {
189                                 portalResponse.setStatus(PortalRestStatusEnum.OK);
190                         } else {
191                                 FieldsValidator fv = portalAdminService.createPortalAdmin(epUser.getOrgUserId());
192                                 if (fv.httpStatusCode.intValue() == HttpServletResponse.SC_OK) {
193                                         portalResponse.setStatus(PortalRestStatusEnum.OK);
194                                 } else {
195                                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
196                                         portalResponse.setMessage(fv.toString());
197                                 }
198                         }
199                 } catch (Exception ex) {
200                         // Uncaught exceptions yield 404 and an empty error page
201                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
202                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
203                         portalResponse.setMessage(ex.toString());
204                 }
205
206                 EcompPortalUtils.logAndSerializeObject(logger, "postPortalAdmin", "response", portalResponse);
207                 return portalResponse;
208         }
209
210         /**
211          * Gets the specified application that is on-boarded in Portal.
212          * 
213          * @param request
214          *            HttpServletRequest
215          * @param appId
216          *            Application ID to get
217          * @param response
218          *            httpServletResponse
219          * @return OnboardingApp objects
220          */
221         @ApiOperation(value = "Gets the specified application that is on-boarded in Portal.", response = OnboardingApp.class)
222         @RequestMapping(value = { ONBOARD_APP + "/{appId}" }, method = RequestMethod.GET, produces = "application/json")
223         @ResponseBody
224         public OnboardingApp getOnboardAppExternal(HttpServletRequest request, HttpServletResponse response,
225                         @PathVariable("appId") Long appId) {
226                 EPApp epApp = appService.getApp(appId);
227                 OnboardingApp obApp = new OnboardingApp();
228                 epApp.setAppPassword(EPCommonSystemProperties.APP_DISPLAY_PASSWORD); //to hide password from get request
229                 appService.createOnboardingFromApp(epApp, obApp);
230                 EcompPortalUtils.logAndSerializeObject(logger, "getOnboardAppExternal", "response", obApp);
231                 return obApp;
232         }
233
234         /**
235          * Adds a new application to Portal. The My Logins App Owner in the request
236          * must be the organization user ID of a person who is a Portal
237          * administrator.
238          * 
239          * <pre>
240          * { 
241                 "myLoginsAppOwner" : "abc123",
242                 "name": "dashboard",
243                 "url": "http://k8s/something",
244                 "restUrl" : "http://targeturl.com",
245                 "restrictedApp" : true,
246                 "isOpen" : true,
247                 "isEnabled": false
248                 }
249          * </pre>
250          * 
251          * @param request
252          *            HttpServletRequest
253          * @param response
254          *            httpServletResponse
255          * @param newOnboardApp
256          *            Message with details about the app to add
257          * @return PortalRestResponse
258          */
259         @ApiOperation(value = "Adds a new application to Portal.", response = PortalRestResponse.class)
260         @RequestMapping(value = { ONBOARD_APP }, method = RequestMethod.POST, produces = "application/json")
261         @ResponseBody
262         public PortalRestResponse<String> postOnboardAppExternal(HttpServletRequest request, HttpServletResponse response,
263                         @Valid @RequestBody OnboardingApp newOnboardApp) {
264                 EcompPortalUtils.logAndSerializeObject(logger, "postOnboardAppExternal", "request", newOnboardApp);
265                 PortalRestResponse<String> portalResponse = new PortalRestResponse<>();
266                 if (newOnboardApp != null){
267                         Validator validator = VALIDATOR_FACTORY.getValidator();
268                         Set<ConstraintViolation<OnboardingApp>> constraintViolations = validator.validate(newOnboardApp);
269                         if (!constraintViolations.isEmpty()){
270                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
271                                 portalResponse.setMessage("Data is not valid");
272                                 return portalResponse;
273                         }
274                 }
275                 // Validate fields
276                 if (newOnboardApp.id != null) {
277                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
278                         portalResponse.setMessage("Unexpected field: id");
279                         return portalResponse;
280                 }
281                 if (newOnboardApp.name == null || newOnboardApp.name.trim().length() == 0 //
282                                 || newOnboardApp.url == null || newOnboardApp.url.trim().length() == 0 //
283                                 || newOnboardApp.restUrl == null || newOnboardApp.restUrl.trim().length() == 0
284                                 || newOnboardApp.myLoginsAppOwner == null || newOnboardApp.myLoginsAppOwner.trim().length() == 0
285                                 || newOnboardApp.restrictedApp == null //
286                                 || newOnboardApp.isOpen == null //
287                                 || newOnboardApp.isEnabled == null) {
288                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
289                         portalResponse.setMessage(
290                                         "Missing required field: name, url, restUrl, restrictedApp, isOpen, isEnabled, myLoginsAppOwner");
291                         return portalResponse;
292                 }
293
294                 try {
295                         List<EPUser> userList = userService.getUserByUserId(newOnboardApp.myLoginsAppOwner);
296                         if (userList == null || userList.size() != 1) {
297                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
298                                 portalResponse.setMessage("Failed to find user: " + newOnboardApp.myLoginsAppOwner);
299                                 return portalResponse;
300                         }
301
302                         EPUser epUser = userList.get(0);
303                         // Check for Portal admin status
304                         if (! adminRolesService.isSuperAdmin(epUser)) {
305                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
306                                 portalResponse.setMessage("User lacks Portal admin role: " + epUser.getLoginId());
307                                 return portalResponse;                          
308                         }
309                                 
310                         newOnboardApp.normalize();
311                         FieldsValidator fv = appService.addOnboardingApp(newOnboardApp, epUser);
312                         if (fv.httpStatusCode.intValue() == HttpServletResponse.SC_OK) {
313                                 portalResponse.setStatus(PortalRestStatusEnum.OK);
314                         } else {
315                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
316                                 portalResponse.setMessage(fv.toString());
317                         }
318                 } catch (Exception ex) {
319                         // Uncaught exceptions yield 404 and an empty error page
320                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
321                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
322                         portalResponse.setMessage(ex.toString());
323                 }
324                 EcompPortalUtils.logAndSerializeObject(logger, "postOnboardAppExternal", "response", portalResponse);
325                 return portalResponse;
326         }
327
328         /**
329          * Updates information about an on-boarded application in Portal. The My
330          * Logins App Owner in the request must be the organization user ID of a
331          * person who is a Portal administrator.
332          * <pre>
333            { 
334                 "id" : 123,
335                 "myLoginsAppOwner" : "abc123",
336                 "name": "dashboard",
337                 "url": "http://k8s/something",
338                 "restUrl" : "http://targeturl.com",
339                 "restrictedApp" : true,
340                 "isOpen" : true,
341                 "isEnabled": false
342                 }
343                 </pre>
344          * @param request
345          *            HttpServletRequest
346          * @param response
347          *            httpServletResponse
348          * @param appId
349          *            application id
350          * @param oldOnboardApp
351          *            Message with details about the app to add
352          * @return PortalRestResponse
353          */
354         @ApiOperation(value = "Updates information about an on-boarded application in Portal.", response = PortalRestResponse.class)
355         @RequestMapping(value = { ONBOARD_APP + "/{appId}" }, method = RequestMethod.PUT, produces = "application/json")
356         @ResponseBody
357         public PortalRestResponse<String> putOnboardAppExternal(HttpServletRequest request, HttpServletResponse response,
358                         @PathVariable("appId") Long appId, @Valid @RequestBody OnboardingApp oldOnboardApp) {
359                 EcompPortalUtils.logAndSerializeObject(logger, "putOnboardAppExternal", "request", oldOnboardApp);
360                 PortalRestResponse<String> portalResponse = new PortalRestResponse<>();
361
362                 if (oldOnboardApp != null){
363                         Validator validator = VALIDATOR_FACTORY.getValidator();
364                         Set<ConstraintViolation<OnboardingApp>> constraintViolations = validator.validate(oldOnboardApp);
365                         if (!constraintViolations.isEmpty()){
366                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
367                                 portalResponse.setMessage("Data is not valid");
368                                 return portalResponse;
369                         }
370                 }
371
372                 // Validate fields.
373                 if (oldOnboardApp.id == null || !appId.equals(oldOnboardApp.id)) {
374                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
375                         portalResponse.setMessage("Unexpected value for field: id");
376                         return portalResponse;
377                 }
378                 if (oldOnboardApp.name == null || oldOnboardApp.name.trim().length() == 0 //
379                                 || oldOnboardApp.url == null || oldOnboardApp.url.trim().length() == 0 //
380                                 || oldOnboardApp.restUrl == null || oldOnboardApp.restUrl.trim().length() == 0
381                                 || oldOnboardApp.myLoginsAppOwner == null || oldOnboardApp.myLoginsAppOwner.trim().length() == 0
382                                 || oldOnboardApp.restrictedApp == null //
383                                 || oldOnboardApp.isOpen == null //
384                                 || oldOnboardApp.isEnabled == null) {
385                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
386                         portalResponse.setMessage(
387                                         "Missing required field: name, url, restUrl, restrictedApp, isOpen, isEnabled, myLoginsAppOwner");
388                         return portalResponse;
389                 }
390
391                 try {
392                         List<EPUser> userList = userService.getUserByUserId(oldOnboardApp.myLoginsAppOwner);
393                         if (userList == null || userList.size() != 1) {
394                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
395                                 portalResponse.setMessage("Failed to find user: " + oldOnboardApp.myLoginsAppOwner);
396                                 return portalResponse;
397                         }
398
399                         EPUser epUser = userList.get(0);
400                         // Check for Portal admin status
401                         if (! adminRolesService.isSuperAdmin(epUser)) {
402                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
403                                 portalResponse.setMessage("User lacks Portal admin role: " + epUser.getLoginId());
404                                 return portalResponse;                          
405                         }
406
407                         oldOnboardApp.normalize();
408                         FieldsValidator fv = appService.modifyOnboardingApp(oldOnboardApp, epUser);
409                         if (fv.httpStatusCode.intValue() == HttpServletResponse.SC_OK) {
410                                 portalResponse.setStatus(PortalRestStatusEnum.OK);
411                         } else {
412                                 portalResponse.setStatus(PortalRestStatusEnum.ERROR);
413                                 portalResponse.setMessage(fv.toString());
414                         }
415                 } catch (Exception ex) {
416                         // Uncaught exceptions yield 404 and an empty error page
417                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
418                         portalResponse.setStatus(PortalRestStatusEnum.ERROR);
419                         portalResponse.setMessage(ex.toString());
420                 }
421                 EcompPortalUtils.logAndSerializeObject(logger, "putOnboardAppExternal", "response", portalResponse);
422                 return portalResponse;
423         }
424
425 }