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(
76      name = "ResourceListsProviders",
77      title = "Admin UI - Resources List",
78      abstractText = "This service provides key-value list from different resources to use in the admin UI.",
79      notes = { "This service offers access to list providers for the admin UI.",
80                "<strong>Important:</strong> "
81                  + "<em>This service is for exclusive use by the module admin-ui. Its API might change "
82                  + "anytime without prior notice. Any dependencies other than the admin UI will be strictly ignored. "
83                  + "DO NOT use this for integration of third-party applications.<em>"})
84  @Component(
85      immediate = true,
86      service = ListProvidersEndpoint.class,
87      property = {
88          "service.description=Admin UI - Resource List Provider Endpoint",
89          "opencast.service.type=org.opencastproject.adminui.ListProvidersEndpoint",
90          "opencast.service.path=/admin-ng/resources",
91      }
92  )
93  @JaxrsResource
94  public class ListProvidersEndpoint {
95  
96    private static final Logger logger = LoggerFactory.getLogger(ListProvidersEndpoint.class);
97  
98    public static final Response UNAUTHORIZED = Response.status(Response.Status.UNAUTHORIZED).build();
99    public static final Response NOT_FOUND = Response.status(Response.Status.NOT_FOUND).build();
100   public static final Response SERVER_ERROR = Response.serverError().build();
101   public static final Response NO_CONTENT = Response.noContent().build();
102 
103   private SecurityService securityService;
104   private ListProvidersService listProvidersService;
105   private SeriesEndpoint seriesEndpoint;
106 
107   /** This regex is used to reduce the users in the filter selectbox.
108    * The filter is located in the top right corner in the admin ui. */
109   private static final String PROP_KEY_USER_FILTER_REGEX = "org.opencastproject.adminui.filter.user.regex";
110   private static final String PROP_KEY_USER_FILTER_REGEX_DEFAULT = ".*";
111 
112   protected void activate(BundleContext bundleContext) {
113     logger.info("Activate list provider service");
114     JSONUtils.setUserRegex(StringUtils.defaultIfBlank(
115             bundleContext.getProperty(PROP_KEY_USER_FILTER_REGEX),
116             PROP_KEY_USER_FILTER_REGEX_DEFAULT));
117   }
118 
119   /** OSGi callback for series services. */
120   @Reference
121   public void setListProvidersService(ListProvidersService listProvidersService) {
122     this.listProvidersService = listProvidersService;
123   }
124 
125   /** OSGi callback for sercurity service. */
126   @Reference
127   public void setSecurityService(SecurityService securitySerivce) {
128     this.securityService = securitySerivce;
129   }
130 
131   /** OSGi callback for series end point. */
132   @Reference
133   public void setSeriesEndpoint(SeriesEndpoint seriesEndpoint) {
134     this.seriesEndpoint = seriesEndpoint;
135   }
136 
137   @GET
138   @Path("{source}.json")
139   @Produces(MediaType.APPLICATION_JSON)
140   @RestQuery(
141       name = "list",
142       description = "Provides key-value list from the given source",
143       pathParameters = {
144           @RestParameter(name = "source", description = "The source for the key-value list", isRequired = true,
145               type = RestParameter.Type.STRING)
146       },
147       restParameters = {
148           @RestParameter(description = "The maximum number of items to return per page", isRequired = false,
149               name = "limit", type = RestParameter.Type.INTEGER),
150           @RestParameter(description = "The offset", isRequired = false, name = "offset",
151               type = RestParameter.Type.INTEGER),
152           @RestParameter(description = "Filters", isRequired = false, name = "filter",
153               type = RestParameter.Type.STRING)
154       },
155       responses = {
156           @RestResponse(description = "Returns the key-value list for the given source.",
157               responseCode = HttpServletResponse.SC_OK)
158       },
159       returnDescription = "")
160   public Response getList(@PathParam("source") final String source, @QueryParam("limit") final int limit,
161       @QueryParam("filter") final String filter, @QueryParam("offset") final int offset,
162       @Context HttpHeaders headers) {
163 
164     ResourceListQueryImpl query = new ResourceListQueryImpl();
165     query.setLimit(limit);
166     query.setOffset(offset);
167     addRequestFiltersToQuery(filter, query);
168     Map<String, String> autocompleteList;
169     try {
170       autocompleteList = listProvidersService.getList(source, query, false);
171     } catch (ListProviderNotFoundException e) {
172       logger.debug("No list found for {}", source, e);
173       return NOT_FOUND;
174     } catch (ListProviderException e) {
175       logger.error("Server error when getting list from provider {}", source, e);
176       return SERVER_ERROR;
177     }
178 
179     JSONObject jsonList;
180     try {
181       jsonList = generateJSONObject(autocompleteList);
182     } catch (JsonCreationException e) {
183       logger.error("Not able to generate resources list JSON from source {}", source, e);
184       return SERVER_ERROR;
185     }
186 
187     return Response.ok(jsonList.toString()).build();
188   }
189 
190   @GET
191   @Path("components.json")
192   @Produces(MediaType.APPLICATION_JSON)
193   @RestQuery(
194       name = "components",
195       description = "Provides a set of constants lists (right now only eventCommentReasons) for use in the admin UI",
196       responses = {
197           @RestResponse(description = "Returns a set of constants lists (right now only eventCommentReasons) for use "
198               + "in the admin UI", responseCode = HttpServletResponse.SC_OK)
199       },
200       returnDescription = "")
201   public Response getComponents(@Context HttpHeaders headers) {
202     String[] sources = { "eventCommentReasons" };
203     ResourceListQuery query = new ResourceListQueryImpl();
204 
205     JSONObject list = new JSONObject();
206 
207     for (String source : sources) {
208       if (listProvidersService.hasProvider(source)) {
209         JSONObject subList;
210         try {
211           subList = generateJSONObject(listProvidersService.getList(source, query, true));
212           list.put(source, subList);
213         } catch (JsonCreationException e) {
214           logger.error("Not able to generate resources list JSON from source {}", source, e);
215           return SERVER_ERROR;
216         } catch (ListProviderException e) {
217           logger.error("Not able to get list from provider {}", source, e);
218           return SERVER_ERROR;
219         }
220       } else {
221         return NOT_FOUND;
222       }
223     }
224 
225     return Response.ok(list.toString()).build();
226   }
227 
228   @GET
229   @Path("providers.json")
230   @Produces(MediaType.APPLICATION_JSON)
231   @RestQuery(
232       name = "availableProviders",
233       description = "Provides the list of the available list providers",
234       responses = {
235           @RestResponse(description = "Returns the availables list providers.",
236               responseCode = HttpServletResponse.SC_OK)
237       },
238       returnDescription = "")
239   public Response getAvailablesProviders(@Context HttpHeaders headers) {
240     JSONArray list = new JSONArray();
241 
242     list.add(listProvidersService.getAvailableProviders());
243 
244     return Response.ok(list.toString()).build();
245   }
246 
247   @GET
248   @Path("{page}/filters.json")
249   @Produces(MediaType.APPLICATION_JSON)
250   @RestQuery(
251       name = "filters",
252       description = "Provides filters for the given page",
253       pathParameters = {
254           @RestParameter(name = "page", description = "The page for which the filters are required", isRequired = true,
255               type = RestParameter.Type.STRING)
256       },
257       responses = {
258           @RestResponse(description = "Returns the filters for the given page.",
259               responseCode = HttpServletResponse.SC_OK)
260       },
261       returnDescription = "")
262   public Response getFilters(@PathParam("page") final String page, @Context HttpHeaders headers)
263           throws ListProviderException {
264 
265     ResourceListQuery query;
266 
267     if ("series".equals(page)) {
268       query = new SeriesListQuery();
269     } else if ("events".equals(page)) {
270       query = new EventListQuery();
271     } else if ("jobs".equals(page)) {
272       query = new JobsListQuery();
273     } else if ("recordings".equals(page)) {
274       query = new AgentsListQuery();
275     } else if ("users".equals(page)) {
276       query = new UsersListQuery();
277     } else if ("groups".equals(page)) {
278       query = new GroupsListQuery();
279     } else if ("acls".equals(page)) {
280       query = new AclsListQuery();
281     } else if ("servers".equals(page)) {
282       query = new ServersListQuery();
283     } else if ("services".equals(page)) {
284       query = new ServicesListQuery();
285     } else if ("themes".equals(page)) {
286       query = new ThemesListQuery();
287     } else {
288       logger.debug("No filters defined for the page {}.", page);
289       return NO_CONTENT;
290     }
291 
292     try {
293       if ("events".equals(page) && seriesEndpoint.getOnlySeriesWithWriteAccessEventsFilter()) {
294         Map<String, String> seriesWriteAccess = seriesEndpoint.getUserSeriesByAccess(true);
295         return RestUtils.okJson(JSONUtils.filtersToJSONSeriesWriteAccess(query, listProvidersService,
296                 seriesWriteAccess));
297       } else {
298         return RestUtils.okJson(JSONUtils.filtersToJSON(query, listProvidersService,
299             securityService.getOrganization()));
300       }
301     } catch (ListProviderException e) {
302       logger.error("Not able to get list of options for the filters for the page {}", page, e);
303       return SERVER_ERROR;
304     }
305   }
306 
307 }