Skip to content
This repository has been archived by the owner on Aug 20, 2021. It is now read-only.

Commit

Permalink
feat(api): export API definition for a specific Gravitee.io APIM version
Browse files Browse the repository at this point in the history
  • Loading branch information
tcompiegne committed Sep 24, 2018
1 parent 1aafea2 commit a1d33d2
Show file tree
Hide file tree
Showing 20 changed files with 1,127 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.gravitee.management.model.api;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.gravitee.common.component.Lifecycle;
import io.gravitee.definition.model.Path;
Expand All @@ -31,6 +32,13 @@
import java.util.*;

/**
* --------------------------------------------------------------------------------------------------------------
* --------------------------------------------------------------------------------------------------------------
* /!\ Do not forget to update {@see io.gravitee.management.service.jackson.ser.api.ApiDefaultSerializer}
* for each modification of the ApiEntity class to apply export API changes /!\
* --------------------------------------------------------------------------------------------------------------
* --------------------------------------------------------------------------------------------------------------
*
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author Nicolas GERAUD (nicolas.geraud at graviteesource.com)
* @author GraviteeSource Team
Expand Down Expand Up @@ -100,6 +108,9 @@ public class ApiEntity {
@JsonProperty(value = "path_mappings")
private Set<String> pathMappings = new HashSet<>();

@JsonIgnore
private Map<String, Object> metadata = new HashMap<>();

public String getId() {
return id;
}
Expand Down Expand Up @@ -284,6 +295,14 @@ public void setPathMappings(Set<String> pathMappings) {
this.pathMappings = pathMappings;
}

public Map<String, Object> getMetadata() {
return metadata;
}

public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.gravitee.management.service.QualityMetricsService;
import io.gravitee.management.service.exceptions.ApiNotFoundException;
import io.gravitee.management.service.exceptions.ForbiddenAccessException;
import io.gravitee.management.service.jackson.ser.api.ApiSerializer;
import io.gravitee.repository.management.model.NotificationReferenceType;
import io.swagger.annotations.*;
import org.glassfish.jersey.message.internal.HttpHeaderReader;
Expand Down Expand Up @@ -395,11 +396,12 @@ public Response updateWithDefinition(
})
public Response exportDefinition(
@PathParam("api") String api,
@QueryParam("version") @DefaultValue("default") String version,
@QueryParam("exclude") @DefaultValue("") String exclude) {
final ApiEntity apiEntity = (ApiEntity) get(api).getEntity();
filterSensitiveData(apiEntity);
return Response
.ok(apiService.exportAsJson(api, exclude.split(",")))
.ok(apiService.exportAsJson(api, version, exclude.split(",")))
.header(HttpHeaders.CONTENT_DISPOSITION, format("attachment;filename=%s", getExportFilename(apiEntity)))
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public interface ApiService {

ApiEntity rollback(String apiId, UpdateApiEntity api);

String exportAsJson(String apiId, String... filteredFields);
String exportAsJson(String apiId, String exportVersion, String... filteredFields);

ApiEntity createOrUpdateWithDefinition(ApiEntity apiEntity, String apiDefinition, String userId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.gravitee.common.component.Lifecycle;
import io.gravitee.common.utils.UUID;
import io.gravitee.definition.model.EndpointGroup;
Expand All @@ -40,6 +39,7 @@
import io.gravitee.management.model.plan.PlanQuery;
import io.gravitee.management.service.*;
import io.gravitee.management.service.exceptions.*;
import io.gravitee.management.service.jackson.ser.api.ApiSerializer;
import io.gravitee.management.service.notification.ApiHook;
import io.gravitee.management.service.notification.HookScope;
import io.gravitee.management.service.notification.NotificationParamsBuilder;
Expand All @@ -66,16 +66,14 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.gravitee.management.model.EventType.PUBLISH_API;
import static io.gravitee.management.model.PageType.SWAGGER;
import static io.gravitee.repository.management.model.Api.AuditEvent.*;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toMap;
import static io.gravitee.management.model.EventType.PUBLISH_API;
import static java.util.Collections.singleton;
import static java.util.Comparator.comparing;
import static io.gravitee.repository.management.model.Visibility.PUBLIC;
import static java.util.Collections.singletonList;
import static java.util.Collections.*;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.apache.commons.lang3.StringUtils.isBlank;

/**
Expand Down Expand Up @@ -695,76 +693,17 @@ private ApiEntity deployLastPublishedAPI(String apiId, String userId, EventType
}

@Override
public String exportAsJson(final String apiId, String... filteredFields) {
final ApiEntity apiEntity = findById(apiId);
List<String> filteredFiedsList = Arrays.asList(filteredFields);

apiEntity.setId(null);
apiEntity.setCreatedAt(null);
apiEntity.setUpdatedAt(null);
apiEntity.setDeployedAt(null);
apiEntity.setPrimaryOwner(null);
apiEntity.setState(null);

ObjectNode apiJsonNode = objectMapper.valueToTree(apiEntity);
String field;

field = "groups";
if (!filteredFiedsList.contains(field)) {
apiJsonNode.remove(field);
if (apiEntity.getGroups() != null && !apiEntity.getGroups().isEmpty()) {
Set<GroupEntity> groupEntities = groupService.findByIds(apiEntity.getGroups());
apiJsonNode.putPOJO(field, groupEntities.stream().map(GroupEntity::getName).collect(Collectors.toSet()));
}
}

field = "members";
if (!filteredFiedsList.contains(field)) {
Set<MemberEntity> members = membershipService.getMembers(MembershipReferenceType.API, apiId, RoleScope.API);
if (members != null) {
members.forEach(m -> {
m.setId(null);
m.setFirstname(null);
m.setLastname(null);
m.setEmail(null);
m.setPermissions(null);
m.setCreatedAt(null);
m.setUpdatedAt(null);
});
}
apiJsonNode.putPOJO(field, members == null ? Collections.emptyList() : members);
}

field = "pages";
if (!filteredFiedsList.contains(field)) {
List<PageListItem> pageListItems = pageService.findApiPagesByApi(apiId);
List<PageEntity> pages = null;
if (pageListItems != null) {
pages = new ArrayList<>(pageListItems.size());
List<PageEntity> finalPages = pages;
pageListItems.forEach(f -> {
PageEntity pageEntity = pageService.findById(f.getId());
pageEntity.setId(null);
finalPages.add(pageEntity);
});
}
apiJsonNode.putPOJO(field, pages == null ? Collections.emptyList() : pages);
}
public String exportAsJson(final String apiId, String exportVersion, String... filteredFields) {
ApiEntity apiEntity = findById(apiId);

field = "plans";
if (!filteredFiedsList.contains(field)) {
Set<PlanEntity> plans = planService.findByApi(apiId);
Set<PlanEntity> plansToAdd = plans == null
? Collections.emptySet()
: plans.stream()
.filter(p -> !PlanStatus.CLOSED.equals(p.getStatus()))
.collect(Collectors.toSet());
apiJsonNode.putPOJO(field, plansToAdd);
}
// set metadata for serialize process
Map<String, Object> metadata = new HashMap<>();
metadata.put(ApiSerializer.METADATA_EXPORT_VERSION, exportVersion);
metadata.put(ApiSerializer.METADATA_FILTERED_FIELDS_LIST, Arrays.asList(filteredFields));
apiEntity.setMetadata(metadata);

try {
apiJsonNode.remove("permission");
return objectMapper.writeValueAsString(apiJsonNode);
return objectMapper.writeValueAsString(apiEntity);
} catch (final Exception e) {
LOGGER.error("An error occurs while trying to JSON serialize the API {}", apiEntity, e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* 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.service.jackson.ser.api;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import io.gravitee.management.model.api.ApiEntity;

import java.io.IOException;
import java.util.Collection;
import java.util.stream.Collectors;

/**
* @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com)
* @author GraviteeSource Team
*/
public class Api1_15VersionSerializer extends ApiSerializer {

public Api1_15VersionSerializer() {
super(ApiEntity.class);
}

@Override
public void serialize(ApiEntity apiEntity, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
super.serialize(apiEntity, jsonGenerator, serializerProvider);

// proxy part
if (apiEntity.getProxy() != null) {
jsonGenerator.writeObjectFieldStart("proxy");
jsonGenerator.writeObjectField("context_path", apiEntity.getProxy().getContextPath());
jsonGenerator.writeObjectField("strip_context_path", apiEntity.getProxy().isStripContextPath());
jsonGenerator.writeObjectField("loggingMode", apiEntity.getProxy().getLoggingMode());
jsonGenerator.writeObjectField("endpoints", apiEntity.getProxy().getGroups().stream()
.map(endpointGroup -> endpointGroup.getEndpoints())
.flatMap(Collection::stream)
.collect(Collectors.toList()));

// load balancing (get load balancing of the first endpoints group)
jsonGenerator.writeObjectField("load_balancing", apiEntity.getProxy().getGroups().iterator().next().getLoadBalancer());

if (apiEntity.getProxy().getFailover() != null) {
jsonGenerator.writeObjectField("failover", apiEntity.getProxy().getFailover());
}

if (apiEntity.getProxy().getCors() != null) {
jsonGenerator.writeObjectField("cors", apiEntity.getProxy().getCors());
}

jsonGenerator.writeEndObject();
}

// must end the writing process
jsonGenerator.writeEndObject();
}

@Override
public Version version() {
return Version.V_1_15;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* 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.service.jackson.ser.api;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import io.gravitee.management.model.api.ApiEntity;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
* @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com)
* @author GraviteeSource Team
*/
public class ApiCompositeSerializer extends ApiSerializer implements InitializingBean {

@Autowired
private ApplicationContext applicationContext;
private List<ApiSerializer> serializers = new LinkedList<>();

public ApiCompositeSerializer() {
super(ApiEntity.class);
}

@Override
public boolean canHandle(ApiEntity apiEntity) {
return true;
}

@Override
public void serialize(ApiEntity apiEntity, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
serializers
.stream()
.filter(serializer -> serializer.canHandle(apiEntity))
.findFirst()
// fall back to default
.orElse(serializers.get(0))
.serialize(apiEntity, jsonGenerator, serializerProvider);
}

@Override
public Version version() {
return null;
}

@Override
public void afterPropertiesSet() {
addSerializer(new ApiDefaultSerializer());
addSerializer(new Api1_15VersionSerializer());
}

private void addSerializer(ApiSerializer apiSerializer) {
apiSerializer.setApplicationContext(applicationContext);
serializers.add(apiSerializer);
}

public void setSerializers(List<ApiSerializer> serializers) {
this.serializers = serializers;
}
}
Loading

0 comments on commit a1d33d2

Please sign in to comment.