Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduction of CreateV4ApiUseCase #6827

Merged
merged 10 commits into from Mar 7, 2024
Expand Up @@ -18,6 +18,8 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -28,6 +30,8 @@
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author GraviteeSource Team
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
Expand Down
Expand Up @@ -99,6 +99,7 @@ public class Api implements Serializable {
@NotNull
private Map<@NotEmpty String, @NotNull Plan> plans;

@Builder.Default
private FlowExecution flowExecution = new FlowExecution();

private List<Flow> flows;
Expand Down
Expand Up @@ -17,6 +17,7 @@

import static java.util.stream.Collectors.toMap;

import io.gravitee.apim.core.api.model.NewApi;
import io.gravitee.apim.core.api.model.crd.ApiCRD;
import io.gravitee.rest.api.management.v2.rest.model.Api;
import io.gravitee.rest.api.management.v2.rest.model.ApiLinks;
Expand All @@ -34,7 +35,6 @@
import io.gravitee.rest.api.model.ReviewEntity;
import io.gravitee.rest.api.model.v4.api.ApiEntity;
import io.gravitee.rest.api.model.v4.api.GenericApiEntity;
import io.gravitee.rest.api.model.v4.api.NewApiEntity;
import io.gravitee.rest.api.model.v4.api.UpdateApiEntity;
import jakarta.ws.rs.core.UriInfo;
import java.util.ArrayList;
Expand Down Expand Up @@ -72,6 +72,19 @@ public interface ApiMapper {
ApiMapper INSTANCE = Mappers.getMapper(ApiMapper.class);

// Api
default Api map(io.gravitee.apim.core.api.model.Api api, UriInfo uriInfo, Boolean isSynchronized) {
GenericApi.DeploymentStateEnum state = null;

if (isSynchronized != null) {
state = isSynchronized ? GenericApi.DeploymentStateEnum.DEPLOYED : GenericApi.DeploymentStateEnum.NEED_REDEPLOY;
}

if (api != null && api.getDefinitionVersion() == io.gravitee.definition.model.DefinitionVersion.V4) {
return new io.gravitee.rest.api.management.v2.rest.model.Api(this.mapToV4(api, uriInfo, state));
}
return null;
}

default Api map(GenericApiEntity apiEntity, UriInfo uriInfo, Boolean isSynchronized) {
GenericApi.DeploymentStateEnum state = null;

Expand Down Expand Up @@ -116,6 +129,18 @@ default List<Api> map(List<GenericApiEntity> apiEntities, UriInfo uriInfo, Funct
@Mapping(target = "links", expression = "java(computeApiLinks(apiEntity, uriInfo))")
ApiV4 mapToV4(ApiEntity apiEntity, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);

@Mapping(target = "apiVersion", source = "source.version")
@Mapping(target = "analytics", source = "source.apiDefinitionV4.analytics")
@Mapping(target = "deploymentState", source = "deploymentState")
@Mapping(target = "endpointGroups", source = "source.apiDefinitionV4.endpointGroups")
@Mapping(target = "flowExecution", source = "source.apiDefinitionV4.flowExecution")
@Mapping(target = "flows", source = "source.apiDefinitionV4.flows")
@Mapping(target = "lifecycleState", source = "source.apiLifecycleState")
@Mapping(target = "links", expression = "java(computeCoreApiLinks(source, uriInfo))")
@Mapping(target = "listeners", source = "source.apiDefinitionV4.listeners", qualifiedByName = "fromListeners")
@Mapping(target = "state", source = "source.lifecycleState")
ApiV4 mapToV4(io.gravitee.apim.core.api.model.Api source, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);
jgiovaresco marked this conversation as resolved.
Show resolved Hide resolved

@Mapping(target = "links", expression = "java(computeApiLinks(apiEntity, uriInfo))")
ApiV2 mapToV2(io.gravitee.rest.api.model.api.ApiEntity apiEntity, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);

Expand All @@ -134,7 +159,7 @@ io.gravitee.rest.api.management.v2.rest.model.ApiV1 mapToV1(
ApiEntity map(ApiV4 api);

@Mapping(target = "listeners", qualifiedByName = "toListeners")
NewApiEntity map(CreateApiV4 api);
NewApi map(CreateApiV4 api);

@Mapping(target = "listeners", qualifiedByName = "toListeners")
@Mapping(target = "plans", qualifiedByName = "mapPlanCRD")
Expand Down Expand Up @@ -167,6 +192,13 @@ default ApiLinks computeApiLinks(GenericApiEntity api, UriInfo uriInfo) {
.backgroundUrl(ManagementApiLinkHelper.apiBackgroundURL(uriInfo.getBaseUriBuilder(), api));
}

@Named("computeCoreApiLinks")
default ApiLinks computeCoreApiLinks(io.gravitee.apim.core.api.model.Api api, UriInfo uriInfo) {
return new ApiLinks()
.pictureUrl(ManagementApiLinkHelper.apiPictureURL(uriInfo.getBaseUriBuilder(), api))
.backgroundUrl(ManagementApiLinkHelper.apiBackgroundURL(uriInfo.getBaseUriBuilder(), api));
}

@Named("mapPlanCRD")
default Map<String, io.gravitee.apim.core.api.model.crd.PlanCRD> mapPlanCRD(Map<String, PlanCRD> plans) {
return plans
Expand Down
Expand Up @@ -19,7 +19,9 @@
import static io.gravitee.rest.api.service.impl.search.lucene.transformer.ApiDocumentTransformer.FIELD_TYPE_VALUE;

import com.google.common.base.Strings;
import io.gravitee.apim.core.api.domain_service.ApiStateDomainService;
import io.gravitee.apim.core.api.exception.InvalidPathsException;
import io.gravitee.apim.core.api.use_case.CreateV4ApiUseCase;
import io.gravitee.apim.core.api.use_case.ImportCRDUseCase;
import io.gravitee.apim.core.api.use_case.VerifyApiHostsUseCase;
import io.gravitee.apim.core.api.use_case.VerifyApiPathsUseCase;
Expand Down Expand Up @@ -110,6 +112,12 @@ public ApiResource getApiResource() {
return resourceContext.getResource(ApiResource.class);
}

@Inject
private ApiStateDomainService apiStateDomainService;

@Inject
private CreateV4ApiUseCase createV4ApiUseCase;

@Inject
private ImportCRDUseCase importCRDUseCase;

Expand All @@ -119,13 +127,28 @@ public ApiResource getApiResource() {
@Permissions({ @Permission(value = RolePermission.ENVIRONMENT_API, acls = { RolePermissionAction.CREATE }) })
public Response createApi(@Valid @NotNull final CreateApiV4 api) {
// NOTE: Only for V4 API. V2 API is planned to be supported in the future.
NewApiEntity newApiEntity = ApiMapper.INSTANCE.map(api);
ApiEntity newApi = apiServiceV4.create(GraviteeContext.getExecutionContext(), newApiEntity, getAuthenticatedUser());
var executionContext = GraviteeContext.getExecutionContext();
var userDetails = getAuthenticatedUserDetails();

AuditInfo audit = AuditInfo
.builder()
.organizationId(executionContext.getOrganizationId())
.environmentId(executionContext.getEnvironmentId())
.actor(
AuditActor
.builder()
.userId(userDetails.getUsername())
.userSource(userDetails.getSource())
.userSourceId(userDetails.getSourceId())
.build()
)
.build();
var output = createV4ApiUseCase.execute(new CreateV4ApiUseCase.Input(ApiMapper.INSTANCE.map(api), audit));

boolean isSynchronized = apiStateService.isSynchronized(GraviteeContext.getExecutionContext(), newApi);
boolean isSynchronized = apiStateDomainService.isSynchronized(output.api(), audit);
return Response
.created(this.getLocationHeader(newApi.getId()))
.entity(ApiMapper.INSTANCE.map(newApi, uriInfo, isSynchronized))
.created(this.getLocationHeader(output.api().getId()))
.entity(ApiMapper.INSTANCE.map(output.api(), uriInfo, isSynchronized))
.build();
}

Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package io.gravitee.rest.api.management.v2.rest.utils;

import io.gravitee.apim.core.api.model.Api;
import io.gravitee.rest.api.model.v4.api.GenericApiEntity;
import io.gravitee.rest.api.service.common.GraviteeContext;
import jakarta.ws.rs.core.UriBuilder;
Expand Down Expand Up @@ -45,6 +46,28 @@ public static String apiBackgroundURL(UriBuilder baseUriBuilder, GenericApiEntit
);
}

public static String apiPictureURL(UriBuilder baseUriBuilder, Api api) {
return resourcesURL(
baseUriBuilder,
api.getId(),
"apis",
null,
"picture",
null != api.getUpdatedAt() ? api.getUpdatedAt().toInstant().toEpochMilli() : null
);
}

public static String apiBackgroundURL(UriBuilder baseUriBuilder, Api api) {
return resourcesURL(
baseUriBuilder,
api.getId(),
"apis",
null,
"background",
null != api.getUpdatedAt() ? api.getUpdatedAt().toInstant().toEpochMilli() : null
);
}

private static String resourcesURL(
UriBuilder baseUriBuilder,
String resourceId,
Expand Down