View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.adminui.endpoint;
23  
24  import static org.opencastproject.adminui.endpoint.EndpointUtil.addRequestFiltersToQuery;
25  import static org.opencastproject.adminui.endpoint.EndpointUtil.generateJSONObject;
26  
27  import org.opencastproject.adminui.exception.JsonCreationException;
28  import org.opencastproject.index.service.resources.list.query.AclsListQuery;
29  import org.opencastproject.index.service.resources.list.query.AgentsListQuery;
30  import org.opencastproject.index.service.resources.list.query.EventListQuery;
31  import org.opencastproject.index.service.resources.list.query.GroupsListQuery;
32  import org.opencastproject.index.service.resources.list.query.JobsListQuery;
33  import org.opencastproject.index.service.resources.list.query.SeriesListQuery;
34  import org.opencastproject.index.service.resources.list.query.ServersListQuery;
35  import org.opencastproject.index.service.resources.list.query.ServicesListQuery;
36  import org.opencastproject.index.service.resources.list.query.ThemesListQuery;
37  import org.opencastproject.index.service.resources.list.query.UsersListQuery;
38  import org.opencastproject.index.service.util.JSONUtils;
39  import org.opencastproject.index.service.util.RestUtils;
40  import org.opencastproject.list.api.ListProviderException;
41  import org.opencastproject.list.api.ListProvidersService;
42  import org.opencastproject.list.api.ResourceListQuery;
43  import org.opencastproject.list.impl.ListProviderNotFoundException;
44  import org.opencastproject.list.impl.ResourceListQueryImpl;
45  import org.opencastproject.security.api.SecurityService;
46  import org.opencastproject.util.doc.rest.RestParameter;
47  import org.opencastproject.util.doc.rest.RestQuery;
48  import org.opencastproject.util.doc.rest.RestResponse;
49  import org.opencastproject.util.doc.rest.RestService;
50  
51  import org.apache.commons.lang3.StringUtils;
52  import org.json.simple.JSONArray;
53  import org.json.simple.JSONObject;
54  import org.osgi.framework.BundleContext;
55  import org.osgi.service.component.annotations.Component;
56  import org.osgi.service.component.annotations.Reference;
57  import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
58  import org.slf4j.Logger;
59  import org.slf4j.LoggerFactory;
60  
61  import java.util.Map;
62  
63  import javax.servlet.http.HttpServletResponse;
64  import javax.ws.rs.GET;
65  import javax.ws.rs.Path;
66  import javax.ws.rs.PathParam;
67  import javax.ws.rs.Produces;
68  import javax.ws.rs.QueryParam;
69  import javax.ws.rs.core.Context;
70  import javax.ws.rs.core.HttpHeaders;
71  import javax.ws.rs.core.MediaType;
72  import javax.ws.rs.core.Response;
73  
74  @Path("/admin-ng/resources")
75  @RestService(name = "ResourceListsProviders", title = "Admin UI - Resources List",
76    abstractText = "This service provides key-value list from different resources to use in the admin UI.",
77    notes = { "This service offers access to list providers for the admin UI.",
78              "<strong>Important:</strong> "
79                + "<em>This service is for exclusive use by the module admin-ui. Its API might change "
80                + "anytime without prior notice. Any dependencies other than the admin UI will be strictly ignored. "
81                + "DO NOT use this for integration of third-party applications.<em>"})
82  @Component(
83          immediate = true,
84          service = ListProvidersEndpoint.class,
85          property = {
86                  "service.description=Admin UI - Resource List Provider Endpoint",
87                  "opencast.service.type=org.opencastproject.adminui.ListProvidersEndpoint",
88                  "opencast.service.path=/admin-ng/resources",
89          }
90  )
91  @JaxrsResource
92  public class ListProvidersEndpoint {
93  
94    private static final Logger logger = LoggerFactory.getLogger(ListProvidersEndpoint.class);
95  
96    public static final Response UNAUTHORIZED = Response.status(Response.Status.UNAUTHORIZED).build();
97    public static final Response NOT_FOUND = Response.status(Response.Status.NOT_FOUND).build();
98    public static final Response SERVER_ERROR = Response.serverError().build();
99    public static final Response NO_CONTENT = Response.noContent().build();
100 
101   private SecurityService securityService;
102   private ListProvidersService listProvidersService;
103   private SeriesEndpoint seriesEndpoint;
104 
105   /** This regex is used to reduce the users in the filter selectbox.
106    * The filter is located in the top right corner in the admin ui. */
107   private static final String PROP_KEY_USER_FILTER_REGEX = "org.opencastproject.adminui.filter.user.regex";
108   private static final String PROP_KEY_USER_FILTER_REGEX_DEFAULT = ".*";
109 
110   protected void activate(BundleContext bundleContext) {
111     logger.info("Activate list provider service");
112     JSONUtils.setUserRegex(StringUtils.defaultIfBlank(
113             bundleContext.getProperty(PROP_KEY_USER_FILTER_REGEX),
114             PROP_KEY_USER_FILTER_REGEX_DEFAULT));
115   }
116 
117   /** OSGi callback for series services. */
118   @Reference
119   public void setListProvidersService(ListProvidersService listProvidersService) {
120     this.listProvidersService = listProvidersService;
121   }
122 
123   /** OSGi callback for sercurity service. */
124   @Reference
125   public void setSecurityService(SecurityService securitySerivce) {
126     this.securityService = securitySerivce;
127   }
128 
129   /** OSGi callback for series end point. */
130   @Reference
131   public void setSeriesEndpoint(SeriesEndpoint seriesEndpoint) {
132     this.seriesEndpoint = seriesEndpoint;
133   }
134 
135   @GET
136   @Path("{source}.json")
137   @Produces(MediaType.APPLICATION_JSON)
138   @RestQuery(name = "list", description = "Provides key-value list from the given source", pathParameters = { @RestParameter(name = "source", description = "The source for the key-value list", isRequired = true, type = RestParameter.Type.STRING) }, restParameters = {
139           @RestParameter(description = "The maximum number of items to return per page", isRequired = false, name = "limit", type = RestParameter.Type.INTEGER),
140           @RestParameter(description = "The offset", isRequired = false, name = "offset", type = RestParameter.Type.INTEGER),
141           @RestParameter(description = "Filters", isRequired = false, name = "filter", type = RestParameter.Type.STRING) }, responses = { @RestResponse(description = "Returns the key-value list for the given source.", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "")
142   public Response getList(@PathParam("source") final String source, @QueryParam("limit") final int limit,
143           @QueryParam("filter") final String filter, @QueryParam("offset") final int offset,
144           @Context HttpHeaders headers) {
145 
146     ResourceListQueryImpl query = new ResourceListQueryImpl();
147     query.setLimit(limit);
148     query.setOffset(offset);
149     addRequestFiltersToQuery(filter, query);
150     Map<String, String> autocompleteList;
151     try {
152       autocompleteList = listProvidersService.getList(source, query, false);
153     } catch (ListProviderNotFoundException e) {
154       logger.debug("No list found for {}", source, e);
155       return NOT_FOUND;
156     } catch (ListProviderException e) {
157       logger.error("Server error when getting list from provider {}", source, e);
158       return SERVER_ERROR;
159     }
160 
161     JSONObject jsonList;
162     try {
163       jsonList = generateJSONObject(autocompleteList);
164     } catch (JsonCreationException e) {
165       logger.error("Not able to generate resources list JSON from source {}", source, e);
166       return SERVER_ERROR;
167     }
168 
169     return Response.ok(jsonList.toString()).build();
170   }
171 
172   @GET
173   @Path("components.json")
174   @Produces(MediaType.APPLICATION_JSON)
175   @RestQuery(name = "components", description = "Provides a set of constants lists (right now only eventCommentReasons) for use in the admin UI",
176     responses = { @RestResponse(description = "Returns a set of constants lists (right now only eventCommentReasons) for use in the admin UI",
177     responseCode = HttpServletResponse.SC_OK) }, returnDescription = "")
178   public Response getComponents(@Context HttpHeaders headers) {
179     String[] sources = { "eventCommentReasons" };
180     ResourceListQuery query = new ResourceListQueryImpl();
181 
182     JSONObject list = new JSONObject();
183 
184     for (String source : sources) {
185       if (listProvidersService.hasProvider(source)) {
186         JSONObject subList;
187         try {
188           subList = generateJSONObject(listProvidersService.getList(source, query, true));
189           list.put(source, subList);
190         } catch (JsonCreationException e) {
191           logger.error("Not able to generate resources list JSON from source {}", source, e);
192           return SERVER_ERROR;
193         } catch (ListProviderException e) {
194           logger.error("Not able to get list from provider {}", source, e);
195           return SERVER_ERROR;
196         }
197       } else {
198         return NOT_FOUND;
199       }
200     }
201 
202     return Response.ok(list.toString()).build();
203   }
204 
205   @GET
206   @Path("providers.json")
207   @Produces(MediaType.APPLICATION_JSON)
208   @RestQuery(name = "availableProviders", description = "Provides the list of the available list providers", responses = { @RestResponse(description = "Returns the availables list providers.", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "")
209   public Response getAvailablesProviders(@Context HttpHeaders headers) {
210     JSONArray list = new JSONArray();
211 
212     list.add(listProvidersService.getAvailableProviders());
213 
214     return Response.ok(list.toString()).build();
215   }
216 
217   @GET
218   @Path("{page}/filters.json")
219   @Produces(MediaType.APPLICATION_JSON)
220   @RestQuery(name = "filters", description = "Provides filters for the given page", pathParameters = { @RestParameter(name = "page", description = "The page for which the filters are required", isRequired = true, type = RestParameter.Type.STRING) }, responses = { @RestResponse(description = "Returns the filters for the given page.", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "")
221   public Response getFilters(@PathParam("page") final String page, @Context HttpHeaders headers)
222           throws ListProviderException {
223 
224     ResourceListQuery query;
225 
226     if ("series".equals(page)) {
227       query = new SeriesListQuery();
228     } else if ("events".equals(page)) {
229       query = new EventListQuery();
230     } else if ("jobs".equals(page)) {
231       query = new JobsListQuery();
232     } else if ("recordings".equals(page)) {
233       query = new AgentsListQuery();
234     } else if ("users".equals(page)) {
235       query = new UsersListQuery();
236     } else if ("groups".equals(page)) {
237       query = new GroupsListQuery();
238     } else if ("acls".equals(page)) {
239       query = new AclsListQuery();
240     } else if ("servers".equals(page)) {
241       query = new ServersListQuery();
242     } else if ("services".equals(page)) {
243       query = new ServicesListQuery();
244     } else if ("themes".equals(page)) {
245       query = new ThemesListQuery();
246     } else {
247       logger.debug("No filters defined for the page {}.", page);
248       return NO_CONTENT;
249     }
250 
251     try {
252       if ("events".equals(page) && seriesEndpoint.getOnlySeriesWithWriteAccessEventsFilter()) {
253         Map<String, String> seriesWriteAccess = seriesEndpoint.getUserSeriesByAccess(true);
254         return RestUtils.okJson(JSONUtils.filtersToJSONSeriesWriteAccess(query, listProvidersService,
255                 seriesWriteAccess));
256       } else {
257         return RestUtils.okJson(JSONUtils.filtersToJSON(query, listProvidersService, securityService.getOrganization()));
258       }
259     } catch (ListProviderException e) {
260       logger.error("Not able to get list of options for the filters for the page {}", page, e);
261       return SERVER_ERROR;
262     }
263   }
264 
265 }