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.WebApplicationException;
032import javax.ws.rs.core.Context;
033import javax.ws.rs.core.HttpHeaders;
034import javax.ws.rs.core.MediaType;
035import javax.ws.rs.core.Response;
036
037import org.nuxeo.ecm.webengine.model.Template;
038import org.nuxeo.ecm.webengine.model.WebObject;
039import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException;
040import org.nuxeo.ecm.webengine.model.exceptions.WebSecurityException;
041import org.nuxeo.ecm.webengine.model.impl.ModuleRoot;
042
043import com.unboundid.scim.data.AuthenticationScheme;
044import com.unboundid.scim.data.BulkConfig;
045import com.unboundid.scim.data.ChangePasswordConfig;
046import com.unboundid.scim.data.FilterConfig;
047import com.unboundid.scim.data.PatchConfig;
048import com.unboundid.scim.data.ServiceProviderConfig;
049import com.unboundid.scim.data.SortConfig;
050import com.unboundid.scim.data.XmlDataFormatConfig;
051import com.unboundid.scim.schema.CoreSchema;
052
053/**
054 * The root entry for the WebEngine module.
055 *
056 * @author tiry
057 * @since 7.4
058 */
059@Path("/scim/v1")
060@Produces("text/html;charset=UTF-8")
061@WebObject(type = "SCIMRoot")
062public class SCIMRoot extends ModuleRoot {
063
064    @Path("/Users")
065    public Object doGetUsersResource() {
066        return newObject("users");
067    }
068
069    @Path("/Users.json")
070    public Object doGetUsersJsonResource() {
071        return newObject("users", MediaType.APPLICATION_JSON_TYPE);
072    }
073
074    @Path("/Users.xml")
075    public Object doGetUsersXmlResource() {
076        return newObject("users", MediaType.APPLICATION_XML_TYPE);
077    }
078
079    @Path("/Groups")
080    public Object doGetGroups() {
081        return newObject("groups");
082    }
083
084    @Path("/Groups.json")
085    public Object doGetGroupsAsJson() {
086        return newObject("groups", MediaType.APPLICATION_JSON_TYPE);
087    }
088
089    @Path("/Groups.xml")
090    public Object doGetGroupsAsJXml() {
091        return newObject("groups", MediaType.APPLICATION_XML_TYPE);
092    }
093
094    protected Object getSchema(String schemaName, String format) {
095
096        String viewName = "user-schema";
097
098        if (schemaName.equalsIgnoreCase("users")) {
099            viewName = "user-schema";
100        } else if (schemaName.equalsIgnoreCase("groups")) {
101            viewName = "group-schema";
102        }
103
104        Template tmpl = getView(viewName + "." + format);
105        return tmpl;
106    }
107
108    @GET
109    @Path("/Schemas/{schemaName}")
110    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" })
111    public Object getSchema(@PathParam("schemaName") String schemaName, @Context HttpHeaders headers) {
112
113        List<String> accepted = headers.getRequestHeader("Accept");
114
115        if (accepted.contains(MediaType.APPLICATION_JSON)) {
116            return getSchema(schemaName, "json");
117        }
118        return getSchema(schemaName, "xml");
119    }
120
121    @GET
122    @Path("/Schemas/{schemaName}.json")
123    @Produces({ MediaType.APPLICATION_JSON })
124    public Object getSchemaAsJson(@PathParam("schemaName") String schemaName) {
125        return getSchema(schemaName, "json");
126    }
127
128    @GET
129    @Path("/Schemas/{schemaName}.xml")
130    @Produces({ MediaType.APPLICATION_XML })
131    public Object getSchemaAsXml(@PathParam("schemaName") String schemaName) {
132        return getSchema(schemaName, "xml");
133    }
134
135    @GET
136    @Path("/ServiceProviderConfigs")
137    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" })
138    public ServiceProviderConfig getConfig() {
139
140        ServiceProviderConfig config = new ServiceProviderConfig(CoreSchema.SERVICE_PROVIDER_CONFIG_SCHEMA_DESCRIPTOR);
141
142        config.setId("Nuxeo");
143        config.setExternalId("Nuxeo");
144
145        // auth config
146        Collection<AuthenticationScheme> authSchemes = new ArrayList<>();
147        authSchemes.add(AuthenticationScheme.createBasic(true));
148        config.setAuthenticationSchemes(authSchemes);
149
150        // Filter
151        FilterConfig filterConfig = new FilterConfig(true, 1000);
152        config.setFilterConfig(filterConfig);
153
154        // Bulk Config : for now
155        BulkConfig bulkConfig = new BulkConfig(false, 0, 0);
156        config.setBulkConfig(bulkConfig);
157
158        // Pwd
159        ChangePasswordConfig changePasswordConfig = new ChangePasswordConfig(false);
160        config.setChangePasswordConfig(changePasswordConfig);
161
162        config.setPatchConfig(new PatchConfig(false));
163
164        config.setSortConfig(new SortConfig(true));
165
166        config.setXmlDataFormatConfig(new XmlDataFormatConfig(true));
167
168        return config;
169    }
170
171    @Override
172    public Object handleError(WebApplicationException e) {
173        if (e instanceof WebSecurityException) {
174            return Response.status(401).entity("not authorized").type("text/plain").build();
175        } else if (e instanceof WebResourceNotFoundException) {
176            return Response.status(404).entity(e.getMessage()).type("text/plain").build();
177        } else {
178            return super.handleError(e);
179        }
180    }
181}