001/* 002 * (C) Copyright 2015 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 */ 018 019package org.nuxeo.scim.server.jaxrs; 020 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.List; 024 025import javax.ws.rs.GET; 026import javax.ws.rs.Path; 027import javax.ws.rs.PathParam; 028import javax.ws.rs.Produces; 029import javax.ws.rs.WebApplicationException; 030import javax.ws.rs.core.Context; 031import javax.ws.rs.core.HttpHeaders; 032import javax.ws.rs.core.MediaType; 033import javax.ws.rs.core.Response; 034 035import org.nuxeo.ecm.webengine.model.Template; 036import org.nuxeo.ecm.webengine.model.WebObject; 037import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException; 038import org.nuxeo.ecm.webengine.model.exceptions.WebSecurityException; 039import org.nuxeo.ecm.webengine.model.impl.ModuleRoot; 040 041import com.unboundid.scim.data.AuthenticationScheme; 042import com.unboundid.scim.data.BulkConfig; 043import com.unboundid.scim.data.ChangePasswordConfig; 044import com.unboundid.scim.data.FilterConfig; 045import com.unboundid.scim.data.PatchConfig; 046import com.unboundid.scim.data.ServiceProviderConfig; 047import com.unboundid.scim.data.SortConfig; 048import com.unboundid.scim.data.XmlDataFormatConfig; 049import com.unboundid.scim.schema.CoreSchema; 050 051/** 052 * The root entry for the WebEngine module. 053 * 054 * @author tiry 055 * @since 7.4 056 */ 057@Path("/scim/v1") 058@Produces("text/html;charset=UTF-8") 059@WebObject(type = "SCIMRoot") 060public class SCIMRoot extends ModuleRoot { 061 062 @Path("/Users") 063 public Object doGetUsersResource() { 064 return newObject("users"); 065 } 066 067 @Path("/Users.json") 068 public Object doGetUsersJsonResource() { 069 return newObject("users", MediaType.APPLICATION_JSON_TYPE); 070 } 071 072 @Path("/Users.xml") 073 public Object doGetUsersXmlResource() { 074 return newObject("users", MediaType.APPLICATION_XML_TYPE); 075 } 076 077 @Path("/Groups") 078 public Object doGetGroups() { 079 return newObject("groups"); 080 } 081 082 @Path("/Groups.json") 083 public Object doGetGroupsAsJson() { 084 return newObject("groups", MediaType.APPLICATION_JSON_TYPE); 085 } 086 087 @Path("/Groups.xml") 088 public Object doGetGroupsAsJXml() { 089 return newObject("groups", MediaType.APPLICATION_XML_TYPE); 090 } 091 092 protected Object getSchema(String schemaName, String format) { 093 094 String viewName = "user-schema"; 095 096 if (schemaName.equalsIgnoreCase("users")) { 097 viewName = "user-schema"; 098 } else if (schemaName.equalsIgnoreCase("groups")) { 099 viewName = "group-schema"; 100 } 101 102 Template tmpl = getView(viewName + "." + format); 103 return tmpl; 104 } 105 106 @GET 107 @Path("/Schemas/{schemaName}") 108 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" }) 109 public Object getSchema(@PathParam("schemaName") String schemaName, @Context HttpHeaders headers) { 110 111 List<String> accepted = headers.getRequestHeader("Accept"); 112 113 if (accepted.contains(MediaType.APPLICATION_JSON)) { 114 return getSchema(schemaName, "json"); 115 } 116 return getSchema(schemaName, "xml"); 117 } 118 119 @GET 120 @Path("/Schemas/{schemaName}.json") 121 @Produces({ MediaType.APPLICATION_JSON }) 122 public Object getSchemaAsJson(@PathParam("schemaName") String schemaName) { 123 return getSchema(schemaName, "json"); 124 } 125 126 @GET 127 @Path("/Schemas/{schemaName}.xml") 128 @Produces({ MediaType.APPLICATION_XML }) 129 public Object getSchemaAsXml(@PathParam("schemaName") String schemaName) { 130 return getSchema(schemaName, "xml"); 131 } 132 133 @GET 134 @Path("/ServiceProviderConfigs") 135 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" }) 136 public ServiceProviderConfig getConfig() { 137 138 ServiceProviderConfig config = new ServiceProviderConfig(CoreSchema.SERVICE_PROVIDER_CONFIG_SCHEMA_DESCRIPTOR); 139 140 config.setId("Nuxeo"); 141 config.setExternalId("Nuxeo"); 142 143 // auth config 144 Collection<AuthenticationScheme> authSchemes = new ArrayList<>(); 145 authSchemes.add(AuthenticationScheme.createBasic(true)); 146 config.setAuthenticationSchemes(authSchemes); 147 148 // Filter 149 FilterConfig filterConfig = new FilterConfig(true, 1000); 150 config.setFilterConfig(filterConfig); 151 152 // Bulk Config : for now 153 BulkConfig bulkConfig = new BulkConfig(false, 0, 0); 154 config.setBulkConfig(bulkConfig); 155 156 // Pwd 157 ChangePasswordConfig changePasswordConfig = new ChangePasswordConfig(false); 158 config.setChangePasswordConfig(changePasswordConfig); 159 160 config.setPatchConfig(new PatchConfig(false)); 161 162 config.setSortConfig(new SortConfig(true)); 163 164 config.setXmlDataFormatConfig(new XmlDataFormatConfig(true)); 165 166 return config; 167 } 168 169 @Override 170 public Object handleError(WebApplicationException e) { 171 if (e instanceof WebSecurityException) { 172 return Response.status(401).entity("not authorized").type("text/plain").build(); 173 } else if (e instanceof WebResourceNotFoundException) { 174 return Response.status(404).entity(e.getMessage()).type("text/plain").build(); 175 } else { 176 return super.handleError(e); 177 } 178 } 179}