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  package org.opencastproject.security.urlsigning.service.impl;
22  
23  import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
24  import static org.apache.commons.lang3.StringUtils.trimToNull;
25  import static org.opencastproject.util.doc.rest.RestParameter.Type.STRING;
26  
27  import org.opencastproject.security.urlsigning.exception.UrlSigningException;
28  import org.opencastproject.security.urlsigning.service.UrlSigningService;
29  import org.opencastproject.util.doc.rest.RestParameter;
30  import org.opencastproject.util.doc.rest.RestQuery;
31  import org.opencastproject.util.doc.rest.RestResponse;
32  import org.opencastproject.util.doc.rest.RestService;
33  
34  import org.joda.time.DateTime;
35  import org.joda.time.DateTimeConstants;
36  import org.osgi.service.component.annotations.Component;
37  import org.osgi.service.component.annotations.Reference;
38  import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
39  
40  import javax.ws.rs.DefaultValue;
41  import javax.ws.rs.GET;
42  import javax.ws.rs.Path;
43  import javax.ws.rs.Produces;
44  import javax.ws.rs.QueryParam;
45  import javax.ws.rs.core.MediaType;
46  import javax.ws.rs.core.Response;
47  
48  @Path("/signing")
49  @RestService(
50      name = "urlsigning",
51      title = "URL Signing Endpoint",
52      notes = "This is a testing endpoint to play around with the URL Signing Service",
53      abstractText = ""
54  )
55  @Component(
56      immediate = true,
57      service = UrlSigningEndpoint.class,
58      property = {
59          "service.description=Url Signing REST Endpoint",
60          "opencast.service.type=org.opencastproject.security.urlsigning.testing",
61          "opencast.service.path=/signing",
62          "opencast.service.publish=false",
63          "opencast.service.jobproducer=false"
64      }
65  )
66  @JaxrsResource
67  public class UrlSigningEndpoint {
68  
69    private UrlSigningService signingService;
70  
71    /** OSGi DI callback */
72    @Reference
73    void setUrlSigningService(UrlSigningService signingService) {
74      this.signingService = signingService;
75    }
76  
77    @GET
78    @Produces({ MediaType.TEXT_PLAIN })
79    @Path("accepts")
80    @RestQuery(
81        name = "accepts",
82        description = "Checks if the signing service accepts to sign the URL",
83        restParameters = {
84            @RestParameter(name = "baseUrl", isRequired = true, description = "The URL to sign", type = STRING)
85        },
86        responses = {
87            @RestResponse(description = "'true' or 'false'", responseCode = 200)
88        },
89        returnDescription = ""
90    )
91    public Response accepts(@QueryParam("baseUrl") final String baseUrl) {
92      if (signingService.accepts(baseUrl)) {
93        return Response.ok(Boolean.TRUE.toString()).build();
94      } else {
95        return Response.ok(Boolean.FALSE.toString()).build();
96      }
97    }
98  
99    @GET
100   @Produces({ MediaType.TEXT_PLAIN })
101   @Path("sign")
102   @RestQuery(
103       name = "sign",
104       description = "Return a signed URL",
105       restParameters = {
106           @RestParameter(name = "baseUrl", isRequired = true, description = "The URL to sign", type = STRING),
107           @RestParameter(
108               name = "validUntil",
109               isRequired = true,
110               type = RestParameter.Type.INTEGER,
111               defaultValue = "0",
112               description = "The UNIX epoch time until when a signed URL should remain valid"
113           ),
114           @RestParameter(
115               name = "validFrom",
116               isRequired = false,
117               type = RestParameter.Type.INTEGER,
118               defaultValue = "0",
119               description = "The UNIX epoch time from when a signed URL should become valid"
120           ),
121           @RestParameter(
122               name = "ipAddr",
123               isRequired = false,
124               type = STRING,
125               defaultValue = "",
126               description = "The IP addresse of the user that is allowed to access the resource"
127           )
128       },
129       responses = { @RestResponse(description = "A URL", responseCode = 200) },
130       returnDescription = ""
131   )
132   public Response sign(
133       @QueryParam("baseUrl") final String baseUrl,
134       @QueryParam("validUntil") final long validUntil,
135       @QueryParam("validFrom") @DefaultValue("0") long validFrom,
136       @QueryParam("ipAddr") @DefaultValue("") String ipAddr
137   ) {
138     try {
139       if (signingService.accepts(baseUrl)) {
140         final String signedUrl = signingService.sign(baseUrl, new DateTime(validUntil
141                 * DateTimeConstants.MILLIS_PER_SECOND), (validFrom > 0 ? new DateTime(validFrom
142                 * DateTimeConstants.MILLIS_PER_SECOND) : null), trimToNull(ipAddr));
143         return Response.ok(signedUrl).build();
144       } else {
145         return Response.status(SC_BAD_REQUEST).build();
146       }
147     } catch (UrlSigningException e) {
148       return Response.status(SC_BAD_REQUEST).entity(e.getMessage()).build();
149     }
150   }
151 
152 }