From 29fb699f1220a5023ddba44733f1e5391e81655a Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Fri, 22 Mar 2019 17:20:28 -0600 Subject: [PATCH 01/11] #1659 adding the PortletPreferenceRESTController to uPortal --- .../rest/PortletPrefsRESTController.java | 515 +++++++++++++++ .../rest/PortletPrefsRESTControllerTest.java | 591 ++++++++++++++++++ .../GuestPortletEntityPreferencesAPIImpl.java | 177 ++++++ .../PortletEntityPreferencesAPIImpl.java | 173 +++++ .../services/PortletPreferencesFactory.java | 6 + .../PortletPreferencesFactoryImpl.java | 35 +- 6 files changed, 1496 insertions(+), 1 deletion(-) create mode 100644 uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java create mode 100644 uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java create mode 100644 uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java create mode 100644 uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java new file mode 100644 index 00000000000..08ca3e12f07 --- /dev/null +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -0,0 +1,515 @@ +package org.apereo.portal.rest; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.annotations.ApiParam; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.portlet.PortletPreferences; +import javax.portlet.ReadOnlyException; +import javax.portlet.WindowState; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apereo.portal.jpa.BasePortalJpaDao; +import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; +import org.apereo.portal.portlet.dao.IPortletDefinitionDao; +import org.apereo.portal.portlet.om.IPortletDefinition; +import org.apereo.portal.portlet.om.IPortletDefinitionId; +import org.apereo.portal.portlet.om.IPortletEntity; +import org.apereo.portal.portlet.om.IPortletPreference; +import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; +import org.apereo.portal.portlet.registry.IPortletEntityRegistry; +import org.apereo.portal.security.AuthorizationPrincipalHelper; +import org.apereo.portal.security.IAuthorizationPrincipal; +import org.apereo.portal.security.IPerson; +import org.apereo.portal.security.IPersonManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.support.TransactionOperations; +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.RequestParam; + +@Controller +public class PortletPrefsRESTController { + + protected final Log logger = LogFactory.getLog(getClass()); + private ObjectMapper mapper; + + private IPersonManager personManager; + + private final boolean DEFINITION_MODE=true; + private final boolean ENTITY_MODE=false; + + @Autowired + public void setPersonManager(IPersonManager personManager) { + this.personManager = personManager; + } + + private IPortletDefinitionDao portletDao; + + @Autowired + public void setPortletDao(IPortletDefinitionDao portletDao) { + this.portletDao = portletDao; + } + + private IPortletEntityRegistry portletEntityRegistry; + + @Autowired + public void setPortletEntityRegistry(IPortletEntityRegistry portletEntityRegistry) { + this.portletEntityRegistry = portletEntityRegistry; + } + + private IPortletDefinitionRegistry portletDefinitionRegistry; + + @Autowired + public void setPortletDefinitionRegistry(IPortletDefinitionRegistry portletDefinitionRegistry){ + this.portletDefinitionRegistry = portletDefinitionRegistry; + } + + private TransactionOperations transactionOperations; + + @Autowired + @Qualifier(BasePortalJpaDao.PERSISTENCE_UNIT_NAME) + public void setTransactionOperations(TransactionOperations transactionOperations) { + this.transactionOperations = transactionOperations; + } + + private PortletPreferencesFactory portletPreferencesFactory; + + @Autowired + @Qualifier("portletPreferencesFactory") + public void setPortletPreferencesFactoryAPI(PortletPreferencesFactory portletPreferencesFactory){ + this.portletPreferencesFactory=portletPreferencesFactory; + } + + + + public PortletPrefsRESTController() { + this.mapper=new ObjectMapper(); + } + + @RequestMapping(value = "/prefs/getentity/{fname}", method = RequestMethod.GET) + public ResponseEntity getEntity(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to get entity for") + @PathVariable(value = "fname") String fname) { + try{ + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\""+portletDefinition.getFName()+"\": {"); + stringBuilder.append(" \"layoutNodeID\": \""+entity.getLayoutNodeId()+"\","); + stringBuilder.append(" \"userID\": \""+entity.getUserId()+"\","); + stringBuilder.append(" \"entityID\": \""+entity.getPortletEntityId()+"\","); + stringBuilder.append(" \"windowStates\": ["); + boolean comma=false; + for(Map.Entry entry : entity.getWindowStates().entrySet()){ + stringBuilder.append(" { \"stylesheetID\": \""); + stringBuilder.append(entry.getKey()); + stringBuilder.append("\", \"windowState\": \""); + stringBuilder.append(entry.getValue().toString()); + stringBuilder.append("\"},"); + comma=true; + } + if (comma) { + stringBuilder.setLength(stringBuilder.length() - 1); + } + stringBuilder.append(" ] } }"); + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(stringBuilder.toString()); + }catch(IllegalArgumentException e){ + if(e.getMessage().contains("No portlet definition found for id '")){ + String error="ERROR: User not authorized to access portlet '"+fname+"'."; + logger.info(error); + return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); + } + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + }catch(Exception e){ + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } + + //return ResponseEntity.badRequest().build(); + } + + + //returns the entity composite preferences for the portlet in question + @RequestMapping(value = "/prefs/getprefs/{fname}", method = RequestMethod.GET) + public ResponseEntity getCompositePrefs(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") String fname) { + + try { + + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + //config mode of true is definition, false for entity (guest or user) + boolean config=ENTITY_MODE; + PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,config); + + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefs.getMap())); + + } catch(IllegalArgumentException e){ + if(e.getMessage().contains("No portlet definition found for id '")){ + String error="ERROR: User not authorized to access portlet '"+fname+"'."; + logger.info(error); + return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); + } + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + e.printStackTrace(); + logger.error("threw error trying to retrieve composite preferences",e); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + //maybe get rid of this one + @RequestMapping(value = "/prefs/getentityonlyprefs/{fname}", method = RequestMethod.GET) + public ResponseEntity getEntityOnlyPrefs(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") String fname) { + try { + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + + PortletPreferences defprefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,DEFINITION_MODE); + PortletPreferences entprefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,ENTITY_MODE); + Map eprefs=getEntityOnly(entprefs.getMap(),defprefs.getMap()); + + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(eprefs)); + } catch(IllegalArgumentException e){ + if(e.getMessage().contains("No portlet definition found for id '")){ + String error="ERROR: User not authorized to access portlet '"+fname+"'."; + logger.info(error); + return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); + } + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } catch(Exception e){ + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } + + } + + //get the entity preferences by comparing the entity with the defintion and returning the entity ones that are different + private Map getEntityOnly(Map entity, Map definition){ + Map result=new HashMap<>(); + for(Map.Entry entry : entity.entrySet()){ + String key=entry.getKey(); + String[] value=entry.getValue(); + if(!definition.containsKey(key)){ + //the entity has something the definition does not + result.put(key,value); + }else{ + //they both have it so compare the two + String[] defvalues = definition.get(key); + if(value==null){ + if(defvalues != null){ + result.put(key,value); + }//otherwise they're both null so don't add + }else{ + if(!Arrays.equals(value, defvalues)){ + result.put(key,value); + }//otherwise they're the same so don't add + } + } + } + return result; + } + + //technically I guess we could get the full discriptor set by + /* final PortletDefinition portletDescriptor = + this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); + final Preferences descriptorPreferences = portletDescriptor.getPortletPreferences(); + for (final Preference preference : descriptorPreferences.getPortletPreferences()) { + final IPortletPreference preferenceWrapper = new PortletPreferenceImpl(preference); + basePortletPreferences.put(preferenceWrapper.getName(), preferenceWrapper); + } + */ + //without needing to do the compare + + //get the discriptor only preferences by comparing the entity with the defintion and returning the discriptor ones that are missing + private Map getDescriptorOnly(Map descriptor, List definition) { + Map defprefs=new HashMap<>(); + Map result= new HashMap<>(); + for(IPortletPreference p:definition){ + defprefs.put(p.getName(),p.getValues()); + } + for(Map.Entry entry : descriptor.entrySet()){ + if(!defprefs.containsKey(entry.getKey())){ + result.put(entry.getKey(),entry.getValue()); + } + } + return result; + } + + //must be authenticated and a portal administrator + @RequestMapping(value = "/prefs/getdefinitionprefs/{fname}", method = RequestMethod.GET) + public ResponseEntity getDefinitionPrefs(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") String fname) { + HttpSession session = request.getSession(false); + if(session == null){ + return new ResponseEntity<>("",HttpStatus.NOT_FOUND); + } + final IPerson person = personManager.getPerson(request); + if(person.isGuest()){ + logger.warn("Guest user tried to access getDefinitionPrefs. Possible hacking attempt."); + return new ResponseEntity<>("ERROR: guest cannot use this action.",HttpStatus.UNAUTHORIZED); + } + else if(!person.getSecurityContext().isAuthenticated()){ + logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs while not authenticated. Possible hacking attempt."); + return new ResponseEntity<>("ERROR: must be logged in to use this action.",HttpStatus.UNAUTHORIZED); + } + + try { + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + + if(!canConfigure(person,portletDefinition.getPortletDefinitionId())){ + logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs for portlet: {"+fname+"} without configuration permissions. Possible hacking attempt."); + return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.UNAUTHORIZED); + } + + List prefs = portletDefinition.getPortletPreferences();//this should probably return the descriptor prefs too... + + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefMap(prefs))); + }catch(Exception e){ + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } +// final org.springframework.security.core.Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); +// final String username = (String) authentication.getPrincipal(); +// final Collection authorities = authentication.getAuthorities(); + + } + + private boolean canConfigure(IPerson user, IPortletDefinitionId portletDefinitionId){ + final IAuthorizationPrincipal principal = + AuthorizationPrincipalHelper.principalFromUser(user); + return principal.canConfigure(portletDefinitionId.toString());//this might backfire, will have to figure out exactly how it's figuring out if it can be configured + } + + private Map prefMap(List prefs){ + Map map=new HashMap<>(); + for(IPortletPreference p : prefs){ + map.put(p.getName(),p.getValues()); + } + return map; + } + + + @RequestMapping(value = "/prefs/putdefinitionprefs", method = RequestMethod.PUT) + public ResponseEntity putDefinitionPrefs(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to store preferences for") + @RequestParam(value = "fname", required=true) String fname, + @ApiParam(value = "the entity preferences to be stored in a single json object ex. " + + "{\"key1\":\"value1\",\"key2\":\"value2\", ...}. " + + "Values can be strings, booleans, numbers, null, or a jsonarray of values " + + "(objects can be stored as a value as serialized strings). " + + "This will overwrite any currently saved preferences for the portlet" + + " with the same key as the pairs put in.") + @RequestBody String body) { + + HttpSession session = request.getSession(false); + if(session == null){ + return new ResponseEntity<>("",HttpStatus.NOT_FOUND); + } + final IPerson person = personManager.getPerson(request); + if(person.isGuest()){ + return new ResponseEntity<>("ERROR: guests may not use this action.",HttpStatus.FORBIDDEN); + } + else if(!person.getSecurityContext().isAuthenticated()){ + return new ResponseEntity<>("ERROR: must be logged in to use this action.",HttpStatus.UNAUTHORIZED); + } + + try { + JsonNode map = mapper.readTree(body); + + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + + if(!canConfigure(person,entity.getPortletDefinitionId())){ + return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.FORBIDDEN); + } + //config mode of true is definition + PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,DEFINITION_MODE); + + boolean stored = storePrefs(prefs,map); + return ResponseEntity.ok().body(stored); + + } catch(IllegalArgumentException e){ + if(e.getMessage().contains("No portlet definition found for id '")){ + String error="ERROR: User not authorized to access portlet '"+fname+"'."; + logger.info(error); + return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); + } + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (IOException e) { + e.printStackTrace(); + logger.error("threw error trying to parse preferences",e); + return ResponseEntity.badRequest().body(e.getMessage()); + + } catch (Exception e) { + e.printStackTrace(); + logger.error("threw error trying to store preferences",e); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } + + } + + + + @RequestMapping(value = "/prefs/putprefs", method = RequestMethod.PUT) + public ResponseEntity putEntityPrefs(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to store preferences for") + @RequestParam(value="fname", required=true) String fname, + @ApiParam(value = "the entity preferences to be stored in a single json object ex. " + + "{\"key1\":\"value1\",\"key2\":\"value2\", ...}. " + + "Values can be strings, booleans, numbers, null, or a jsonarray of values " + + "(objects can be stored as a value as serialized strings). " + + "This will overwrite any currently saved preferences for the portlet" + + " with the same key as the key passed in.") + @RequestBody String body) { + try { + JsonNode map = mapper.readTree(body); + + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + //configMode of false is Entity + PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,ENTITY_MODE); + + boolean stored = storePrefs(prefs,map); + return ResponseEntity.ok().body(stored); + + } catch(IllegalArgumentException e){ + if(e.getMessage().contains("No portlet definition found for id '")){ + String error="ERROR: User not authorized to access portlet '"+fname+"'."; + logger.info(error); + return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); + } + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (IOException e) { + e.printStackTrace(); + logger.error("threw error trying to parse preferences",e); + return ResponseEntity.badRequest().body(e.getMessage()); + + } catch(PreferenceException e){ + logger.info(e.getMessage()); + return ResponseEntity.badRequest().body(e.getMessage()); + } catch(ReadOnlyException e) { + logger.info(e.getMessage()); + return ResponseEntity.badRequest().body(e.getMessage()); + } catch(Exception e) { + e.printStackTrace(); + logger.error("threw error trying to store preferences",e); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } + + } + + //process the + private boolean storePrefs(PortletPreferences prefs, JsonNode map)throws Exception{ + if(prefs==null){ + return false; + } + + try{ + Iterator nodes = map.fields(); + Map tempMap=new HashMap<>(); + while(nodes.hasNext()){ + Map.Entry entry=(Map.Entry)nodes.next(); + String key=entry.getKey(); + JsonNode node=entry.getValue(); + if(node.isValueNode()){ + String[] temp={node.asText()}; + tempMap.put(key,temp); + }else if(node.isArray()){ + List array=new ArrayList(); + for(JsonNode innerNode:node){ + if(innerNode.isValueNode()){ + array.add(innerNode.asText()); + }else{ + throw new PreferenceException("ERROR: preference arrays must only contain strings, numbers, booleans, or null"); + } + } + tempMap.put(key,array.toArray(new String[array.size()])); + }else{ + throw new PreferenceException("ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls"); + } + } + for(Map.Entry entry : tempMap.entrySet()){ + prefs.setValues(entry.getKey(),entry.getValue()); + } + prefs.store(); + return true; + + }catch(Exception e){ + throw e; + } + } + + private class PreferenceException extends Exception{ + + public PreferenceException(){ + super(); + } + + public PreferenceException(String message){ + super(message); + } + + public PreferenceException(String message, Exception cause){ + super(message,cause); + } + + } + +} + + diff --git a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java new file mode 100644 index 00000000000..c8a792a9f03 --- /dev/null +++ b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java @@ -0,0 +1,591 @@ +package org.apereo.portal.rest; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.portlet.PortletPreferences; +import javax.portlet.ReadOnlyException; +import javax.portlet.WindowState; +import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; +import org.apereo.portal.portlet.dao.IPortletDefinitionDao; +import org.apereo.portal.portlet.dao.jpa.PortletDefinitionImpl; +import org.apereo.portal.portlet.om.IPortletDefinition; +import org.apereo.portal.portlet.om.IPortletDefinitionId; +import org.apereo.portal.portlet.om.IPortletEntity; +import org.apereo.portal.portlet.om.IPortletEntityId; +import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; +import org.apereo.portal.portlet.registry.IPortletEntityRegistry; +import org.apereo.portal.security.IPerson; +import org.apereo.portal.security.IPersonManager; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.transaction.support.TransactionOperations; + + +public class PortletPrefsRESTControllerTest { + + + @InjectMocks + private PortletPrefsRESTController portletPrefsRESTController; + + @Mock + private IPersonManager personManager; + + @Mock + private IPortletDefinitionDao portletDao; + + @Mock + private IPortletEntityRegistry portletEntityRegistry; + + @Mock + private IPortletDefinitionRegistry portletDefinitionRegistry; + + @Mock + private TransactionOperations transactionOperations; + + @Mock + private PortletPreferencesFactory portletPreferencesFactory; + + private MockHttpServletRequest req; + + private MockHttpServletResponse res; + + private String non_existant_name="non-existent-portlet"; + private String not_authorized_name="not-authorized-portlet"; + private String valid_name="bob-portlet"; + private IPortletDefinition valid_portletDefinitionMock = mock(PortletDefinitionImpl.class); + private IPortletDefinitionId valid_portletDefIDMock = mock(IPortletDefinitionId.class); + private IPortletEntity valid_entityMock = mock(IPortletEntity.class); + private ObjectMapper mapper=new ObjectMapper(); + private IPerson valid_person=mock(IPerson.class,RETURNS_DEEP_STUBS); + + @Before + public void setUp() throws Exception { + + portletPrefsRESTController=new PortletPrefsRESTController(); + res = new MockHttpServletResponse(); + req = new MockHttpServletRequest(); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("session", "true"); + req.setSession(session); + MockitoAnnotations.initMocks(this); + + //non-existant mocks + Mockito.when(portletDao.getPortletDefinitionByFname(non_existant_name)).thenReturn(null); + + //not-authorized to subscribe mocks + IPortletDefinitionId not_authorized_portletDefIDMock = mock(IPortletDefinitionId.class); + IPortletDefinition not_authorized_portletDefinitionMock = mock(PortletDefinitionImpl.class); + Mockito.when(portletDao.getPortletDefinitionByFname(not_authorized_name)).thenReturn(not_authorized_portletDefinitionMock); + Mockito.when(not_authorized_portletDefinitionMock.getPortletDefinitionId()).thenReturn(not_authorized_portletDefIDMock); + Mockito.when(portletEntityRegistry.getOrCreateDefaultPortletEntity(req, not_authorized_portletDefIDMock)).thenThrow( + new IllegalArgumentException( "No portlet definition found for id '200'.")); + + //authorized to subscribe common methods + Mockito.when(portletDao.getPortletDefinitionByFname(valid_name)).thenReturn(valid_portletDefinitionMock); + Mockito.when(valid_portletDefinitionMock.getPortletDefinitionId()).thenReturn(valid_portletDefIDMock); + Mockito.when(portletEntityRegistry.getOrCreateDefaultPortletEntity(req, valid_portletDefIDMock)).thenReturn(valid_entityMock); + + + Mockito.when(personManager.getPerson(req)).thenReturn(valid_person); + Mockito.when(valid_person.isGuest()).thenReturn(false); + Mockito.when(valid_person.getSecurityContext().isAuthenticated()).thenReturn(true); + } + + @Test//test that it returns the correct json when the fname is present in the database + public void getEntity() { + + String valid_layoutid="bobLayoutNode"; + String valid_entityid="bobEntityID"; + int userid = 2; + + //test specific mocks + IPortletEntityId entityIDMock = mock(IPortletEntityId.class); + Map windowStateMock= new HashMap<>(); + windowStateMock.put(new Long(90),new WindowState("bob-state")); + //test specific mock methods + Mockito.when(valid_portletDefinitionMock.getFName()).thenReturn(valid_name); + Mockito.when(valid_entityMock.getLayoutNodeId()).thenReturn(valid_layoutid); + Mockito.when(valid_entityMock.getUserId()).thenReturn(userid); + Mockito.when(valid_entityMock.getPortletEntityId()).thenReturn(entityIDMock); + Mockito.when(entityIDMock.toString()).thenReturn(valid_entityid); + Mockito.when(valid_entityMock.getWindowStates()).thenReturn(windowStateMock); + + //test specific json result + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\""+valid_name+"\": {"); + stringBuilder.append(" \"layoutNodeID\": \""+valid_layoutid+"\","); + stringBuilder.append(" \"userID\": \""+userid+"\","); + stringBuilder.append(" \"entityID\": \""+valid_entityid+"\","); + stringBuilder.append(" \"windowStates\": ["); + boolean comma=false; + for(Map.Entry entry : windowStateMock.entrySet()){ + stringBuilder.append(" { \"stylesheetID\": \""); + stringBuilder.append(entry.getKey()); + stringBuilder.append("\", \"windowState\": \""); + stringBuilder.append(entry.getValue().toString()); + stringBuilder.append("\"},"); + comma=true; + } + if (comma) { + stringBuilder.setLength(stringBuilder.length() - 1); + } + stringBuilder.append(" ] } }"); + + ResponseEntity response = portletPrefsRESTController.getEntity(req,res,valid_name); + Assert.assertEquals(200,response.getStatusCodeValue()); + + Assert.assertEquals(stringBuilder.toString(),(String)response.getBody()); + } + + @Test//test that it returns a 400 when the portlet fname does not exits + public void getEntityNonExistent() { + ResponseEntity response = portletPrefsRESTController.getEntity(req,res,non_existant_name); + Assert.assertEquals(404,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + } + + @Test + public void getEntityNotAuthorized() { + + ResponseEntity response = portletPrefsRESTController.getEntity(req,res,not_authorized_name); + Assert.assertEquals(403,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + } + + @Test + public void getCompositePrefsNonExistent() { + + ResponseEntity response = portletPrefsRESTController.getCompositePrefs(req,res,non_existant_name); + Assert.assertEquals(404,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + } + + @Test + public void getCompositePrefsNotAuthorized() { + + ResponseEntity response = portletPrefsRESTController.getCompositePrefs(req,res,not_authorized_name); + Assert.assertEquals(403,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + } + + @Test + public void getCompositePrefs() { + + PortletPreferences prefs=mock(PortletPreferences.class); + Map map=new HashMap<>(); + String[] pref1={"bob1","bob2","bob3"}; + String[] pref2={"true"}; + map.put("pref1",pref1); + map.put("pref2",pref2); + JsonNode jsonmap = mapper.valueToTree(map); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + Mockito.when(prefs.getMap()).thenReturn(map); + + + ResponseEntity response = portletPrefsRESTController.getCompositePrefs(req,res,valid_name); + Assert.assertEquals(200,response.getStatusCodeValue()); + JsonNode body=null; + try { + body=mapper.readTree((String)response.getBody()); + }catch(IOException e){ + fail("failed to parse the json from the api: "+e.getMessage()); + } + Assert.assertTrue("Json is not equal, \nExpected: "+jsonmap.toString()+"\nActual: "+body.toString(),jsonmap.equals(body)); + + } + + + @Test + public void getEntityOnlyPrefsNonExistant() { + ResponseEntity response = portletPrefsRESTController.getEntityOnlyPrefs(req,res,non_existant_name); + Assert.assertEquals(404,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + } + + @Test + public void getEntityOnlyPrefsNotAuthorized() { + + ResponseEntity response = portletPrefsRESTController.getEntityOnlyPrefs(req,res,not_authorized_name); + Assert.assertEquals(403,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + } + + @Test + public void getEntityOnlyPrefs() { + PortletPreferences defPrefs=mock(PortletPreferences.class); + PortletPreferences entPrefs=mock(PortletPreferences.class); + + Map defMap=new HashMap<>(); + String[] pref1={"bob1","bob2","bob3"}; + String[] pref2={"true"}; + defMap.put("pref1",pref1); + defMap.put("pref2",pref2); + + Map entMap=new HashMap<>(); + entMap.put("pref1",pref1); + entMap.put("pref2",pref2); + String[] newPref2={"false"}; + entMap.put("pref2",newPref2); + + Map entOnlyMap = new HashMap<>(); + entOnlyMap.put("pref2", newPref2); + + JsonNode jsonmap = mapper.valueToTree(entOnlyMap); + + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,true)) + .thenReturn(defPrefs); + Mockito.when(defPrefs.getMap()).thenReturn(defMap); + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(entPrefs); + Mockito.when(entPrefs.getMap()).thenReturn(entMap); + + + + ResponseEntity response = portletPrefsRESTController.getEntityOnlyPrefs(req,res,valid_name); + Assert.assertEquals(200,response.getStatusCodeValue()); + JsonNode body=null; + try { + body=mapper.readTree((String)response.getBody()); + }catch(IOException e){ + fail("failed to parse the json from the api: "+e.getMessage()); + } + Assert.assertTrue("Json is not equal, \nExpected: "+jsonmap.toString()+"\nActual: "+body.toString(),jsonmap.equals(body)); + } + + @Test + public void getDefinitionPrefsNoSession() { + MockHttpServletRequest req2 = new MockHttpServletRequest(); + req2.setSession(null); + + ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req2,res,valid_name); + Assert.assertEquals(404,response.getStatusCodeValue()); + } + + @Test + public void getDefinitionPrefsGuest() { + IPerson person=mock(IPerson.class); + MockHttpServletRequest req2 = new MockHttpServletRequest(); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("session", "true"); + req2.setSession(session); + Mockito.when(personManager.getPerson(req2)).thenReturn(person); + Mockito.when(person.isGuest()).thenReturn(true); + + ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req2,res,valid_name); + Assert.assertEquals(401,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: guest cannot use this action.",(String)response.getBody()); + } + + @Test + public void getDefinitionPrefsSessionNotAuthenticated() { + IPerson person=mock(IPerson.class,RETURNS_DEEP_STUBS); + MockHttpServletRequest req2 = new MockHttpServletRequest(); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("session", "false"); + req2.setSession(session); + Mockito.when(personManager.getPerson(req2)).thenReturn(person); + Mockito.when(person.isGuest()).thenReturn(false); + Mockito.when(person.getSecurityContext().isAuthenticated()).thenReturn(false); + + ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req2,res,valid_name); + Assert.assertEquals(401,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: must be logged in to use this action.",(String)response.getBody()); + } + + @Test + public void getDefinitionPrefsSessionNonExistant() { + + ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req,res,non_existant_name); + Assert.assertEquals(404,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + } + + @Test + public void getDefinitionPrefsSessionNonConfig() { + //can't programatically test this one without setting up a full stack since it calls the static method: + // AuthorizationPrincipalHelper.principalFromUser(user) + //to insure that only portal administrators or others with configuration authority can configure. + // *Could easily be implemented by using PowerMock + //has been thouroughly tested through manual testing though + } + + + @Test + public void getDefinitionPrefs() { + //can't progamatically test this one without setting up a full stack since it calls the static method: + // AuthorizationPrincipalHelper.principalFromUser(user) + //to insure that only portal administrators or others with configuration authority can configure. + // *Could easily be implemented by using PowerMock + //has been thouroughly tested through manual testing though + } + + @Test + public void putDefinitionPrefsNoSession() { + String body="{\"pref1\":\"value1\"}"; + MockHttpServletRequest req2 = new MockHttpServletRequest(); + req2.setSession(null); + + ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req2,res,valid_name,body); + Assert.assertEquals(404,response.getStatusCodeValue()); + } + + @Test + public void putDefinitionPrefsGuest() { + String body="{\"pref1\":\"value1\"}"; + IPerson person=mock(IPerson.class); + MockHttpServletRequest req2 = new MockHttpServletRequest(); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("session", "true"); + req2.setSession(session); + Mockito.when(personManager.getPerson(req2)).thenReturn(person); + Mockito.when(person.isGuest()).thenReturn(true); + + ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req2,res,valid_name,body); + Assert.assertEquals(403,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: guests may not use this action.",(String)response.getBody()); + } + + @Test + public void putDefinitionPrefsSessionNotAuthenticated() { + String body="{\"pref1\":\"value1\"}"; + IPerson person=mock(IPerson.class,RETURNS_DEEP_STUBS); + MockHttpServletRequest req2 = new MockHttpServletRequest(); + MockHttpSession session = new MockHttpSession(); + session.setAttribute("session", "false"); + req2.setSession(session); + Mockito.when(personManager.getPerson(req2)).thenReturn(person); + Mockito.when(person.isGuest()).thenReturn(false); + Mockito.when(person.getSecurityContext().isAuthenticated()).thenReturn(false); + + ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req2,res,valid_name,body); + Assert.assertEquals(401,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: must be logged in to use this action.",(String)response.getBody()); + } + + @Test + public void putDefinitionPrefsSessionNonExistant() { + String body="{\"pref1\":\"value1\"}"; + ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req,res,non_existant_name,body); + Assert.assertEquals(404,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + } + + @Test + public void putDefinitionInvalidJson() { + String body="{\"pref1\":\"bob\""; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,true)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + } + + @Test + public void putDefinitionPrefsSessionNonConfig() { + //can't programatically test this one without setting up a full stack since it calls the static method: + // AuthorizationPrincipalHelper.principalFromUser(user) + //to insure that only portal administrators or others with configuration authority can configure. + // *Could easily be implemented by using PowerMock + //has been thouroughly tested through manual testing though + } + + @Test + public void putDefinitionPrefs() { + //can't programatically test this one without setting up a full stack since it calls the static method: + // AuthorizationPrincipalHelper.principalFromUser(user) + //to insure that only portal administrators or others with configuration authority can configure. + // *Could easily be implemented by using PowerMock + //has been thouroughly tested through manual testing though + } + + @Test + public void putEntityPrefsNonExistant() { + String body="{\"pref1\":\"bob\"}"; + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,non_existant_name,body); + Assert.assertEquals(404,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + } + + @Test + public void putEntityPrefsNotAuthorized() { + String body="{\"pref1\":\"bob\"}"; + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,not_authorized_name,body); + Assert.assertEquals(403,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + } + + @Test + public void putEntityPrefsInvalidJson() { + String body="{\"pref1\":\"bob\""; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + } + + + @Test + public void putEntityPrefsObjectPref() { + String body="{\"pref1\":{\"name\":\"bob\"}}"; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls",(String)response.getBody()); + } + + @Test + public void putEntityPrefsMultipleArray() { + String body="{\"pref1\":[\"bob\",[\"name\",\"bob\"]]}"; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: preference arrays must only contain strings, numbers, booleans, or null",(String)response.getBody()); + } + + @Test + public void putEntityPrefsObjectArray() { + String body="{\"pref1\":[{\"bob\":[\"name\",\"bob\"]}]}"; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: preference arrays must only contain strings, numbers, booleans, or null",(String)response.getBody()); + } + + @Test + public void putEntityPrefsReadOnly() throws Exception{ + String body="{\"pref1\":\"bob\"}"; + String[] values= {"bob"}; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + Mockito.doThrow(new ReadOnlyException("Preference '" + "pref1" + "' is read only")).when(prefs).setValues("pref1", values); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + Assert.assertEquals("Preference 'pref1' is read only",(String)response.getBody()); + + } + + @Test + public void putEntityPrefs() throws Exception{ + String body="{\"pref1\":\"bob\"}"; + String[] values= {"bob"}; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Mockito.verify(prefs, times(1)).setValues("pref1", values); + Mockito.verify(prefs, times(1)).store(); + Assert.assertEquals(200,response.getStatusCodeValue()); + Assert.assertEquals(true,(boolean)response.getBody()); + + } + + + @Test + public void putEntityPrefsArray() throws Exception{ + String body="{\"pref1\":[\"bob\",\"joe\"]}"; + String[] values= {"bob","joe"}; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Mockito.verify(prefs, times(1)).setValues("pref1", values); + Mockito.verify(prefs, times(1)).store(); + Assert.assertEquals(200,response.getStatusCodeValue()); + Assert.assertEquals(true,(boolean)response.getBody()); + + } + + @Test + public void putEntityPrefsAllTypes() throws Exception{ + String body="{\"pref1\":[\"bob\",true,false,null,1,50.9]}"; + String[] values= {"bob","true","false","null","1","50.9"}; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Mockito.verify(prefs, times(1)).setValues("pref1", values); + Mockito.verify(prefs, times(1)).store(); + Assert.assertEquals(200,response.getStatusCodeValue()); + Assert.assertEquals(true,(boolean)response.getBody()); + + } + + @Test + public void putEntityPrefsMultiplePrefs() throws Exception{ + String body="{\"pref1\":[\"bob\",\"joe\"],\"pref2\":true}"; + String[] values1= {"bob","joe"}; + String[] values2= {"true"}; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Mockito.verify(prefs, times(1)).setValues("pref1", values1); + Mockito.verify(prefs, times(1)).setValues("pref2", values2); + Mockito.verify(prefs, times(1)).store(); + Assert.assertEquals(200,response.getStatusCodeValue()); + Assert.assertEquals(true,(boolean)response.getBody()); + + } + + + +} diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java new file mode 100644 index 00000000000..6f534928758 --- /dev/null +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java @@ -0,0 +1,177 @@ +/** + * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. Apereo + * licenses this file to you 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 the + * following location: + * + *

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.apereo.portal.portlet.container.services; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import javax.portlet.ValidatorException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import org.apache.pluto.container.om.portlet.PortletDefinition; +import org.apache.pluto.container.om.portlet.Preference; +import org.apache.pluto.container.om.portlet.Preferences; +import org.apereo.portal.portlet.dao.jpa.PortletPreferenceImpl; +import org.apereo.portal.portlet.om.IPortletDefinition; +import org.apereo.portal.portlet.om.IPortletDefinitionId; +import org.apereo.portal.portlet.om.IPortletEntity; +import org.apereo.portal.portlet.om.IPortletEntityId; +import org.apereo.portal.portlet.om.IPortletPreference; +import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; +import org.apereo.portal.portlet.registry.IPortletEntityRegistry; + +/** Preferences impl that manipulates the portlet entity level preference data for Guests used only for the REST API */ +public class GuestPortletEntityPreferencesAPIImpl + extends AbstractPortletPreferencesImpl { + protected static final String PORTLET_PREFERENCES_MAP_ATTRIBUTE = + GuestPortletEntityPreferencesAPIImpl.class.getName() + ".PORTLET_PREFERENCES_MAP"; + + private final HttpServletRequest portletRequest; + private final IPortletEntityId portletEntityId; + + private final IPortletEntityRegistry portletEntityRegistry; + private final IPortletDefinitionRegistry portletDefinitionRegistry; + + public GuestPortletEntityPreferencesAPIImpl( + HttpServletRequest portletRequest, + IPortletEntityRegistry portletEntityRegistry, + IPortletDefinitionRegistry portletDefinitionRegistry, + IPortletEntityId portletEntityId, + boolean render) { + super(render); + + this.portletRequest = portletRequest; + this.portletEntityRegistry = portletEntityRegistry; + this.portletDefinitionRegistry = portletDefinitionRegistry; + this.portletEntityId = portletEntityId; + } + + @Override + protected IPortletEntity getInitializationContext() { + return this.portletEntityRegistry.getPortletEntity(portletRequest, portletEntityId); + } + + @Override + protected Object getLogDescription() { + return this.getInitializationContext(); + } + + @Override + protected void loadTargetPortletPreferences( + IPortletEntity portletEntity, + Map targetPortletPreferences) { + final Map sessionPreferences = + this.getSessionPreferences(portletEntityId, portletRequest); + if (sessionPreferences != null) { + targetPortletPreferences.putAll(sessionPreferences); + } + } + + @Override + @SuppressWarnings("Duplicates") + protected void loadBasePortletPreferences( + IPortletEntity portletEntity, Map basePortletPreferences) { + final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition(); + + // Add descriptor prefs to base Map + final IPortletDefinitionId portletDefinitionId = portletDefinition.getPortletDefinitionId(); + final PortletDefinition portletDescriptor = + this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); + final Preferences descriptorPreferences = portletDescriptor.getPortletPreferences(); + for (final Preference preference : descriptorPreferences.getPortletPreferences()) { + final IPortletPreference preferenceWrapper = new PortletPreferenceImpl(preference); + basePortletPreferences.put(preferenceWrapper.getName(), preferenceWrapper); + } + + // Add definition prefs to base Map + final List definitionPreferences = + portletDefinition.getPortletPreferences(); + for (final IPortletPreference preference : definitionPreferences) { + basePortletPreferences.put(preference.getName(), preference); + } + + // Add entity prefs to base Map + final List entityPreferences = portletEntity.getPortletPreferences(); + for (final IPortletPreference preference : entityPreferences) { + basePortletPreferences.put(preference.getName(), preference); + } + } + + @Override + protected boolean storeInternal() throws IOException, ValidatorException { + final Map targetPortletPreferences = + this.getTargetPortletPreferences(); + if (targetPortletPreferences.isEmpty()) { + return false; + } + + this.storeSessionPreferences(portletEntityId, portletRequest, targetPortletPreferences); + + return true; + } + + /** + * Gets the session-stored map of IPortletPreferences for the specified request and + * IPortletEntityId. + * + * @return Map of IPortletPreferences for the entity and session, may be null if no preferences + * have been set. + */ + @SuppressWarnings({"unchecked","Duplicates"}) + protected Map getSessionPreferences( + IPortletEntityId portletEntityId, HttpServletRequest httpServletRequest) { + final HttpSession session = httpServletRequest.getSession(); + + final Map> portletPreferences; + + // Sync on the session to ensure the Map isn't in the process of being created + synchronized (session) { + portletPreferences = + (Map>) + session.getAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE); + } + + if (portletPreferences == null) { + return null; + } + + return portletPreferences.get(portletEntityId); + } + + @SuppressWarnings({"unchecked","Duplicates"}) + protected void storeSessionPreferences( + IPortletEntityId portletEntityId, + HttpServletRequest httpServletRequest, + Map preferences) { + final HttpSession session = httpServletRequest.getSession(); + + Map> portletPreferences; + + // Sync on the session to ensure other threads aren't creating the Map at the same time + synchronized (session) { + portletPreferences = + (Map>) + session.getAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE); + if (portletPreferences == null) { + portletPreferences = + new ConcurrentHashMap>(); + session.setAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE, portletPreferences); + } + } + + portletPreferences.put(portletEntityId, preferences); + } +} diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java new file mode 100644 index 00000000000..a32c4b8c49e --- /dev/null +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java @@ -0,0 +1,173 @@ +/** + * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. Apereo + * licenses this file to you 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 the + * following location: + * + *

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.apereo.portal.portlet.container.services; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import javax.portlet.ValidatorException; +import javax.servlet.http.HttpServletRequest; +import org.apache.pluto.container.om.portlet.PortletDefinition; +import org.apache.pluto.container.om.portlet.Preference; +import org.apache.pluto.container.om.portlet.Preferences; +import org.apereo.portal.portlet.dao.jpa.PortletPreferenceImpl; +import org.apereo.portal.portlet.om.IPortletDefinition; +import org.apereo.portal.portlet.om.IPortletDefinitionId; +import org.apereo.portal.portlet.om.IPortletEntity; +import org.apereo.portal.portlet.om.IPortletEntityId; +import org.apereo.portal.portlet.om.IPortletPreference; +import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; +import org.apereo.portal.portlet.registry.IPortletEntityRegistry; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionOperations; + +/** Preferences impl that manipulates the portlet entity level preference data for the REST API*/ +public class PortletEntityPreferencesAPIImpl extends AbstractPortletPreferencesImpl { + private final HttpServletRequest portletRequest; + private final IPortletEntityId portletEntityId; + + private final IPortletEntityRegistry portletEntityRegistry; + private final IPortletDefinitionRegistry portletDefinitionRegistry; + private final TransactionOperations transactionOperations; + + public PortletEntityPreferencesAPIImpl( + HttpServletRequest portletRequestContext, + IPortletEntityRegistry portletEntityRegistry, + IPortletDefinitionRegistry portletDefinitionRegistry, + TransactionOperations transactionOperations, + IPortletEntityId portletEntityId) { + super(false); + + this.portletRequest = portletRequestContext; + this.portletEntityRegistry = portletEntityRegistry; + this.portletDefinitionRegistry = portletDefinitionRegistry; + this.transactionOperations = transactionOperations; + this.portletEntityId = portletEntityId; + } + + @Override + protected IPortletEntity getInitializationContext() { + final HttpServletRequest containerRequest = + this.portletRequest; + return this.portletEntityRegistry.getPortletEntity(containerRequest, portletEntityId); + } + + @Override + protected Object getLogDescription() { + return this.getInitializationContext(); + } + + @Override + protected void loadTargetPortletPreferences( + IPortletEntity portletEntity, + Map targetPortletPreferences) { + final List entityPreferences = portletEntity.getPortletPreferences(); + for (final IPortletPreference preference : entityPreferences) { + targetPortletPreferences.put(preference.getName(), preference); + } + } + + @Override + @SuppressWarnings("Duplicates") + protected void loadBasePortletPreferences( + IPortletEntity portletEntity, Map basePortletPreferences) { + final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition(); + + // Add descriptor prefs to base Map + final IPortletDefinitionId portletDefinitionId = portletDefinition.getPortletDefinitionId(); + final PortletDefinition portletDescriptor = + this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); + final Preferences descriptorPreferences = portletDescriptor.getPortletPreferences(); + for (final Preference preference : descriptorPreferences.getPortletPreferences()) { + final IPortletPreference preferenceWrapper = new PortletPreferenceImpl(preference); + basePortletPreferences.put(preferenceWrapper.getName(), preferenceWrapper); + } + + // Add definition prefs to base Map + final List definitionPreferences = + portletDefinition.getPortletPreferences(); + for (final IPortletPreference preference : definitionPreferences) { + basePortletPreferences.put(preference.getName(), preference); + } + } + + @Override + @SuppressWarnings("Duplicates") + protected boolean storeInternal() throws IOException, ValidatorException { + final HttpServletRequest containerRequest = portletRequest; + + final IPortletEntity portletEntity = + this.portletEntityRegistry.getPortletEntity(containerRequest, portletEntityId); + final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId(); + final Lock portletEntityLock = + this.portletEntityRegistry.getPortletEntityLock(containerRequest, portletEntityId); + + // Do a tryLock first so that we can warn about concurrent preference modification if it + // fails + boolean locked = portletEntityLock.tryLock(); + try { + if (!locked) { + logger.warn( + "Concurrent portlet preferences modification by: " + + portletEntity + + " " + + "This has the potential for changes to preferences to be lost. " + + "This portlet should be modified to synchronize its preference modifications appropriately", + new Throwable()); + + portletEntityLock.lock(); + locked = true; + } + + return this.transactionOperations.execute( + new TransactionCallback() { + @Override + public Boolean doInTransaction(TransactionStatus status) { + // Refresh the entity to avoid optimistic locking errors + final IPortletEntity portletEntity = + portletEntityRegistry.getPortletEntity( + containerRequest, portletEntityId); + + final Map targetPortletPreferences = + getTargetPortletPreferences(); + final Collection values = + targetPortletPreferences.values(); + final boolean modified = + portletEntity.setPortletPreferences( + new ArrayList(values)); + if (!modified) { + // Nothing actually changed, skip the store + return Boolean.FALSE; + } + + portletEntityRegistry.storePortletEntity( + containerRequest, portletEntity); + + return Boolean.TRUE; + } + }); + } finally { + // check if locked, needed due to slightly more complex logic around the tryLock and + // logging + if (locked) { + portletEntityLock.unlock(); + } + } + } +} diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java index 430cb72872a..482cba2f8f4 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java @@ -15,7 +15,9 @@ package org.apereo.portal.portlet.container.services; import javax.portlet.PortletPreferences; +import javax.servlet.http.HttpServletRequest; import org.apache.pluto.container.PortletRequestContext; +import org.apereo.portal.portlet.om.IPortletEntity; /** Creates {@link PortletPreferences} objects */ public interface PortletPreferencesFactory { @@ -23,4 +25,8 @@ public interface PortletPreferencesFactory { /** Create portlet preferences for the specified portlet request context */ PortletPreferences createPortletPreferences( final PortletRequestContext requestContext, boolean render); + + /** Create portlet preferences for the specified portlet request context for the REST API calls (since they don't have access to the portletRequestContext (and technically don't need it)) */ + PortletPreferences createAPIPortletPreferences( + final HttpServletRequest requestContext, IPortletEntity portletEntity, boolean render, boolean configMode); } diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java index 0dbae4bf3cd..e7f6cb9a4ae 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java @@ -37,7 +37,7 @@ import org.springframework.transaction.support.TransactionOperations; /** Creates {@link PortletPreferences} objects */ -@Service +@Service("portletPreferencesFactory") public class PortletPreferencesFactoryImpl implements PortletPreferencesFactory { private IPersonManager personManager; private IPortletWindowRegistry portletWindowRegistry; @@ -113,6 +113,39 @@ public PortletPreferences createPortletPreferences( } } + /** + * method that creates REST API specific PortletPreferences + * */ + @Override + public PortletPreferences createAPIPortletPreferences( + final HttpServletRequest requestContext, IPortletEntity portletEntity, boolean render, boolean configMode) { + final HttpServletRequest containerRequest = requestContext; + + + if (configMode) { + final IPortletDefinitionId portletDefinitionId = portletEntity.getPortletDefinitionId(); + return new PortletDefinitionPreferencesImpl( + portletDefinitionRegistry, transactionOperations, portletDefinitionId, render); + } else if (this.isStoreInMemory(containerRequest)) { + final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId(); + return new GuestPortletEntityPreferencesAPIImpl( + requestContext, + portletEntityRegistry, + portletDefinitionRegistry, + portletEntityId, + render); + } else { + final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId(); + return new PortletEntityPreferencesAPIImpl( + requestContext, + portletEntityRegistry, + portletDefinitionRegistry, + transactionOperations, + portletEntityId); + } + } + + protected boolean isStoreInMemory(HttpServletRequest containerRequest) { if (this.storeGuestPreferencesInMemory && isGuestUser(containerRequest)) { return true; From 9fa0f2569ead37bf04ebf164dc2edf66cc30509f Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Fri, 22 Mar 2019 18:42:51 -0600 Subject: [PATCH 02/11] #1659 missed a test case for invalid json --- .../org/apereo/portal/rest/PortletPrefsRESTController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index 08ca3e12f07..cfd21dd569c 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -483,6 +483,9 @@ private boolean storePrefs(PortletPreferences prefs, JsonNode map)throws Excepti throw new PreferenceException("ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls"); } } + if(tempMap.size()==0){ + throw new PreferenceException("ERROR: invalid json. json must be in key:value pairs."); + } for(Map.Entry entry : tempMap.entrySet()){ prefs.setValues(entry.getKey(),entry.getValue()); } From e132032eff633951dd714eb4a587c4558b600fb2 Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Tue, 26 Mar 2019 14:46:11 -0600 Subject: [PATCH 03/11] #1659 got most of the javadoc done, fixed some of the tests to be more thorough, added a new method to be consistent with current implementation --- .../rest/PortletPrefsRESTController.java | 162 +++++++++++++++--- .../rest/PortletPrefsRESTControllerTest.java | 55 ++++-- 2 files changed, 175 insertions(+), 42 deletions(-) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index cfd21dd569c..0fb4fc18f77 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -18,14 +18,12 @@ import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apereo.portal.jpa.BasePortalJpaDao; import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; import org.apereo.portal.portlet.dao.IPortletDefinitionDao; import org.apereo.portal.portlet.om.IPortletDefinition; import org.apereo.portal.portlet.om.IPortletDefinitionId; import org.apereo.portal.portlet.om.IPortletEntity; import org.apereo.portal.portlet.om.IPortletPreference; -import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; import org.apereo.portal.portlet.registry.IPortletEntityRegistry; import org.apereo.portal.security.AuthorizationPrincipalHelper; import org.apereo.portal.security.IAuthorizationPrincipal; @@ -37,13 +35,13 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; -import org.springframework.transaction.support.TransactionOperations; 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.RequestParam; +/** PortletPrefsRESTController provides REST targets for preference operations for soffits and webcomponents. */ @Controller public class PortletPrefsRESTController { @@ -74,21 +72,6 @@ public void setPortletEntityRegistry(IPortletEntityRegistry portletEntityRegistr this.portletEntityRegistry = portletEntityRegistry; } - private IPortletDefinitionRegistry portletDefinitionRegistry; - - @Autowired - public void setPortletDefinitionRegistry(IPortletDefinitionRegistry portletDefinitionRegistry){ - this.portletDefinitionRegistry = portletDefinitionRegistry; - } - - private TransactionOperations transactionOperations; - - @Autowired - @Qualifier(BasePortalJpaDao.PERSISTENCE_UNIT_NAME) - public void setTransactionOperations(TransactionOperations transactionOperations) { - this.transactionOperations = transactionOperations; - } - private PortletPreferencesFactory portletPreferencesFactory; @Autowired @@ -103,6 +86,18 @@ public PortletPrefsRESTController() { this.mapper=new ObjectMapper(); } + + /** + * Get uPortal Entity information for portlet/soffit/webcomponent. This method provides a REST interface for obtaining uPortal + * portlet/soffit/webcomponent metadata + * + *

The path for this method is /prefs/getentity/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to find the entity information for + */ + /*non-javadoc + * I used this primarily for testing, could be useful given that it returns the windowstate, etc + * up to you if you want to keep it or modify it + * */ @RequestMapping(value = "/prefs/getentity/{fname}", method = RequestMethod.GET) public ResponseEntity getEntity(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "The portlet fname to get entity for") @@ -148,10 +143,20 @@ public ResponseEntity getEntity(HttpServletRequest request, HttpServletResponse return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); } - //return ResponseEntity.badRequest().build(); } + /** + * Get uPortal Preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining + * the entity preferences for the portlet/soffit/webcomponent + * + *

The path for this method is /prefs/getprefs/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to return the composite entity preferences. These are the per-user preferences for the given + * portlet/soffit/webcomponent including any non-overwritten definition and descriptor preferences for the given + * portlet/soffit/webcomponent. Basically every preference for the soffit with the current user's preferences set. + * Will include extra preferences for soffits including the url, so please set any of these to read-only + * + */ //returns the entity composite preferences for the portlet in question @RequestMapping(value = "/prefs/getprefs/{fname}", method = RequestMethod.GET) public ResponseEntity getCompositePrefs(HttpServletRequest request, HttpServletResponse response, @@ -187,7 +192,19 @@ public ResponseEntity getCompositePrefs(HttpServletRequest request, HttpServletR } } - //maybe get rid of this one + /** + * Get uPortal Preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining + * only the entity preferences for the portlet/soffit/webcomponent + * + *

The path for this method is /prefs/getprefs/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to return the composite entity preferences. These are the per-user preferences for the given + * portlet/soffit/webcomponent. Includes only the user set preferences, does not include any defaults set in the definition + * + */ + /*maybe get rid of this one? don't know if there is any specific use for it given that the preferences needed might be set in + * any of the entity, definition, or descriptor preferences. But is useful if you only need the user set preferences and are + * not relying on a default in the definition. + */ @RequestMapping(value = "/prefs/getentityonlyprefs/{fname}", method = RequestMethod.GET) public ResponseEntity getEntityOnlyPrefs(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "The portlet fname to find preferences for") @@ -221,6 +238,7 @@ public ResponseEntity getEntityOnlyPrefs(HttpServletRequest request, HttpServlet } + //get the entity preferences by comparing the entity with the defintion and returning the entity ones that are different private Map getEntityOnly(Map entity, Map definition){ Map result=new HashMap<>(); @@ -258,7 +276,7 @@ private Map getEntityOnly(Map entity, Map getDescriptorOnly(Map descriptor, List definition) { Map defprefs=new HashMap<>(); Map result= new HashMap<>(); @@ -273,9 +291,78 @@ private Map getDescriptorOnly(Map descriptor return result; } + /** + * Get uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining + * the definition preferences for the portlet/soffit/webcomponent + * + *

The path for this method is /prefs/getdefinitionprefs/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to return the composite definition preferences. These are the default preferences for the given + * portlet/soffit/webcomponent including any non-overwritten descriptor preferences for the given + * portlet/soffit/webcomponent. Will include extra preferences for soffits including the url, so please set any of these to read-only + * when you define them. + * You must be logged in as a portal administrator or have configuration rights for the given portlet/soffit/webcomponent + * in uPortal to access these. Will return a 403 or 404 otherwise + * + */ //must be authenticated and a portal administrator @RequestMapping(value = "/prefs/getdefinitionprefs/{fname}", method = RequestMethod.GET) public ResponseEntity getDefinitionPrefs(HttpServletRequest request, HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") String fname) { + HttpSession session = request.getSession(false); + if(session == null){ + return new ResponseEntity<>("",HttpStatus.NOT_FOUND); + } + final IPerson person = personManager.getPerson(request); + if(person.isGuest()){ + logger.warn("Guest user tried to access getDefinitionPrefs. Possible hacking attempt."); + return new ResponseEntity<>("ERROR: guest cannot use this action.",HttpStatus.UNAUTHORIZED); + } + else if(!person.getSecurityContext().isAuthenticated()){ + logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs while not authenticated. Possible hacking attempt."); + return new ResponseEntity<>("ERROR: must be logged in to use this action.",HttpStatus.UNAUTHORIZED); + } + + try { + IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); + if(portletDefinition==null){ + return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); + } + + if(!canConfigure(person,portletDefinition.getPortletDefinitionId())){ + logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs for portlet: {"+fname+"} without configuration permissions. Possible hacking attempt."); + return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.UNAUTHORIZED); + } + + IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + + PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,DEFINITION_MODE); + + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefs.getMap())); + }catch(Exception e){ + e.printStackTrace(); + logger.error(e.getMessage()); + return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + } + + + } + + /** + * Get uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining + * the definition preferences for the portlet/soffit/webcomponent + * + *

The path for this method is /prefs/getdefinitiononlyprefs/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to return the definition preferences. These are the default preferences for the given + * portlet/soffit/webcomponent. Will include extra preferences for soffits -including the url- so please set any of these to read-only + * when you define them. + * You must be logged in as a portal administrator or have configuration rights for the given portlet/soffit/webcomponent + * in uPortal to access these. Will return a 403 or 404 otherwise + * + */ + //must be authenticated and a portal administrator + @RequestMapping(value = "/prefs/getdefinitiononlyprefs/{fname}", method = RequestMethod.GET) + public ResponseEntity getDefinitionOnlyPrefs(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "The portlet fname to find preferences for") @PathVariable(value = "fname") String fname) { HttpSession session = request.getSession(false); @@ -303,7 +390,7 @@ else if(!person.getSecurityContext().isAuthenticated()){ return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.UNAUTHORIZED); } - List prefs = portletDefinition.getPortletPreferences();//this should probably return the descriptor prefs too... + List prefs = portletDefinition.getPortletPreferences(); return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefMap(prefs))); }catch(Exception e){ @@ -311,16 +398,14 @@ else if(!person.getSecurityContext().isAuthenticated()){ logger.error(e.getMessage()); return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); } -// final org.springframework.security.core.Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); -// final String username = (String) authentication.getPrincipal(); -// final Collection authorities = authentication.getAuthorities(); + } private boolean canConfigure(IPerson user, IPortletDefinitionId portletDefinitionId){ final IAuthorizationPrincipal principal = AuthorizationPrincipalHelper.principalFromUser(user); - return principal.canConfigure(portletDefinitionId.toString());//this might backfire, will have to figure out exactly how it's figuring out if it can be configured + return principal.canConfigure(portletDefinitionId.toString()); } private Map prefMap(List prefs){ @@ -331,7 +416,19 @@ private Map prefMap(List prefs){ return map; } - + /** + * Set uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining + * the definition preferences for the portlet/soffit/webcomponent + * + *

The path for this method is /prefs/putdefinitionprefs/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to set definition preferences for. These are the default preferences for the given + * portlet/soffit/webcomponent. This will set the key:value(s) pairs provided into the defintion preferences + * overwriting any current definition preferences with the same key, adding a new key:value(s) pair if the key does not exits. + * You must be logged in as a portal administrator or have configuration rights for the given portlet/soffit/webcomponent + * in uPortal to access these. Will return a 403 or 404 otherwise + * + */ + //need to be an administrator @RequestMapping(value = "/prefs/putdefinitionprefs", method = RequestMethod.PUT) public ResponseEntity putDefinitionPrefs(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "The portlet fname to store preferences for") @@ -398,7 +495,16 @@ else if(!person.getSecurityContext().isAuthenticated()){ } - + /** + * Set uPortal entity preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining + * the definition preferences for the portlet/soffit/webcomponent + * + *

The path for this method is /prefs/putprefs/fname. The fname is a string representing the fname of the + * portlet/soffit/webcomponent to set entity preferences for. These are the user preferences for the given + * portlet/soffit/webcomponent. This will set the key:value(s) pairs provided into the entity preferences + * overwriting any current entity preferences with the same key, adding a new key:value(s) pair if the key does not exits. + * + */ @RequestMapping(value = "/prefs/putprefs", method = RequestMethod.PUT) public ResponseEntity putEntityPrefs(HttpServletRequest request, HttpServletResponse response, @ApiParam(value = "The portlet fname to store preferences for") diff --git a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java index c8a792a9f03..9af18441df7 100644 --- a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java +++ b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java @@ -1,6 +1,8 @@ package org.apereo.portal.rest; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -20,7 +22,6 @@ import org.apereo.portal.portlet.om.IPortletDefinitionId; import org.apereo.portal.portlet.om.IPortletEntity; import org.apereo.portal.portlet.om.IPortletEntityId; -import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; import org.apereo.portal.portlet.registry.IPortletEntityRegistry; import org.apereo.portal.security.IPerson; import org.apereo.portal.security.IPersonManager; @@ -35,7 +36,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; -import org.springframework.transaction.support.TransactionOperations; + public class PortletPrefsRESTControllerTest { @@ -53,12 +54,6 @@ public class PortletPrefsRESTControllerTest { @Mock private IPortletEntityRegistry portletEntityRegistry; - @Mock - private IPortletDefinitionRegistry portletDefinitionRegistry; - - @Mock - private TransactionOperations transactionOperations; - @Mock private PortletPreferencesFactory portletPreferencesFactory; @@ -391,7 +386,7 @@ public void putDefinitionPrefsSessionNonExistant() { } @Test - public void putDefinitionInvalidJson() { + public void putDefinitionInvalidJson() throws Exception{ String body="{\"pref1\":\"bob\""; PortletPreferences prefs=mock(PortletPreferences.class); @@ -401,8 +396,11 @@ public void putDefinitionInvalidJson() { ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req,res,valid_name,body); Assert.assertEquals(400,response.getStatusCodeValue()); + Mockito.verify(prefs, times(0)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); } + @Test public void putDefinitionPrefsSessionNonConfig() { //can't programatically test this one without setting up a full stack since it calls the static method: @@ -438,7 +436,7 @@ public void putEntityPrefsNotAuthorized() { } @Test - public void putEntityPrefsInvalidJson() { + public void putEntityPrefsInvalidJson() throws Exception { String body="{\"pref1\":\"bob\""; PortletPreferences prefs=mock(PortletPreferences.class); @@ -448,11 +446,13 @@ public void putEntityPrefsInvalidJson() { ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Assert.assertEquals(400,response.getStatusCodeValue()); + Mockito.verify(prefs, times(0)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); } @Test - public void putEntityPrefsObjectPref() { + public void putEntityPrefsObjectPref() throws Exception { String body="{\"pref1\":{\"name\":\"bob\"}}"; PortletPreferences prefs=mock(PortletPreferences.class); @@ -463,10 +463,12 @@ public void putEntityPrefsObjectPref() { ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Assert.assertEquals(400,response.getStatusCodeValue()); Assert.assertEquals("ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls",(String)response.getBody()); + Mockito.verify(prefs, times(0)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); } @Test - public void putEntityPrefsMultipleArray() { + public void putEntityPrefsMultipleArray() throws Exception { String body="{\"pref1\":[\"bob\",[\"name\",\"bob\"]]}"; PortletPreferences prefs=mock(PortletPreferences.class); @@ -477,10 +479,12 @@ public void putEntityPrefsMultipleArray() { ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Assert.assertEquals(400,response.getStatusCodeValue()); Assert.assertEquals("ERROR: preference arrays must only contain strings, numbers, booleans, or null",(String)response.getBody()); + Mockito.verify(prefs, times(0)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); } @Test - public void putEntityPrefsObjectArray() { + public void putEntityPrefsObjectArray() throws Exception { String body="{\"pref1\":[{\"bob\":[\"name\",\"bob\"]}]}"; PortletPreferences prefs=mock(PortletPreferences.class); @@ -491,10 +495,12 @@ public void putEntityPrefsObjectArray() { ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Assert.assertEquals(400,response.getStatusCodeValue()); Assert.assertEquals("ERROR: preference arrays must only contain strings, numbers, booleans, or null",(String)response.getBody()); + Mockito.verify(prefs, times(0)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); } @Test - public void putEntityPrefsReadOnly() throws Exception{ + public void putEntityPrefsReadOnly() throws Exception { String body="{\"pref1\":\"bob\"}"; String[] values= {"bob"}; PortletPreferences prefs=mock(PortletPreferences.class); @@ -508,7 +514,24 @@ public void putEntityPrefsReadOnly() throws Exception{ ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Assert.assertEquals(400,response.getStatusCodeValue()); Assert.assertEquals("Preference 'pref1' is read only",(String)response.getBody()); + Mockito.verify(prefs, times(1)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); + } + @Test//regression test. found it returned true even though it stored nothing. make sure it rejects non-key-value-pairs + public void putEntityPrefsSingleValue() throws Exception{ + String body="\"string\""; + PortletPreferences prefs=mock(PortletPreferences.class); + + Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) + .thenReturn(prefs); + + + ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + Assert.assertEquals(400,response.getStatusCodeValue()); + Assert.assertEquals("ERROR: invalid json. json must be in key:value pairs.",(String)response.getBody()); + Mockito.verify(prefs, times(0)).setValues(anyString(), any()); + Mockito.verify(prefs, times(0)).store(); } @Test @@ -523,6 +546,7 @@ public void putEntityPrefs() throws Exception{ ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Mockito.verify(prefs, times(1)).setValues("pref1", values); + Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); Assert.assertEquals(200,response.getStatusCodeValue()); Assert.assertEquals(true,(boolean)response.getBody()); @@ -542,6 +566,7 @@ public void putEntityPrefsArray() throws Exception{ ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Mockito.verify(prefs, times(1)).setValues("pref1", values); + Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); Assert.assertEquals(200,response.getStatusCodeValue()); Assert.assertEquals(true,(boolean)response.getBody()); @@ -560,6 +585,7 @@ public void putEntityPrefsAllTypes() throws Exception{ ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Mockito.verify(prefs, times(1)).setValues("pref1", values); + Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); Assert.assertEquals(200,response.getStatusCodeValue()); Assert.assertEquals(true,(boolean)response.getBody()); @@ -580,6 +606,7 @@ public void putEntityPrefsMultiplePrefs() throws Exception{ ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); Mockito.verify(prefs, times(1)).setValues("pref1", values1); Mockito.verify(prefs, times(1)).setValues("pref2", values2); + Mockito.verify(prefs, times(2)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); Assert.assertEquals(200,response.getStatusCodeValue()); Assert.assertEquals(true,(boolean)response.getBody()); From 6db24b6e89d5f31930a30d88a2f0dbaf38a90938 Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Wed, 27 Mar 2019 18:55:05 -0600 Subject: [PATCH 04/11] #1659 some more documentation --- .../java/org/apereo/portal/rest/PortletPrefsRESTController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index 0fb4fc18f77..9f7d6f6714a 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -497,7 +497,7 @@ else if(!person.getSecurityContext().isAuthenticated()){ /** * Set uPortal entity preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * the definition preferences for the portlet/soffit/webcomponent + * the entity preferences for the portlet/soffit/webcomponent * *

The path for this method is /prefs/putprefs/fname. The fname is a string representing the fname of the * portlet/soffit/webcomponent to set entity preferences for. These are the user preferences for the given From 20c0b4b5c73e8c1d2030eb94d46ef8f5099e896e Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Fri, 5 Apr 2019 16:21:37 -0600 Subject: [PATCH 05/11] #1659 added to the readme --- docs/developer/other/API.md | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/developer/other/API.md b/docs/developer/other/API.md index 637c6b358d5..8998b02595e 100644 --- a/docs/developer/other/API.md +++ b/docs/developer/other/API.md @@ -106,3 +106,44 @@ Example response: } } ``` +###Portlet Preferences + +`/api/prefs/{task}` + +(example: `http://localhost:8080/uPortal/api/prefs/getprefs/weather` ) + +These endpoints provide a way for soffits and web-components to access and store custom preferences for +individual soffits and web-components. There are several different endpoints for the various ways to store +and retrieve these preferences. This is an overview of the general uses. See the Swagger UI documentation +for specifics of each endpoint. + +####Regular preferences vs default preferences + +To access the regular (entity) preferences of an individual soffit or web-component use the endpoints with +only prefs in the name. These will return or store the preferences associated with the specific user for the +specific soffit/web-component. This will return/store the same information as the internal call to the preferences +for portlets per entity. + +NOTE: In order to protect unwanted meddling of portlet/soffit/web-component behavior, any preferences that you do not +want changed must be declared as readonly when set at registration. Otherwise users can potentially override these +settings for themselves. + +To access the default (definition) preferences of an individual soffit or web-component use the endpoints with +definitionprefs in the name. These will return or store the preferences associated with the definition of the +specific soffit/web-component set when registered with uPortal. This will return/store the same information as +the internal call to the preferences for portlets. + +NOTE: These calls will be rejected if attempted by any user without administrative privileges. This prevents +unauthorized meddling of default preferences since these calls can allow one to overwrite readonly preferences. + +####Only calls + +There are two calls with only in their names. These are used to single out the preferences that are only associated +with the called level without any extra. These are included because the normal retrieve calls return every preference +up to the desired level, with any conflicting information overwritten by the higher level (just as the portlet calls do). +If you wish to receive the preferences only associated with a specific level use these calls. + +NOTE: This may not return the preferences you expect. For example, any soffit calling the definitononly call will receive +the `org.apereo.portal.soffit.connector.SoffitConnectorController.serviceUrl` value and any soffit data model preferences +as well as other definition preferences. +Also be aware, if the user has no preferences set and you call entityonly you will receive an empty response body. From 99c6daba723d65289e3938f41be8efa118ce086f Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Fri, 5 Apr 2019 17:12:24 -0600 Subject: [PATCH 06/11] #1659 PortletPreferenceRESTController: getting it up to code spec --- .../rest/PortletPrefsRESTController.java | 746 ++++++++++-------- .../rest/PortletPrefsRESTControllerTest.java | 667 +++++++++------- .../GuestPortletEntityPreferencesAPIImpl.java | 55 +- .../PortletEntityPreferencesAPIImpl.java | 94 +-- .../services/PortletPreferencesFactory.java | 11 +- .../PortletPreferencesFactoryImpl.java | 34 +- 6 files changed, 873 insertions(+), 734 deletions(-) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index 9f7d6f6714a..4349e775a0c 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -1,8 +1,6 @@ package org.apereo.portal.rest; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.annotations.ApiParam; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -10,12 +8,17 @@ import java.util.Iterator; import java.util.List; import java.util.Map; + import javax.portlet.PortletPreferences; import javax.portlet.ReadOnlyException; import javax.portlet.WindowState; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.annotations.ApiParam; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; @@ -41,7 +44,10 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -/** PortletPrefsRESTController provides REST targets for preference operations for soffits and webcomponents. */ +/** + * PortletPrefsRESTController provides REST targets for preference operations for soffits and + * webcomponents. + */ @Controller public class PortletPrefsRESTController { @@ -50,8 +56,8 @@ public class PortletPrefsRESTController { private IPersonManager personManager; - private final boolean DEFINITION_MODE=true; - private final boolean ENTITY_MODE=false; + private final boolean DEFINITION_MODE = true; + private final boolean ENTITY_MODE = false; @Autowired public void setPersonManager(IPersonManager personManager) { @@ -76,549 +82,601 @@ public void setPortletEntityRegistry(IPortletEntityRegistry portletEntityRegistr @Autowired @Qualifier("portletPreferencesFactory") - public void setPortletPreferencesFactoryAPI(PortletPreferencesFactory portletPreferencesFactory){ - this.portletPreferencesFactory=portletPreferencesFactory; + public void setPortletPreferencesFactoryAPI( + PortletPreferencesFactory portletPreferencesFactory) { + this.portletPreferencesFactory = portletPreferencesFactory; } - - public PortletPrefsRESTController() { - this.mapper=new ObjectMapper(); + this.mapper = new ObjectMapper(); } - /** - * Get uPortal Entity information for portlet/soffit/webcomponent. This method provides a REST interface for obtaining uPortal - * portlet/soffit/webcomponent metadata + * Get uPortal Entity information for portlet/soffit/webcomponent. This method provides a REST + * interface for obtaining uPortal portlet/soffit/webcomponent metadata * - *

The path for this method is /prefs/getentity/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to find the entity information for + *

The path for this method is /prefs/getentity/fname. The fname is a string representing the + * fname of the portlet/soffit/webcomponent to find the entity information for */ /*non-javadoc - * I used this primarily for testing, could be useful given that it returns the windowstate, etc - * up to you if you want to keep it or modify it - * */ + * I used this primarily for testing, could be useful given that it returns the windowstate, etc + * up to you if you want to keep it or modify it + * */ @RequestMapping(value = "/prefs/getentity/{fname}", method = RequestMethod.GET) - public ResponseEntity getEntity(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to get entity for") - @PathVariable(value = "fname") String fname) { - try{ + public ResponseEntity getEntity( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to get entity for") @PathVariable(value = "fname") + String fname) { + try { IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + IPortletEntity entity = + portletEntityRegistry.getOrCreateDefaultPortletEntity( + request, portletDefinition.getPortletDefinitionId()); StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\""+portletDefinition.getFName()+"\": {"); - stringBuilder.append(" \"layoutNodeID\": \""+entity.getLayoutNodeId()+"\","); - stringBuilder.append(" \"userID\": \""+entity.getUserId()+"\","); - stringBuilder.append(" \"entityID\": \""+entity.getPortletEntityId()+"\","); + stringBuilder.append("{\"" + portletDefinition.getFName() + "\": {"); + stringBuilder.append(" \"layoutNodeID\": \"" + entity.getLayoutNodeId() + "\","); + stringBuilder.append(" \"userID\": \"" + entity.getUserId() + "\","); + stringBuilder.append(" \"entityID\": \"" + entity.getPortletEntityId() + "\","); stringBuilder.append(" \"windowStates\": ["); - boolean comma=false; - for(Map.Entry entry : entity.getWindowStates().entrySet()){ + boolean comma = false; + for (Map.Entry entry : entity.getWindowStates().entrySet()) { stringBuilder.append(" { \"stylesheetID\": \""); stringBuilder.append(entry.getKey()); stringBuilder.append("\", \"windowState\": \""); stringBuilder.append(entry.getValue().toString()); stringBuilder.append("\"},"); - comma=true; + comma = true; } if (comma) { stringBuilder.setLength(stringBuilder.length() - 1); } stringBuilder.append(" ] } }"); - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(stringBuilder.toString()); - }catch(IllegalArgumentException e){ - if(e.getMessage().contains("No portlet definition found for id '")){ - String error="ERROR: User not authorized to access portlet '"+fname+"'."; + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(stringBuilder.toString()); + } catch (IllegalArgumentException e) { + if (e.getMessage().contains("No portlet definition found for id '")) { + String error = "ERROR: User not authorized to access portlet '" + fname + "'."; logger.info(error); return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - }catch(Exception e){ - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } - } - /** - * Get uPortal Preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * the entity preferences for the portlet/soffit/webcomponent - * - *

The path for this method is /prefs/getprefs/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to return the composite entity preferences. These are the per-user preferences for the given - * portlet/soffit/webcomponent including any non-overwritten definition and descriptor preferences for the given - * portlet/soffit/webcomponent. Basically every preference for the soffit with the current user's preferences set. - * Will include extra preferences for soffits including the url, so please set any of these to read-only + * Get uPortal Preferecnces for portlet/soffit/webcomponent. This method provides a REST + * interface for uPortal for obtaining the entity preferences for the + * portlet/soffit/webcomponent * + *

The path for this method is /prefs/getprefs/fname. The fname is a string representing the + * fname of the portlet/soffit/webcomponent to return the composite entity preferences. These + * are the per-user preferences for the given portlet/soffit/webcomponent including any + * non-overwritten definition and descriptor preferences for the given + * portlet/soffit/webcomponent. Basically every preference for the soffit with the current + * user's preferences set. Will include extra preferences for soffits including the url, so + * please set any of these to read-only */ - //returns the entity composite preferences for the portlet in question + // returns the entity composite preferences for the portlet in question @RequestMapping(value = "/prefs/getprefs/{fname}", method = RequestMethod.GET) - public ResponseEntity getCompositePrefs(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to find preferences for") - @PathVariable(value = "fname") String fname) { + public ResponseEntity getCompositePrefs( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") + String fname) { try { IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); - //config mode of true is definition, false for entity (guest or user) - boolean config=ENTITY_MODE; - PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,config); - - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefs.getMap())); - - } catch(IllegalArgumentException e){ - if(e.getMessage().contains("No portlet definition found for id '")){ - String error="ERROR: User not authorized to access portlet '"+fname+"'."; + IPortletEntity entity = + portletEntityRegistry.getOrCreateDefaultPortletEntity( + request, portletDefinition.getPortletDefinitionId()); + boolean config = ENTITY_MODE; + PortletPreferences prefs = + portletPreferencesFactory.createAPIPortletPreferences( + request, entity, false, config); + + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(mapper.writeValueAsString(prefs.getMap())); + + } catch (IllegalArgumentException e) { + if (e.getMessage().contains("No portlet definition found for id '")) { + String error = "ERROR: User not authorized to access portlet '" + fname + "'."; logger.info(error); return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { - e.printStackTrace(); - logger.error("threw error trying to retrieve composite preferences",e); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + + logger.error("threw error trying to retrieve composite preferences", e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** - * Get uPortal Preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * only the entity preferences for the portlet/soffit/webcomponent - * - *

The path for this method is /prefs/getprefs/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to return the composite entity preferences. These are the per-user preferences for the given - * portlet/soffit/webcomponent. Includes only the user set preferences, does not include any defaults set in the definition + * Get uPortal Preferecnces for portlet/soffit/webcomponent. This method provides a REST + * interface for uPortal for obtaining only the entity preferences for the + * portlet/soffit/webcomponent * + *

The path for this method is /prefs/getprefs/fname. The fname is a string representing the + * fname of the portlet/soffit/webcomponent to return the composite entity preferences. These + * are the per-user preferences for the given portlet/soffit/webcomponent. Includes only the + * user set preferences, does not include any defaults set in the definition */ /*maybe get rid of this one? don't know if there is any specific use for it given that the preferences needed might be set in - * any of the entity, definition, or descriptor preferences. But is useful if you only need the user set preferences and are - * not relying on a default in the definition. - */ + * any of the entity, definition, or descriptor preferences. But is useful if you only need the user set preferences and are + * not relying on a default in the definition. + */ @RequestMapping(value = "/prefs/getentityonlyprefs/{fname}", method = RequestMethod.GET) - public ResponseEntity getEntityOnlyPrefs(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to find preferences for") - @PathVariable(value = "fname") String fname) { + public ResponseEntity getEntityOnlyPrefs( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") + String fname) { try { IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); - - PortletPreferences defprefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,DEFINITION_MODE); - PortletPreferences entprefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,ENTITY_MODE); - Map eprefs=getEntityOnly(entprefs.getMap(),defprefs.getMap()); - - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(eprefs)); - } catch(IllegalArgumentException e){ - if(e.getMessage().contains("No portlet definition found for id '")){ - String error="ERROR: User not authorized to access portlet '"+fname+"'."; + IPortletEntity entity = + portletEntityRegistry.getOrCreateDefaultPortletEntity( + request, portletDefinition.getPortletDefinitionId()); + + PortletPreferences defprefs = + portletPreferencesFactory.createAPIPortletPreferences( + request, entity, false, DEFINITION_MODE); + PortletPreferences entprefs = + portletPreferencesFactory.createAPIPortletPreferences( + request, entity, false, ENTITY_MODE); + Map eprefs = getEntityOnly(entprefs.getMap(), defprefs.getMap()); + + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(mapper.writeValueAsString(eprefs)); + } catch (IllegalArgumentException e) { + if (e.getMessage().contains("No portlet definition found for id '")) { + String error = "ERROR: User not authorized to access portlet '" + fname + "'."; logger.info(error); return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - } catch(Exception e){ - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - } - - } + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { - //get the entity preferences by comparing the entity with the defintion and returning the entity ones that are different - private Map getEntityOnly(Map entity, Map definition){ - Map result=new HashMap<>(); - for(Map.Entry entry : entity.entrySet()){ - String key=entry.getKey(); - String[] value=entry.getValue(); - if(!definition.containsKey(key)){ - //the entity has something the definition does not - result.put(key,value); - }else{ - //they both have it so compare the two - String[] defvalues = definition.get(key); - if(value==null){ - if(defvalues != null){ - result.put(key,value); - }//otherwise they're both null so don't add - }else{ - if(!Arrays.equals(value, defvalues)){ - result.put(key,value); - }//otherwise they're the same so don't add - } - } + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } - return result; } - //technically I guess we could get the full discriptor set by - /* final PortletDefinition portletDescriptor = - this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); - final Preferences descriptorPreferences = portletDescriptor.getPortletPreferences(); - for (final Preference preference : descriptorPreferences.getPortletPreferences()) { - final IPortletPreference preferenceWrapper = new PortletPreferenceImpl(preference); - basePortletPreferences.put(preferenceWrapper.getName(), preferenceWrapper); - } - */ - //without needing to do the compare - - //get the discriptor only preferences by comparing the entity with the defintion and returning the descriptor ones that are missing - private Map getDescriptorOnly(Map descriptor, List definition) { - Map defprefs=new HashMap<>(); - Map result= new HashMap<>(); - for(IPortletPreference p:definition){ - defprefs.put(p.getName(),p.getValues()); - } - for(Map.Entry entry : descriptor.entrySet()){ - if(!defprefs.containsKey(entry.getKey())){ - result.put(entry.getKey(),entry.getValue()); + // get the entity preferences by comparing the entity with the defintion and returning the + // entity ones that are different + private Map getEntityOnly( + Map entity, Map definition) { + Map result = new HashMap<>(); + for (Map.Entry entry : entity.entrySet()) { + String key = entry.getKey(); + String[] value = entry.getValue(); + if (!definition.containsKey(key)) { + // the entity has something the definition does not + result.put(key, value); + } else { + // they both have it so compare the two + String[] defvalues = definition.get(key); + if (value == null) { + if (defvalues != null) { + result.put(key, value); + } // otherwise they're both null so don't add + } else { + if (!Arrays.equals(value, defvalues)) { + result.put(key, value); + } // otherwise they're the same so don't add + } } } return result; } /** - * Get uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * the definition preferences for the portlet/soffit/webcomponent - * - *

The path for this method is /prefs/getdefinitionprefs/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to return the composite definition preferences. These are the default preferences for the given - * portlet/soffit/webcomponent including any non-overwritten descriptor preferences for the given - * portlet/soffit/webcomponent. Will include extra preferences for soffits including the url, so please set any of these to read-only - * when you define them. - * You must be logged in as a portal administrator or have configuration rights for the given portlet/soffit/webcomponent - * in uPortal to access these. Will return a 403 or 404 otherwise + * Get uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a + * REST interface for uPortal for obtaining the definition preferences for the + * portlet/soffit/webcomponent * + *

The path for this method is /prefs/getdefinitionprefs/fname. The fname is a string + * representing the fname of the portlet/soffit/webcomponent to return the composite definition + * preferences. These are the default preferences for the given portlet/soffit/webcomponent + * including any non-overwritten descriptor preferences for the given + * portlet/soffit/webcomponent. Will include extra preferences for soffits including the url, so + * please set any of these to read-only when you define them. You must be logged in as a portal + * administrator or have configuration rights for the given portlet/soffit/webcomponent in + * uPortal to access these. Will return a 403 or 404 otherwise */ - //must be authenticated and a portal administrator + // must be authenticated and a portal administrator @RequestMapping(value = "/prefs/getdefinitionprefs/{fname}", method = RequestMethod.GET) - public ResponseEntity getDefinitionPrefs(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to find preferences for") - @PathVariable(value = "fname") String fname) { + public ResponseEntity getDefinitionPrefs( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") + String fname) { HttpSession session = request.getSession(false); - if(session == null){ - return new ResponseEntity<>("",HttpStatus.NOT_FOUND); + if (session == null) { + return new ResponseEntity<>("", HttpStatus.NOT_FOUND); } final IPerson person = personManager.getPerson(request); - if(person.isGuest()){ + if (person.isGuest()) { logger.warn("Guest user tried to access getDefinitionPrefs. Possible hacking attempt."); - return new ResponseEntity<>("ERROR: guest cannot use this action.",HttpStatus.UNAUTHORIZED); - } - else if(!person.getSecurityContext().isAuthenticated()){ - logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs while not authenticated. Possible hacking attempt."); - return new ResponseEntity<>("ERROR: must be logged in to use this action.",HttpStatus.UNAUTHORIZED); + return new ResponseEntity<>( + "ERROR: guest cannot use this action.", HttpStatus.UNAUTHORIZED); + } else if (!person.getSecurityContext().isAuthenticated()) { + logger.warn( + "Person: {" + + person.getUserName() + + "} tried to access getDefinitionPrefs while not authenticated. Possible hacking attempt."); + return new ResponseEntity<>( + "ERROR: must be logged in to use this action.", HttpStatus.UNAUTHORIZED); } try { IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - if(!canConfigure(person,portletDefinition.getPortletDefinitionId())){ - logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs for portlet: {"+fname+"} without configuration permissions. Possible hacking attempt."); - return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.UNAUTHORIZED); + if (!canConfigure(person, portletDefinition.getPortletDefinitionId())) { + logger.warn( + "Person: {" + + person.getUserName() + + "} tried to access getDefinitionPrefs for portlet: {" + + fname + + "} without configuration permissions. Possible hacking attempt."); + return new ResponseEntity<>( + "ERROR: user is not authorized to perform this action", + HttpStatus.UNAUTHORIZED); } - IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); + IPortletEntity entity = + portletEntityRegistry.getOrCreateDefaultPortletEntity( + request, portletDefinition.getPortletDefinitionId()); - PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,DEFINITION_MODE); - - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefs.getMap())); - }catch(Exception e){ - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - } + PortletPreferences prefs = + portletPreferencesFactory.createAPIPortletPreferences( + request, entity, false, DEFINITION_MODE); + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(mapper.writeValueAsString(prefs.getMap())); + } catch (Exception e) { + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } } /** - * Get uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * the definition preferences for the portlet/soffit/webcomponent - * - *

The path for this method is /prefs/getdefinitiononlyprefs/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to return the definition preferences. These are the default preferences for the given - * portlet/soffit/webcomponent. Will include extra preferences for soffits -including the url- so please set any of these to read-only - * when you define them. - * You must be logged in as a portal administrator or have configuration rights for the given portlet/soffit/webcomponent - * in uPortal to access these. Will return a 403 or 404 otherwise + * Get uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a + * REST interface for uPortal for obtaining the definition preferences for the + * portlet/soffit/webcomponent * + *

The path for this method is /prefs/getdefinitiononlyprefs/fname. The fname is a string + * representing the fname of the portlet/soffit/webcomponent to return the definition + * preferences. These are the default preferences for the given portlet/soffit/webcomponent. + * Will include extra preferences for soffits -including the url- so please set any of these to + * read-only when you define them. You must be logged in as a portal administrator or have + * configuration rights for the given portlet/soffit/webcomponent in uPortal to access these. + * Will return a 403 or 404 otherwise */ - //must be authenticated and a portal administrator + // must be authenticated and a portal administrator @RequestMapping(value = "/prefs/getdefinitiononlyprefs/{fname}", method = RequestMethod.GET) - public ResponseEntity getDefinitionOnlyPrefs(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to find preferences for") - @PathVariable(value = "fname") String fname) { + public ResponseEntity getDefinitionOnlyPrefs( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to find preferences for") + @PathVariable(value = "fname") + String fname) { HttpSession session = request.getSession(false); - if(session == null){ - return new ResponseEntity<>("",HttpStatus.NOT_FOUND); + if (session == null) { + return new ResponseEntity<>("", HttpStatus.NOT_FOUND); } final IPerson person = personManager.getPerson(request); - if(person.isGuest()){ + if (person.isGuest()) { logger.warn("Guest user tried to access getDefinitionPrefs. Possible hacking attempt."); - return new ResponseEntity<>("ERROR: guest cannot use this action.",HttpStatus.UNAUTHORIZED); - } - else if(!person.getSecurityContext().isAuthenticated()){ - logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs while not authenticated. Possible hacking attempt."); - return new ResponseEntity<>("ERROR: must be logged in to use this action.",HttpStatus.UNAUTHORIZED); + return new ResponseEntity<>( + "ERROR: guest cannot use this action.", HttpStatus.UNAUTHORIZED); + } else if (!person.getSecurityContext().isAuthenticated()) { + logger.warn( + "Person: {" + + person.getUserName() + + "} tried to access getDefinitionPrefs while not authenticated. Possible hacking attempt."); + return new ResponseEntity<>( + "ERROR: must be logged in to use this action.", HttpStatus.UNAUTHORIZED); } try { IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - if(!canConfigure(person,portletDefinition.getPortletDefinitionId())){ - logger.warn("Person: {"+person.getUserName()+"} tried to access getDefinitionPrefs for portlet: {"+fname+"} without configuration permissions. Possible hacking attempt."); - return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.UNAUTHORIZED); + if (!canConfigure(person, portletDefinition.getPortletDefinitionId())) { + logger.warn( + "Person: {" + + person.getUserName() + + "} tried to access getDefinitionPrefs for portlet: {" + + fname + + "} without configuration permissions. Possible hacking attempt."); + return new ResponseEntity<>( + "ERROR: user is not authorized to perform this action", + HttpStatus.UNAUTHORIZED); } List prefs = portletDefinition.getPortletPreferences(); - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(mapper.writeValueAsString(prefMap(prefs))); - }catch(Exception e){ - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - } - + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(mapper.writeValueAsString(prefMap(prefs))); + } catch (Exception e) { + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } } - private boolean canConfigure(IPerson user, IPortletDefinitionId portletDefinitionId){ + private boolean canConfigure(IPerson user, IPortletDefinitionId portletDefinitionId) { final IAuthorizationPrincipal principal = - AuthorizationPrincipalHelper.principalFromUser(user); + AuthorizationPrincipalHelper.principalFromUser(user); return principal.canConfigure(portletDefinitionId.toString()); } - private Map prefMap(List prefs){ - Map map=new HashMap<>(); - for(IPortletPreference p : prefs){ - map.put(p.getName(),p.getValues()); + private Map prefMap(List prefs) { + Map map = new HashMap<>(); + for (IPortletPreference p : prefs) { + map.put(p.getName(), p.getValues()); } return map; } /** - * Set uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * the definition preferences for the portlet/soffit/webcomponent - * - *

The path for this method is /prefs/putdefinitionprefs/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to set definition preferences for. These are the default preferences for the given - * portlet/soffit/webcomponent. This will set the key:value(s) pairs provided into the defintion preferences - * overwriting any current definition preferences with the same key, adding a new key:value(s) pair if the key does not exits. - * You must be logged in as a portal administrator or have configuration rights for the given portlet/soffit/webcomponent - * in uPortal to access these. Will return a 403 or 404 otherwise + * Set uPortal definition preferecnces for portlet/soffit/webcomponent. This method provides a + * REST interface for uPortal for obtaining the definition preferences for the + * portlet/soffit/webcomponent * + *

The path for this method is /prefs/putdefinitionprefs/fname. The fname is a string + * representing the fname of the portlet/soffit/webcomponent to set definition preferences for. + * These are the default preferences for the given portlet/soffit/webcomponent. This will set + * the key:value(s) pairs provided into the defintion preferences overwriting any current + * definition preferences with the same key, adding a new key:value(s) pair if the key does not + * exits. You must be logged in as a portal administrator or have configuration rights for the + * given portlet/soffit/webcomponent in uPortal to access these. Will return a 403 or 404 + * otherwise */ - //need to be an administrator + // need to be an administrator @RequestMapping(value = "/prefs/putdefinitionprefs", method = RequestMethod.PUT) - public ResponseEntity putDefinitionPrefs(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to store preferences for") - @RequestParam(value = "fname", required=true) String fname, - @ApiParam(value = "the entity preferences to be stored in a single json object ex. " + - "{\"key1\":\"value1\",\"key2\":\"value2\", ...}. " + - "Values can be strings, booleans, numbers, null, or a jsonarray of values " + - "(objects can be stored as a value as serialized strings). " + - "This will overwrite any currently saved preferences for the portlet" + - " with the same key as the pairs put in.") - @RequestBody String body) { + public ResponseEntity putDefinitionPrefs( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to store preferences for") + @RequestParam(value = "fname", required = true) + String fname, + @ApiParam( + value = + "the entity preferences to be stored in a single json object ex. " + + "{\"key1\":\"value1\",\"key2\":\"value2\", ...}. " + + "Values can be strings, booleans, numbers, null, or a jsonarray of values " + + "(objects can be stored as a value as serialized strings). " + + "This will overwrite any currently saved preferences for the portlet" + + " with the same key as the pairs put in.") + @RequestBody + String body) { HttpSession session = request.getSession(false); - if(session == null){ - return new ResponseEntity<>("",HttpStatus.NOT_FOUND); + if (session == null) { + return new ResponseEntity<>("", HttpStatus.NOT_FOUND); } final IPerson person = personManager.getPerson(request); - if(person.isGuest()){ - return new ResponseEntity<>("ERROR: guests may not use this action.",HttpStatus.FORBIDDEN); - } - else if(!person.getSecurityContext().isAuthenticated()){ - return new ResponseEntity<>("ERROR: must be logged in to use this action.",HttpStatus.UNAUTHORIZED); + if (person.isGuest()) { + return new ResponseEntity<>( + "ERROR: guests may not use this action.", HttpStatus.FORBIDDEN); + } else if (!person.getSecurityContext().isAuthenticated()) { + return new ResponseEntity<>( + "ERROR: must be logged in to use this action.", HttpStatus.UNAUTHORIZED); } try { JsonNode map = mapper.readTree(body); IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); - - if(!canConfigure(person,entity.getPortletDefinitionId())){ - return new ResponseEntity<>("ERROR: user is not authorized to perform this action",HttpStatus.FORBIDDEN); + IPortletEntity entity = + portletEntityRegistry.getOrCreateDefaultPortletEntity( + request, portletDefinition.getPortletDefinitionId()); + + if (!canConfigure(person, entity.getPortletDefinitionId())) { + return new ResponseEntity<>( + "ERROR: user is not authorized to perform this action", + HttpStatus.FORBIDDEN); } - //config mode of true is definition - PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,DEFINITION_MODE); - boolean stored = storePrefs(prefs,map); + PortletPreferences prefs = + portletPreferencesFactory.createAPIPortletPreferences( + request, entity, false, DEFINITION_MODE); + + boolean stored = storePrefs(prefs, map); return ResponseEntity.ok().body(stored); - } catch(IllegalArgumentException e){ - if(e.getMessage().contains("No portlet definition found for id '")){ - String error="ERROR: User not authorized to access portlet '"+fname+"'."; + } catch (IllegalArgumentException e) { + if (e.getMessage().contains("No portlet definition found for id '")) { + String error = "ERROR: User not authorized to access portlet '" + fname + "'."; logger.info(error); return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (IOException e) { - e.printStackTrace(); - logger.error("threw error trying to parse preferences",e); + + logger.error("threw error trying to parse preferences", e); return ResponseEntity.badRequest().body(e.getMessage()); } catch (Exception e) { - e.printStackTrace(); - logger.error("threw error trying to store preferences",e); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - } + logger.error("threw error trying to store preferences", e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } } - /** - * Set uPortal entity preferecnces for portlet/soffit/webcomponent. This method provides a REST interface for uPortal for obtaining - * the entity preferences for the portlet/soffit/webcomponent - * - *

The path for this method is /prefs/putprefs/fname. The fname is a string representing the fname of the - * portlet/soffit/webcomponent to set entity preferences for. These are the user preferences for the given - * portlet/soffit/webcomponent. This will set the key:value(s) pairs provided into the entity preferences - * overwriting any current entity preferences with the same key, adding a new key:value(s) pair if the key does not exits. + * Set uPortal entity preferecnces for portlet/soffit/webcomponent. This method provides a REST + * interface for uPortal for obtaining the entity preferences for the + * portlet/soffit/webcomponent * + *

The path for this method is /prefs/putprefs/fname. The fname is a string representing the + * fname of the portlet/soffit/webcomponent to set entity preferences for. These are the user + * preferences for the given portlet/soffit/webcomponent. This will set the key:value(s) pairs + * provided into the entity preferences overwriting any current entity preferences with the same + * key, adding a new key:value(s) pair if the key does not exits. */ @RequestMapping(value = "/prefs/putprefs", method = RequestMethod.PUT) - public ResponseEntity putEntityPrefs(HttpServletRequest request, HttpServletResponse response, - @ApiParam(value = "The portlet fname to store preferences for") - @RequestParam(value="fname", required=true) String fname, - @ApiParam(value = "the entity preferences to be stored in a single json object ex. " + - "{\"key1\":\"value1\",\"key2\":\"value2\", ...}. " + - "Values can be strings, booleans, numbers, null, or a jsonarray of values " + - "(objects can be stored as a value as serialized strings). " + - "This will overwrite any currently saved preferences for the portlet" + - " with the same key as the key passed in.") - @RequestBody String body) { + public ResponseEntity putEntityPrefs( + HttpServletRequest request, + HttpServletResponse response, + @ApiParam(value = "The portlet fname to store preferences for") + @RequestParam(value = "fname", required = true) + String fname, + @ApiParam( + value = + "the entity preferences to be stored in a single json object ex. " + + "{\"key1\":\"value1\",\"key2\":\"value2\", ...}. " + + "Values can be strings, booleans, numbers, null, or a jsonarray of values " + + "(objects can be stored as a value as serialized strings). " + + "This will overwrite any currently saved preferences for the portlet" + + " with the same key as the key passed in.") + @RequestBody + String body) { try { JsonNode map = mapper.readTree(body); IPortletDefinition portletDefinition = portletDao.getPortletDefinitionByFname(fname); - if(portletDefinition==null){ + if (portletDefinition == null) { return new ResponseEntity<>("ERROR: Portlet not found", HttpStatus.NOT_FOUND); } - IPortletEntity entity = portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinition.getPortletDefinitionId()); - //configMode of false is Entity - PortletPreferences prefs=portletPreferencesFactory.createAPIPortletPreferences(request,entity,false,ENTITY_MODE); + IPortletEntity entity = + portletEntityRegistry.getOrCreateDefaultPortletEntity( + request, portletDefinition.getPortletDefinitionId()); - boolean stored = storePrefs(prefs,map); + PortletPreferences prefs = + portletPreferencesFactory.createAPIPortletPreferences( + request, entity, false, ENTITY_MODE); + + boolean stored = storePrefs(prefs, map); return ResponseEntity.ok().body(stored); - } catch(IllegalArgumentException e){ - if(e.getMessage().contains("No portlet definition found for id '")){ - String error="ERROR: User not authorized to access portlet '"+fname+"'."; + } catch (IllegalArgumentException e) { + if (e.getMessage().contains("No portlet definition found for id '")) { + String error = "ERROR: User not authorized to access portlet '" + fname + "'."; logger.info(error); return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - e.printStackTrace(); - logger.error(e.getMessage()); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); + + logger.error(e.getMessage(),e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (IOException e) { - e.printStackTrace(); - logger.error("threw error trying to parse preferences",e); + + logger.error("threw error trying to parse user preferences", e); return ResponseEntity.badRequest().body(e.getMessage()); - } catch(PreferenceException e){ + } catch (PreferenceException e) { logger.info(e.getMessage()); return ResponseEntity.badRequest().body(e.getMessage()); - } catch(ReadOnlyException e) { + } catch (ReadOnlyException e) { logger.info(e.getMessage()); return ResponseEntity.badRequest().body(e.getMessage()); - } catch(Exception e) { - e.printStackTrace(); - logger.error("threw error trying to store preferences",e); - return new ResponseEntity<>(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR); - } + } catch (Exception e) { + logger.error("threw error trying to store preferences", e); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } } - //process the - private boolean storePrefs(PortletPreferences prefs, JsonNode map)throws Exception{ - if(prefs==null){ + // process the incoming map to ensure validity then store + private boolean storePrefs(PortletPreferences prefs, JsonNode map) throws Exception { + if (prefs == null) { return false; } - try{ + try { Iterator nodes = map.fields(); - Map tempMap=new HashMap<>(); - while(nodes.hasNext()){ - Map.Entry entry=(Map.Entry)nodes.next(); - String key=entry.getKey(); - JsonNode node=entry.getValue(); - if(node.isValueNode()){ - String[] temp={node.asText()}; - tempMap.put(key,temp); - }else if(node.isArray()){ - List array=new ArrayList(); - for(JsonNode innerNode:node){ - if(innerNode.isValueNode()){ + Map tempMap = new HashMap<>(); + while (nodes.hasNext()) { + Map.Entry entry = (Map.Entry) nodes.next(); + String key = entry.getKey(); + JsonNode node = entry.getValue(); + if (node.isValueNode()) { + String[] temp = {node.asText()}; + tempMap.put(key, temp); + } else if (node.isArray()) { + List array = new ArrayList(); + for (JsonNode innerNode : node) { + if (innerNode.isValueNode()) { array.add(innerNode.asText()); - }else{ - throw new PreferenceException("ERROR: preference arrays must only contain strings, numbers, booleans, or null"); + } else { + throw new PreferenceException( + "ERROR: preference arrays must only contain strings, numbers, booleans, or null"); } } - tempMap.put(key,array.toArray(new String[array.size()])); - }else{ - throw new PreferenceException("ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls"); + tempMap.put(key, array.toArray(new String[array.size()])); + } else { + throw new PreferenceException( + "ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls"); } } - if(tempMap.size()==0){ - throw new PreferenceException("ERROR: invalid json. json must be in key:value pairs."); + if (tempMap.size() == 0) { + throw new PreferenceException( + "ERROR: invalid json. json must be in key:value pairs."); } - for(Map.Entry entry : tempMap.entrySet()){ - prefs.setValues(entry.getKey(),entry.getValue()); + for (Map.Entry entry : tempMap.entrySet()) { + prefs.setValues(entry.getKey(), entry.getValue()); } prefs.store(); return true; - }catch(Exception e){ + } catch (Exception e) { throw e; } } - private class PreferenceException extends Exception{ + private class PreferenceException extends Exception { - public PreferenceException(){ + public PreferenceException() { super(); } - public PreferenceException(String message){ + public PreferenceException(String message) { super(message); } - public PreferenceException(String message, Exception cause){ - super(message,cause); + public PreferenceException(String message, Exception cause) { + super(message, cause); } - } - } - - diff --git a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java index 9af18441df7..35d128bf16a 100644 --- a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java +++ b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java @@ -7,14 +7,17 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.IOException; import java.util.HashMap; import java.util.Map; + import javax.portlet.PortletPreferences; import javax.portlet.ReadOnlyException; import javax.portlet.WindowState; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; import org.apereo.portal.portlet.dao.IPortletDefinitionDao; import org.apereo.portal.portlet.dao.jpa.PortletDefinitionImpl; @@ -37,43 +40,35 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; - - public class PortletPrefsRESTControllerTest { + @InjectMocks private PortletPrefsRESTController portletPrefsRESTController; - @InjectMocks - private PortletPrefsRESTController portletPrefsRESTController; - - @Mock - private IPersonManager personManager; + @Mock private IPersonManager personManager; - @Mock - private IPortletDefinitionDao portletDao; + @Mock private IPortletDefinitionDao portletDao; - @Mock - private IPortletEntityRegistry portletEntityRegistry; + @Mock private IPortletEntityRegistry portletEntityRegistry; - @Mock - private PortletPreferencesFactory portletPreferencesFactory; + @Mock private PortletPreferencesFactory portletPreferencesFactory; private MockHttpServletRequest req; private MockHttpServletResponse res; - private String non_existant_name="non-existent-portlet"; - private String not_authorized_name="not-authorized-portlet"; - private String valid_name="bob-portlet"; + private String non_existant_name = "non-existent-portlet"; + private String not_authorized_name = "not-authorized-portlet"; + private String valid_name = "bob-portlet"; private IPortletDefinition valid_portletDefinitionMock = mock(PortletDefinitionImpl.class); private IPortletDefinitionId valid_portletDefIDMock = mock(IPortletDefinitionId.class); private IPortletEntity valid_entityMock = mock(IPortletEntity.class); - private ObjectMapper mapper=new ObjectMapper(); - private IPerson valid_person=mock(IPerson.class,RETURNS_DEEP_STUBS); + private ObjectMapper mapper = new ObjectMapper(); + private IPerson valid_person = mock(IPerson.class, RETURNS_DEEP_STUBS); @Before public void setUp() throws Exception { - portletPrefsRESTController=new PortletPrefsRESTController(); + portletPrefsRESTController = new PortletPrefsRESTController(); res = new MockHttpServletResponse(); req = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); @@ -81,40 +76,49 @@ public void setUp() throws Exception { req.setSession(session); MockitoAnnotations.initMocks(this); - //non-existant mocks + // non-existant mocks Mockito.when(portletDao.getPortletDefinitionByFname(non_existant_name)).thenReturn(null); - //not-authorized to subscribe mocks + // not-authorized to subscribe mocks IPortletDefinitionId not_authorized_portletDefIDMock = mock(IPortletDefinitionId.class); IPortletDefinition not_authorized_portletDefinitionMock = mock(PortletDefinitionImpl.class); - Mockito.when(portletDao.getPortletDefinitionByFname(not_authorized_name)).thenReturn(not_authorized_portletDefinitionMock); - Mockito.when(not_authorized_portletDefinitionMock.getPortletDefinitionId()).thenReturn(not_authorized_portletDefIDMock); - Mockito.when(portletEntityRegistry.getOrCreateDefaultPortletEntity(req, not_authorized_portletDefIDMock)).thenThrow( - new IllegalArgumentException( "No portlet definition found for id '200'.")); - - //authorized to subscribe common methods - Mockito.when(portletDao.getPortletDefinitionByFname(valid_name)).thenReturn(valid_portletDefinitionMock); - Mockito.when(valid_portletDefinitionMock.getPortletDefinitionId()).thenReturn(valid_portletDefIDMock); - Mockito.when(portletEntityRegistry.getOrCreateDefaultPortletEntity(req, valid_portletDefIDMock)).thenReturn(valid_entityMock); - + Mockito.when(portletDao.getPortletDefinitionByFname(not_authorized_name)) + .thenReturn(not_authorized_portletDefinitionMock); + Mockito.when(not_authorized_portletDefinitionMock.getPortletDefinitionId()) + .thenReturn(not_authorized_portletDefIDMock); + Mockito.when( + portletEntityRegistry.getOrCreateDefaultPortletEntity( + req, not_authorized_portletDefIDMock)) + .thenThrow( + new IllegalArgumentException("No portlet definition found for id '200'.")); + + // authorized to subscribe common methods + Mockito.when(portletDao.getPortletDefinitionByFname(valid_name)) + .thenReturn(valid_portletDefinitionMock); + Mockito.when(valid_portletDefinitionMock.getPortletDefinitionId()) + .thenReturn(valid_portletDefIDMock); + Mockito.when( + portletEntityRegistry.getOrCreateDefaultPortletEntity( + req, valid_portletDefIDMock)) + .thenReturn(valid_entityMock); Mockito.when(personManager.getPerson(req)).thenReturn(valid_person); Mockito.when(valid_person.isGuest()).thenReturn(false); Mockito.when(valid_person.getSecurityContext().isAuthenticated()).thenReturn(true); } - @Test//test that it returns the correct json when the fname is present in the database + @Test // test that it returns the correct json when the fname is present in the database public void getEntity() { - String valid_layoutid="bobLayoutNode"; - String valid_entityid="bobEntityID"; + String valid_layoutid = "bobLayoutNode"; + String valid_entityid = "bobEntityID"; int userid = 2; - //test specific mocks + // test specific mocks IPortletEntityId entityIDMock = mock(IPortletEntityId.class); - Map windowStateMock= new HashMap<>(); - windowStateMock.put(new Long(90),new WindowState("bob-state")); - //test specific mock methods + Map windowStateMock = new HashMap<>(); + windowStateMock.put(new Long(90), new WindowState("bob-state")); + // test specific mock methods Mockito.when(valid_portletDefinitionMock.getFName()).thenReturn(valid_name); Mockito.when(valid_entityMock.getLayoutNodeId()).thenReturn(valid_layoutid); Mockito.when(valid_entityMock.getUserId()).thenReturn(userid); @@ -122,149 +126,172 @@ public void getEntity() { Mockito.when(entityIDMock.toString()).thenReturn(valid_entityid); Mockito.when(valid_entityMock.getWindowStates()).thenReturn(windowStateMock); - //test specific json result + // test specific json result StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\""+valid_name+"\": {"); - stringBuilder.append(" \"layoutNodeID\": \""+valid_layoutid+"\","); - stringBuilder.append(" \"userID\": \""+userid+"\","); - stringBuilder.append(" \"entityID\": \""+valid_entityid+"\","); + stringBuilder.append("{\"" + valid_name + "\": {"); + stringBuilder.append(" \"layoutNodeID\": \"" + valid_layoutid + "\","); + stringBuilder.append(" \"userID\": \"" + userid + "\","); + stringBuilder.append(" \"entityID\": \"" + valid_entityid + "\","); stringBuilder.append(" \"windowStates\": ["); - boolean comma=false; - for(Map.Entry entry : windowStateMock.entrySet()){ + boolean comma = false; + for (Map.Entry entry : windowStateMock.entrySet()) { stringBuilder.append(" { \"stylesheetID\": \""); stringBuilder.append(entry.getKey()); stringBuilder.append("\", \"windowState\": \""); stringBuilder.append(entry.getValue().toString()); stringBuilder.append("\"},"); - comma=true; + comma = true; } if (comma) { stringBuilder.setLength(stringBuilder.length() - 1); } stringBuilder.append(" ] } }"); - ResponseEntity response = portletPrefsRESTController.getEntity(req,res,valid_name); - Assert.assertEquals(200,response.getStatusCodeValue()); + ResponseEntity response = portletPrefsRESTController.getEntity(req, res, valid_name); + Assert.assertEquals(200, response.getStatusCodeValue()); - Assert.assertEquals(stringBuilder.toString(),(String)response.getBody()); + Assert.assertEquals(stringBuilder.toString(), (String) response.getBody()); } - @Test//test that it returns a 400 when the portlet fname does not exits + @Test // test that it returns a 400 when the portlet fname does not exits public void getEntityNonExistent() { - ResponseEntity response = portletPrefsRESTController.getEntity(req,res,non_existant_name); - Assert.assertEquals(404,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + ResponseEntity response = portletPrefsRESTController.getEntity(req, res, non_existant_name); + Assert.assertEquals(404, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found", (String) response.getBody()); } @Test public void getEntityNotAuthorized() { - ResponseEntity response = portletPrefsRESTController.getEntity(req,res,not_authorized_name); - Assert.assertEquals(403,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getEntity(req, res, not_authorized_name); + Assert.assertEquals(403, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: User not authorized to access portlet '" + not_authorized_name + "'.", + (String) response.getBody()); } @Test public void getCompositePrefsNonExistent() { - ResponseEntity response = portletPrefsRESTController.getCompositePrefs(req,res,non_existant_name); - Assert.assertEquals(404,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getCompositePrefs(req, res, non_existant_name); + Assert.assertEquals(404, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found", (String) response.getBody()); } @Test public void getCompositePrefsNotAuthorized() { - ResponseEntity response = portletPrefsRESTController.getCompositePrefs(req,res,not_authorized_name); - Assert.assertEquals(403,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getCompositePrefs(req, res, not_authorized_name); + Assert.assertEquals(403, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: User not authorized to access portlet '" + not_authorized_name + "'.", + (String) response.getBody()); } @Test public void getCompositePrefs() { - PortletPreferences prefs=mock(PortletPreferences.class); - Map map=new HashMap<>(); - String[] pref1={"bob1","bob2","bob3"}; - String[] pref2={"true"}; - map.put("pref1",pref1); - map.put("pref2",pref2); + PortletPreferences prefs = mock(PortletPreferences.class); + Map map = new HashMap<>(); + String[] pref1 = {"bob1", "bob2", "bob3"}; + String[] pref2 = {"true"}; + map.put("pref1", pref1); + map.put("pref2", pref2); JsonNode jsonmap = mapper.valueToTree(map); - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); Mockito.when(prefs.getMap()).thenReturn(map); - - ResponseEntity response = portletPrefsRESTController.getCompositePrefs(req,res,valid_name); - Assert.assertEquals(200,response.getStatusCodeValue()); - JsonNode body=null; + ResponseEntity response = + portletPrefsRESTController.getCompositePrefs(req, res, valid_name); + Assert.assertEquals(200, response.getStatusCodeValue()); + JsonNode body = null; try { - body=mapper.readTree((String)response.getBody()); - }catch(IOException e){ - fail("failed to parse the json from the api: "+e.getMessage()); + body = mapper.readTree((String) response.getBody()); + } catch (IOException e) { + fail("failed to parse the json from the api: " + e.getMessage()); } - Assert.assertTrue("Json is not equal, \nExpected: "+jsonmap.toString()+"\nActual: "+body.toString(),jsonmap.equals(body)); - + Assert.assertTrue( + "Json is not equal, \nExpected: " + + jsonmap.toString() + + "\nActual: " + + body.toString(), + jsonmap.equals(body)); } - @Test public void getEntityOnlyPrefsNonExistant() { - ResponseEntity response = portletPrefsRESTController.getEntityOnlyPrefs(req,res,non_existant_name); - Assert.assertEquals(404,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getEntityOnlyPrefs(req, res, non_existant_name); + Assert.assertEquals(404, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found", (String) response.getBody()); } @Test public void getEntityOnlyPrefsNotAuthorized() { - ResponseEntity response = portletPrefsRESTController.getEntityOnlyPrefs(req,res,not_authorized_name); - Assert.assertEquals(403,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getEntityOnlyPrefs(req, res, not_authorized_name); + Assert.assertEquals(403, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: User not authorized to access portlet '" + not_authorized_name + "'.", + (String) response.getBody()); } @Test public void getEntityOnlyPrefs() { - PortletPreferences defPrefs=mock(PortletPreferences.class); - PortletPreferences entPrefs=mock(PortletPreferences.class); - - Map defMap=new HashMap<>(); - String[] pref1={"bob1","bob2","bob3"}; - String[] pref2={"true"}; - defMap.put("pref1",pref1); - defMap.put("pref2",pref2); - - Map entMap=new HashMap<>(); - entMap.put("pref1",pref1); - entMap.put("pref2",pref2); - String[] newPref2={"false"}; - entMap.put("pref2",newPref2); - - Map entOnlyMap = new HashMap<>(); + PortletPreferences defPrefs = mock(PortletPreferences.class); + PortletPreferences entPrefs = mock(PortletPreferences.class); + + Map defMap = new HashMap<>(); + String[] pref1 = {"bob1", "bob2", "bob3"}; + String[] pref2 = {"true"}; + defMap.put("pref1", pref1); + defMap.put("pref2", pref2); + + Map entMap = new HashMap<>(); + entMap.put("pref1", pref1); + entMap.put("pref2", pref2); + String[] newPref2 = {"false"}; + entMap.put("pref2", newPref2); + + Map entOnlyMap = new HashMap<>(); entOnlyMap.put("pref2", newPref2); JsonNode jsonmap = mapper.valueToTree(entOnlyMap); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,true)) - .thenReturn(defPrefs); + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, true)) + .thenReturn(defPrefs); Mockito.when(defPrefs.getMap()).thenReturn(defMap); - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(entPrefs); + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(entPrefs); Mockito.when(entPrefs.getMap()).thenReturn(entMap); - - - ResponseEntity response = portletPrefsRESTController.getEntityOnlyPrefs(req,res,valid_name); - Assert.assertEquals(200,response.getStatusCodeValue()); - JsonNode body=null; + ResponseEntity response = + portletPrefsRESTController.getEntityOnlyPrefs(req, res, valid_name); + Assert.assertEquals(200, response.getStatusCodeValue()); + JsonNode body = null; try { - body=mapper.readTree((String)response.getBody()); - }catch(IOException e){ - fail("failed to parse the json from the api: "+e.getMessage()); + body = mapper.readTree((String) response.getBody()); + } catch (IOException e) { + fail("failed to parse the json from the api: " + e.getMessage()); } - Assert.assertTrue("Json is not equal, \nExpected: "+jsonmap.toString()+"\nActual: "+body.toString(),jsonmap.equals(body)); + Assert.assertTrue( + "Json is not equal, \nExpected: " + + jsonmap.toString() + + "\nActual: " + + body.toString(), + jsonmap.equals(body)); } @Test @@ -272,13 +299,14 @@ public void getDefinitionPrefsNoSession() { MockHttpServletRequest req2 = new MockHttpServletRequest(); req2.setSession(null); - ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req2,res,valid_name); - Assert.assertEquals(404,response.getStatusCodeValue()); + ResponseEntity response = + portletPrefsRESTController.getDefinitionPrefs(req2, res, valid_name); + Assert.assertEquals(404, response.getStatusCodeValue()); } @Test public void getDefinitionPrefsGuest() { - IPerson person=mock(IPerson.class); + IPerson person = mock(IPerson.class); MockHttpServletRequest req2 = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); session.setAttribute("session", "true"); @@ -286,14 +314,15 @@ public void getDefinitionPrefsGuest() { Mockito.when(personManager.getPerson(req2)).thenReturn(person); Mockito.when(person.isGuest()).thenReturn(true); - ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req2,res,valid_name); - Assert.assertEquals(401,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: guest cannot use this action.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getDefinitionPrefs(req2, res, valid_name); + Assert.assertEquals(401, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: guest cannot use this action.", (String) response.getBody()); } @Test public void getDefinitionPrefsSessionNotAuthenticated() { - IPerson person=mock(IPerson.class,RETURNS_DEEP_STUBS); + IPerson person = mock(IPerson.class, RETURNS_DEEP_STUBS); MockHttpServletRequest req2 = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); session.setAttribute("session", "false"); @@ -302,52 +331,59 @@ public void getDefinitionPrefsSessionNotAuthenticated() { Mockito.when(person.isGuest()).thenReturn(false); Mockito.when(person.getSecurityContext().isAuthenticated()).thenReturn(false); - ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req2,res,valid_name); - Assert.assertEquals(401,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: must be logged in to use this action.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getDefinitionPrefs(req2, res, valid_name); + Assert.assertEquals(401, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: must be logged in to use this action.", (String) response.getBody()); } @Test public void getDefinitionPrefsSessionNonExistant() { - ResponseEntity response = portletPrefsRESTController.getDefinitionPrefs(req,res,non_existant_name); - Assert.assertEquals(404,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.getDefinitionPrefs(req, res, non_existant_name); + Assert.assertEquals(404, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found", (String) response.getBody()); } @Test public void getDefinitionPrefsSessionNonConfig() { - //can't programatically test this one without setting up a full stack since it calls the static method: + // can't programatically test this one without setting up a full stack since it calls the + // static method: // AuthorizationPrincipalHelper.principalFromUser(user) - //to insure that only portal administrators or others with configuration authority can configure. + // to insure that only portal administrators or others with configuration authority can + // configure. // *Could easily be implemented by using PowerMock - //has been thouroughly tested through manual testing though + // has been thouroughly tested through manual testing though } - @Test public void getDefinitionPrefs() { - //can't progamatically test this one without setting up a full stack since it calls the static method: + // can't progamatically test this one without setting up a full stack since it calls the + // static method: // AuthorizationPrincipalHelper.principalFromUser(user) - //to insure that only portal administrators or others with configuration authority can configure. + // to insure that only portal administrators or others with configuration authority can + // configure. // *Could easily be implemented by using PowerMock - //has been thouroughly tested through manual testing though + // has been thouroughly tested through manual testing though } @Test public void putDefinitionPrefsNoSession() { - String body="{\"pref1\":\"value1\"}"; + String body = "{\"pref1\":\"value1\"}"; MockHttpServletRequest req2 = new MockHttpServletRequest(); req2.setSession(null); - ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req2,res,valid_name,body); - Assert.assertEquals(404,response.getStatusCodeValue()); + ResponseEntity response = + portletPrefsRESTController.putDefinitionPrefs(req2, res, valid_name, body); + Assert.assertEquals(404, response.getStatusCodeValue()); } @Test public void putDefinitionPrefsGuest() { - String body="{\"pref1\":\"value1\"}"; - IPerson person=mock(IPerson.class); + String body = "{\"pref1\":\"value1\"}"; + IPerson person = mock(IPerson.class); MockHttpServletRequest req2 = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); session.setAttribute("session", "true"); @@ -355,15 +391,16 @@ public void putDefinitionPrefsGuest() { Mockito.when(personManager.getPerson(req2)).thenReturn(person); Mockito.when(person.isGuest()).thenReturn(true); - ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req2,res,valid_name,body); - Assert.assertEquals(403,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: guests may not use this action.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.putDefinitionPrefs(req2, res, valid_name, body); + Assert.assertEquals(403, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: guests may not use this action.", (String) response.getBody()); } @Test public void putDefinitionPrefsSessionNotAuthenticated() { - String body="{\"pref1\":\"value1\"}"; - IPerson person=mock(IPerson.class,RETURNS_DEEP_STUBS); + String body = "{\"pref1\":\"value1\"}"; + IPerson person = mock(IPerson.class, RETURNS_DEEP_STUBS); MockHttpServletRequest req2 = new MockHttpServletRequest(); MockHttpSession session = new MockHttpSession(); session.setAttribute("session", "false"); @@ -372,247 +409,281 @@ public void putDefinitionPrefsSessionNotAuthenticated() { Mockito.when(person.isGuest()).thenReturn(false); Mockito.when(person.getSecurityContext().isAuthenticated()).thenReturn(false); - ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req2,res,valid_name,body); - Assert.assertEquals(401,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: must be logged in to use this action.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.putDefinitionPrefs(req2, res, valid_name, body); + Assert.assertEquals(401, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: must be logged in to use this action.", (String) response.getBody()); } @Test public void putDefinitionPrefsSessionNonExistant() { - String body="{\"pref1\":\"value1\"}"; - ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req,res,non_existant_name,body); - Assert.assertEquals(404,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + String body = "{\"pref1\":\"value1\"}"; + ResponseEntity response = + portletPrefsRESTController.putDefinitionPrefs(req, res, non_existant_name, body); + Assert.assertEquals(404, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found", (String) response.getBody()); } @Test - public void putDefinitionInvalidJson() throws Exception{ - String body="{\"pref1\":\"bob\""; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,true)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putDefinitionPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); + public void putDefinitionInvalidJson() throws Exception { + String body = "{\"pref1\":\"bob\""; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, true)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putDefinitionPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); Mockito.verify(prefs, times(0)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } - @Test public void putDefinitionPrefsSessionNonConfig() { - //can't programatically test this one without setting up a full stack since it calls the static method: + // can't programatically test this one without setting up a full stack since it calls the + // static method: // AuthorizationPrincipalHelper.principalFromUser(user) - //to insure that only portal administrators or others with configuration authority can configure. + // to insure that only portal administrators or others with configuration authority can + // configure. // *Could easily be implemented by using PowerMock - //has been thouroughly tested through manual testing though + // has been thouroughly tested through manual testing though } @Test public void putDefinitionPrefs() { - //can't programatically test this one without setting up a full stack since it calls the static method: + // can't programatically test this one without setting up a full stack since it calls the + // static method: // AuthorizationPrincipalHelper.principalFromUser(user) - //to insure that only portal administrators or others with configuration authority can configure. + // to insure that only portal administrators or others with configuration authority can + // configure. // *Could easily be implemented by using PowerMock - //has been thouroughly tested through manual testing though + // has been thouroughly tested through manual testing though } @Test public void putEntityPrefsNonExistant() { - String body="{\"pref1\":\"bob\"}"; - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,non_existant_name,body); - Assert.assertEquals(404,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: Portlet not found",(String)response.getBody()); + String body = "{\"pref1\":\"bob\"}"; + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, non_existant_name, body); + Assert.assertEquals(404, response.getStatusCodeValue()); + Assert.assertEquals("ERROR: Portlet not found", (String) response.getBody()); } @Test public void putEntityPrefsNotAuthorized() { - String body="{\"pref1\":\"bob\"}"; - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,not_authorized_name,body); - Assert.assertEquals(403,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: User not authorized to access portlet '"+not_authorized_name+"'.",(String)response.getBody()); + String body = "{\"pref1\":\"bob\"}"; + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, not_authorized_name, body); + Assert.assertEquals(403, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: User not authorized to access portlet '" + not_authorized_name + "'.", + (String) response.getBody()); } @Test public void putEntityPrefsInvalidJson() throws Exception { - String body="{\"pref1\":\"bob\""; - PortletPreferences prefs=mock(PortletPreferences.class); + String body = "{\"pref1\":\"bob\""; + PortletPreferences prefs = mock(PortletPreferences.class); - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); Mockito.verify(prefs, times(0)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } - @Test public void putEntityPrefsObjectPref() throws Exception { - String body="{\"pref1\":{\"name\":\"bob\"}}"; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls",(String)response.getBody()); + String body = "{\"pref1\":{\"name\":\"bob\"}}"; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: preferences must be strings, numbers, booleans, null, or arrays of strings, numbers, booleans, or nulls", + (String) response.getBody()); Mockito.verify(prefs, times(0)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } @Test public void putEntityPrefsMultipleArray() throws Exception { - String body="{\"pref1\":[\"bob\",[\"name\",\"bob\"]]}"; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: preference arrays must only contain strings, numbers, booleans, or null",(String)response.getBody()); + String body = "{\"pref1\":[\"bob\",[\"name\",\"bob\"]]}"; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: preference arrays must only contain strings, numbers, booleans, or null", + (String) response.getBody()); Mockito.verify(prefs, times(0)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } @Test public void putEntityPrefsObjectArray() throws Exception { - String body="{\"pref1\":[{\"bob\":[\"name\",\"bob\"]}]}"; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: preference arrays must only contain strings, numbers, booleans, or null",(String)response.getBody()); + String body = "{\"pref1\":[{\"bob\":[\"name\",\"bob\"]}]}"; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: preference arrays must only contain strings, numbers, booleans, or null", + (String) response.getBody()); Mockito.verify(prefs, times(0)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } @Test public void putEntityPrefsReadOnly() throws Exception { - String body="{\"pref1\":\"bob\"}"; - String[] values= {"bob"}; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - Mockito.doThrow(new ReadOnlyException("Preference '" + "pref1" + "' is read only")).when(prefs).setValues("pref1", values); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); - Assert.assertEquals("Preference 'pref1' is read only",(String)response.getBody()); + String body = "{\"pref1\":\"bob\"}"; + String[] values = {"bob"}; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + Mockito.doThrow(new ReadOnlyException("Preference '" + "pref1" + "' is read only")) + .when(prefs) + .setValues("pref1", values); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); + Assert.assertEquals("Preference 'pref1' is read only", (String) response.getBody()); Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } - @Test//regression test. found it returned true even though it stored nothing. make sure it rejects non-key-value-pairs - public void putEntityPrefsSingleValue() throws Exception{ - String body="\"string\""; - PortletPreferences prefs=mock(PortletPreferences.class); + @Test // regression test. found it returned true even though it stored nothing. make sure it + // rejects non-key-value-pairs + public void putEntityPrefsSingleValue() throws Exception { + String body = "\"string\""; + PortletPreferences prefs = mock(PortletPreferences.class); - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); - Assert.assertEquals(400,response.getStatusCodeValue()); - Assert.assertEquals("ERROR: invalid json. json must be in key:value pairs.",(String)response.getBody()); + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); + Assert.assertEquals(400, response.getStatusCodeValue()); + Assert.assertEquals( + "ERROR: invalid json. json must be in key:value pairs.", + (String) response.getBody()); Mockito.verify(prefs, times(0)).setValues(anyString(), any()); Mockito.verify(prefs, times(0)).store(); } @Test - public void putEntityPrefs() throws Exception{ - String body="{\"pref1\":\"bob\"}"; - String[] values= {"bob"}; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + public void putEntityPrefs() throws Exception { + String body = "{\"pref1\":\"bob\"}"; + String[] values = {"bob"}; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); Mockito.verify(prefs, times(1)).setValues("pref1", values); Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); - Assert.assertEquals(200,response.getStatusCodeValue()); - Assert.assertEquals(true,(boolean)response.getBody()); - + Assert.assertEquals(200, response.getStatusCodeValue()); + Assert.assertEquals(true, (boolean) response.getBody()); } - @Test - public void putEntityPrefsArray() throws Exception{ - String body="{\"pref1\":[\"bob\",\"joe\"]}"; - String[] values= {"bob","joe"}; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + public void putEntityPrefsArray() throws Exception { + String body = "{\"pref1\":[\"bob\",\"joe\"]}"; + String[] values = {"bob", "joe"}; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); Mockito.verify(prefs, times(1)).setValues("pref1", values); Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); - Assert.assertEquals(200,response.getStatusCodeValue()); - Assert.assertEquals(true,(boolean)response.getBody()); - + Assert.assertEquals(200, response.getStatusCodeValue()); + Assert.assertEquals(true, (boolean) response.getBody()); } @Test - public void putEntityPrefsAllTypes() throws Exception{ - String body="{\"pref1\":[\"bob\",true,false,null,1,50.9]}"; - String[] values= {"bob","true","false","null","1","50.9"}; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + public void putEntityPrefsAllTypes() throws Exception { + String body = "{\"pref1\":[\"bob\",true,false,null,1,50.9]}"; + String[] values = {"bob", "true", "false", "null", "1", "50.9"}; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); Mockito.verify(prefs, times(1)).setValues("pref1", values); Mockito.verify(prefs, times(1)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); - Assert.assertEquals(200,response.getStatusCodeValue()); - Assert.assertEquals(true,(boolean)response.getBody()); - + Assert.assertEquals(200, response.getStatusCodeValue()); + Assert.assertEquals(true, (boolean) response.getBody()); } @Test - public void putEntityPrefsMultiplePrefs() throws Exception{ - String body="{\"pref1\":[\"bob\",\"joe\"],\"pref2\":true}"; - String[] values1= {"bob","joe"}; - String[] values2= {"true"}; - PortletPreferences prefs=mock(PortletPreferences.class); - - Mockito.when(portletPreferencesFactory.createAPIPortletPreferences(req,valid_entityMock,false,false)) - .thenReturn(prefs); - - - ResponseEntity response = portletPrefsRESTController.putEntityPrefs(req,res,valid_name,body); + public void putEntityPrefsMultiplePrefs() throws Exception { + String body = "{\"pref1\":[\"bob\",\"joe\"],\"pref2\":true}"; + String[] values1 = {"bob", "joe"}; + String[] values2 = {"true"}; + PortletPreferences prefs = mock(PortletPreferences.class); + + Mockito.when( + portletPreferencesFactory.createAPIPortletPreferences( + req, valid_entityMock, false, false)) + .thenReturn(prefs); + + ResponseEntity response = + portletPrefsRESTController.putEntityPrefs(req, res, valid_name, body); Mockito.verify(prefs, times(1)).setValues("pref1", values1); Mockito.verify(prefs, times(1)).setValues("pref2", values2); Mockito.verify(prefs, times(2)).setValues(anyString(), any()); Mockito.verify(prefs, times(1)).store(); - Assert.assertEquals(200,response.getStatusCodeValue()); - Assert.assertEquals(true,(boolean)response.getBody()); - + Assert.assertEquals(200, response.getStatusCodeValue()); + Assert.assertEquals(true, (boolean) response.getBody()); } - - - } diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java index 6f534928758..2f22901990e 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/GuestPortletEntityPreferencesAPIImpl.java @@ -33,11 +33,14 @@ import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; import org.apereo.portal.portlet.registry.IPortletEntityRegistry; -/** Preferences impl that manipulates the portlet entity level preference data for Guests used only for the REST API */ +/** + * Preferences impl that manipulates the portlet entity level preference data for Guests used only + * for the REST API + */ public class GuestPortletEntityPreferencesAPIImpl - extends AbstractPortletPreferencesImpl { + extends AbstractPortletPreferencesImpl { protected static final String PORTLET_PREFERENCES_MAP_ATTRIBUTE = - GuestPortletEntityPreferencesAPIImpl.class.getName() + ".PORTLET_PREFERENCES_MAP"; + GuestPortletEntityPreferencesAPIImpl.class.getName() + ".PORTLET_PREFERENCES_MAP"; private final HttpServletRequest portletRequest; private final IPortletEntityId portletEntityId; @@ -46,11 +49,11 @@ public class GuestPortletEntityPreferencesAPIImpl private final IPortletDefinitionRegistry portletDefinitionRegistry; public GuestPortletEntityPreferencesAPIImpl( - HttpServletRequest portletRequest, - IPortletEntityRegistry portletEntityRegistry, - IPortletDefinitionRegistry portletDefinitionRegistry, - IPortletEntityId portletEntityId, - boolean render) { + HttpServletRequest portletRequest, + IPortletEntityRegistry portletEntityRegistry, + IPortletDefinitionRegistry portletDefinitionRegistry, + IPortletEntityId portletEntityId, + boolean render) { super(render); this.portletRequest = portletRequest; @@ -71,10 +74,10 @@ protected Object getLogDescription() { @Override protected void loadTargetPortletPreferences( - IPortletEntity portletEntity, - Map targetPortletPreferences) { + IPortletEntity portletEntity, + Map targetPortletPreferences) { final Map sessionPreferences = - this.getSessionPreferences(portletEntityId, portletRequest); + this.getSessionPreferences(portletEntityId, portletRequest); if (sessionPreferences != null) { targetPortletPreferences.putAll(sessionPreferences); } @@ -83,13 +86,13 @@ protected void loadTargetPortletPreferences( @Override @SuppressWarnings("Duplicates") protected void loadBasePortletPreferences( - IPortletEntity portletEntity, Map basePortletPreferences) { + IPortletEntity portletEntity, Map basePortletPreferences) { final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition(); // Add descriptor prefs to base Map final IPortletDefinitionId portletDefinitionId = portletDefinition.getPortletDefinitionId(); final PortletDefinition portletDescriptor = - this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); + this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); final Preferences descriptorPreferences = portletDescriptor.getPortletPreferences(); for (final Preference preference : descriptorPreferences.getPortletPreferences()) { final IPortletPreference preferenceWrapper = new PortletPreferenceImpl(preference); @@ -98,7 +101,7 @@ protected void loadBasePortletPreferences( // Add definition prefs to base Map final List definitionPreferences = - portletDefinition.getPortletPreferences(); + portletDefinition.getPortletPreferences(); for (final IPortletPreference preference : definitionPreferences) { basePortletPreferences.put(preference.getName(), preference); } @@ -113,7 +116,7 @@ protected void loadBasePortletPreferences( @Override protected boolean storeInternal() throws IOException, ValidatorException { final Map targetPortletPreferences = - this.getTargetPortletPreferences(); + this.getTargetPortletPreferences(); if (targetPortletPreferences.isEmpty()) { return false; } @@ -130,9 +133,9 @@ protected boolean storeInternal() throws IOException, ValidatorException { * @return Map of IPortletPreferences for the entity and session, may be null if no preferences * have been set. */ - @SuppressWarnings({"unchecked","Duplicates"}) + @SuppressWarnings({"unchecked", "Duplicates"}) protected Map getSessionPreferences( - IPortletEntityId portletEntityId, HttpServletRequest httpServletRequest) { + IPortletEntityId portletEntityId, HttpServletRequest httpServletRequest) { final HttpSession session = httpServletRequest.getSession(); final Map> portletPreferences; @@ -140,8 +143,8 @@ protected Map getSessionPreferences( // Sync on the session to ensure the Map isn't in the process of being created synchronized (session) { portletPreferences = - (Map>) - session.getAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE); + (Map>) + session.getAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE); } if (portletPreferences == null) { @@ -151,11 +154,11 @@ protected Map getSessionPreferences( return portletPreferences.get(portletEntityId); } - @SuppressWarnings({"unchecked","Duplicates"}) + @SuppressWarnings({"unchecked", "Duplicates"}) protected void storeSessionPreferences( - IPortletEntityId portletEntityId, - HttpServletRequest httpServletRequest, - Map preferences) { + IPortletEntityId portletEntityId, + HttpServletRequest httpServletRequest, + Map preferences) { final HttpSession session = httpServletRequest.getSession(); Map> portletPreferences; @@ -163,11 +166,11 @@ protected void storeSessionPreferences( // Sync on the session to ensure other threads aren't creating the Map at the same time synchronized (session) { portletPreferences = - (Map>) - session.getAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE); + (Map>) + session.getAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE); if (portletPreferences == null) { portletPreferences = - new ConcurrentHashMap>(); + new ConcurrentHashMap>(); session.setAttribute(PORTLET_PREFERENCES_MAP_ATTRIBUTE, portletPreferences); } } diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java index a32c4b8c49e..e0b3331f811 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletEntityPreferencesAPIImpl.java @@ -37,8 +37,9 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionOperations; -/** Preferences impl that manipulates the portlet entity level preference data for the REST API*/ -public class PortletEntityPreferencesAPIImpl extends AbstractPortletPreferencesImpl { +/** Preferences impl that manipulates the portlet entity level preference data for the REST API */ +public class PortletEntityPreferencesAPIImpl + extends AbstractPortletPreferencesImpl { private final HttpServletRequest portletRequest; private final IPortletEntityId portletEntityId; @@ -47,11 +48,11 @@ public class PortletEntityPreferencesAPIImpl extends AbstractPortletPreferencesI private final TransactionOperations transactionOperations; public PortletEntityPreferencesAPIImpl( - HttpServletRequest portletRequestContext, - IPortletEntityRegistry portletEntityRegistry, - IPortletDefinitionRegistry portletDefinitionRegistry, - TransactionOperations transactionOperations, - IPortletEntityId portletEntityId) { + HttpServletRequest portletRequestContext, + IPortletEntityRegistry portletEntityRegistry, + IPortletDefinitionRegistry portletDefinitionRegistry, + TransactionOperations transactionOperations, + IPortletEntityId portletEntityId) { super(false); this.portletRequest = portletRequestContext; @@ -63,8 +64,7 @@ public PortletEntityPreferencesAPIImpl( @Override protected IPortletEntity getInitializationContext() { - final HttpServletRequest containerRequest = - this.portletRequest; + final HttpServletRequest containerRequest = this.portletRequest; return this.portletEntityRegistry.getPortletEntity(containerRequest, portletEntityId); } @@ -75,8 +75,8 @@ protected Object getLogDescription() { @Override protected void loadTargetPortletPreferences( - IPortletEntity portletEntity, - Map targetPortletPreferences) { + IPortletEntity portletEntity, + Map targetPortletPreferences) { final List entityPreferences = portletEntity.getPortletPreferences(); for (final IPortletPreference preference : entityPreferences) { targetPortletPreferences.put(preference.getName(), preference); @@ -86,13 +86,13 @@ protected void loadTargetPortletPreferences( @Override @SuppressWarnings("Duplicates") protected void loadBasePortletPreferences( - IPortletEntity portletEntity, Map basePortletPreferences) { + IPortletEntity portletEntity, Map basePortletPreferences) { final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition(); // Add descriptor prefs to base Map final IPortletDefinitionId portletDefinitionId = portletDefinition.getPortletDefinitionId(); final PortletDefinition portletDescriptor = - this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); + this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId); final Preferences descriptorPreferences = portletDescriptor.getPortletPreferences(); for (final Preference preference : descriptorPreferences.getPortletPreferences()) { final IPortletPreference preferenceWrapper = new PortletPreferenceImpl(preference); @@ -101,7 +101,7 @@ protected void loadBasePortletPreferences( // Add definition prefs to base Map final List definitionPreferences = - portletDefinition.getPortletPreferences(); + portletDefinition.getPortletPreferences(); for (final IPortletPreference preference : definitionPreferences) { basePortletPreferences.put(preference.getName(), preference); } @@ -113,10 +113,10 @@ protected boolean storeInternal() throws IOException, ValidatorException { final HttpServletRequest containerRequest = portletRequest; final IPortletEntity portletEntity = - this.portletEntityRegistry.getPortletEntity(containerRequest, portletEntityId); + this.portletEntityRegistry.getPortletEntity(containerRequest, portletEntityId); final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId(); final Lock portletEntityLock = - this.portletEntityRegistry.getPortletEntityLock(containerRequest, portletEntityId); + this.portletEntityRegistry.getPortletEntityLock(containerRequest, portletEntityId); // Do a tryLock first so that we can warn about concurrent preference modification if it // fails @@ -124,44 +124,44 @@ protected boolean storeInternal() throws IOException, ValidatorException { try { if (!locked) { logger.warn( - "Concurrent portlet preferences modification by: " - + portletEntity - + " " - + "This has the potential for changes to preferences to be lost. " - + "This portlet should be modified to synchronize its preference modifications appropriately", - new Throwable()); + "Concurrent portlet preferences modification by: " + + portletEntity + + " " + + "This has the potential for changes to preferences to be lost. " + + "This portlet should be modified to synchronize its preference modifications appropriately", + new Throwable()); portletEntityLock.lock(); locked = true; } return this.transactionOperations.execute( - new TransactionCallback() { - @Override - public Boolean doInTransaction(TransactionStatus status) { - // Refresh the entity to avoid optimistic locking errors - final IPortletEntity portletEntity = - portletEntityRegistry.getPortletEntity( - containerRequest, portletEntityId); - - final Map targetPortletPreferences = - getTargetPortletPreferences(); - final Collection values = - targetPortletPreferences.values(); - final boolean modified = - portletEntity.setPortletPreferences( - new ArrayList(values)); - if (!modified) { - // Nothing actually changed, skip the store - return Boolean.FALSE; + new TransactionCallback() { + @Override + public Boolean doInTransaction(TransactionStatus status) { + // Refresh the entity to avoid optimistic locking errors + final IPortletEntity portletEntity = + portletEntityRegistry.getPortletEntity( + containerRequest, portletEntityId); + + final Map targetPortletPreferences = + getTargetPortletPreferences(); + final Collection values = + targetPortletPreferences.values(); + final boolean modified = + portletEntity.setPortletPreferences( + new ArrayList(values)); + if (!modified) { + // Nothing actually changed, skip the store + return Boolean.FALSE; + } + + portletEntityRegistry.storePortletEntity( + containerRequest, portletEntity); + + return Boolean.TRUE; } - - portletEntityRegistry.storePortletEntity( - containerRequest, portletEntity); - - return Boolean.TRUE; - } - }); + }); } finally { // check if locked, needed due to slightly more complex logic around the tryLock and // logging diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java index 482cba2f8f4..c6f6c899e62 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java @@ -16,6 +16,7 @@ import javax.portlet.PortletPreferences; import javax.servlet.http.HttpServletRequest; + import org.apache.pluto.container.PortletRequestContext; import org.apereo.portal.portlet.om.IPortletEntity; @@ -26,7 +27,13 @@ public interface PortletPreferencesFactory { PortletPreferences createPortletPreferences( final PortletRequestContext requestContext, boolean render); - /** Create portlet preferences for the specified portlet request context for the REST API calls (since they don't have access to the portletRequestContext (and technically don't need it)) */ + /** + * Create portlet preferences for the specified portlet request context for the REST API calls + * (since they don't have access to the portletRequestContext (and technically don't need it)) + */ PortletPreferences createAPIPortletPreferences( - final HttpServletRequest requestContext, IPortletEntity portletEntity, boolean render, boolean configMode); + final HttpServletRequest requestContext, + IPortletEntity portletEntity, + boolean render, + boolean configMode); } diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java index e7f6cb9a4ae..0de741d3daf 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java @@ -16,6 +16,7 @@ import javax.portlet.PortletPreferences; import javax.servlet.http.HttpServletRequest; + import org.apache.pluto.container.PortletRequestContext; import org.apache.pluto.container.PortletWindow; import org.apereo.portal.jpa.BasePortalJpaDao; @@ -113,39 +114,38 @@ public PortletPreferences createPortletPreferences( } } - /** - * method that creates REST API specific PortletPreferences - * */ + /** method that creates REST API specific PortletPreferences */ @Override public PortletPreferences createAPIPortletPreferences( - final HttpServletRequest requestContext, IPortletEntity portletEntity, boolean render, boolean configMode) { + final HttpServletRequest requestContext, + IPortletEntity portletEntity, + boolean render, + boolean configMode) { final HttpServletRequest containerRequest = requestContext; - if (configMode) { final IPortletDefinitionId portletDefinitionId = portletEntity.getPortletDefinitionId(); return new PortletDefinitionPreferencesImpl( - portletDefinitionRegistry, transactionOperations, portletDefinitionId, render); + portletDefinitionRegistry, transactionOperations, portletDefinitionId, render); } else if (this.isStoreInMemory(containerRequest)) { final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId(); return new GuestPortletEntityPreferencesAPIImpl( - requestContext, - portletEntityRegistry, - portletDefinitionRegistry, - portletEntityId, - render); + requestContext, + portletEntityRegistry, + portletDefinitionRegistry, + portletEntityId, + render); } else { final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId(); return new PortletEntityPreferencesAPIImpl( - requestContext, - portletEntityRegistry, - portletDefinitionRegistry, - transactionOperations, - portletEntityId); + requestContext, + portletEntityRegistry, + portletDefinitionRegistry, + transactionOperations, + portletEntityId); } } - protected boolean isStoreInMemory(HttpServletRequest containerRequest) { if (this.storeGuestPreferencesInMemory && isGuestUser(containerRequest)) { return true; From 0b6a8898b318522545389651ba55c28941d33c83 Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Fri, 5 Apr 2019 17:48:09 -0600 Subject: [PATCH 07/11] #1659 getting missed code spec --- .../rest/PortletPrefsRESTController.java | 27 +++++++++---------- .../rest/PortletPrefsRESTControllerTest.java | 7 ++--- .../services/PortletPreferencesFactory.java | 1 - .../PortletPreferencesFactoryImpl.java | 1 - 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index 4349e775a0c..c2713dd70cc 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -1,6 +1,8 @@ package org.apereo.portal.rest; - +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.annotations.ApiParam; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -8,17 +10,12 @@ import java.util.Iterator; import java.util.List; import java.util.Map; - import javax.portlet.PortletPreferences; import javax.portlet.ReadOnlyException; import javax.portlet.WindowState; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.annotations.ApiParam; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; @@ -144,10 +141,10 @@ public ResponseEntity getEntity( logger.info(error); return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -199,7 +196,7 @@ public ResponseEntity getCompositePrefs( return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { @@ -256,11 +253,11 @@ public ResponseEntity getEntityOnlyPrefs( return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -364,7 +361,7 @@ public ResponseEntity getDefinitionPrefs( .body(mapper.writeValueAsString(prefs.getMap())); } catch (Exception e) { - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -433,7 +430,7 @@ public ResponseEntity getDefinitionOnlyPrefs( .body(mapper.writeValueAsString(prefMap(prefs))); } catch (Exception e) { - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -529,7 +526,7 @@ public ResponseEntity putDefinitionPrefs( return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (IOException e) { @@ -597,7 +594,7 @@ public ResponseEntity putEntityPrefs( return new ResponseEntity<>(error, HttpStatus.FORBIDDEN); } - logger.error(e.getMessage(),e); + logger.error(e.getMessage(), e); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } catch (IOException e) { diff --git a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java index 35d128bf16a..20f0a948dab 100644 --- a/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java +++ b/uPortal-api/uPortal-api-rest/src/test/java/org/apereo/portal/rest/PortletPrefsRESTControllerTest.java @@ -7,17 +7,14 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; - +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.HashMap; import java.util.Map; - import javax.portlet.PortletPreferences; import javax.portlet.ReadOnlyException; import javax.portlet.WindowState; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apereo.portal.portlet.container.services.PortletPreferencesFactory; import org.apereo.portal.portlet.dao.IPortletDefinitionDao; import org.apereo.portal.portlet.dao.jpa.PortletDefinitionImpl; diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java index c6f6c899e62..b9d775b2c06 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactory.java @@ -16,7 +16,6 @@ import javax.portlet.PortletPreferences; import javax.servlet.http.HttpServletRequest; - import org.apache.pluto.container.PortletRequestContext; import org.apereo.portal.portlet.om.IPortletEntity; diff --git a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java index 0de741d3daf..ed527f9a5c3 100644 --- a/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java +++ b/uPortal-rendering/src/main/java/org/apereo/portal/portlet/container/services/PortletPreferencesFactoryImpl.java @@ -16,7 +16,6 @@ import javax.portlet.PortletPreferences; import javax.servlet.http.HttpServletRequest; - import org.apache.pluto.container.PortletRequestContext; import org.apache.pluto.container.PortletWindow; import org.apereo.portal.jpa.BasePortalJpaDao; From 4962b3203dfe04b9b003e0c78ea95df56dedbb94 Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Fri, 5 Apr 2019 18:28:02 -0600 Subject: [PATCH 08/11] #1659 updated API.md with necessary information --- docs/developer/other/API.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/developer/other/API.md b/docs/developer/other/API.md index 8998b02595e..6b4d7de7bee 100644 --- a/docs/developer/other/API.md +++ b/docs/developer/other/API.md @@ -115,7 +115,10 @@ Example response: These endpoints provide a way for soffits and web-components to access and store custom preferences for individual soffits and web-components. There are several different endpoints for the various ways to store and retrieve these preferences. This is an overview of the general uses. See the Swagger UI documentation -for specifics of each endpoint. +for specifics of each endpoint. + +NOTE: to use any of these endpoints the soffit/web-component must know its own fname as registered in uPortal. +This is essential to the functionality of the endpoints ####Regular preferences vs default preferences From 9ad7ca6ebab74b40b1b84c2a9e230c77ad179a5e Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Wed, 24 Apr 2019 19:21:40 -0600 Subject: [PATCH 09/11] resolving comment --- docs/developer/other/API.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/developer/other/API.md b/docs/developer/other/API.md index 6b4d7de7bee..081ac65c567 100644 --- a/docs/developer/other/API.md +++ b/docs/developer/other/API.md @@ -106,7 +106,7 @@ Example response: } } ``` -###Portlet Preferences +### Portlet Preferences `/api/prefs/{task}` @@ -120,7 +120,7 @@ for specifics of each endpoint. NOTE: to use any of these endpoints the soffit/web-component must know its own fname as registered in uPortal. This is essential to the functionality of the endpoints -####Regular preferences vs default preferences +#### Regular preferences vs default preferences To access the regular (entity) preferences of an individual soffit or web-component use the endpoints with only prefs in the name. These will return or store the preferences associated with the specific user for the @@ -139,7 +139,7 @@ the internal call to the preferences for portlets. NOTE: These calls will be rejected if attempted by any user without administrative privileges. This prevents unauthorized meddling of default preferences since these calls can allow one to overwrite readonly preferences. -####Only calls +#### Only calls There are two calls with only in their names. These are used to single out the preferences that are only associated with the called level without any extra. These are included because the normal retrieve calls return every preference From 6a306bcc23cb405512858438f53743ce2e4136bf Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Wed, 24 Apr 2019 19:24:29 -0600 Subject: [PATCH 10/11] update PortletPrefsRESTController.java to resolve conversation --- .../java/org/apereo/portal/rest/PortletPrefsRESTController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index c2713dd70cc..599409da080 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -463,7 +463,6 @@ private Map prefMap(List prefs) { * given portlet/soffit/webcomponent in uPortal to access these. Will return a 403 or 404 * otherwise */ - // need to be an administrator @RequestMapping(value = "/prefs/putdefinitionprefs", method = RequestMethod.PUT) public ResponseEntity putDefinitionPrefs( HttpServletRequest request, From c8f52842c7ab5db968e440d5163cd7a6fbe7101b Mon Sep 17 00:00:00 2001 From: Jacobus Crawford Date: Wed, 24 Apr 2019 19:32:46 -0600 Subject: [PATCH 11/11] Update PortletPrefsRESTController.java to resolve problem --- .../java/org/apereo/portal/rest/PortletPrefsRESTController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java index 599409da080..74522469bcd 100644 --- a/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java +++ b/uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/rest/PortletPrefsRESTController.java @@ -304,7 +304,6 @@ private Map getEntityOnly( * administrator or have configuration rights for the given portlet/soffit/webcomponent in * uPortal to access these. Will return a 403 or 404 otherwise */ - // must be authenticated and a portal administrator @RequestMapping(value = "/prefs/getdefinitionprefs/{fname}", method = RequestMethod.GET) public ResponseEntity getDefinitionPrefs( HttpServletRequest request, @@ -379,7 +378,6 @@ public ResponseEntity getDefinitionPrefs( * configuration rights for the given portlet/soffit/webcomponent in uPortal to access these. * Will return a 403 or 404 otherwise */ - // must be authenticated and a portal administrator @RequestMapping(value = "/prefs/getdefinitiononlyprefs/{fname}", method = RequestMethod.GET) public ResponseEntity getDefinitionOnlyPrefs( HttpServletRequest request,