GroupRoleEndpoint.java
/*
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.userdirectory.endpoint;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
import static javax.servlet.http.HttpServletResponse.SC_CREATED;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import org.opencastproject.security.api.JaxbGroupList;
import org.opencastproject.security.api.UnauthorizedException;
import org.opencastproject.userdirectory.ConflictException;
import org.opencastproject.userdirectory.JpaGroupRoleProvider;
import org.opencastproject.util.NotFoundException;
import org.opencastproject.util.doc.rest.RestParameter;
import org.opencastproject.util.doc.rest.RestParameter.Type;
import org.opencastproject.util.doc.rest.RestQuery;
import org.opencastproject.util.doc.rest.RestResponse;
import org.opencastproject.util.doc.rest.RestService;
import org.apache.commons.lang3.StringUtils;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* A REST EndPoint for JpaGroupRoleProvider.
*/
@Path("/groups")
@RestService(
name = "groups",
title = "Internal group manager",
abstractText = "This service offers the ability to manage the groups for internal accounts.",
notes = {
"All paths above are relative to the REST endpoint base (something like http://your.server/files)",
"If the service is down or not working it will return a status 503, this means the the "
+ "underlying service is not working and is either restarting or has failed",
"A status code 500 means a general failure has occurred which is not recoverable and was "
+ "not anticipated. In other words, there is a bug! You should file an error report "
+ "with your server logs from the time when the error occurred: "
+ "<a href=\"https://github.com/opencast/opencast/issues\">Opencast Issue Tracker</a>"
}
)
@Component(
property = {
"service.description=Group Role REST EndPoint",
"opencast.service.type=org.opencastproject.userdirectory.endpoint.GroupRoleEndpoint",
"opencast.service.jobproducer=false",
"opencast.service.path=/groups"
},
immediate = false,
service = { GroupRoleEndpoint.class }
)
@JaxrsResource
public class GroupRoleEndpoint {
/** The logger */
private static final Logger logger = LoggerFactory.getLogger(GroupRoleEndpoint.class);
/** the jpaGroupRoleProvider Impl service */
private JpaGroupRoleProvider jpaGroupRoleProvider;
/**
* @param jpaGroupRoleProvider
* the jpaGroupRoleProvider to set
*/
@Reference
public void setJpaGroupRoleProvider(JpaGroupRoleProvider jpaGroupRoleProvider) {
this.jpaGroupRoleProvider = jpaGroupRoleProvider;
}
/**
* Callback for activation of this component.
*/
@Activate
public void activate() {
logger.info("Activating {}", getClass().getName());
}
@GET
@Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_JSON })
@Path("groups.{format:xml|json}")
@RestQuery(
name = "allgroup",
description = "Returns a list of groups",
returnDescription = "Returns a JSON or XML representation of the list of groups available "
+ "the current user's organization",
pathParameters = {
@RestParameter(
name = "format",
description = "The output format (json or xml) of the response body.",
isRequired = true,
type = RestParameter.Type.STRING
)
},
restParameters = {
@RestParameter(
name = "limit",
defaultValue = "100",
description = "The maximum number of items to return per page.",
isRequired = false,
type = RestParameter.Type.STRING
),
@RestParameter(
name = "offset",
defaultValue = "0",
description = "The page number.",
isRequired = false,
type = RestParameter.Type.STRING
)
},
responses = { @RestResponse(responseCode = SC_OK, description = "The groups.") }
)
public Response getGroupsAsJsonOrXml(
@PathParam("format") String format,
@QueryParam("limit") int limit,
@QueryParam("offset") int offset
) {
try {
final String type = "json".equals(format) ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_XML;
JaxbGroupList list = jpaGroupRoleProvider.getGroups(limit, offset);
return Response.ok().entity(list).type(type).build();
} catch (Exception e) {
logger.info("Unable to get groups", e);
return Response.serverError().entity(buildUnexpectedErrorMessage(e)).build();
}
}
@DELETE
@Path("{id}")
@RestQuery(
name = "removegroup",
description = "Remove a group",
returnDescription = "Return no content",
pathParameters = {
@RestParameter(
name = "id",
description = "The group identifier",
isRequired = true,
type = Type.STRING
),
},
responses = {
@RestResponse(
responseCode = SC_OK,
description = "Group deleted"
),
@RestResponse(
responseCode = SC_FORBIDDEN,
description = "Not enough permissions to remove a group with the admin role."
),
@RestResponse(
responseCode = SC_NOT_FOUND,
description = "Group not found."
),
@RestResponse(
responseCode = SC_INTERNAL_SERVER_ERROR,
description = "An internal server error occured."
),
}
)
public Response removeGroup(@PathParam("id") String groupId) {
try {
jpaGroupRoleProvider.removeGroup(groupId);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(SC_NOT_FOUND).build();
} catch (UnauthorizedException e) {
return Response.status(SC_FORBIDDEN).build();
} catch (Exception e) {
throw new WebApplicationException(e);
}
}
@POST
@Path("")
@RestQuery(
name = "createGroup",
description = "Add a group",
returnDescription = "Return the status codes",
restParameters = {
@RestParameter(
name = "name",
description = "The group name",
isRequired = true,
type = Type.STRING
),
@RestParameter(
name = "description",
description = "The group description",
isRequired = false,
type = Type.STRING
),
@RestParameter(
name = "roles",
description = "A comma seperated string of additional group roles",
isRequired = false,
type = Type.TEXT
),
@RestParameter(
name = "users",
description = "A comma seperated string of group members",
isRequired = false,
type = Type.TEXT
),
},
responses = {
@RestResponse(
responseCode = SC_CREATED,
description = "Group created"
),
@RestResponse(
responseCode = SC_BAD_REQUEST,
description = "Name too long"
),
@RestResponse(
responseCode = SC_FORBIDDEN,
description = "Not enough permissions to create a group with the admin role."
),
@RestResponse(
responseCode = SC_CONFLICT,
description = "An group with this name already exists."
),
}
)
public Response createGroup(
@FormParam("name") String name,
@FormParam("description") String description,
@FormParam("roles") String roles,
@FormParam("users") String users
) {
try {
jpaGroupRoleProvider.createGroup(name, description, roles, users);
} catch (IllegalArgumentException e) {
logger.warn("Unable to create group {}: {}", name, e.getMessage());
return Response.status(SC_BAD_REQUEST).build();
} catch (UnauthorizedException e) {
return Response.status(SC_FORBIDDEN).build();
} catch (ConflictException e) {
return Response.status(SC_CONFLICT).build();
}
return Response.status(SC_CREATED).build();
}
@PUT
@Path("{id}")
@RestQuery(
name = "updateGroup",
description = "Update a group",
returnDescription = "Return the status codes",
pathParameters = {
@RestParameter(name = "id", description = "The group identifier", isRequired = true, type = Type.STRING),
},
restParameters = {
@RestParameter(
name = "name",
description = "The group name",
isRequired = true,
type = Type.STRING
),
@RestParameter(
name = "description",
description = "The group description",
isRequired = false,
type = Type.STRING
),
@RestParameter(
name = "roles",
description = "A comma seperated string of additional group roles",
isRequired = false,
type = Type.TEXT
),
@RestParameter(
name = "users",
description = "A comma seperated string of group members",
isRequired = true,
type = Type.TEXT
),
},
responses = {
@RestResponse(
responseCode = SC_OK,
description = "Group updated"
),
@RestResponse(
responseCode = SC_FORBIDDEN,
description = "Not enough permissions to update a group with the admin role."
),
@RestResponse(
responseCode = SC_NOT_FOUND,
description = "Group not found"
),
@RestResponse(
responseCode = SC_BAD_REQUEST,
description = "Name too long"
),
}
)
public Response updateGroup(
@PathParam("id") String groupId,
@FormParam("name") String name,
@FormParam("description") String description,
@FormParam("roles") String roles,
@FormParam("users") String users
) throws NotFoundException {
try {
jpaGroupRoleProvider.updateGroup(groupId, name, description, roles, users);
} catch (IllegalArgumentException e) {
logger.warn("Unable to update group id {}: {}", groupId, e.getMessage());
return Response.status(SC_BAD_REQUEST).build();
} catch (UnauthorizedException ex) {
return Response.status(SC_FORBIDDEN).build();
}
return Response.ok().build();
}
/**
* Borrowed from FileUploadRestService.java
*
* Builds an error message in case of an unexpected error in an endpoint
* method, includes the exception type and message if existing.
*
* TODO append stack trace
*
* @param e
* Exception that was thrown
* @return error message
*/
private String buildUnexpectedErrorMessage(Exception e) {
StringBuilder sb = new StringBuilder();
sb.append("Unexpected error (").append(e.getClass().getName()).append(")");
String message = e.getMessage();
if (StringUtils.isNotBlank(message)) {
sb.append(": ").append(message);
}
return sb.toString();
}
}