/*-
* ============LICENSE_START==========================================
* ONAP Portal
* ===================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
* ===================================================================
*
* Unless otherwise specified, all software contained herein is licensed
* under the Apache License, Version 2.0 (the "License");
* you may not use this software except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Unless otherwise specified, all documentation contained herein is licensed
* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
* you may not use this documentation except in compliance with the License.
* You may obtain a copy of the License at
*
* https://creativecommons.org/licenses/by/4.0/
*
* Unless required by applicable law or agreed to in writing, documentation
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ============LICENSE_END============================================
*
*
*/
package org.onap.portalapp.portal.controller;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import lombok.NoArgsConstructor;
import org.onap.portalapp.portal.domain.EPApp;
import org.onap.portalapp.portal.domain.EPUser;
import org.onap.portalapp.portal.ecomp.model.PortalRestResponse;
import org.onap.portalapp.portal.ecomp.model.PortalRestStatusEnum;
import org.onap.portalapp.portal.logging.aop.EPAuditLog;
import org.onap.portalapp.portal.service.AdminRolesService;
import org.onap.portalapp.portal.service.EPAppService;
import org.onap.portalapp.portal.service.PortalAdminService;
import org.onap.portalapp.portal.service.UserService;
import org.onap.portalapp.portal.transport.FieldsValidator;
import org.onap.portalapp.portal.transport.OnboardingApp;
import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
import org.onap.portalapp.portal.utils.EcompPortalUtils;
import org.onap.portalapp.portal.utils.PortalConstants;
import org.onap.portalapp.validation.DataValidator;
import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* Processes requests from external systems (i.e., not the front-end web UI).
* First use case is ONAP Controller, which has to create an admin and onboard
* itself upon launch of a fresh Portal.
*
* Listens on the "auxapi" path prefix. Provides alternate implementations of
* methods in several existing controllers because an EPUser object is not
* available in the session for these requests.
*
* Checks credentials sent via HTTP Basic Authentication. The Portal's basic
* HTTP authentication system requires that the user names and endpoints are
* registered together.
*/
@RestController
@RequestMapping(PortalConstants.REST_AUX_API)
@Configuration
@EnableAspectJAutoProxy
@EPAuditLog
@NoArgsConstructor
public class AppsControllerExternalRequest implements BasicAuthenticationController {
private static final String ONBOARD_APP = "/onboardApp";
private static final String DATA_IS_NOT_VALID = "Data is not valid";
private static final String REQUEST = "request";
private static final String RESPONSE = "response";
private static final DataValidator DATA_VALIDATOR = new DataValidator();
private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AppsControllerExternalRequest.class);
private AdminRolesService adminRolesService;
private EPAppService appService;
private PortalAdminService portalAdminService;
private UserService userService;
@Autowired
public AppsControllerExternalRequest(AdminRolesService adminRolesService,
EPAppService appService, PortalAdminService portalAdminService,
UserService userService) {
this.adminRolesService = adminRolesService;
this.appService = appService;
this.portalAdminService = portalAdminService;
this.userService = userService;
}
/**
* Creates a new user as a Portal administrator.
*
*
* { "loginId" : "abc123", "loginPwd": "", "email":"ecomp@controller" }
*
*
* @param request HttpServletRequest
* @param epUser User details; the email and orgUserId fields are mandatory
* @param response HttpServletResponse
* @return PortalRestResponse with success or failure
*/
@ApiOperation(value = "Creates a new user as a Portal administrator.", response = PortalRestResponse.class)
@RequestMapping(value = "/portalAdmin", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public PortalRestResponse postPortalAdmin(HttpServletRequest request, HttpServletResponse response,
@Valid @RequestBody EPUser epUser) {
EcompPortalUtils.logAndSerializeObject(logger, "postPortalAdmin", REQUEST, epUser);
PortalRestResponse portalResponse = new PortalRestResponse<>();
if (epUser == null) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("User can not be NULL");
return portalResponse;
} else if (!DATA_VALIDATOR.isValid(epUser)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(DATA_IS_NOT_VALID);
return portalResponse;
}
if (epUser.getEmail() == null || epUser.getEmail().trim().length() == 0 //
|| epUser.getLoginId() == null || epUser.getLoginId().trim().length() == 0 //
|| epUser.getLoginPwd() == null) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("Missing required field: email, loginId, or loginPwd");
return portalResponse;
}
try {
// Check for existing user; create if not found.
List userList = userService.getUserByUserId(epUser.getOrgUserId());
if (userList == null || userList.isEmpty()) {
// Create user with first, last names etc.; do check for
// duplicates.
String userCreateResult = userService.saveNewUser(epUser, "Yes");
if (!"success".equals(userCreateResult)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(userCreateResult);
return portalResponse;
}
}
// Check for Portal admin status; promote if not.
if (adminRolesService.isSuperAdmin(epUser)) {
portalResponse.setStatus(PortalRestStatusEnum.OK);
} else {
FieldsValidator fv;
fv = portalAdminService.createPortalAdmin(epUser.getOrgUserId());
if (fv != null && fv.httpStatusCode.intValue() == HttpServletResponse.SC_OK) {
portalResponse.setStatus(PortalRestStatusEnum.OK);
} else {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
if (fv != null) {
portalResponse.setMessage(fv.toString());
}
}
}
} catch (Exception ex) {
// Uncaught exceptions yield 404 and an empty error page
logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), ex);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(ex.toString());
}
EcompPortalUtils.logAndSerializeObject(logger, "postPortalAdmin", RESPONSE, portalResponse);
return portalResponse;
}
/**
* Gets the specified application that is on-boarded in Portal.
*
* @param request HttpServletRequest
* @param appId Application ID to get
* @param response httpServletResponse
* @return OnboardingApp objects
*/
@ApiOperation(value = "Gets the specified application that is on-boarded in Portal.", response = OnboardingApp.class)
@RequestMapping(value = {ONBOARD_APP + "/{appId}"}, method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public OnboardingApp getOnboardAppExternal(HttpServletRequest request, HttpServletResponse response,
@PathVariable("appId") Long appId) {
EPApp epApp = appService.getApp(appId);
OnboardingApp obApp = new OnboardingApp();
epApp.setAppPassword(EPCommonSystemProperties.APP_DISPLAY_PASSWORD); //to hide password from get request
appService.createOnboardingFromApp(epApp, obApp);
EcompPortalUtils.logAndSerializeObject(logger, "getOnboardAppExternal", RESPONSE, obApp);
return obApp;
}
/**
* Adds a new application to Portal. The My Logins App Owner in the request must be the organization user ID of a
* person who is a Portal administrator.
*
*
* {
* "myLoginsAppOwner" : "abc123",
* "name": "dashboard",
* "url": "http://k8s/something",
* "restUrl" : "http://targeturl.com",
* "restrictedApp" : true,
* "isOpen" : true,
* "isEnabled": false
* }
*
*
* @param request HttpServletRequest
* @param response httpServletResponse
* @param newOnboardApp Message with details about the app to add
* @return PortalRestResponse
*/
@ApiOperation(value = "Adds a new application to Portal.", response = PortalRestResponse.class)
@RequestMapping(value = {ONBOARD_APP}, method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public PortalRestResponse postOnboardAppExternal(HttpServletRequest request, HttpServletResponse response,
@Valid @RequestBody OnboardingApp newOnboardApp) {
EcompPortalUtils.logAndSerializeObject(logger, "postOnboardAppExternal", REQUEST, newOnboardApp);
PortalRestResponse portalResponse = new PortalRestResponse<>();
if (newOnboardApp == null) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("newOnboardApp can not be NULL");
return portalResponse;
} else if (!DATA_VALIDATOR.isValid(newOnboardApp)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(DATA_IS_NOT_VALID);
return portalResponse;
}
// Validate fields
if (newOnboardApp.id != null) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("Unexpected field: id");
return portalResponse;
}
if (checkOnboardingApp(newOnboardApp)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(
"Missing required field: name, url, restUrl, restrictedApp, isOpen, isEnabled, myLoginsAppOwner");
return portalResponse;
}
try {
List userList;
userList = userService.getUserByUserId(newOnboardApp.myLoginsAppOwner);
if (userList == null || userList.size() != 1) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("Failed to find user: " + newOnboardApp.myLoginsAppOwner);
return portalResponse;
}
EPUser epUser = userList.get(0);
// Check for Portal admin status
if (!adminRolesService.isSuperAdmin(epUser)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("User lacks Portal admin role: " + epUser.getLoginId());
return portalResponse;
}
newOnboardApp.normalize();
FieldsValidator fv = appService.addOnboardingApp(newOnboardApp, epUser);
if (fv.httpStatusCode.intValue() == HttpServletResponse.SC_OK) {
portalResponse.setStatus(PortalRestStatusEnum.OK);
} else {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(fv.toString());
}
} catch (Exception ex) {
// Uncaught exceptions yield 404 and an empty error page
logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), ex);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(ex.toString());
}
EcompPortalUtils.logAndSerializeObject(logger, "postOnboardAppExternal", RESPONSE, portalResponse);
return portalResponse;
}
/**
* Updates information about an on-boarded application in Portal. The My Logins App Owner in the request must be
* the organization user ID of a person who is a Portal administrator.
*
* {
* "id" : 123,
* "myLoginsAppOwner" : "abc123",
* "name": "dashboard",
* "url": "http://k8s/something",
* "restUrl" : "http://targeturl.com",
* "restrictedApp" : true,
* "isOpen" : true,
* "isEnabled": false
* }
*
*
* @param request HttpServletRequest
* @param response httpServletResponse
* @param appId application id
* @param oldOnboardApp Message with details about the app to add
* @return PortalRestResponse
*/
@ApiOperation(value = "Updates information about an on-boarded application in Portal.", response = PortalRestResponse.class)
@RequestMapping(value = {ONBOARD_APP + "/{appId}"}, method = RequestMethod.PUT, produces = "application/json")
@ResponseBody
public PortalRestResponse putOnboardAppExternal(HttpServletRequest request, HttpServletResponse response,
@PathVariable("appId") Long appId, @Valid @RequestBody OnboardingApp oldOnboardApp) {
EcompPortalUtils.logAndSerializeObject(logger, "putOnboardAppExternal", REQUEST, oldOnboardApp);
PortalRestResponse portalResponse = new PortalRestResponse<>();
if (oldOnboardApp == null){
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("OnboardingApp can not be NULL");
return portalResponse;
}else if (!DATA_VALIDATOR.isValid(oldOnboardApp)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(DATA_IS_NOT_VALID);
return portalResponse;
}
// Validate fields.
if (appId == null || !appId.equals(oldOnboardApp.id)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("Unexpected value for field: id");
return portalResponse;
}
if (checkOnboardingApp(oldOnboardApp)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(
"Missing required field: name, url, restUrl, restrictedApp, isOpen, isEnabled, myLoginsAppOwner");
return portalResponse;
}
try {
List userList;
userList = userService.getUserByUserId(oldOnboardApp.myLoginsAppOwner);
if (userList == null || userList.size() != 1) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("Failed to find user: " + oldOnboardApp.myLoginsAppOwner);
return portalResponse;
}
EPUser epUser = userList.get(0);
// Check for Portal admin status
if (!adminRolesService.isSuperAdmin(epUser)) {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage("User lacks Portal admin role: " + epUser.getLoginId());
return portalResponse;
}
oldOnboardApp.normalize();
FieldsValidator fv = appService.modifyOnboardingApp(oldOnboardApp, epUser);
if (fv.httpStatusCode.intValue() == HttpServletResponse.SC_OK) {
portalResponse.setStatus(PortalRestStatusEnum.OK);
} else {
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(fv.toString());
}
} catch (Exception ex) {
// Uncaught exceptions yield 404 and an empty error page
logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), ex);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
portalResponse.setStatus(PortalRestStatusEnum.ERROR);
portalResponse.setMessage(ex.toString());
}
EcompPortalUtils.logAndSerializeObject(logger, "putOnboardAppExternal", RESPONSE, portalResponse);
return portalResponse;
}
private boolean checkOnboardingApp(OnboardingApp onboardingApp) {
return checkIfFieldsAreNull(onboardingApp) || checkIfFieldsAreEmpty(onboardingApp);
}
private boolean checkIfFieldsAreNull(OnboardingApp onboardingApp) {
return onboardingApp.name == null || onboardingApp.url == null || onboardingApp.restUrl == null
|| onboardingApp.myLoginsAppOwner == null || onboardingApp.restrictedApp == null
|| onboardingApp.isOpen == null || onboardingApp.isEnabled == null;
}
private boolean checkIfFieldsAreEmpty(OnboardingApp onboardingApp) {
return onboardingApp.name.trim().isEmpty()
|| onboardingApp.url.trim().isEmpty()
|| onboardingApp.restUrl.trim().isEmpty()
|| onboardingApp.myLoginsAppOwner.trim().isEmpty();
}
}