io.gravitee.management.rest.resource.ApisResource Maven / Gradle / Ivy
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0
*
* 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 io.gravitee.management.rest.resource;
import io.gravitee.common.component.Lifecycle;
import io.gravitee.common.http.MediaType;
import io.gravitee.definition.model.VirtualHost;
import io.gravitee.management.model.ImportSwaggerDescriptorEntity;
import io.gravitee.management.model.RatingSummaryEntity;
import io.gravitee.management.model.ViewEntity;
import io.gravitee.management.model.WorkflowState;
import io.gravitee.management.model.api.*;
import io.gravitee.management.model.permissions.RolePermission;
import io.gravitee.management.model.permissions.RolePermissionAction;
import io.gravitee.management.rest.resource.param.ApisParam;
import io.gravitee.management.rest.resource.param.VerifyApiParam;
import io.gravitee.management.rest.security.Permission;
import io.gravitee.management.rest.security.Permissions;
import io.gravitee.management.service.*;
import io.gravitee.management.service.exceptions.ApiAlreadyExistsException;
import io.gravitee.management.service.notification.ApiHook;
import io.gravitee.management.service.notification.Hook;
import io.gravitee.repository.exceptions.TechnicalException;
import io.swagger.annotations.*;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.*;
import static io.gravitee.management.model.Visibility.PUBLIC;
import static io.gravitee.management.model.api.ApiLifecycleState.PUBLISHED;
import static io.gravitee.repository.management.model.View.ALL_ID;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
/**
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author Nicolas GERAUD (nicolas.geraud at graviteesource.com)
* @author GraviteeSource Team
*/
@Path("/apis")
@Api(tags = {"API"})
public class ApisResource extends AbstractResource {
@Context
private UriInfo uriInfo;
@Context
private ResourceContext resourceContext;
@Inject
private ApiService apiService;
@Inject
private SwaggerService swaggerService;
@Inject
private TopApiService topApiService;
@Inject
private RatingService ratingService;
@Inject
private VirtualHostService virtualHostService;
@Inject
private ViewService viewService;
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
value = "List APIs",
notes = "List all the APIs accessible to the current user or only public APIs for non authenticated users.")
@ApiResponses({
@ApiResponse(code = 200, message = "List accessible APIs for current user", response = ApiListItem.class, responseContainer = "List"),
@ApiResponse(code = 500, message = "Internal server error")})
public List listApis(@BeanParam final ApisParam apisParam) {
final ApiQuery apiQuery = new ApiQuery();
if (apisParam.getGroup() != null) {
apiQuery.setGroups(singletonList(apisParam.getGroup()));
}
apiQuery.setContextPath(apisParam.getContextPath());
apiQuery.setLabel(apisParam.getLabel());
apiQuery.setVersion(apisParam.getVersion());
apiQuery.setName(apisParam.getName());
apiQuery.setTag(apisParam.getTag());
apiQuery.setState(apisParam.getState());
if (apisParam.getView() != null && !ALL_ID.equals(apisParam.getView())) {
apiQuery.setView(viewService.findById(apisParam.getView()).getId());
}
final Collection apis;
if (isAdmin()) {
apis = apiService.search(apiQuery);
} else {
if (apisParam.isPortal() || apisParam.isTop()) {
apiQuery.setLifecycleStates(singletonList(PUBLISHED));
}
if (isAuthenticated()) {
apis = apiService.findByUser(getAuthenticatedUser(), apiQuery);
} else {
apiQuery.setVisibility(PUBLIC);
apis = apiService.search(apiQuery);
}
}
if (apisParam.isTop()) {
final List visibleApis = apis.stream().map(ApiEntity::getId).collect(toList());
return topApiService.findAll().stream()
.filter(topApi -> visibleApis.contains(topApi.getApi()))
.map(topApiEntity -> apiService.findById(topApiEntity.getApi()))
.map(this::convert)
.collect(toList());
}
return apis.stream()
.map(this::convert)
.map(this::setManageable)
.sorted((o1, o2) -> String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName()))
.collect(toList());
}
/**
* Create a new API for the authenticated user.
* @param newApiEntity
* @return
*/
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
value = "Create an API",
notes = "User must have API_PUBLISHER or ADMIN role to create an API.")
@ApiResponses({
@ApiResponse(code = 201, message = "API successfully created"),
@ApiResponse(code = 500, message = "Internal server error")})
@Permissions({
@Permission(value = RolePermission.MANAGEMENT_API, acls = RolePermissionAction.CREATE)
})
public Response createApi(
@ApiParam(name = "api", required = true)
@Valid @NotNull final NewApiEntity newApiEntity) throws ApiAlreadyExistsException {
ApiEntity newApi = apiService.create(newApiEntity, getAuthenticatedUser());
if (newApi != null) {
return Response
.created(URI.create("/apis/" + newApi.getId()))
.entity(newApi)
.build();
}
return Response.serverError().build();
}
@POST
@Path("import")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
value = "Create an API by importing an API definition",
notes = "Create an API by importing an existing API definition in JSON format")
@ApiResponses({
@ApiResponse(code = 200, message = "API successfully created"),
@ApiResponse(code = 500, message = "Internal server error")})
@Permissions({
@Permission(value = RolePermission.MANAGEMENT_API, acls = RolePermissionAction.CREATE),
@Permission(value = RolePermission.MANAGEMENT_API, acls = RolePermissionAction.UPDATE)
})
public Response importDefinition(
@ApiParam(name = "definition", required = true) @Valid @NotNull String apiDefinition) {
return Response.ok(apiService.createOrUpdateWithDefinition(
null, apiDefinition, getAuthenticatedUser())).build();
}
@POST
@Path("import/swagger")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create an API definition from a Swagger descriptor")
@ApiResponses({
@ApiResponse(code = 200, message = "API definition from Swagger descriptor", response = ApiEntity.class),
@ApiResponse(code = 500, message = "Internal server error")})
@Permissions({
@Permission(value = RolePermission.MANAGEMENT_API, acls = RolePermissionAction.CREATE)
})
public Response importSwagger(
@ApiParam(name = "swagger", required = true) @Valid @NotNull ImportSwaggerDescriptorEntity swaggerDescriptor) {
final ApiEntity api = apiService.create(swaggerService.createAPI(swaggerDescriptor), getAuthenticatedUser(), swaggerDescriptor);
return Response
.created(URI.create("/apis/" + api.getId()))
.entity(api)
.build();
}
@POST
@Path("verify")
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Check if an API match the following criteria")
@ApiResponses({
@ApiResponse(code = 200, message = "No API match the following criteria"),
@ApiResponse(code = 400, message = "API already exist with the following criteria")})
@Permissions({
@Permission(value = RolePermission.MANAGEMENT_API, acls = RolePermissionAction.CREATE)
})
public Response verify(@Valid VerifyApiParam verifyApiParam) {
// TODO : create verify service to query repository with criteria
virtualHostService.validate(Collections.singletonList(new VirtualHost(verifyApiParam.getContextPath())));
return Response.ok().entity("API context [" + verifyApiParam.getContextPath() + "] is available").build();
}
@GET
@Path("/hooks")
@ApiOperation("Get the list of available hooks")
@Produces(MediaType.APPLICATION_JSON)
public Hook[] getHooks() {
return Arrays.stream(ApiHook.values()).filter(h -> !h.isHidden()).toArray(Hook[]::new);
}
@POST
@Path("_search")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Search for API using the search engine")
@ApiResponses({
@ApiResponse(code = 200, message = "List accessible APIs for current user", response = ApiListItem.class, responseContainer = "List"),
@ApiResponse(code = 500, message = "Internal server error")})
public Response searchApis(@ApiParam(name = "q", required = true) @NotNull @QueryParam("q") String query) {
try {
final Collection apis;
if (isAdmin()) {
apis = apiService.search(new ApiQuery());
} else {
final ApiQuery apiQuery = new ApiQuery();
if (isAuthenticated()) {
apis = apiService.findByUser(getAuthenticatedUser(), apiQuery);
} else {
apiQuery.setVisibility(PUBLIC);
apis = apiService.search(apiQuery);
}
}
Map filters = new HashMap<>();
filters.put("api", apis.stream().map(ApiEntity::getId).collect(toSet()));
return Response.ok().entity(apiService.search(query, filters)
.stream()
.map(this::convert)
.map(this::setManageable)
.collect(toList())).build();
} catch (TechnicalException te) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(te).build();
}
}
@Path("{api}")
public ApiResource getApiResource() {
return resourceContext.getResource(ApiResource.class);
}
@Path("{api}/media")
public ApiMediaResource getApiMediaResource() {
return resourceContext.getResource(ApiMediaResource.class);
}
private ApiListItem convert(ApiEntity api) {
final ApiListItem apiItem = new ApiListItem();
apiItem.setId(api.getId());
apiItem.setName(api.getName());
apiItem.setVersion(api.getVersion());
apiItem.setDescription(api.getDescription());
final UriBuilder ub = uriInfo.getBaseUriBuilder();
final UriBuilder uriBuilder = ub.path("apis").path(api.getId()).path("picture");
if (api.getPicture() != null) {
// force browser to get if updated
uriBuilder.queryParam("hash", api.getPicture().hashCode());
}
apiItem.setPictureUrl(uriBuilder.build().toString());
apiItem.setViews(api.getViews());
apiItem.setCreatedAt(api.getCreatedAt());
apiItem.setUpdatedAt(api.getUpdatedAt());
apiItem.setLabels(api.getLabels());
apiItem.setPrimaryOwner(api.getPrimaryOwner());
if (api.getVisibility() != null) {
apiItem.setVisibility(io.gravitee.management.model.Visibility.valueOf(api.getVisibility().toString()));
}
if (api.getState() != null) {
apiItem.setState(Lifecycle.State.valueOf(api.getState().toString()));
}
if (api.getProxy() != null) {
apiItem.setVirtualHosts(api.getProxy().getVirtualHosts());
}
if (ratingService.isEnabled()) {
final RatingSummaryEntity ratingSummary = ratingService.findSummaryByApi(api.getId());
apiItem.setRate(ratingSummary.getAverageRate());
apiItem.setNumberOfRatings(ratingSummary.getNumberOfRatings());
}
apiItem.setTags(api.getTags());
if (api.getLifecycleState() != null) {
apiItem.setLifecycleState(ApiLifecycleState.valueOf(api.getLifecycleState().toString()));
}
if (api.getWorkflowState() != null) {
apiItem.setWorkflowState(WorkflowState.valueOf(api.getWorkflowState().toString()));
}
return apiItem;
}
private ApiListItem setManageable(ApiListItem api) {
api.setManageable(isAuthenticated() &&
(isAdmin() || hasPermission(RolePermission.API_GATEWAY_DEFINITION, api.getId(), RolePermissionAction.READ))
);
return api;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy