/* * Copyright 2013, 2014, 2015 EnergyOS.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file 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. */ package org.energyos.espi.thirdparty.web; import java.security.Principal; import java.util.Arrays; import java.util.Set; import java.util.UUID; import javax.persistence.NoResultException; import javax.xml.bind.JAXBException; import org.energyos.espi.common.domain.ApplicationInformation; import org.energyos.espi.common.domain.Authorization; import org.energyos.espi.common.domain.Routes; import org.energyos.espi.common.service.ApplicationInformationService; import org.energyos.espi.common.service.AuthorizationService; import org.energyos.espi.common.service.StateService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller @PreAuthorize("hasRole('ROLE_USER')") public class ScopeSelectionController extends BaseController { @Autowired private ApplicationInformationService applicationInformationService; @Autowired private AuthorizationService authorizationService; @Autowired @Qualifier("stateService") private StateService stateService; @RequestMapping(value = Routes.THIRD_PARTY_SCOPE_SELECTION_SCREEN, method = RequestMethod.GET) public String scopeSelection(@RequestParam("scope") String[] scopes, ModelMap model) throws JAXBException { System.out .printf("ScopeSelectionController: HttpRequest Method: GET, scopes: %s\n", Arrays.asList(scopes)); model.put("scopeList", Arrays.asList(scopes)); return "/RetailCustomer/ScopeSelection"; } @RequestMapping(value = Routes.THIRD_PARTY_SCOPE_SELECTION_SCREEN_WITH_RETAIL_CUSTOMER_ID, method = RequestMethod.POST) public String scopeSelection( @RequestParam("Data_custodian") String dataCustodianId, @RequestParam("Data_custodian_URL") String dataCustodianURL) throws JAXBException { System.out .printf("ScopeSelectionController: HttpRequest Method: POST, dataCustodianID: %s dataCustodianURL: %s\n", dataCustodianId, dataCustodianURL); ApplicationInformation applicationInformation = applicationInformationService .findByDataCustodianClientId(dataCustodianId); return "redirect:" + dataCustodianURL + "?" + newScopeParams(applicationInformation.getScope()) + "&ThirdPartyID=" + applicationInformation.getClientId(); } @RequestMapping(value = Routes.THIRD_PARTY_SCOPE_SELECTION_SCREEN, method = RequestMethod.POST) public String scopeAuthorization(@RequestParam("scope") String scope, @RequestParam("DataCustodianID") String dataCustodianId, Principal principal) throws JAXBException { System.out .printf("ScopeSelectionController: HttpRequest Method: POST, scope: %s dataCustodianID: %s\n", scope, dataCustodianId); ApplicationInformation applicationInformation = applicationInformationService .findByDataCustodianClientId(dataCustodianId); try { // Does an ACTIVE authorization record exist for the requested Scope Authorization currentAuthorization = authorizationService .findByScope(scope, currentCustomer(principal).getId()); // Is this a valid authorization record? if (currentAuthorization.getStatus() == null) { // Delete the invalid record and continue request authorizationService.delete(currentAuthorization); throw new NoResultException(); } else { // Is the existing authorization record Active if (!currentAuthorization.getStatus().equals("1")) { // No, create a new authorization record entry throw new NoResultException(); } } } catch (NoResultException | EmptyResultDataAccessException e) { // No authorization record exist for the requested Scope Authorization authorization = new Authorization(); // Initialize authorization record content authorization.setApplicationInformation(applicationInformation); authorization.setThirdParty(applicationInformation.getClientId()); authorization.setRetailCustomer(currentCustomer(principal)); authorization.setState(stateService.newState()); authorization.setUUID(UUID.randomUUID()); authorization.setResponseType("code"); authorization.setScope(scope); authorizationService.persist(authorization); return "redirect:" + applicationInformation .getAuthorizationServerAuthorizationEndpoint() + "?client_id=" + applicationInformation.getClientId() + "&redirect_uri=" + applicationInformation.getRedirectUri() + "&response_type=code&scope=" + scope + "&state=" + authorization.getState(); } // TODO: If an Oauth access token already exists, do we want to display // the "UsagePoint" screen? // Display the Authorization List screen if an OAuth access token // already exist return "redirect:/RetailCustomer/" + currentCustomer(principal).getId() + "/AuthorizationList"; } public void setAuthorizationService( AuthorizationService authorizationService) { this.authorizationService = authorizationService; } public void setStateService(StateService stateService) { this.stateService = stateService; } public void setApplicationInformationService( ApplicationInformationService applicationInformationService) { this.applicationInformationService = applicationInformationService; } public static String newScopeParams(Set<String> scopes) { StringBuilder sb = new StringBuilder(); int i = 0; for (String scope : scopes) { if (i > 0) sb.append("&"); sb.append("scope=" + scope); i++; } return sb.toString(); } }