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}