001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 */ 020 021package org.nuxeo.scim.server.jaxrs; 022 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.List; 026 027import javax.ws.rs.GET; 028import javax.ws.rs.Path; 029import javax.ws.rs.PathParam; 030import javax.ws.rs.Produces; 031import javax.ws.rs.core.Context; 032import javax.ws.rs.core.HttpHeaders; 033import javax.ws.rs.core.MediaType; 034import javax.ws.rs.core.Response; 035 036import org.nuxeo.ecm.webengine.model.Template; 037import org.nuxeo.ecm.webengine.model.WebObject; 038import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException; 039import org.nuxeo.ecm.webengine.model.exceptions.WebSecurityException; 040import org.nuxeo.ecm.webengine.model.impl.ModuleRoot; 041 042import com.unboundid.scim.data.AuthenticationScheme; 043import com.unboundid.scim.data.BulkConfig; 044import com.unboundid.scim.data.ChangePasswordConfig; 045import com.unboundid.scim.data.FilterConfig; 046import com.unboundid.scim.data.PatchConfig; 047import com.unboundid.scim.data.ServiceProviderConfig; 048import com.unboundid.scim.data.SortConfig; 049import com.unboundid.scim.data.XmlDataFormatConfig; 050import com.unboundid.scim.schema.CoreSchema; 051 052/** 053 * The root entry for the WebEngine module. 054 * 055 * @author tiry 056 * @since 7.4 057 */ 058@Path("/scim/v1") 059@Produces("text/html;charset=UTF-8") 060@WebObject(type = "SCIMRoot") 061public class SCIMRoot extends ModuleRoot { 062 063 @Path("/Users") 064 public Object doGetUsersResource() { 065 return newObject("users"); 066 } 067 068 @Path("/Users.json") 069 public Object doGetUsersJsonResource() { 070 return newObject("users", MediaType.APPLICATION_JSON_TYPE); 071 } 072 073 @Path("/Users.xml") 074 public Object doGetUsersXmlResource() { 075 return newObject("users", MediaType.APPLICATION_XML_TYPE); 076 } 077 078 @Path("/Groups") 079 public Object doGetGroups() { 080 return newObject("groups"); 081 } 082 083 @Path("/Groups.json") 084 public Object doGetGroupsAsJson() { 085 return newObject("groups", MediaType.APPLICATION_JSON_TYPE); 086 } 087 088 @Path("/Groups.xml") 089 public Object doGetGroupsAsJXml() { 090 return newObject("groups", MediaType.APPLICATION_XML_TYPE); 091 } 092 093 protected Object getSchema(String schemaName, String format) { 094 095 String viewName = "user-schema"; 096 097 if (schemaName.equalsIgnoreCase("users")) { 098 viewName = "user-schema"; 099 } else if (schemaName.equalsIgnoreCase("groups")) { 100 viewName = "group-schema"; 101 } 102 103 Template tmpl = getView(viewName + "." + format); 104 return tmpl; 105 } 106 107 @GET 108 @Path("/Schemas/{schemaName}") 109 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" }) 110 public Object getSchema(@PathParam("schemaName") String schemaName, @Context HttpHeaders headers) { 111 112 List<String> accepted = headers.getRequestHeader("Accept"); 113 114 if (accepted.contains(MediaType.APPLICATION_JSON)) { 115 return getSchema(schemaName, "json"); 116 } 117 return getSchema(schemaName, "xml"); 118 } 119 120 @GET 121 @Path("/Schemas/{schemaName}.json") 122 @Produces({ MediaType.APPLICATION_JSON }) 123 public Object getSchemaAsJson(@PathParam("schemaName") String schemaName) { 124 return getSchema(schemaName, "json"); 125 } 126 127 @GET 128 @Path("/Schemas/{schemaName}.xml") 129 @Produces({ MediaType.APPLICATION_XML }) 130 public Object getSchemaAsXml(@PathParam("schemaName") String schemaName) { 131 return getSchema(schemaName, "xml"); 132 } 133 134 @GET 135 @Path("/ServiceProviderConfigs") 136 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" }) 137 public ServiceProviderConfig getConfig() { 138 139 ServiceProviderConfig config = new ServiceProviderConfig(CoreSchema.SERVICE_PROVIDER_CONFIG_SCHEMA_DESCRIPTOR); 140 141 config.setId("Nuxeo"); 142 config.setExternalId("Nuxeo"); 143 144 // auth config 145 Collection<AuthenticationScheme> authSchemes = new ArrayList<>(); 146 authSchemes.add(AuthenticationScheme.createBasic(true)); 147 config.setAuthenticationSchemes(authSchemes); 148 149 // Filter 150 FilterConfig filterConfig = new FilterConfig(true, 1000); 151 config.setFilterConfig(filterConfig); 152 153 // Bulk Config : for now 154 BulkConfig bulkConfig = new BulkConfig(false, 0, 0); 155 config.setBulkConfig(bulkConfig); 156 157 // Pwd 158 ChangePasswordConfig changePasswordConfig = new ChangePasswordConfig(false); 159 config.setChangePasswordConfig(changePasswordConfig); 160 161 config.setPatchConfig(new PatchConfig(false)); 162 163 config.setSortConfig(new SortConfig(true)); 164 165 config.setXmlDataFormatConfig(new XmlDataFormatConfig(true)); 166 167 return config; 168 } 169 170 @Override 171 public Object handleError(Throwable t) { 172 if (t instanceof WebSecurityException) { 173 return Response.status(401).entity("not authorized").type("text/plain").build(); 174 } else if (t instanceof WebResourceNotFoundException) { 175 return Response.status(404).entity(t.getMessage()).type("text/plain").build(); 176 } else { 177 return super.handleError(t); 178 } 179 } 180}