diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiBean.java index fc54f84300..a4a2ddb3d2 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiBean.java @@ -42,7 +42,7 @@ @Table(name = "apis") @IdClass(OrganizationBasedCompositeId.class) @JsonInclude(Include.NON_NULL) -public class ApiBean implements Serializable { +public class ApiBean implements Serializable, Cloneable { private static final long serialVersionUID = 1526742536153467539L; @@ -181,4 +181,12 @@ public String toString() { + ", description=" + description + ", createdBy=" + createdBy + ", createdOn=" + createdOn + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiVersionBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiVersionBean.java index 3053b20fab..0750831d52 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiVersionBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/apis/ApiVersionBean.java @@ -52,7 +52,7 @@ @Table(name = "api_versions", uniqueConstraints = { @UniqueConstraint(columnNames = { "api_id", "api_org_id", "version" }) }) @JsonInclude(Include.NON_NULL) -public class ApiVersionBean implements Serializable { +public class ApiVersionBean implements Serializable, Cloneable { private static final long serialVersionUID = -2218697175049442690L; @@ -414,4 +414,12 @@ public String toString() { + ", publishedOn=" + publishedOn + ", retiredOn=" + retiredOn + ", definitionType=" + definitionType + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientBean.java index 49b8976ca5..a216899f2f 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientBean.java @@ -42,7 +42,7 @@ @Table(name = "clients") @IdClass(OrganizationBasedCompositeId.class) @JsonInclude(Include.NON_NULL) -public class ClientBean implements Serializable { +public class ClientBean implements Serializable, Cloneable { private static final long serialVersionUID = -197129444021040365L; @@ -158,5 +158,13 @@ public String toString() { + ", description=" + description + ", createdBy=" + createdBy + ", createdOn=" + createdOn + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientVersionBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientVersionBean.java index e3b1347626..3c5c18bdb9 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientVersionBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/clients/ClientVersionBean.java @@ -48,7 +48,7 @@ @UniqueConstraint(columnNames = { "client_id", "client_org_id", "version" }), @UniqueConstraint(columnNames = { "apikey" })}) @JsonInclude(Include.NON_NULL) -public class ClientVersionBean implements Serializable { +public class ClientVersionBean implements Serializable, Cloneable { private static final long serialVersionUID = -2218697175049442690L; @@ -282,5 +282,13 @@ public String toString() { + ", modifiedBy=" + modifiedBy + ", modifiedOn=" + modifiedOn + ", publishedOn=" + publishedOn + ", retiredOn=" + retiredOn + ", apikey=" + apikey + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/contracts/ContractBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/contracts/ContractBean.java index def6f0e549..8ebba69312 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/contracts/ContractBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/contracts/ContractBean.java @@ -44,7 +44,7 @@ @Entity @Table(name = "contracts", uniqueConstraints = { @UniqueConstraint(columnNames = { "clientv_id", "apiv_id" }) }) -public class ContractBean implements Serializable { +public class ContractBean implements Serializable, Cloneable { private static final long serialVersionUID = -8534463608508756791L; @@ -169,5 +169,13 @@ public String toString() { return "ContractBean [id=" + id + ", client=" + client + ", api=" + api + ", plan=" + plan + ", createdBy=" + createdBy + ", createdOn=" + createdOn + "]"; } - + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanBean.java index 1aaedb4568..bbc9c10bee 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanBean.java @@ -42,7 +42,7 @@ @Table(name = "plans") @IdClass(OrganizationBasedCompositeId.class) @JsonInclude(Include.NON_NULL) -public class PlanBean implements Serializable { +public class PlanBean implements Serializable, Cloneable { private static final long serialVersionUID = -7961331943587584049L; @@ -157,5 +157,13 @@ public String toString() { return "PlanBean [organization=" + organization + ", id=" + id + ", name=" + name + ", description=" + description + ", createdBy=" + createdBy + ", createdOn=" + createdOn + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanVersionBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanVersionBean.java index 06ce57d592..6508376759 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanVersionBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/plans/PlanVersionBean.java @@ -42,7 +42,7 @@ @Entity @Table(name = "plan_versions", uniqueConstraints = { @UniqueConstraint(columnNames = { "plan_id", "plan_org_id", "version" }) }) -public class PlanVersionBean implements Serializable { +public class PlanVersionBean implements Serializable, Cloneable { private static final long serialVersionUID = -2218697175049442690L; @@ -243,5 +243,13 @@ public String toString() { + ", createdBy=" + createdBy + ", createdOn=" + createdOn + ", modifiedBy=" + modifiedBy + ", modifiedOn=" + modifiedOn + ", lockedOn=" + lockedOn + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/policies/PolicyBean.java b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/policies/PolicyBean.java index 023acc3f73..2fbfcd7d8b 100644 --- a/manager/api/beans/src/main/java/io/apiman/manager/api/beans/policies/PolicyBean.java +++ b/manager/api/beans/src/main/java/io/apiman/manager/api/beans/policies/PolicyBean.java @@ -52,7 +52,7 @@ @Entity @Table(name = "policies") @JsonInclude(Include.NON_NULL) -public class PolicyBean implements Serializable { +public class PolicyBean implements Serializable, Cloneable { private static final long serialVersionUID = -8534463608508756791L; @@ -346,5 +346,13 @@ public String toString() { + createdBy + ", createdOn=" + createdOn + ", modifiedBy=" + modifiedBy + ", modifiedOn=" + modifiedOn + ", definition=" + definition + ", orderIndex=" + orderIndex + "]"; } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/manager/api/core/src/main/java/io/apiman/manager/api/core/logging/StringBuilderLogger.java b/manager/api/core/src/main/java/io/apiman/manager/api/core/logging/StringBuilderLogger.java new file mode 100644 index 0000000000..f94a2c7cd0 --- /dev/null +++ b/manager/api/core/src/main/java/io/apiman/manager/api/core/logging/StringBuilderLogger.java @@ -0,0 +1,105 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.core.logging; + +/** + * Logs to a string builder. + * @author eric.wittmann@gmail.com + */ +@SuppressWarnings("nls") +public class StringBuilderLogger implements IApimanLogger { + + private StringBuilder builder = new StringBuilder(); + + /** + * Constructor. + */ + public StringBuilderLogger() { + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#info(java.lang.String) + */ + @Override + public void info(String message) { + append("INFO: " + message); + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#warn(java.lang.String) + */ + @Override + public void warn(String message) { + append("WARN: " + message); + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#debug(java.lang.String) + */ + @Override + public void debug(String message) { + append("DEBUG: " + message); + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#trace(java.lang.String) + */ + @Override + public void trace(String message) { + append("TRACE: " + message); + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#error(java.lang.Throwable) + */ + @Override + public void error(Throwable error) { + append("ERROR: " + error.getMessage()); + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#error(java.lang.String, java.lang.Throwable) + */ + @Override + public void error(String message, Throwable error) { + append("ERROR: " + message); + } + + /** + * Append to the builder. + * @param message + */ + private void append(String message) { + builder.append(message); + builder.append("\n"); + } + + /** + * @return the log data + */ + public String string() { + return builder.toString(); + } + + /** + * Reset the builder to empty. + */ + public void reset() { + builder = new StringBuilder(); + } + +} diff --git a/manager/api/core/src/main/java/io/apiman/manager/api/core/logging/SystemOutLogger.java b/manager/api/core/src/main/java/io/apiman/manager/api/core/logging/SystemOutLogger.java new file mode 100644 index 0000000000..ff6f7ae29a --- /dev/null +++ b/manager/api/core/src/main/java/io/apiman/manager/api/core/logging/SystemOutLogger.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.core.logging; + +/** + * @author eric.wittmann@gmail.com + */ +public class SystemOutLogger implements IApimanLogger { + + /** + * Constructor. + */ + public SystemOutLogger() { + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#info(java.lang.String) + */ + @Override + public void info(String message) { + System.out.println("INFO: " + message); //$NON-NLS-1$ + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#warn(java.lang.String) + */ + @Override + public void warn(String message) { + System.out.println("WARN: " + message); //$NON-NLS-1$ + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#debug(java.lang.String) + */ + @Override + public void debug(String message) { + System.out.println("DEBUG: " + message); //$NON-NLS-1$ + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#trace(java.lang.String) + */ + @Override + public void trace(String message) { + System.out.println("TRACE: " + message); //$NON-NLS-1$ + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#error(java.lang.Throwable) + */ + @Override + public void error(Throwable error) { + System.out.println("** ERROR **"); //$NON-NLS-1$ + error.printStackTrace(); + } + + /** + * @see io.apiman.manager.api.core.logging.IApimanLogger#error(java.lang.String, java.lang.Throwable) + */ + @Override + public void error(String message, Throwable error) { + System.out.println("** ERROR: " + message + " **"); //$NON-NLS-1$ //$NON-NLS-2$ + error.printStackTrace(); + } + +} diff --git a/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/json/JsonExportWriter.java b/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/json/JsonExportWriter.java index 2a879861cc..7d3c92276c 100644 --- a/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/json/JsonExportWriter.java +++ b/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/json/JsonExportWriter.java @@ -277,6 +277,7 @@ public IExportWriter startPlans() { public IExportWriter startPlan(PlanBean plan) { writeStartObject(); try { + plan = (PlanBean) plan.clone(); plan.setOrganization(null); jg.writeObjectField(PlanBean.class.getSimpleName(), plan); } catch (Exception e) { @@ -301,6 +302,7 @@ public IExportWriter startPlanVersions() { public IExportWriter startPlanVersion(PlanVersionBean pvb) { writeStartObject(); try { + pvb = (PlanVersionBean) pvb.clone(); pvb.setPlan(null); jg.writeObjectField(PlanVersionBean.class.getSimpleName(), pvb); } catch (Exception e) { @@ -331,10 +333,15 @@ public IExportWriter writePlanPolicy(PolicyBean policy) { * @return */ private IExportWriter writePolicy(PolicyBean policy) { - PolicyDefinitionBean definition = new PolicyDefinitionBean(); - definition.setId(policy.getDefinition().getId()); - policy.setDefinition(definition); - writePojo(policy); + try { + policy = (PolicyBean) policy.clone(); + PolicyDefinitionBean definition = new PolicyDefinitionBean(); + definition.setId(policy.getDefinition().getId()); + policy.setDefinition(definition); + writePojo(policy); + } catch (Exception e) { + throw new RuntimeException(e); + } return this; } @@ -399,6 +406,7 @@ public IExportWriter startApis() { public IExportWriter startApi(ApiBean api) { writeStartObject(); try { + api = (ApiBean) api.clone(); api.setOrganization(null); jg.writeObjectField(ApiBean.class.getSimpleName(), api); } catch (Exception e) { @@ -420,11 +428,12 @@ public IExportWriter startApiVersions() { * @see io.apiman.manager.api.exportimport.write.IExportWriter#startApiVersion(io.apiman.manager.api.beans.apis.ApiVersionBean) */ @Override - public IExportWriter startApiVersion(ApiVersionBean pvb) { + public IExportWriter startApiVersion(ApiVersionBean avb) { writeStartObject(); try { - pvb.setApi(null); - jg.writeObjectField(ApiVersionBean.class.getSimpleName(), pvb); + avb = (ApiVersionBean) avb.clone(); + avb.setApi(null); + jg.writeObjectField(ApiVersionBean.class.getSimpleName(), avb); } catch (Exception e) { throw new RuntimeException(e); } @@ -509,6 +518,7 @@ public IExportWriter startClients() { public IExportWriter startClient(ClientBean client) { writeStartObject(); try { + client = (ClientBean) client.clone(); client.setOrganization(null); jg.writeObjectField(ClientBean.class.getSimpleName(), client); } catch (Exception e) { @@ -530,11 +540,12 @@ public IExportWriter startClientVersions() { * @see io.apiman.manager.api.exportimport.write.IExportWriter#startClientVersion(io.apiman.manager.api.beans.ClientVersionBean.ClientVersionBean) */ @Override - public IExportWriter startClientVersion(ClientVersionBean pvb) { + public IExportWriter startClientVersion(ClientVersionBean cvb) { writeStartObject(); try { - pvb.setClient(null); - jg.writeObjectField(ClientVersionBean.class.getSimpleName(), pvb); + cvb = (ClientVersionBean) cvb.clone(); + cvb.setClient(null); + jg.writeObjectField(ClientVersionBean.class.getSimpleName(), cvb); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageExporter.java b/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageExporter.java index b35b1fc9ca..05694528d1 100644 --- a/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageExporter.java +++ b/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageExporter.java @@ -223,6 +223,7 @@ private void exportClients(String orgId) { Iterator contractIter = storage.getAllContracts(orgId, clientBean.getId(), versionBean.getVersion()); while (contractIter.hasNext()) { ContractBean contractBean = contractIter.next(); + contractBean = (ContractBean) contractBean.clone(); contractBean.setClient(null); contractBean.setApi(minifyApi(contractBean.getApi())); contractBean.setPlan(minifyPlan(contractBean.getPlan())); diff --git a/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageImportDispatcher.java b/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageImportDispatcher.java index 3996add0de..a89d587da6 100644 --- a/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageImportDispatcher.java +++ b/manager/api/export-import/src/main/java/io/apiman/manager/api/exportimport/manager/StorageImportDispatcher.java @@ -518,6 +518,7 @@ private void registerClients() throws StorageException { client.setOrganizationId(versionBean.getClient().getOrganization().getId()); client.setClientId(versionBean.getClient().getId()); client.setVersion(versionBean.getVersion()); + client.setApiKey(versionBean.getApikey()); Set contracts = new HashSet<>(); while (contractBeans.hasNext()) { diff --git a/manager/api/jpa/src/main/java/io/apiman/manager/api/jpa/AbstractJpaStorage.java b/manager/api/jpa/src/main/java/io/apiman/manager/api/jpa/AbstractJpaStorage.java index 284edeae1a..a299d64f42 100644 --- a/manager/api/jpa/src/main/java/io/apiman/manager/api/jpa/AbstractJpaStorage.java +++ b/manager/api/jpa/src/main/java/io/apiman/manager/api/jpa/AbstractJpaStorage.java @@ -432,7 +432,7 @@ public boolean hasNext() { @Override public T next() { T rval = results.get(resultIndex++); - entityManager().detach(rval); +// entityManager().detach(rval); if (resultIndex >= results.size()) { fetch(); } diff --git a/manager/api/migrator/.gitignore b/manager/api/migrator/.gitignore new file mode 100644 index 0000000000..b83d22266a --- /dev/null +++ b/manager/api/migrator/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/manager/api/migrator/pom.xml b/manager/api/migrator/pom.xml new file mode 100644 index 0000000000..b319cce50f --- /dev/null +++ b/manager/api/migrator/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + io.apiman + apiman-manager-api + 1.2.3-SNAPSHOT + + apiman-manager-api-migrator + bundle + apiman-manager-api-migrator + + + + ${project.groupId} + apiman-common-util + + + ${project.groupId} + apiman-manager-api-core + + + ${project.groupId} + apiman-manager-api-config + + + + + commons-io + commons-io + + + commons-lang + commons-lang + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + javax.enterprise + cdi-api + provided + + + joda-time + joda-time + + + + + ${project.groupId} + apiman-test-common + test + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + + diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/DataMigrator.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/DataMigrator.java new file mode 100644 index 0000000000..0fde765410 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/DataMigrator.java @@ -0,0 +1,246 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import io.apiman.manager.api.config.Version; +import io.apiman.manager.api.core.logging.ApimanLogger; +import io.apiman.manager.api.core.logging.IApimanLogger; +import io.apiman.manager.api.core.logging.SystemOutLogger; +import io.apiman.manager.api.migrator.i18n.Messages; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Used to migrate exported data from an older version of apiman to the + * latest version. This is useful when upgrading from older versions of + * apiman to the latest. + * @author eric.wittmann@gmail.com + */ +@Dependent +public class DataMigrator implements IReaderHandler { + + @Inject + private Version version; + @Inject @ApimanLogger(DataMigrator.class) + private IApimanLogger logger; + + private IDataMigratorWriter writer; + private VersionMigratorChain chain; + + /** + * Constructor. + */ + public DataMigrator() { + } + + /** + * Migrate the data export file (fromSource) from whatever version it + * is to the latest apiman version format and write the result to a + * file (toDest). + * @param fromSource + * @param toDest + */ + public void migrate(File fromSource, File toDest) { + IReaderHandler readerHandler = this; + try (IDataMigratorReader reader = new JsonDataMigratorReader(fromSource); + IDataMigratorWriter writer = new JsonDataMigratorWriter(toDest)) { + this.writer = writer; + reader.read(readerHandler); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Migrate the data export file (fromSource) from whatever version it + * is to the latest apiman version format and write the result to a + * file (toDest). + * + * Note: this method will automatically close the streams - the caller + * does not need to do this. + * @param fromSource + * @param toDest + */ + public void migrate(InputStream fromSource, OutputStream toDest) { + IReaderHandler readerHandler = this; + try (IDataMigratorReader reader = new JsonDataMigratorReader(fromSource); + IDataMigratorWriter writer = new JsonDataMigratorWriter(toDest)) { + this.writer = writer; + reader.read(readerHandler); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Main method - used when running the data migrator in standalone + * mode. + * @param args + */ + public static void main(String[] args) { + File from; + File to; + + if (args.length < 2) { + System.out.println("Usage: DataMigrator "); //$NON-NLS-1$ + return; + } + + String frompath = args[0]; + String topath = args[1]; + + from = new File(frompath); + to = new File(topath); + + System.out.println("Starting data migration."); //$NON-NLS-1$ + System.out.println(" From: " + from); //$NON-NLS-1$ + System.out.println(" To: " + to); //$NON-NLS-1$ + DataMigrator migrator = new DataMigrator(); + migrator.setLogger(new SystemOutLogger()); + Version version = new Version(); + version.postConstruct(); + migrator.setVersion(version); + migrator.migrate(from, to); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onMetaData(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onMetaData(ObjectNode node) throws IOException { + String fromVersion = node.get("apimanVersion").asText(); //$NON-NLS-1$ + String toVersion = this.getVersion().getVersionString(); + + chain = VersionMigrators.chain(fromVersion, toVersion); + + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingNow", fromVersion)); //$NON-NLS-1$ + chain.migrateMetaData(node); + node.put("apimanVersion", toVersion); //$NON-NLS-1$ + } + writer.writeMetaData(node); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onUser(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onUser(ObjectNode node) throws IOException { + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingUser", node.get("username"))); //$NON-NLS-1$ //$NON-NLS-2$ + chain.migrateUser(node); + } + writer.writeUser(node); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onGateway(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onGateway(ObjectNode node) throws IOException { + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingGateway", node.get("name"))); //$NON-NLS-1$ //$NON-NLS-2$ + chain.migrateGateway(node); + } + writer.writeGateway(node); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onPlugin(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onPlugin(ObjectNode node) throws IOException { + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingPlugin", node.get("name"))); //$NON-NLS-1$ //$NON-NLS-2$ + chain.migratePlugin(node); + } + writer.writePlugin(node); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onRole(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onRole(ObjectNode node) throws IOException { + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingRole", node.get("name"))); //$NON-NLS-1$ //$NON-NLS-2$ + chain.migrateRole(node); + } + writer.writeRole(node); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onPolicyDefinition(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onPolicyDefinition(ObjectNode node) throws IOException { + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingPolicyDef", node.get("name"))); //$NON-NLS-1$ //$NON-NLS-2$ + chain.migratePolicyDefinition(node); + } + writer.writePolicyDefinition(node); + } + + /** + * @see io.apiman.manager.api.migrator.IReaderHandler#onOrg(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void onOrg(ObjectNode node) throws IOException { + if (chain.hasMigrators()) { + logger.info(Messages.i18n.format("DataMigrator.MigratingOrg", node.get("OrganizationBean").get("name"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + chain.migrateOrg(node); + } + writer.writeOrg(node); + } + + /** + * @return the version + */ + public Version getVersion() { + return version; + } + + /** + * @param version the version to set + */ + public void setVersion(Version version) { + this.version = version; + } + + /** + * @return the logger + */ + public IApimanLogger getLogger() { + return logger; + } + + /** + * @param logger the logger to set + */ + public void setLogger(IApimanLogger logger) { + this.logger = logger; + } + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/DataMigratorException.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/DataMigratorException.java new file mode 100644 index 0000000000..c9b6160c09 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/DataMigratorException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +/** + * @author eric.wittmann@gmail.com + */ +public class DataMigratorException extends Exception { + + private static final long serialVersionUID = -854957952006437312L; + + /** + * Constructor. + */ + public DataMigratorException(Exception rootError) { + super(rootError); + } +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IDataMigratorReader.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IDataMigratorReader.java new file mode 100644 index 0000000000..bfe6f9493e --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IDataMigratorReader.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import java.io.IOException; + +/** + * @author eric.wittmann@gmail.com + */ +public interface IDataMigratorReader extends AutoCloseable { + + /** + * @param readerHandler + */ + public void read(IReaderHandler readerHandler) throws IOException; + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IDataMigratorWriter.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IDataMigratorWriter.java new file mode 100644 index 0000000000..3a6e5fb6c3 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IDataMigratorWriter.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import java.io.IOException; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author eric.wittmann@gmail.com + */ +public interface IDataMigratorWriter extends AutoCloseable { + + public void writeMetaData(ObjectNode node) throws IOException; + + public void writeUser(ObjectNode node) throws IOException; + + public void writeGateway(ObjectNode node) throws IOException; + + public void writePlugin(ObjectNode node) throws IOException; + + public void writeRole(ObjectNode node) throws IOException; + + public void writePolicyDefinition(ObjectNode node) throws IOException; + + public void writeOrg(ObjectNode node) throws IOException; + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IReaderHandler.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IReaderHandler.java new file mode 100644 index 0000000000..e0821d4c00 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IReaderHandler.java @@ -0,0 +1,44 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import java.io.IOException; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * As the data migrator's reader reads the data in the export file, + * it will invoke methods on this handler interface. + * @author eric.wittmann@gmail.com + */ +public interface IReaderHandler { + + public void onMetaData(ObjectNode node) throws IOException; + + public void onUser(ObjectNode node) throws IOException; + + public void onGateway(ObjectNode node) throws IOException; + + public void onPlugin(ObjectNode node) throws IOException; + + public void onRole(ObjectNode node) throws IOException; + + public void onPolicyDefinition(ObjectNode node) throws IOException; + + public void onOrg(ObjectNode node) throws IOException; + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IVersionMigrator.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IVersionMigrator.java new file mode 100644 index 0000000000..0c49a95ff6 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/IVersionMigrator.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Responsible for migrating export data from one version to the next. + * Typically a chain of these migrators is used so that the data can + * be migrated from version X to version Y. + * @author eric.wittmann@gmail.com + */ +public interface IVersionMigrator { + + public void migrateMetaData(ObjectNode node); + + public void migrateUser(ObjectNode node); + + public void migrateGateway(ObjectNode node); + + public void migratePlugin(ObjectNode node); + + public void migrateRole(ObjectNode node); + + public void migratePolicyDefinition(ObjectNode node); + + public void migrateOrg(ObjectNode node); + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/JsonDataMigratorReader.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/JsonDataMigratorReader.java new file mode 100644 index 0000000000..397ffdc9ed --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/JsonDataMigratorReader.java @@ -0,0 +1,153 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author eric.wittmann@gmail.com + */ +public class JsonDataMigratorReader implements IDataMigratorReader { + + private final JsonParser jp; + private final InputStream in; + + /** + * Constructor. + * @param fromSource + * @throws IOException + */ + public JsonDataMigratorReader(File fromSource) throws IOException { + this(new FileInputStream(fromSource)); + } + + /** + * Constructor. + * @param fromSource + * @throws IOException + */ + public JsonDataMigratorReader(InputStream fromSource) throws IOException { + this.in = fromSource; + jp = new JsonFactory().createParser(in); + jp.setCodec(new ObjectMapper()); + } + + /** + * @see java.lang.AutoCloseable#close() + */ + @Override + public void close() throws Exception { + IOUtils.closeQuietly(in); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorReader#read(io.apiman.manager.api.migrator.IReaderHandler) + */ + @Override + public void read(IReaderHandler readerHandler) throws IOException { + try { + JsonToken current = jp.nextToken(); + + if (current != JsonToken.START_OBJECT) { + throw new IOException("Expected start object at root."); //$NON-NLS-1$ + } + + while (jp.nextToken() != JsonToken.END_OBJECT) { + String name = jp.getCurrentName(); + current = jp.nextToken(); + + if (name.equals("Metadata")) { //$NON-NLS-1$ + ObjectNode obj = readObjectNode(); + readerHandler.onMetaData(obj); + } else if (name.equals("Gateways")) { //$NON-NLS-1$ + readArrayStart(); + while (jp.getCurrentToken() == JsonToken.START_OBJECT) { + ObjectNode obj = readObjectNode(); + readerHandler.onGateway(obj); + jp.nextToken(); + } + } else if (name.equals("Plugins")) { //$NON-NLS-1$ + readArrayStart(); + while (jp.getCurrentToken() == JsonToken.START_OBJECT) { + ObjectNode obj = readObjectNode(); + readerHandler.onPlugin(obj); + jp.nextToken(); + } + } else if (name.equals("Roles")) { //$NON-NLS-1$ + readArrayStart(); + while (jp.getCurrentToken() == JsonToken.START_OBJECT) { + ObjectNode obj = readObjectNode(); + readerHandler.onRole(obj); + jp.nextToken(); + } + } else if (name.equals("PolicyDefinitions")) { //$NON-NLS-1$ + readArrayStart(); + while (jp.getCurrentToken() == JsonToken.START_OBJECT) { + ObjectNode obj = readObjectNode(); + readerHandler.onPolicyDefinition(obj); + jp.nextToken(); + } + } else if (name.equals("Users")) { //$NON-NLS-1$ + readArrayStart(); + while (jp.getCurrentToken() == JsonToken.START_OBJECT) { + ObjectNode obj = readObjectNode(); + readerHandler.onUser(obj); + jp.nextToken(); + } + } else if (name.equals("Orgs")) { //$NON-NLS-1$ + readArrayStart(); + while (jp.getCurrentToken() == JsonToken.START_OBJECT) { + ObjectNode obj = readObjectNode(); + readerHandler.onOrg(obj); + jp.nextToken(); + } + } + } + } finally { + IOUtils.closeQuietly(in); + } + } + + private void readArrayStart() throws IOException, JsonParseException { + JsonToken token = jp.getCurrentToken(); + if (token != JsonToken.START_ARRAY) { + throw new IOException("Unexpected token (array start expected)."); //$NON-NLS-1$ + } + jp.nextToken(); + } + + /** + * @return reads an object from the input + * @throws IOException + */ + private ObjectNode readObjectNode() throws IOException { + return (ObjectNode) jp.readValueAsTree(); + } + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/JsonDataMigratorWriter.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/JsonDataMigratorWriter.java new file mode 100644 index 0000000000..516e58e9df --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/JsonDataMigratorWriter.java @@ -0,0 +1,164 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.io.IOUtils; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonEncoding; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author eric.wittmann@gmail.com + */ +public class JsonDataMigratorWriter implements IDataMigratorWriter { + + private final OutputStream os; + private final JsonFactory jsonFactory = new JsonFactory(); + private final JsonGenerator jg; + private final ObjectMapper om = new ObjectMapper(); + private final Set sections = new HashSet<>(); + + /** + * Constructor. + * @param toDest + * @throws IOException + */ + public JsonDataMigratorWriter(File toDest) throws IOException { + this(new FileOutputStream(toDest)); + } + + /** + * Constructor. + * @param output + */ + public JsonDataMigratorWriter(OutputStream output) throws IOException { + this.os = output; + om.setSerializationInclusion(JsonInclude.Include.NON_NULL); + jg = jsonFactory.createGenerator(output, JsonEncoding.UTF8); + jg.useDefaultPrettyPrinter(); + jg.setCodec(om); + jg.writeStartObject(); // Set out the base/root object + } + + /** + * @see java.lang.AutoCloseable#close() + */ + @Override + public void close() throws Exception { + jg.writeEndArray(); + jg.writeEndObject(); + jg.flush(); + IOUtils.closeQuietly(os); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writeMetaData(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writeMetaData(ObjectNode node) throws IOException { + jg.writeObjectField("Metadata", node); //$NON-NLS-1$ + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writeUser(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writeUser(ObjectNode node) throws IOException { + if (!sections.contains("Users")) { //$NON-NLS-1$ + jg.writeArrayFieldStart("Users"); //$NON-NLS-1$ + sections.add("Users"); //$NON-NLS-1$ + } + jg.writeObject(node); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writeGateway(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writeGateway(ObjectNode node) throws IOException { + if (!sections.contains("Gateways")) { //$NON-NLS-1$ + jg.writeEndArray(); + jg.writeArrayFieldStart("Gateways"); //$NON-NLS-1$ + sections.add("Gateways"); //$NON-NLS-1$ + } + jg.writeObject(node); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writePlugin(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writePlugin(ObjectNode node) throws IOException { + if (!sections.contains("Plugins")) { //$NON-NLS-1$ + jg.writeEndArray(); + jg.writeArrayFieldStart("Plugins"); //$NON-NLS-1$ + sections.add("Plugins"); //$NON-NLS-1$ + } + jg.writeObject(node); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writeRole(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writeRole(ObjectNode node) throws IOException { + if (!sections.contains("Roles")) { //$NON-NLS-1$ + jg.writeEndArray(); + jg.writeArrayFieldStart("Roles"); //$NON-NLS-1$ + sections.add("Roles"); //$NON-NLS-1$ + } + jg.writeObject(node); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writePolicyDefinition(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writePolicyDefinition(ObjectNode node) throws IOException { + if (!sections.contains("PolicyDefinitions")) { //$NON-NLS-1$ + jg.writeEndArray(); + jg.writeArrayFieldStart("PolicyDefinitions"); //$NON-NLS-1$ + sections.add("PolicyDefinitions"); //$NON-NLS-1$ + } + jg.writeObject(node); + } + + /** + * @see io.apiman.manager.api.migrator.IDataMigratorWriter#writeOrg(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void writeOrg(ObjectNode node) throws IOException { + if (!sections.contains("Orgs")) { //$NON-NLS-1$ + jg.writeEndArray(); + jg.writeArrayFieldStart("Orgs"); //$NON-NLS-1$ + sections.add("Orgs"); //$NON-NLS-1$ + } + jg.writeObject(node); + } + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/VersionMigratorChain.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/VersionMigratorChain.java new file mode 100644 index 0000000000..dd070b82bf --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/VersionMigratorChain.java @@ -0,0 +1,116 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import java.util.List; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Models a chain of version migrators. Used to apply a set of migrators to a + * piece of data. + * @author eric.wittmann@gmail.com + */ +public class VersionMigratorChain implements IVersionMigrator { + + private final List migrators; + + /** + * Constructor. + */ + public VersionMigratorChain(List migrators) { + this.migrators = migrators; + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateMetaData(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateMetaData(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migrateMetaData(node); + } + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateUser(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateUser(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migrateUser(node); + } + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateGateway(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateGateway(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migrateGateway(node); + } + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migratePlugin(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migratePlugin(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migratePlugin(node); + } + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateRole(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateRole(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migrateRole(node); + } + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migratePolicyDefinition(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migratePolicyDefinition(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migratePolicyDefinition(node); + } + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateOrg(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateOrg(ObjectNode node) { + for (IVersionMigrator migrator : migrators) { + migrator.migrateOrg(node); + } + } + + /** + * @return true if there is at least one migrator in the chain + */ + public boolean hasMigrators() { + return !migrators.isEmpty(); + } + +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/VersionMigrators.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/VersionMigrators.java new file mode 100644 index 0000000000..5b91bf3798 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/VersionMigrators.java @@ -0,0 +1,129 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import io.apiman.manager.api.migrator.vms.Version122FinalMigrator; + +import java.util.ArrayList; +import java.util.List; + +/** + * All of the migrators - one for each version that requires migration (one for + * each version for which a data model change was made). + * @author eric.wittmann@gmail.com + */ +public class VersionMigrators { + + private static final List migrators = new ArrayList<>(); + static { + migrators.add(new Entry("1.2.2.Final", new Version122FinalMigrator())); //$NON-NLS-1$ + } + + /** + * Gets the chain of migrators to use when migrating from version X to version Y. + * @param fromVersion + * @param toVersion + */ + public static VersionMigratorChain chain(String fromVersion, String toVersion) { + List matchedMigrators = new ArrayList<>(); + for (Entry entry : migrators) { + if (entry.isBetween(fromVersion, toVersion)) { + matchedMigrators.add(entry.migrator); + } + } + return new VersionMigratorChain(matchedMigrators); + } + + protected static class Entry { + public final String version; + public final IVersionMigrator migrator; + + /** + * Constructor. + * @param version + * @param migrator + */ + public Entry(String version, IVersionMigrator migrator) { + this.version = version; + this.migrator = migrator; + } + + /** + * Returns true if the version that this entry applies to lies in + * between the given two versions. Note that 'from' is inclusive + * and 'to' is exclusive. + * @param from + * @param to + */ + public boolean isBetween(String from, String to) { + VersionComponents fromV = new VersionComponents(from); + VersionComponents toV = new VersionComponents(to); + VersionComponents v = new VersionComponents(version); + + return v.compareTo(fromV) >= 0 && v.compareTo(toV) < 0; + } + } + + private static class VersionComponents implements Comparable { + public int major; + public int minor; + public int patch; + + /** + * Constructor. + * @param version + */ + public VersionComponents(String version) { + @SuppressWarnings("nls") + String[] split = version.replace("-SNAPSHOT", "").split("\\."); + major = new Integer(split[0]); + minor = new Integer(split[1]); + patch = new Integer(split[2]); + } + + /** + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(VersionComponents other) { + if (major < other.major) { + return -1; + } + if (major > other.major ) { + return 1; + } + + if (minor < other.minor) { + return -1; + } + if (minor > other.minor ) { + return 1; + } + + if (patch < other.patch) { + return -1; + } + if (patch > other.patch ) { + return 1; + } + + return 0; + } + + + } +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/i18n/Messages.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/i18n/Messages.java new file mode 100644 index 0000000000..2796564b43 --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/i18n/Messages.java @@ -0,0 +1,35 @@ +/* + * Copyright 2014 JBoss Inc + * + * 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.apiman.manager.api.migrator.i18n; + +import io.apiman.common.util.AbstractMessages; + +/** + * I18N Messages + * + * @author eric.wittmann@redhat.com + */ +public class Messages extends AbstractMessages { + + public static final Messages i18n = new Messages(); + + /** + * Constructor. + */ + public Messages() { + super(Messages.class); + } +} diff --git a/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/vms/Version122FinalMigrator.java b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/vms/Version122FinalMigrator.java new file mode 100644 index 0000000000..a6a645cdba --- /dev/null +++ b/manager/api/migrator/src/main/java/io/apiman/manager/api/migrator/vms/Version122FinalMigrator.java @@ -0,0 +1,112 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator.vms; + +import io.apiman.manager.api.core.IApiKeyGenerator; +import io.apiman.manager.api.core.UuidApiKeyGenerator; +import io.apiman.manager.api.migrator.IVersionMigrator; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author eric.wittmann@gmail.com + */ +public class Version122FinalMigrator implements IVersionMigrator { + + IApiKeyGenerator keyGenerator = new UuidApiKeyGenerator(); + + /** + * Constructor. + */ + public Version122FinalMigrator() { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateMetaData(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateMetaData(ObjectNode node) { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateUser(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateUser(ObjectNode node) { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateGateway(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateGateway(ObjectNode node) { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migratePlugin(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migratePlugin(ObjectNode node) { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateRole(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateRole(ObjectNode node) { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migratePolicyDefinition(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migratePolicyDefinition(ObjectNode node) { + } + + /** + * @see io.apiman.manager.api.migrator.IVersionMigrator#migrateOrg(com.fasterxml.jackson.databind.node.ObjectNode) + */ + @Override + public void migrateOrg(ObjectNode node) { + ArrayNode clients = (ArrayNode) node.get("Clients"); //$NON-NLS-1$ + if (clients != null && clients.size() > 0) { + for (JsonNode clientNode : clients) { + ObjectNode client = (ObjectNode) clientNode; + ArrayNode versions = (ArrayNode) client.get("Versions"); //$NON-NLS-1$ + if (versions != null && versions.size() > 0) { + for (JsonNode versionNode : versions) { + ObjectNode version = (ObjectNode) versionNode; + + ObjectNode clientVersionBean = (ObjectNode) version.get("ClientVersionBean"); //$NON-NLS-1$ + clientVersionBean.put("apikey", keyGenerator.generate()); //$NON-NLS-1$ + + ArrayNode contracts = (ArrayNode) version.get("Contracts"); //$NON-NLS-1$ + if (contracts != null && contracts.size() > 0) { + for (JsonNode contractNode : contracts) { + ObjectNode contract = (ObjectNode) contractNode; + contract.remove("apikey"); //$NON-NLS-1$ + } + } + } + } + } + } + + } +} diff --git a/manager/api/migrator/src/main/resources/META-INF/beans.xml b/manager/api/migrator/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/manager/api/migrator/src/main/resources/io/apiman/manager/api/migrator/i18n/messages.properties b/manager/api/migrator/src/main/resources/io/apiman/manager/api/migrator/i18n/messages.properties new file mode 100644 index 0000000000..2cf86aa31f --- /dev/null +++ b/manager/api/migrator/src/main/resources/io/apiman/manager/api/migrator/i18n/messages.properties @@ -0,0 +1,7 @@ +DataMigrator.MigratingNow=Migrating export data from old version {0}. +DataMigrator.MigratingUser=Migrating User: {0} +DataMigrator.MigratingGateway=Migrating Gateway: {0} +DataMigrator.MigratingPlugin=Migrating Plugin: {0} +DataMigrator.MigratingRole=Migrating Role: {0} +DataMigrator.MigratingPolicyDef=Migrating Policy Def: {0} +DataMigrator.MigratingOrg=Migrating Organization: {0} diff --git a/manager/api/migrator/src/test/java/io/apiman/manager/api/migrator/DataMigratorTest.java b/manager/api/migrator/src/test/java/io/apiman/manager/api/migrator/DataMigratorTest.java new file mode 100644 index 0000000000..b15d1e24b2 --- /dev/null +++ b/manager/api/migrator/src/test/java/io/apiman/manager/api/migrator/DataMigratorTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import io.apiman.manager.api.config.Version; +import io.apiman.manager.api.core.logging.StringBuilderLogger; +import io.apiman.test.common.json.JsonArrayOrderingType; +import io.apiman.test.common.json.JsonCompare; +import io.apiman.test.common.json.JsonMissingFieldType; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.util.Date; + +import org.apache.commons.io.FileUtils; +import org.junit.Test; + +/** + * @author eric.wittmann@gmail.com + */ +@SuppressWarnings("nls") +public class DataMigratorTest { + + /** + * Test method for {@link io.apiman.manager.api.migrator.DataMigrator#migrate(java.io.File, java.io.File)}. + */ + @Test + public void testMigrate122to123() throws Exception { + doTest( "export-files/export-from-1.2.2.Final.json", + "export-files/export-from-1.2.2.Final_expected.json", + "1.2.3.Final"); + } + + private void doTest(String fileToMigrate, String expectedResultFile, String versionToMigrateTo) throws Exception { + Version version = new Version(); + setVersion(version, versionToMigrateTo); + StringBuilderLogger logger = new StringBuilderLogger(); + + File tempOutputFile = File.createTempFile("_apiman", "tst"); + tempOutputFile.deleteOnExit(); + + try { + DataMigrator migrator = new DataMigrator(); + migrator.setLogger(logger); + migrator.setVersion(version); + + InputStream input = getClass().getClassLoader().getResourceAsStream(fileToMigrate); + OutputStream output = new FileOutputStream(tempOutputFile); + + // Migrate the data! + migrator.migrate(input, output); + + JsonCompare compare = new JsonCompare(); + compare.setArrayOrdering(JsonArrayOrderingType.strict); + compare.setIgnoreCase(false); + compare.setMissingField(JsonMissingFieldType.fail); + try ( FileInputStream actual = new FileInputStream(tempOutputFile); + InputStream expected = getClass().getClassLoader().getResourceAsStream(expectedResultFile); ) { + compare.assertJson(expected, actual); + } + } finally { + FileUtils.deleteQuietly(tempOutputFile); + } + } + + /** + * @param version + * @param versionString + * @throws Exception + */ + private static void setVersion(Version version, String versionString) throws Exception { + Field field = version.getClass().getDeclaredField("versionString"); + field.setAccessible(true); + field.set(version, versionString); + + field = version.getClass().getDeclaredField("versionDate"); + field.setAccessible(true); + field.set(version, new Date().toString()); + } + +} diff --git a/manager/api/migrator/src/test/java/io/apiman/manager/api/migrator/VersionMigratorsTest.java b/manager/api/migrator/src/test/java/io/apiman/manager/api/migrator/VersionMigratorsTest.java new file mode 100644 index 0000000000..6aa9034f49 --- /dev/null +++ b/manager/api/migrator/src/test/java/io/apiman/manager/api/migrator/VersionMigratorsTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.manager.api.migrator; + +import io.apiman.manager.api.migrator.VersionMigrators.Entry; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author eric.wittmann@gmail.com + */ +@SuppressWarnings("nls") +public class VersionMigratorsTest { + + @Test + public void testVersionComponents1() { + Entry entry = new Entry("1.2.2.Final", null); + Assert.assertTrue(entry.isBetween("1.2.0-SNAPSHOT", "1.2.3.Final")); + Assert.assertTrue(entry.isBetween("0.1.1.CR1", "2.2.7-SNAPSHOT")); + + Assert.assertFalse(entry.isBetween("2.1.3.Final", "2.4.7.Final")); + Assert.assertFalse(entry.isBetween("1.0.3.Final", "1.0.9.Final")); + Assert.assertFalse(entry.isBetween("1.0.0.Final", "1.2.2.Final")); + } + + @Test + public void testVersionComponents2() { + Entry entry = new Entry("10.2.783.Final", null); + Assert.assertTrue(entry.isBetween("1.0.0.Final", "11.7.3-SNAPSHOT")); + + Assert.assertFalse(entry.isBetween("1.2.0-SNAPSHOT", "1.2.3.Final")); + Assert.assertFalse(entry.isBetween("0.1.1.CR1", "2.2.7-SNAPSHOT")); + Assert.assertFalse(entry.isBetween("2.1.3.Final", "2.4.7.Final")); + Assert.assertFalse(entry.isBetween("1.0.3.Final", "1.0.9.Final")); + } + +} diff --git a/manager/api/migrator/src/test/resources/export-files/export-from-1.2.2.Final.json b/manager/api/migrator/src/test/resources/export-files/export-from-1.2.2.Final.json new file mode 100644 index 0000000000..420e5a93ec --- /dev/null +++ b/manager/api/migrator/src/test/resources/export-files/export-from-1.2.2.Final.json @@ -0,0 +1,1568 @@ +{ + "Metadata" : { + "exportedOn" : "2016-03-17T14:53:01Z", + "apimanVersion" : "1.2.2.Final" + }, + "Users" : [ { + "username" : "admin", + "fullName" : "Admin", + "email" : "admin@example.org", + "joinedOn" : "2016-02-29T13:43:22Z", + "admin" : false + } ], + "Gateways" : [ { + "id" : "TheGateway", + "name" : "The Gateway", + "description" : "This is the gateway.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-02-29T13:43:24Z", + "type" : "REST", + "configuration" : "{\"endpoint\":\"https://localhost:8443/apiman-gateway-api\",\"username\":\"apimanager\",\"password\":\"$CRYPT::nexST5ZhchjjNnLBpQBqrA==\"}" + } ], + "Plugins" : [ { + "id" : 78, + "groupId" : "io.apiman.plugins", + "artifactId" : "apiman-plugins-log-policy", + "version" : "1.2.2.Final", + "name" : "Log Policy Plugin", + "description" : "This plugin has policies for logging to std out.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:39Z", + "deleted" : false + }, { + "id" : 79, + "groupId" : "io.apiman.plugins", + "artifactId" : "apiman-plugins-jsonp-policy", + "version" : "1.2.2.Final", + "name" : "JSONP Policy Plugin", + "description" : "A plugin that contributes a policy that turns a standard RESTful endpoint into a JSONP compatible endpoint.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:49Z", + "deleted" : false + } ], + "Roles" : [ { + "id" : "OrganizationOwner", + "name" : "Organization Owner", + "description" : "Automatically granted to the user who creates an Organization. Grants all privileges.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:23Z", + "autoGrant" : true, + "permissions" : [ "orgView", "apiAdmin", "apiView", "planEdit", "planView", "apiEdit", "clientAdmin", "orgEdit", "clientView", "planAdmin", "orgAdmin", "clientEdit" ] + }, { + "id" : "ClientAppDeveloper", + "name" : "Client App Developer", + "description" : "Users responsible for creating and managing client apps should be granted this role within an Organization.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "permissions" : [ "clientAdmin", "clientView", "clientEdit" ] + }, { + "id" : "APIDeveloper", + "name" : "API Developer", + "description" : "Users responsible for creating and managing APIs should be granted this role within an Organization.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "permissions" : [ "apiAdmin", "apiView", "planEdit", "planView", "apiEdit", "planAdmin" ] + }, { + "id" : "PlanMaster", + "name" : "Plan Master", + "description" : "The master of all plans!", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:20Z", + "permissions" : [ "planEdit", "planView", "planAdmin" ] + } ], + "PolicyDefinitions" : [ { + "id" : "IPWhitelistPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IPWhitelistPolicy", + "name" : "IP Whitelist Policy", + "description" : "Only requests that originate from a specified set of valid IP addresses will be allowed through.", + "icon" : "filter", + "templates" : [ { + "template" : "Only requests that originate from the set of ${ipList.size()} configured IP address(es) will be allowed to invoke the managed API." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "IPBlacklistPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IPBlacklistPolicy", + "name" : "IP Blacklist Policy", + "description" : "Requests that originate from a specified set of valid IP addresses will be denied access.", + "icon" : "thumbs-down", + "templates" : [ { + "template" : "Requests that originate from the set of ${ipList.size()} configured IP address(es) will be denied access to the managed API." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "BASICAuthenticationPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.BasicAuthenticationPolicy", + "name" : "BASIC Authentication Policy", + "description" : "Enables HTTP BASIC Authentication on an API. Some configuration required.", + "icon" : "lock", + "templates" : [ { + "template" : "Access to the API is protected by BASIC Authentication through the '${realm}' authentication realm. @if{forwardIdentityHttpHeader != null}Successfully authenticated requests will forward the authenticated identity to the back end API via the '${forwardIdentityHttpHeader}' custom HTTP header.@end{}" + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "RateLimitingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.RateLimitingPolicy", + "name" : "Rate Limiting Policy", + "description" : "Enforces rate configurable request rate limits on an API. This ensures that consumers can't overload an API with too many requests.", + "icon" : "sliders", + "templates" : [ { + "template" : "Consumers are limited to ${limit} requests per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "IgnoredResourcesPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IgnoredResourcesPolicy", + "name" : "Ignored Resources Policy", + "description" : "Requests satisfying the provided regular expression will be ignored.", + "icon" : "eye-slash", + "templates" : [ { + "template" : "Requests matching any of the ${rules.size()} regular expressions provided will receive a 404 error code." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "AuthorizationPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.AuthorizationPolicy", + "name" : "Authorization Policy", + "description" : "Enables fine grained authorization to API resources based on authenticated user roles.", + "icon" : "users", + "templates" : [ { + "template" : "Appropriate authorization roles are required. There are ${rules.size()} authorization rules defined." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "QuotaPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.QuotaPolicy", + "name" : "Quota Policy", + "description" : "Provides a way to limit the total number of requests that can be sent to an API.", + "icon" : "exchange", + "templates" : [ { + "template" : "Consumers cannot exceed their quota of ${limit} requests per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "CachingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.CachingPolicy", + "name" : "Caching Policy", + "description" : "Allows caching of API responses in the Gateway to reduce overall traffic to the back-end API.", + "icon" : "hdd-o", + "templates" : [ { + "template" : "API responses will be cached for ${ttl} seconds." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "TransferQuotaPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.TransferQuotaPolicy", + "name" : "Transfer Quota Policy", + "description" : "Provides a way to limit the total number of bytes that can be transferred from (or to) an API.", + "icon" : "download", + "templates" : [ { + "template" : "Consumers are limited to transferring ${limit} bytes per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "URLRewritingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.URLRewritingPolicy", + "name" : "URL Rewriting Policy", + "description" : "Responses from the back-end API will be modified by fixing up any incorrect URLs found with modified ones. This is useful because apiman works through an API Gateway.", + "icon" : "pencil-square", + "templates" : [ { + "template" : "Responses will be modified by finding all text matching regular expression '${fromRegex}' with '${toReplacement}'." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "TimeRestrictedAccessPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.TimeRestrictedAccessPolicy", + "name" : "Time Restricted Access Policy", + "description" : "Requests matching the specified regular expression and made within the specified time period will be ignored.", + "icon" : "clock-o", + "templates" : [ { + "template" : "Requests matching the regular expression and made outside the specified time period will receive a 423 error code." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "log-headers-policy", + "policyImpl" : "plugin:io.apiman.plugins:apiman-plugins-log-policy:1.2.2.Final:war/io.apiman.plugins.log_policy.LogHeadersPolicy", + "name" : "Log Headers Policy", + "description" : "A policy that logs the headers to std out. Useful to analyse inbound HTTP traffic to the gateway when added as the first policy in the chain or to analyse outbound HTTP traffic from the gateway when added as the last policy in the chain.", + "icon" : "fire", + "templates" : [ ], + "pluginId" : 78, + "formType" : "JsonSchema", + "form" : "schemas/log-policyDef.schema", + "deleted" : false + }, { + "id" : "jsonp-policy", + "policyImpl" : "plugin:io.apiman.plugins:apiman-plugins-jsonp-policy:1.2.2.Final:war/io.apiman.plugins.jsonp_policy.JsonpPolicy", + "name" : "JSONP Policy", + "description" : "Turns an endpoint into a JSONP compatible endpoint.", + "icon" : "bars", + "templates" : [ ], + "pluginId" : 79, + "formType" : "JsonSchema", + "form" : "schemas/jsonp-policyDef.schema", + "deleted" : false + } ], + "Orgs" : [ { + "OrganizationBean" : { + "id" : "Test", + "name" : "Test", + "description" : "A test organization used by the full apiman smoke test suite.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:51Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:51Z" + }, + "Memberships" : [ { + "id" : 2, + "userId" : "admin", + "roleId" : "OrganizationOwner", + "organizationId" : "Test", + "createdOn" : "2016-03-17T09:47:51Z" + } ], + "Plans" : [ { + "PlanBean" : { + "id" : "Gold", + "name" : "Gold", + "description" : "The Gold plan allows users the highest level of API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 5, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "lockedOn" : "2016-03-17T09:47:52Z" + }, + "Policies" : [ { + "id" : 9, + "type" : "Plan", + "organizationId" : "Test", + "entityId" : "Gold", + "entityVersion" : "1.0", + "name" : "Rate Limiting Policy", + "configuration" : "{ \"limit\" : 100, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "definition" : { + "id" : "RateLimitingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + }, { + "PlanBean" : { + "id" : "Silver", + "name" : "Silver", + "description" : "The Silver plan allows users a lower level of API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 7, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "lockedOn" : "2016-03-17T09:47:52Z" + }, + "Policies" : [ { + "id" : 11, + "type" : "Plan", + "organizationId" : "Test", + "entityId" : "Silver", + "entityVersion" : "1.0", + "name" : "Rate Limiting Policy", + "configuration" : "{ \"limit\" : 5, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "definition" : { + "id" : "RateLimitingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Apis" : [ { + "ApiBean" : { + "id" : "echo", + "name" : "echo", + "description" : "A simple echo REST API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 16, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo/echo", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Gold", + "version" : "1.0" + }, { + "planId" : "Silver", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "publishedOn" : "2016-03-17T09:47:53Z" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "public-echo", + "name" : "public-echo", + "description" : "A public echo REST API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 21, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo/public-echo", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:53Z", + "publishedOn" : "2016-03-17T09:47:53Z" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "public-echo-two", + "name" : "public-echo-two", + "description" : "A second public echo API. Tests some plugin policies.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:50:35Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 81, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo", + "endpointType" : "rest", + "endpointContentType" : "json", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:50:35Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:51:01Z", + "publishedOn" : "2016-03-17T10:51:29Z" + }, + "Policies" : [ { + "id" : 85, + "type" : "Api", + "organizationId" : "Test", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "name" : "Log Headers Policy", + "configuration" : "{\"direction\":\"both\"}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:51:01Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:51:01Z", + "definition" : { + "id" : "log-headers-policy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Clients" : [ { + "ClientBean" : { + "id" : "client1", + "name" : "client1", + "description" : "A simple test client.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z" + }, + "Versions" : [ { + "ClientVersionBean" : { + "id" : 26, + "status" : "Registered", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:54:34Z", + "publishedOn" : "2016-03-17T09:54:40Z" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 28, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Gold" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:54:34Z", + "apikey" : "98571b7b-8fc7-4cce-b826-a8264020e211" + } ] + }, { + "ClientVersionBean" : { + "id" : 95, + "status" : "Ready", + "version" : "1.1", + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:05Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T13:28:22Z" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 100, + "api" : { + "api" : { + "organization" : { + "id" : "Foo" + }, + "id" : "foo-echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Foo" + }, + "id" : "Great" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:22Z", + "apikey" : "ac025635-e69d-49da-b9b8-4d960aa832cc" + }, { + "id" : 97, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Gold" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:05Z", + "apikey" : "4e9a4655-d6ee-4591-97fe-e8be5adfe5b0" + } ] + } ] + } ], + "Audits" : [ { + "id" : 1, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Organization", + "createdOn" : "2016-03-17T09:47:51Z", + "what" : "Create" + }, { + "id" : 3, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 4, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 6, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 8, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 10, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, { + "id" : 12, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, { + "id" : 13, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Lock" + }, { + "id" : 14, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Lock" + }, { + "id" : 15, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 17, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 18, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Gold:1.0, Silver:1.0\"},{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"}]}" + }, { + "id" : 19, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Publish" + }, { + "id" : 20, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 22, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 23, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/public-echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, { + "id" : 24, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Publish" + }, { + "id" : 25, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 27, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 29, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:34Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 30, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:34Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 31, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:40Z", + "what" : "Register" + }, { + "id" : 80, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "createdOn" : "2016-03-17T10:50:35Z", + "what" : "Create" + }, { + "id" : 82, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:35Z", + "what" : "Create" + }, { + "id" : 83, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:40Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, { + "id" : 84, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:44Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, { + "id" : 86, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:51:01Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"log-headers-policy\"}" + }, { + "id" : 87, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:51:29Z", + "what" : "Publish" + }, { + "id" : 93, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:51Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, { + "id" : 96, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "Create" + }, { + "id" : 98, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 99, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 101, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:22Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } ] + }, { + "OrganizationBean" : { + "id" : "Foo", + "name" : "Foo", + "description" : "An amazing organization so that we have two for testing.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:54:54Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:54:54Z" + }, + "Memberships" : [ { + "id" : 33, + "userId" : "admin", + "roleId" : "OrganizationOwner", + "organizationId" : "Foo", + "createdOn" : "2016-03-17T09:54:54Z" + } ], + "Plans" : [ { + "PlanBean" : { + "id" : "Good", + "name" : "Good", + "description" : "A pretty good plan.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:06Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 35, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:06Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:55:14Z", + "lockedOn" : "2016-03-17T09:55:15Z" + }, + "Policies" : [ { + "id" : 37, + "type" : "Plan", + "organizationId" : "Foo", + "entityId" : "Good", + "entityVersion" : "1.0", + "name" : "Caching Policy", + "configuration" : "{\"ttl\":10}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:14Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:55:14Z", + "definition" : { + "id" : "CachingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + }, { + "PlanBean" : { + "id" : "Great", + "name" : "Great", + "description" : "A really great plan.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:20Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 41, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:20Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:56:15Z", + "lockedOn" : "2016-03-17T09:56:26Z" + }, + "Policies" : [ { + "id" : 43, + "type" : "Plan", + "organizationId" : "Foo", + "entityId" : "Great", + "entityVersion" : "1.0", + "name" : "Time Restricted Access Policy", + "configuration" : "{\"rules\":[{\"timeStart\":\"2016-03-17T13:00:00.000Z\",\"timeEnd\":\"2016-03-17T21:00:00.000Z\",\"dayStart\":4,\"dayEnd\":5,\"pathPattern\":\".*\"}]}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:15Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:56:15Z", + "definition" : { + "id" : "TimeRestrictedAccessPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Apis" : [ { + "ApiBean" : { + "id" : "foo-echo", + "name" : "foo-echo", + "description" : "An echo service inside the Foo organization.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:33Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 47, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo", + "endpointType" : "rest", + "endpointContentType" : "json", + "endpointProperties" : { + "authorization.type" : "basic", + "basic-auth.requireSSL" : "false", + "basic-auth.username" : "username", + "basic-auth.password" : "password" + }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:33Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:59:25Z", + "publishedOn" : "2016-03-17T10:03:01Z", + "definitionType" : "SwaggerJSON" + }, + "Policies" : [ { + "id" : 52, + "type" : "Api", + "organizationId" : "Foo", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "name" : "BASIC Authentication Policy", + "configuration" : "{\"realm\":\"Foo Echo\",\"forwardIdentityHttpHeader\":\"X-Identity\",\"requireBasicAuth\":true,\"staticIdentity\":{\"identities\":[{\"username\":\"user\",\"password\":\"user\"},{\"username\":\"user1\",\"password\":\"user1\"},{\"username\":\"user2\",\"password\":\"user2\"}]}}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:58:46Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:58:46Z", + "definition" : { + "id" : "BASICAuthenticationPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + }, { + "id" : 54, + "type" : "Api", + "organizationId" : "Foo", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "name" : "Ignored Resources Policy", + "configuration" : "{\"rules\":[{\"verb\":\"*\",\"pathPattern\":\"/admin/.*\"}]}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:59:25Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:59:25Z", + "definition" : { + "id" : "IgnoredResourcesPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 2 + } ] + } ] + }, { + "ApiBean" : { + "id" : "FacebookAPI", + "name" : "Facebook API", + "description" : "The Facebook API is a platform for building applications that are available to the members of the social network of Facebook.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:54Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 65, + "status" : "Published", + "endpoint" : "http://api.facebook.com/restserver.php", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:54Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:05:54Z", + "publishedOn" : "2016-03-17T10:06:11Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "FlickrAPI", + "name" : "Flickr API", + "description" : "The Flickr API can be used to retrieve photos from the Flickr photo sharing service using a variety of feeds.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:55Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 68, + "status" : "Published", + "endpoint" : "http://api.flickr.com/services/rest/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:55Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:05:55Z", + "publishedOn" : "2016-03-17T10:06:15Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "TwitterAPI", + "name" : "Twitter API", + "description" : "The Twitter micro-blogging service includes two RESTful APIs.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:56Z" + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 73, + "status" : "Ready", + "endpoint" : "http://twitter.com/statuses/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:56Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:06:56Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "YouTubeAPI", + "name" : "YouTube API", + "description" : "The Data API allows users to integrate their program with YouTube and allow it to perform many of the operations available on the website.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:57Z" + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 76, + "status" : "Ready", + "endpoint" : "http://gdata.youtube.com/feeds/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:57Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:06:57Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + } ], + "Clients" : [ { + "ClientBean" : { + "id" : "foo-app", + "name" : "foo-app", + "description" : "The foo app! It probably uses the foo-echo API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:26Z" + }, + "Versions" : [ { + "ClientVersionBean" : { + "id" : 62, + "status" : "Registered", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:26Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T13:26:51Z", + "publishedOn" : "2016-03-17T13:26:57Z" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 88, + "api" : { + "api" : { + "organization" : { + "id" : "Foo" + }, + "id" : "foo-echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Foo" + }, + "id" : "Good" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:26:43Z", + "apikey" : "8844afff-ba78-4910-a3a7-3cd5436e6d49" + }, { + "id" : 91, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Silver" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:26:51Z", + "apikey" : "db4c4bf5-153e-407e-9d3a-a28ad43c84c6" + } ] + } ] + } ], + "Audits" : [ { + "id" : 32, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Organization", + "createdOn" : "2016-03-17T09:54:54Z", + "what" : "Create" + }, { + "id" : 34, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "createdOn" : "2016-03-17T09:55:06Z", + "what" : "Create" + }, { + "id" : 36, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:06Z", + "what" : "Create" + }, { + "id" : 38, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:14Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"CachingPolicy\"}" + }, { + "id" : 39, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:15Z", + "what" : "Lock" + }, { + "id" : 40, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "createdOn" : "2016-03-17T09:55:20Z", + "what" : "Create" + }, { + "id" : 42, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:20Z", + "what" : "Create" + }, { + "id" : 44, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:15Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"TimeRestrictedAccessPolicy\"}" + }, { + "id" : 45, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:26Z", + "what" : "Lock" + }, { + "id" : 46, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "createdOn" : "2016-03-17T09:56:33Z", + "what" : "Create" + }, { + "id" : 48, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:33Z", + "what" : "Create" + }, { + "id" : 49, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:57:29Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, { + "id" : 50, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:06Z", + "what" : "UpdateDefinition" + }, { + "id" : 51, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:16Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Good:1.0, Great:1.0\"}]}" + }, { + "id" : 53, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:46Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"BASICAuthenticationPolicy\"}" + }, { + "id" : 55, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:59:25Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"IgnoredResourcesPolicy\"}" + }, { + "id" : 56, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:03:01Z", + "what" : "Publish" + }, { + "id" : 57, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Organization", + "createdOn" : "2016-03-17T10:04:33Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An amazing organization so that we have two for testing.\"}]}" + }, { + "id" : 58, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "createdOn" : "2016-03-17T10:04:42Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A pretty good plan.\"}]}" + }, { + "id" : 59, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "createdOn" : "2016-03-17T10:04:49Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A really great plan.\"}]}" + }, { + "id" : 60, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "createdOn" : "2016-03-17T10:05:00Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An echo service inside the Foo organization.\"}]}" + }, { + "id" : 61, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "createdOn" : "2016-03-17T10:05:26Z", + "what" : "Create" + }, { + "id" : 63, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:26Z", + "what" : "Create" + }, { + "id" : 64, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "createdOn" : "2016-03-17T10:05:54Z", + "what" : "Create" + }, { + "id" : 66, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:54Z", + "what" : "Create" + }, { + "id" : 67, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "createdOn" : "2016-03-17T10:05:55Z", + "what" : "Create" + }, { + "id" : 69, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:55Z", + "what" : "Create" + }, { + "id" : 70, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:11Z", + "what" : "Publish" + }, { + "id" : 71, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:15Z", + "what" : "Publish" + }, { + "id" : 72, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "TwitterAPI", + "createdOn" : "2016-03-17T10:06:56Z", + "what" : "Create" + }, { + "id" : 74, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "TwitterAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:56Z", + "what" : "Create" + }, { + "id" : 75, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "YouTubeAPI", + "createdOn" : "2016-03-17T10:06:57Z", + "what" : "Create" + }, { + "id" : 77, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "YouTubeAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:57Z", + "what" : "Create" + }, { + "id" : 89, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:43Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, { + "id" : 90, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:43Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, { + "id" : 92, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:51Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, { + "id" : 94, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:57Z", + "what" : "Register" + }, { + "id" : 102, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:28:22Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } ] + } ] +} \ No newline at end of file diff --git a/manager/api/migrator/src/test/resources/export-files/export-from-1.2.2.Final_expected.json b/manager/api/migrator/src/test/resources/export-files/export-from-1.2.2.Final_expected.json new file mode 100644 index 0000000000..8de1a11283 --- /dev/null +++ b/manager/api/migrator/src/test/resources/export-files/export-from-1.2.2.Final_expected.json @@ -0,0 +1,1566 @@ +{ + "Metadata" : { + "exportedOn" : "2016-03-17T14:53:01Z", + "apimanVersion" : "1.2.3.Final" + }, + "Users" : [ { + "username" : "admin", + "fullName" : "Admin", + "email" : "admin@example.org", + "joinedOn" : "2016-02-29T13:43:22Z", + "admin" : false + } ], + "Gateways" : [ { + "id" : "TheGateway", + "name" : "The Gateway", + "description" : "This is the gateway.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-02-29T13:43:24Z", + "type" : "REST", + "configuration" : "{\"endpoint\":\"https://localhost:8443/apiman-gateway-api\",\"username\":\"apimanager\",\"password\":\"$CRYPT::nexST5ZhchjjNnLBpQBqrA==\"}" + } ], + "Plugins" : [ { + "id" : 78, + "groupId" : "io.apiman.plugins", + "artifactId" : "apiman-plugins-log-policy", + "version" : "1.2.2.Final", + "name" : "Log Policy Plugin", + "description" : "This plugin has policies for logging to std out.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:39Z", + "deleted" : false + }, { + "id" : 79, + "groupId" : "io.apiman.plugins", + "artifactId" : "apiman-plugins-jsonp-policy", + "version" : "1.2.2.Final", + "name" : "JSONP Policy Plugin", + "description" : "A plugin that contributes a policy that turns a standard RESTful endpoint into a JSONP compatible endpoint.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:49Z", + "deleted" : false + } ], + "Roles" : [ { + "id" : "OrganizationOwner", + "name" : "Organization Owner", + "description" : "Automatically granted to the user who creates an Organization. Grants all privileges.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:23Z", + "autoGrant" : true, + "permissions" : [ "orgView", "apiAdmin", "apiView", "planEdit", "planView", "apiEdit", "clientAdmin", "orgEdit", "clientView", "planAdmin", "orgAdmin", "clientEdit" ] + }, { + "id" : "ClientAppDeveloper", + "name" : "Client App Developer", + "description" : "Users responsible for creating and managing client apps should be granted this role within an Organization.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "permissions" : [ "clientAdmin", "clientView", "clientEdit" ] + }, { + "id" : "APIDeveloper", + "name" : "API Developer", + "description" : "Users responsible for creating and managing APIs should be granted this role within an Organization.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "permissions" : [ "apiAdmin", "apiView", "planEdit", "planView", "apiEdit", "planAdmin" ] + }, { + "id" : "PlanMaster", + "name" : "Plan Master", + "description" : "The master of all plans!", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:20Z", + "permissions" : [ "planEdit", "planView", "planAdmin" ] + } ], + "PolicyDefinitions" : [ { + "id" : "IPWhitelistPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IPWhitelistPolicy", + "name" : "IP Whitelist Policy", + "description" : "Only requests that originate from a specified set of valid IP addresses will be allowed through.", + "icon" : "filter", + "templates" : [ { + "template" : "Only requests that originate from the set of ${ipList.size()} configured IP address(es) will be allowed to invoke the managed API." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "IPBlacklistPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IPBlacklistPolicy", + "name" : "IP Blacklist Policy", + "description" : "Requests that originate from a specified set of valid IP addresses will be denied access.", + "icon" : "thumbs-down", + "templates" : [ { + "template" : "Requests that originate from the set of ${ipList.size()} configured IP address(es) will be denied access to the managed API." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "BASICAuthenticationPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.BasicAuthenticationPolicy", + "name" : "BASIC Authentication Policy", + "description" : "Enables HTTP BASIC Authentication on an API. Some configuration required.", + "icon" : "lock", + "templates" : [ { + "template" : "Access to the API is protected by BASIC Authentication through the '${realm}' authentication realm. @if{forwardIdentityHttpHeader != null}Successfully authenticated requests will forward the authenticated identity to the back end API via the '${forwardIdentityHttpHeader}' custom HTTP header.@end{}" + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "RateLimitingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.RateLimitingPolicy", + "name" : "Rate Limiting Policy", + "description" : "Enforces rate configurable request rate limits on an API. This ensures that consumers can't overload an API with too many requests.", + "icon" : "sliders", + "templates" : [ { + "template" : "Consumers are limited to ${limit} requests per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "IgnoredResourcesPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IgnoredResourcesPolicy", + "name" : "Ignored Resources Policy", + "description" : "Requests satisfying the provided regular expression will be ignored.", + "icon" : "eye-slash", + "templates" : [ { + "template" : "Requests matching any of the ${rules.size()} regular expressions provided will receive a 404 error code." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "AuthorizationPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.AuthorizationPolicy", + "name" : "Authorization Policy", + "description" : "Enables fine grained authorization to API resources based on authenticated user roles.", + "icon" : "users", + "templates" : [ { + "template" : "Appropriate authorization roles are required. There are ${rules.size()} authorization rules defined." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "QuotaPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.QuotaPolicy", + "name" : "Quota Policy", + "description" : "Provides a way to limit the total number of requests that can be sent to an API.", + "icon" : "exchange", + "templates" : [ { + "template" : "Consumers cannot exceed their quota of ${limit} requests per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "CachingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.CachingPolicy", + "name" : "Caching Policy", + "description" : "Allows caching of API responses in the Gateway to reduce overall traffic to the back-end API.", + "icon" : "hdd-o", + "templates" : [ { + "template" : "API responses will be cached for ${ttl} seconds." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "TransferQuotaPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.TransferQuotaPolicy", + "name" : "Transfer Quota Policy", + "description" : "Provides a way to limit the total number of bytes that can be transferred from (or to) an API.", + "icon" : "download", + "templates" : [ { + "template" : "Consumers are limited to transferring ${limit} bytes per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "URLRewritingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.URLRewritingPolicy", + "name" : "URL Rewriting Policy", + "description" : "Responses from the back-end API will be modified by fixing up any incorrect URLs found with modified ones. This is useful because apiman works through an API Gateway.", + "icon" : "pencil-square", + "templates" : [ { + "template" : "Responses will be modified by finding all text matching regular expression '${fromRegex}' with '${toReplacement}'." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "TimeRestrictedAccessPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.TimeRestrictedAccessPolicy", + "name" : "Time Restricted Access Policy", + "description" : "Requests matching the specified regular expression and made within the specified time period will be ignored.", + "icon" : "clock-o", + "templates" : [ { + "template" : "Requests matching the regular expression and made outside the specified time period will receive a 423 error code." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "log-headers-policy", + "policyImpl" : "plugin:io.apiman.plugins:apiman-plugins-log-policy:1.2.2.Final:war/io.apiman.plugins.log_policy.LogHeadersPolicy", + "name" : "Log Headers Policy", + "description" : "A policy that logs the headers to std out. Useful to analyse inbound HTTP traffic to the gateway when added as the first policy in the chain or to analyse outbound HTTP traffic from the gateway when added as the last policy in the chain.", + "icon" : "fire", + "templates" : [ ], + "pluginId" : 78, + "formType" : "JsonSchema", + "form" : "schemas/log-policyDef.schema", + "deleted" : false + }, { + "id" : "jsonp-policy", + "policyImpl" : "plugin:io.apiman.plugins:apiman-plugins-jsonp-policy:1.2.2.Final:war/io.apiman.plugins.jsonp_policy.JsonpPolicy", + "name" : "JSONP Policy", + "description" : "Turns an endpoint into a JSONP compatible endpoint.", + "icon" : "bars", + "templates" : [ ], + "pluginId" : 79, + "formType" : "JsonSchema", + "form" : "schemas/jsonp-policyDef.schema", + "deleted" : false + } ], + "Orgs" : [ { + "OrganizationBean" : { + "id" : "Test", + "name" : "Test", + "description" : "A test organization used by the full apiman smoke test suite.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:51Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:51Z" + }, + "Memberships" : [ { + "id" : 2, + "userId" : "admin", + "roleId" : "OrganizationOwner", + "organizationId" : "Test", + "createdOn" : "2016-03-17T09:47:51Z" + } ], + "Plans" : [ { + "PlanBean" : { + "id" : "Gold", + "name" : "Gold", + "description" : "The Gold plan allows users the highest level of API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 5, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "lockedOn" : "2016-03-17T09:47:52Z" + }, + "Policies" : [ { + "id" : 9, + "type" : "Plan", + "organizationId" : "Test", + "entityId" : "Gold", + "entityVersion" : "1.0", + "name" : "Rate Limiting Policy", + "configuration" : "{ \"limit\" : 100, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "definition" : { + "id" : "RateLimitingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + }, { + "PlanBean" : { + "id" : "Silver", + "name" : "Silver", + "description" : "The Silver plan allows users a lower level of API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 7, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "lockedOn" : "2016-03-17T09:47:52Z" + }, + "Policies" : [ { + "id" : 11, + "type" : "Plan", + "organizationId" : "Test", + "entityId" : "Silver", + "entityVersion" : "1.0", + "name" : "Rate Limiting Policy", + "configuration" : "{ \"limit\" : 5, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "definition" : { + "id" : "RateLimitingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Apis" : [ { + "ApiBean" : { + "id" : "echo", + "name" : "echo", + "description" : "A simple echo REST API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 16, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo/echo", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Gold", + "version" : "1.0" + }, { + "planId" : "Silver", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "publishedOn" : "2016-03-17T09:47:53Z" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "public-echo", + "name" : "public-echo", + "description" : "A public echo REST API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 21, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo/public-echo", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:53Z", + "publishedOn" : "2016-03-17T09:47:53Z" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "public-echo-two", + "name" : "public-echo-two", + "description" : "A second public echo API. Tests some plugin policies.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:50:35Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 81, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo", + "endpointType" : "rest", + "endpointContentType" : "json", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:50:35Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:51:01Z", + "publishedOn" : "2016-03-17T10:51:29Z" + }, + "Policies" : [ { + "id" : 85, + "type" : "Api", + "organizationId" : "Test", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "name" : "Log Headers Policy", + "configuration" : "{\"direction\":\"both\"}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:51:01Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:51:01Z", + "definition" : { + "id" : "log-headers-policy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Clients" : [ { + "ClientBean" : { + "id" : "client1", + "name" : "client1", + "description" : "A simple test client.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z" + }, + "Versions" : [ { + "ClientVersionBean" : { + "id" : 26, + "status" : "Registered", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:54:34Z", + "publishedOn" : "2016-03-17T09:54:40Z", + "apikey" : "*" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 28, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Gold" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:54:34Z" + } ] + }, { + "ClientVersionBean" : { + "id" : 95, + "status" : "Ready", + "version" : "1.1", + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:05Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T13:28:22Z", + "apikey" : "*" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 100, + "api" : { + "api" : { + "organization" : { + "id" : "Foo" + }, + "id" : "foo-echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Foo" + }, + "id" : "Great" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:22Z" + }, { + "id" : 97, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Gold" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:05Z" + } ] + } ] + } ], + "Audits" : [ { + "id" : 1, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Organization", + "createdOn" : "2016-03-17T09:47:51Z", + "what" : "Create" + }, { + "id" : 3, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 4, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 6, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 8, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 10, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, { + "id" : 12, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, { + "id" : 13, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Lock" + }, { + "id" : 14, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Lock" + }, { + "id" : 15, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 17, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 18, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Gold:1.0, Silver:1.0\"},{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"}]}" + }, { + "id" : 19, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Publish" + }, { + "id" : 20, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 22, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 23, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/public-echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, { + "id" : 24, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Publish" + }, { + "id" : 25, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 27, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 29, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:34Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 30, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:34Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 31, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:40Z", + "what" : "Register" + }, { + "id" : 80, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "createdOn" : "2016-03-17T10:50:35Z", + "what" : "Create" + }, { + "id" : 82, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:35Z", + "what" : "Create" + }, { + "id" : 83, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:40Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, { + "id" : 84, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:44Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, { + "id" : 86, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:51:01Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"log-headers-policy\"}" + }, { + "id" : 87, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:51:29Z", + "what" : "Publish" + }, { + "id" : 93, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:51Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, { + "id" : 96, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "Create" + }, { + "id" : 98, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 99, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 101, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:22Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } ] + }, { + "OrganizationBean" : { + "id" : "Foo", + "name" : "Foo", + "description" : "An amazing organization so that we have two for testing.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:54:54Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:54:54Z" + }, + "Memberships" : [ { + "id" : 33, + "userId" : "admin", + "roleId" : "OrganizationOwner", + "organizationId" : "Foo", + "createdOn" : "2016-03-17T09:54:54Z" + } ], + "Plans" : [ { + "PlanBean" : { + "id" : "Good", + "name" : "Good", + "description" : "A pretty good plan.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:06Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 35, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:06Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:55:14Z", + "lockedOn" : "2016-03-17T09:55:15Z" + }, + "Policies" : [ { + "id" : 37, + "type" : "Plan", + "organizationId" : "Foo", + "entityId" : "Good", + "entityVersion" : "1.0", + "name" : "Caching Policy", + "configuration" : "{\"ttl\":10}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:14Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:55:14Z", + "definition" : { + "id" : "CachingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + }, { + "PlanBean" : { + "id" : "Great", + "name" : "Great", + "description" : "A really great plan.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:20Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 41, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:20Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:56:15Z", + "lockedOn" : "2016-03-17T09:56:26Z" + }, + "Policies" : [ { + "id" : 43, + "type" : "Plan", + "organizationId" : "Foo", + "entityId" : "Great", + "entityVersion" : "1.0", + "name" : "Time Restricted Access Policy", + "configuration" : "{\"rules\":[{\"timeStart\":\"2016-03-17T13:00:00.000Z\",\"timeEnd\":\"2016-03-17T21:00:00.000Z\",\"dayStart\":4,\"dayEnd\":5,\"pathPattern\":\".*\"}]}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:15Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:56:15Z", + "definition" : { + "id" : "TimeRestrictedAccessPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Apis" : [ { + "ApiBean" : { + "id" : "foo-echo", + "name" : "foo-echo", + "description" : "An echo service inside the Foo organization.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:33Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 47, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo", + "endpointType" : "rest", + "endpointContentType" : "json", + "endpointProperties" : { + "authorization.type" : "basic", + "basic-auth.requireSSL" : "false", + "basic-auth.username" : "username", + "basic-auth.password" : "password" + }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:33Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:59:25Z", + "publishedOn" : "2016-03-17T10:03:01Z", + "definitionType" : "SwaggerJSON" + }, + "Policies" : [ { + "id" : 52, + "type" : "Api", + "organizationId" : "Foo", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "name" : "BASIC Authentication Policy", + "configuration" : "{\"realm\":\"Foo Echo\",\"forwardIdentityHttpHeader\":\"X-Identity\",\"requireBasicAuth\":true,\"staticIdentity\":{\"identities\":[{\"username\":\"user\",\"password\":\"user\"},{\"username\":\"user1\",\"password\":\"user1\"},{\"username\":\"user2\",\"password\":\"user2\"}]}}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:58:46Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:58:46Z", + "definition" : { + "id" : "BASICAuthenticationPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + }, { + "id" : 54, + "type" : "Api", + "organizationId" : "Foo", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "name" : "Ignored Resources Policy", + "configuration" : "{\"rules\":[{\"verb\":\"*\",\"pathPattern\":\"/admin/.*\"}]}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:59:25Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:59:25Z", + "definition" : { + "id" : "IgnoredResourcesPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 2 + } ] + } ] + }, { + "ApiBean" : { + "id" : "FacebookAPI", + "name" : "Facebook API", + "description" : "The Facebook API is a platform for building applications that are available to the members of the social network of Facebook.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:54Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 65, + "status" : "Published", + "endpoint" : "http://api.facebook.com/restserver.php", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:54Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:05:54Z", + "publishedOn" : "2016-03-17T10:06:11Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "FlickrAPI", + "name" : "Flickr API", + "description" : "The Flickr API can be used to retrieve photos from the Flickr photo sharing service using a variety of feeds.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:55Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 68, + "status" : "Published", + "endpoint" : "http://api.flickr.com/services/rest/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:55Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:05:55Z", + "publishedOn" : "2016-03-17T10:06:15Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "TwitterAPI", + "name" : "Twitter API", + "description" : "The Twitter micro-blogging service includes two RESTful APIs.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:56Z" + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 73, + "status" : "Ready", + "endpoint" : "http://twitter.com/statuses/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:56Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:06:56Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "YouTubeAPI", + "name" : "YouTube API", + "description" : "The Data API allows users to integrate their program with YouTube and allow it to perform many of the operations available on the website.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:57Z" + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 76, + "status" : "Ready", + "endpoint" : "http://gdata.youtube.com/feeds/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:57Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:06:57Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + } ], + "Clients" : [ { + "ClientBean" : { + "id" : "foo-app", + "name" : "foo-app", + "description" : "The foo app! It probably uses the foo-echo API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:26Z" + }, + "Versions" : [ { + "ClientVersionBean" : { + "id" : 62, + "status" : "Registered", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:26Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T13:26:51Z", + "publishedOn" : "2016-03-17T13:26:57Z", + "apikey" : "*" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 88, + "api" : { + "api" : { + "organization" : { + "id" : "Foo" + }, + "id" : "foo-echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Foo" + }, + "id" : "Good" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:26:43Z" + }, { + "id" : 91, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Silver" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:26:51Z" + } ] + } ] + } ], + "Audits" : [ { + "id" : 32, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Organization", + "createdOn" : "2016-03-17T09:54:54Z", + "what" : "Create" + }, { + "id" : 34, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "createdOn" : "2016-03-17T09:55:06Z", + "what" : "Create" + }, { + "id" : 36, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:06Z", + "what" : "Create" + }, { + "id" : 38, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:14Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"CachingPolicy\"}" + }, { + "id" : 39, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:15Z", + "what" : "Lock" + }, { + "id" : 40, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "createdOn" : "2016-03-17T09:55:20Z", + "what" : "Create" + }, { + "id" : 42, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:20Z", + "what" : "Create" + }, { + "id" : 44, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:15Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"TimeRestrictedAccessPolicy\"}" + }, { + "id" : 45, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:26Z", + "what" : "Lock" + }, { + "id" : 46, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "createdOn" : "2016-03-17T09:56:33Z", + "what" : "Create" + }, { + "id" : 48, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:33Z", + "what" : "Create" + }, { + "id" : 49, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:57:29Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, { + "id" : 50, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:06Z", + "what" : "UpdateDefinition" + }, { + "id" : 51, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:16Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Good:1.0, Great:1.0\"}]}" + }, { + "id" : 53, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:46Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"BASICAuthenticationPolicy\"}" + }, { + "id" : 55, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:59:25Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"IgnoredResourcesPolicy\"}" + }, { + "id" : 56, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:03:01Z", + "what" : "Publish" + }, { + "id" : 57, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Organization", + "createdOn" : "2016-03-17T10:04:33Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An amazing organization so that we have two for testing.\"}]}" + }, { + "id" : 58, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "createdOn" : "2016-03-17T10:04:42Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A pretty good plan.\"}]}" + }, { + "id" : 59, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "createdOn" : "2016-03-17T10:04:49Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A really great plan.\"}]}" + }, { + "id" : 60, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "createdOn" : "2016-03-17T10:05:00Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An echo service inside the Foo organization.\"}]}" + }, { + "id" : 61, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "createdOn" : "2016-03-17T10:05:26Z", + "what" : "Create" + }, { + "id" : 63, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:26Z", + "what" : "Create" + }, { + "id" : 64, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "createdOn" : "2016-03-17T10:05:54Z", + "what" : "Create" + }, { + "id" : 66, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:54Z", + "what" : "Create" + }, { + "id" : 67, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "createdOn" : "2016-03-17T10:05:55Z", + "what" : "Create" + }, { + "id" : 69, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:55Z", + "what" : "Create" + }, { + "id" : 70, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:11Z", + "what" : "Publish" + }, { + "id" : 71, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:15Z", + "what" : "Publish" + }, { + "id" : 72, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "TwitterAPI", + "createdOn" : "2016-03-17T10:06:56Z", + "what" : "Create" + }, { + "id" : 74, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "TwitterAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:56Z", + "what" : "Create" + }, { + "id" : 75, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "YouTubeAPI", + "createdOn" : "2016-03-17T10:06:57Z", + "what" : "Create" + }, { + "id" : 77, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "YouTubeAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:57Z", + "what" : "Create" + }, { + "id" : 89, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:43Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, { + "id" : 90, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:43Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, { + "id" : 92, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:51Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, { + "id" : 94, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:57Z", + "what" : "Register" + }, { + "id" : 102, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:28:22Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } ] + } ] +} \ No newline at end of file diff --git a/manager/api/pom.xml b/manager/api/pom.xml index eba5c2490f..605d90400e 100644 --- a/manager/api/pom.xml +++ b/manager/api/pom.xml @@ -20,6 +20,7 @@ ispn jpa micro + migrator rest rest-impl security diff --git a/manager/api/rest-impl/pom.xml b/manager/api/rest-impl/pom.xml index a150f8548b..75fd2342b7 100644 --- a/manager/api/rest-impl/pom.xml +++ b/manager/api/rest-impl/pom.xml @@ -48,6 +48,10 @@ ${project.groupId} apiman-manager-api-export-import-api + + ${project.groupId} + apiman-manager-api-migrator + ${project.groupId} apiman-common-plugin diff --git a/manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/impl/SystemResourceImpl.java b/manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/impl/SystemResourceImpl.java index ffb31479c9..dc95d8d781 100644 --- a/manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/impl/SystemResourceImpl.java +++ b/manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/impl/SystemResourceImpl.java @@ -32,6 +32,7 @@ import io.apiman.manager.api.exportimport.manager.StorageImportDispatcher; import io.apiman.manager.api.exportimport.read.IImportReader; import io.apiman.manager.api.exportimport.write.IExportWriter; +import io.apiman.manager.api.migrator.DataMigrator; import io.apiman.manager.api.rest.contract.ISystemResource; import io.apiman.manager.api.rest.contract.exceptions.SystemErrorException; import io.apiman.manager.api.rest.impl.util.ExceptionFactory; @@ -79,6 +80,8 @@ public class SystemResourceImpl implements ISystemResource { @Inject private StorageImportDispatcher importer; @Inject + private DataMigrator migrator; + @Inject private IDownloadManager downloadManager; @Context @@ -178,16 +181,6 @@ public Response importData() { StreamingOutput stream = new StreamingOutput() { @Override public void write(final OutputStream output) throws IOException, WebApplicationException { - InputStream importData = null; - IImportReader reader; - try { - importData = new FileInputStream(importFile); - reader = new JsonImportReader(importLogger, importData); - } catch (IOException e) { - IOUtils.closeQuietly(importData); - throw new SystemErrorException(e); - } - final PrintWriter writer = new PrintWriter(output); IApimanLogger logger = new IApimanLogger() { @Override @@ -228,6 +221,25 @@ public void debug(String message) { writer.flush(); } }; + + File migratedImportFile = File.createTempFile("apiman_import_migrated", ".json"); //$NON-NLS-1$ //$NON-NLS-2$ + migratedImportFile.deleteOnExit(); + + // Migrate the data (if necessary) + migrator.setLogger(logger); + migrator.migrate(importFile, migratedImportFile); + + // Now import the migrated data + InputStream importData = null; + IImportReader reader; + try { + importData = new FileInputStream(migratedImportFile); + reader = new JsonImportReader(logger, importData); + } catch (IOException e) { + IOUtils.closeQuietly(importData); + throw new SystemErrorException(e); + } + try { importer.setLogger(logger); importer.start(); @@ -238,6 +250,7 @@ public void debug(String message) { } finally { IOUtils.closeQuietly(importData); FileUtils.deleteQuietly(importFile); + FileUtils.deleteQuietly(migratedImportFile); } } }; diff --git a/manager/test/api/src/main/java/io/apiman/manager/test/junit/ManagerRestTester.java b/manager/test/api/src/main/java/io/apiman/manager/test/junit/ManagerRestTester.java index 8e99af050f..df063a36a9 100644 --- a/manager/test/api/src/main/java/io/apiman/manager/test/junit/ManagerRestTester.java +++ b/manager/test/api/src/main/java/io/apiman/manager/test/junit/ManagerRestTester.java @@ -15,12 +15,11 @@ */ package io.apiman.manager.test.junit; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import io.apiman.manager.api.core.util.PolicyTemplateUtil; import io.apiman.manager.test.junit.ManagerRestTester.TestInfo; import io.apiman.manager.test.server.ManagerApiTestServer; import io.apiman.manager.test.server.MockGatewayServlet; +import io.apiman.test.common.json.JsonCompare; import io.apiman.test.common.plan.TestGroupType; import io.apiman.test.common.plan.TestPlan; import io.apiman.test.common.plan.TestType; @@ -48,6 +47,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * A junit test runner that fires up apiman and makes it ready for * use in the tests. This runner also loads up the test plan from @@ -281,8 +283,8 @@ public void evaluate() throws Throwable { ObjectMapper mapper = new ObjectMapper(); JsonNode expected = mapper.readTree(expectedPayload); JsonNode actual = mapper.readTree(actualPayload.trim()); - RestTest mockRT = new RestTest(); - testInfo.plan.runner.assertJson(mockRT, expected, actual); + JsonCompare jsonCompare = new JsonCompare(); + jsonCompare.assertJson(expected, actual); } index++; diff --git a/manager/test/api/src/test/java/io/apiman/manager/test/MigrateTest.java b/manager/test/api/src/test/java/io/apiman/manager/test/MigrateTest.java new file mode 100644 index 0000000000..8b036a9b01 --- /dev/null +++ b/manager/test/api/src/test/java/io/apiman/manager/test/MigrateTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2014 JBoss Inc + * + * 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.apiman.manager.test; + +import io.apiman.manager.test.junit.ManagerRestTestPlan; +import io.apiman.manager.test.junit.ManagerRestTester; + +import org.junit.runner.RunWith; + +/** + * Runs the "export" test plan. + * + * @author eric.wittmann@redhat.com + */ +@RunWith(ManagerRestTester.class) +@ManagerRestTestPlan("test-plans/migrate-testPlan.xml") +public class MigrateTest { +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/000_create-gateway.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/000_create-gateway.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/000_create-gateway.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/000_create-gateway.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/001_create_org.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/001_create_org.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/001_create_org.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/001_create_org.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/002_create-plan1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/002_create-plan1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/002_create-plan1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/002_create-plan1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/publish/003_lock-plan-1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/003.5_lock-plan-1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/publish/003_lock-plan-1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/003.5_lock-plan-1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/003_create-plan1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/003_create-plan1-version-1.0.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/003_create-plan1-version-1.0.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/003_create-plan1-version-1.0.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/004_create-client1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/004_create-client1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/004_create-client1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/004_create-client1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/005_create-client1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/005_create-client1-version-1.0.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/005_create-client1-version-1.0.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/005_create-client1-version-1.0.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/006_create-api1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/006_create-api1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/006_create-api1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/006_create-api1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/007_create-api1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/007_create-api1-version-1.0.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/007_create-api1-version-1.0.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/007_create-api1-version-1.0.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/007.5_update-api1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/008_update-api1-version-1.0.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/007.5_update-api1-version-1.0.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/008_update-api1-version-1.0.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/publish/001_publish-api-1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/009_publish-api-1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/publish/001_publish-api-1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/009_publish-api-1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates/008_create-contract1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/010_create-contract1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/creates/008_create-contract1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/010_create-contract1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/publish/002_register-client-1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-1/011_register-client-1.resttest similarity index 100% rename from manager/test/api/src/test/resources/test-plan-data/export/publish/002_register-client-1.resttest rename to manager/test/api/src/test/resources/test-plan-data/export/creates-1/011_register-client-1.resttest diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/001_create_org.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/001_create_org.resttest new file mode 100644 index 0000000000..4a0448ed0f --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/001_create_org.resttest @@ -0,0 +1,12 @@ +POST /organizations admin/admin +Content-Type: application/json + +{"name":"Organization 2"} +---- +200 +Content-Type: application/json + +{ + "name" : "Organization 2", + "id" : "Organization2" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/002_create-plan1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/002_create-plan1.resttest new file mode 100644 index 0000000000..4e6d2f2226 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/002_create-plan1.resttest @@ -0,0 +1,21 @@ +POST /organizations/Organization2/plans admin/admin +Content-Type: application/json + +{ + "name" : "Plan 1", + "description" : "This is the description of Plan 1." +} +---- +200 +Content-Type: application/json + +{ + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Plan1", + "name" : "Plan 1", + "description" : "This is the description of Plan 1.", + "createdBy" : "admin" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/003.5_lock-plan-1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/003.5_lock-plan-1.resttest new file mode 100644 index 0000000000..6e939d22d7 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/003.5_lock-plan-1.resttest @@ -0,0 +1,11 @@ +POST /actions admin/admin +Content-Type: application/json + +{ + "type" : "lockPlan", + "organizationId" : "Organization2", + "entityId" : "Plan1", + "entityVersion" : "1.0" +} +---- +204 diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/003_create-plan1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/003_create-plan1-version-1.0.resttest new file mode 100644 index 0000000000..34f550c527 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/003_create-plan1-version-1.0.resttest @@ -0,0 +1,26 @@ +POST /organizations/Organization2/plans/Plan1/versions admin/admin +Content-Type: application/json + +{ + "version" : "1.0" +} +---- +200 +Content-Type: application/json + +{ + "plan" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Plan1", + "name" : "Plan 1", + "description" : "This is the description of Plan 1.", + "createdBy":"admin" + }, + "status" : "Created", + "version" : "1.0", + "createdBy" : "admin", + "lockedOn" : null +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/004_create-client1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/004_create-client1.resttest new file mode 100644 index 0000000000..2bac752339 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/004_create-client1.resttest @@ -0,0 +1,21 @@ +POST /organizations/Organization2/clients admin/admin +Content-Type: application/json + +{ + "name" : "Client 1", + "description" : "This is the description of Client 1." +} +---- +200 +Content-Type: application/json + +{ + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Client1", + "name" : "Client 1", + "description" : "This is the description of Client 1.", + "createdBy" : "admin" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/005_create-client1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/005_create-client1-version-1.0.resttest new file mode 100644 index 0000000000..524a6117d8 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/005_create-client1-version-1.0.resttest @@ -0,0 +1,24 @@ +POST /organizations/Organization2/clients/Client1/versions admin/admin +Content-Type: application/json + +{ + "version" : "1.0" +} +---- +200 +Content-Type: application/json + +{ + "client" : { + "organization" : { + "id" : "Organization2" + }, + "id" : "Client1", + "name" : "Client 1", + "description" : "This is the description of Client 1.", + "createdBy":"admin" + }, + "status" : "Created", + "version" : "1.0", + "createdBy" : "admin" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/006_create-api1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/006_create-api1.resttest new file mode 100644 index 0000000000..46e5e33e1a --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/006_create-api1.resttest @@ -0,0 +1,21 @@ +POST /organizations/Organization2/apis admin/admin +Content-Type: application/json + +{ + "name" : "API 1", + "description" : "This is the description of API 1." +} +---- +200 +Content-Type: application/json + +{ + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "API1", + "name" : "API 1", + "description" : "This is the description of API 1.", + "createdBy" : "admin" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/007_create-api1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/007_create-api1-version-1.0.resttest new file mode 100644 index 0000000000..55c4320547 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/007_create-api1-version-1.0.resttest @@ -0,0 +1,25 @@ +POST /organizations/Organization2/apis/API1/versions admin/admin +Content-Type: application/json + +{ + "version" : "1.0" +} +---- +200 +Content-Type: application/json + +{ + "api" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "API1", + "name" : "API 1", + "description" : "This is the description of API 1.", + "createdBy":"admin" + }, + "status" : "Created", + "version" : "1.0", + "createdBy" : "admin" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/008_update-api1-version-1.0.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/008_update-api1-version-1.0.resttest new file mode 100644 index 0000000000..1c445d9591 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/008_update-api1-version-1.0.resttest @@ -0,0 +1,21 @@ +PUT /organizations/Organization2/apis/API1/versions/1.0 admin/admin +Content-Type: application/json + +{ + "endpoint" : "http://localhost:8080/ping", + "endpointType" : "rest", + "plans" : [ + { + "planId" : "Plan1", + "version" : "1.0" + } + ] +} +---- +200 +Content-Type: application/json + +{ + "endpoint" : "http://localhost:8080/ping", + "endpointType" : "rest" +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/009_publish-api-1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/009_publish-api-1.resttest new file mode 100644 index 0000000000..2122082ef7 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/009_publish-api-1.resttest @@ -0,0 +1,11 @@ +POST /actions admin/admin +Content-Type: application/json + +{ + "type" : "publishAPI", + "organizationId" : "Organization2", + "entityId" : "API1", + "entityVersion" : "1.0" +} +---- +204 diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/010_create-contract1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/010_create-contract1.resttest new file mode 100644 index 0000000000..8edf840ad7 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/010_create-contract1.resttest @@ -0,0 +1,65 @@ +POST /organizations/Organization2/clients/Client1/versions/1.0/contracts admin/admin +Content-Type: application/json + +{ + "apiOrgId" : "Organization2", + "apiId" : "API1", + "apiVersion" : "1.0", + "planId" : "Plan1" +} +---- +200 +Content-Type: application/json + +{ + "client" : { + "client" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Client1", + "name" : "Client 1", + "description" : "This is the description of Client 1.", + "createdBy" : "admin" + }, + "status" : "Ready", + "version" : "1.0", + "createdBy" : "admin" + }, + + "api":{ + "api" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "API1", + "name" : "API 1", + "description" : "This is the description of API 1.", + "createdBy" : "admin" + }, + "status" : "Published", + "endpoint" : "http://localhost:8080/ping", + "endpointType" : "rest", + "plans" : [{"planId" : "Plan1","version" : "1.0"}], + "version" : "1.0", + "createdBy" : "admin" + }, + + "plan" : { + "plan" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Plan1", + "name" : "Plan 1", + "description" : "This is the description of Plan 1.", + "createdBy" : "admin" + }, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin" + } +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/011_register-client-1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/011_register-client-1.resttest new file mode 100644 index 0000000000..b585966885 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/011_register-client-1.resttest @@ -0,0 +1,11 @@ +POST /actions admin/admin +Content-Type: application/json + +{ + "type" : "registerClient", + "organizationId" : "Organization2", + "entityId" : "Client1", + "entityVersion" : "1.0" +} +---- +204 diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/012_create-plan1-version-1.1.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/012_create-plan1-version-1.1.resttest new file mode 100644 index 0000000000..4de2b40fd0 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/012_create-plan1-version-1.1.resttest @@ -0,0 +1,28 @@ +POST /organizations/Organization2/plans/Plan1/versions admin/admin +Content-Type: application/json + +{ + "version" : "1.1", + "clone" : true, + "cloneVersion" : "1.0" +} +---- +200 +Content-Type: application/json + +{ + "plan" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Plan1", + "name" : "Plan 1", + "description" : "This is the description of Plan 1.", + "createdBy":"admin" + }, + "status" : "Created", + "version" : "1.1", + "createdBy" : "admin", + "lockedOn" : null +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/creates-2/013_create-plan1-version-1.2.resttest b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/013_create-plan1-version-1.2.resttest new file mode 100644 index 0000000000..4a3559a553 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/creates-2/013_create-plan1-version-1.2.resttest @@ -0,0 +1,28 @@ +POST /organizations/Organization2/plans/Plan1/versions admin/admin +Content-Type: application/json + +{ + "version" : "1.2", + "clone" : true, + "cloneVersion" : "1.0" +} +---- +200 +Content-Type: application/json + +{ + "plan" : { + "organization" : { + "id" : "Organization2", + "name" : "Organization 2" + }, + "id" : "Plan1", + "name" : "Plan 1", + "description" : "This is the description of Plan 1.", + "createdBy":"admin" + }, + "status" : "Created", + "version" : "1.2", + "createdBy" : "admin", + "lockedOn" : null +} diff --git a/manager/test/api/src/test/resources/test-plan-data/export/export/004_export-3.resttest b/manager/test/api/src/test/resources/test-plan-data/export/export/004_export-3.resttest new file mode 100644 index 0000000000..8efd7cf1f8 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/export/export/004_export-3.resttest @@ -0,0 +1,633 @@ +GET /system/export admin/admin +---- +200 +Content-Type: application/json + +{ + "Metadata": { + "exportedOn": "*", + "apimanVersion": "*" + }, + "Users": [ + { + "username": "admin", + "fullName": "Admin", + "email": "admin@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "admin2", + "fullName": "Admin 2", + "email": "admin2@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user1", + "fullName": "User 1", + "email": "user1@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user2", + "fullName": "User 2", + "email": "user2@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user3", + "fullName": "User 3", + "email": "user3@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user4", + "fullName": "User 4", + "email": "user4@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user5", + "fullName": "User 5", + "email": "user5@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "bwayne", + "fullName": "Bruce Wayne", + "email": "bwayne@wayne-enterprises.com", + "joinedOn": "*", + "admin": false + }, + { + "username": "ckent", + "fullName": "Clark Kent", + "email": "ckent@dailyplanet.com", + "joinedOn": "*", + "admin": false + }, + { + "username": "dprince", + "fullName": "Diana Prince", + "email": "dprince@themyscira.gov", + "joinedOn": "*", + "admin": false + } + ], + "Gateways": [ + { + "id": "TheGateway", + "name": "The Gateway", + "description": "This is the gateway.", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "type": "REST", + "configuration": "{\"endpoint\":\"http://localhost:7070/mock-gateway\",\"username\":\"admin\",\"password\":\"$CRYPT::j8rdW76Z5gUI0I+9c8/GrA==\"}" + } + ], + "Plugins": [], + "Roles": [], + "PolicyDefinitions": [], + "Orgs": [ + { + "OrganizationBean": { + "id": "Organization1", + "name": "Organization 1", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*" + }, + "Memberships": [], + "Plans": [ + { + "PlanBean": { + "id": "Plan1", + "name": "Plan 1", + "description": "This is the description of Plan 1.", + "createdBy": "admin", + "createdOn": "*" + }, + "Versions": [ + { + "PlanVersionBean": { + "status": "Locked", + "version": "1.0", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "lockedOn": "*" + }, + "Policies": [] + } + ] + } + ], + "Apis": [ + { + "ApiBean": { + "id": "API1", + "name": "API 1", + "description": "This is the description of API 1.", + "createdBy": "admin", + "createdOn": "*", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "status": "Published", + "endpoint": "http://localhost:8080/ping", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": false, + "plans": [ + { + "planId": "Plan1", + "version": "1.0" + } + ], + "version": "1.0", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "publishedOn": "*" + }, + "Policies": [] + } + ] + } + ], + "Clients": [ + { + "ClientBean": { + "id": "Client1", + "name": "Client 1", + "description": "This is the description of Client 1.", + "createdBy": "admin", + "createdOn": "*" + }, + "Versions": [ + { + "ClientVersionBean": { + "status": "Registered", + "version": "1.0", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "publishedOn": "*", + "apikey": "*" + }, + "Policies": [], + "Contracts": [ + { + "api": { + "api": { + "organization": { + "id": "Organization1" + }, + "id": "API1" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Organization1" + }, + "id": "Plan1" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "*" + } + ] + } + ] + } + ], + "Audits": [ + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Organization", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Plan", + "entityId": "Plan1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Plan", + "entityId": "Plan1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Plan", + "entityId": "Plan1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Lock" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Client", + "entityId": "Client1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Client", + "entityId": "Client1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Api", + "entityId": "API1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Plan1:1.0\"},{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/ping\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"}]}" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Publish" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Client", + "entityId": "Client1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Organization1\",\"clientId\":\"Client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Organization1\",\"apiId\":\"API1\",\"apiVersion\":\"1.0\",\"planId\":\"Plan1\",\"planVersion\":\"1.0\"}" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Organization1\",\"clientId\":\"Client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Organization1\",\"apiId\":\"API1\",\"apiVersion\":\"1.0\",\"planId\":\"Plan1\",\"planVersion\":\"1.0\"}" + }, + { + "who": "admin", + "organizationId": "Organization1", + "entityType": "Client", + "entityId": "Client1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Register" + } + ] + }, + { + "OrganizationBean": { + "id": "Organization2", + "name": "Organization 2", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*" + }, + "Memberships": [], + "Plans": [ + { + "PlanBean": { + "id": "Plan1", + "name": "Plan 1", + "description": "This is the description of Plan 1.", + "createdBy": "admin", + "createdOn": "*" + }, + "Versions": [ + { + "PlanVersionBean": { + "status": "Locked", + "version": "1.0", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "lockedOn": "*" + }, + "Policies": [] + }, + { + "PlanVersionBean": { + "status": "Created", + "version": "1.1", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*" + }, + "Policies": [] + }, + { + "PlanVersionBean": { + "status": "Created", + "version": "1.2", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*" + }, + "Policies": [] + } + ] + } + ], + "Apis": [ + { + "ApiBean": { + "id": "API1", + "name": "API 1", + "description": "This is the description of API 1.", + "createdBy": "admin", + "createdOn": "*", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "status": "Published", + "endpoint": "http://localhost:8080/ping", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": false, + "plans": [ + { + "planId": "Plan1", + "version": "1.0" + } + ], + "version": "1.0", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "publishedOn": "*" + }, + "Policies": [] + } + ] + } + ], + "Clients": [ + { + "ClientBean": { + "id": "Client1", + "name": "Client 1", + "description": "This is the description of Client 1.", + "createdBy": "admin", + "createdOn": "*" + }, + "Versions": [ + { + "ClientVersionBean": { + "status": "Registered", + "version": "1.0", + "createdBy": "admin", + "createdOn": "*", + "modifiedBy": "admin", + "modifiedOn": "*", + "publishedOn": "*", + "apikey": "*" + }, + "Policies": [], + "Contracts": [ + { + "api": { + "api": { + "organization": { + "id": "Organization2" + }, + "id": "API1" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Organization2" + }, + "id": "Plan1" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "*" + } + ] + } + ] + } + ], + "Audits": [ + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Organization", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Plan", + "entityId": "Plan1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Plan", + "entityId": "Plan1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Plan", + "entityId": "Plan1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Lock" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Client", + "entityId": "Client1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Client", + "entityId": "Client1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Api", + "entityId": "API1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Plan1:1.0\"},{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/ping\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"}]}" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Publish" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Client", + "entityId": "Client1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Organization2\",\"clientId\":\"Client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Organization2\",\"apiId\":\"API1\",\"apiVersion\":\"1.0\",\"planId\":\"Plan1\",\"planVersion\":\"1.0\"}" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Api", + "entityId": "API1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Organization2\",\"clientId\":\"Client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Organization2\",\"apiId\":\"API1\",\"apiVersion\":\"1.0\",\"planId\":\"Plan1\",\"planVersion\":\"1.0\"}" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Client", + "entityId": "Client1", + "entityVersion": "1.0", + "createdOn": "*", + "what": "Register" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Plan", + "entityId": "Plan1", + "entityVersion": "1.1", + "createdOn": "*", + "what": "Create" + }, + { + "who": "admin", + "organizationId": "Organization2", + "entityType": "Plan", + "entityId": "Plan1", + "entityVersion": "1.2", + "createdOn": "*", + "what": "Create" + } + ] + } + ] +} \ No newline at end of file diff --git a/manager/test/api/src/test/resources/test-plan-data/import/001_import.resttest b/manager/test/api/src/test/resources/test-plan-data/import/001_import.resttest index 5950456964..ce662489a5 100644 --- a/manager/test/api/src/test/resources/test-plan-data/import/001_import.resttest +++ b/manager/test/api/src/test/resources/test-plan-data/import/001_import.resttest @@ -4,7 +4,7 @@ Content-Type: application/json { "Metadata": { "exportedOn": 1445973221630, - "apimanVersion": "1.2.0-SNAPSHOT" + "apimanVersion": "1.2.3-SNAPSHOT" }, "Users": [ { @@ -371,7 +371,7 @@ Content-Type: text/plain INFO: ---------------------------- INFO: Starting apiman data import. -INFO: Importing data from apiman version: 1.2.0-SNAPSHOT +INFO: Importing data from apiman version: 1.2.3-SNAPSHOT INFO: Importing a user: importeduser INFO: Importing a gateway: The Gateway INFO: Importing an organization: Organization 1 diff --git a/manager/test/api/src/test/resources/test-plan-data/migrate/001_import-1.2.2.Final.resttest b/manager/test/api/src/test/resources/test-plan-data/migrate/001_import-1.2.2.Final.resttest new file mode 100644 index 0000000000..5151e937dd --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/migrate/001_import-1.2.2.Final.resttest @@ -0,0 +1,1754 @@ +POST /system/import admin/admin +Content-Type: application/json + +{ + "Metadata" : { + "exportedOn" : "2016-03-17T14:53:01Z", + "apimanVersion" : "1.2.2.Final" + }, + "Users" : [ { + "username" : "admin", + "fullName" : "Admin", + "email" : "admin@example.org", + "joinedOn" : "2016-02-29T13:43:22Z", + "admin" : false + } ], + "Gateways": [ + { + "id": "TheGateway", + "name": "The Gateway", + "description": "This is the gateway.", + "createdBy": "admin", + "createdOn": 1445973205874, + "modifiedBy": "admin", + "modifiedOn": 1445973205874, + "type": "REST", + "configuration": "{\"endpoint\":\"http://localhost:7070/mock-gateway\",\"username\":\"admin\",\"password\":\"$CRYPT::j8rdW76Z5gUI0I+9c8/GrA==\"}" + } + ], + "Plugins" : [ { + "id" : 78, + "groupId" : "io.apiman.plugins", + "artifactId" : "apiman-plugins-log-policy", + "version" : "1.2.2.Final", + "name" : "Log Policy Plugin", + "description" : "This plugin has policies for logging to std out.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:39Z", + "deleted" : false + }, { + "id" : 79, + "groupId" : "io.apiman.plugins", + "artifactId" : "apiman-plugins-jsonp-policy", + "version" : "1.2.2.Final", + "name" : "JSONP Policy Plugin", + "description" : "A plugin that contributes a policy that turns a standard RESTful endpoint into a JSONP compatible endpoint.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:49Z", + "deleted" : false + } ], + "Roles" : [ { + "id" : "OrganizationOwner", + "name" : "Organization Owner", + "description" : "Automatically granted to the user who creates an Organization. Grants all privileges.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:23Z", + "autoGrant" : true, + "permissions" : [ "orgView", "apiAdmin", "apiView", "planEdit", "planView", "apiEdit", "clientAdmin", "orgEdit", "clientView", "planAdmin", "orgAdmin", "clientEdit" ] + }, { + "id" : "ClientAppDeveloper", + "name" : "Client App Developer", + "description" : "Users responsible for creating and managing client apps should be granted this role within an Organization.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "permissions" : [ "clientAdmin", "clientView", "clientEdit" ] + }, { + "id" : "APIDeveloper", + "name" : "API Developer", + "description" : "Users responsible for creating and managing APIs should be granted this role within an Organization.", + "createdBy" : "admin", + "createdOn" : "2016-02-29T13:43:24Z", + "permissions" : [ "apiAdmin", "apiView", "planEdit", "planView", "apiEdit", "planAdmin" ] + }, { + "id" : "PlanMaster", + "name" : "Plan Master", + "description" : "The master of all plans!", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:49:20Z", + "permissions" : [ "planEdit", "planView", "planAdmin" ] + } ], + "PolicyDefinitions" : [ { + "id" : "IPWhitelistPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IPWhitelistPolicy", + "name" : "IP Whitelist Policy", + "description" : "Only requests that originate from a specified set of valid IP addresses will be allowed through.", + "icon" : "filter", + "templates" : [ { + "template" : "Only requests that originate from the set of ${ipList.size()} configured IP address(es) will be allowed to invoke the managed API." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "IPBlacklistPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IPBlacklistPolicy", + "name" : "IP Blacklist Policy", + "description" : "Requests that originate from a specified set of valid IP addresses will be denied access.", + "icon" : "thumbs-down", + "templates" : [ { + "template" : "Requests that originate from the set of ${ipList.size()} configured IP address(es) will be denied access to the managed API." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "BASICAuthenticationPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.BasicAuthenticationPolicy", + "name" : "BASIC Authentication Policy", + "description" : "Enables HTTP BASIC Authentication on an API. Some configuration required.", + "icon" : "lock", + "templates" : [ { + "template" : "Access to the API is protected by BASIC Authentication through the '${realm}' authentication realm. @if{forwardIdentityHttpHeader != null}Successfully authenticated requests will forward the authenticated identity to the back end API via the '${forwardIdentityHttpHeader}' custom HTTP header.@end{}" + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "RateLimitingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.RateLimitingPolicy", + "name" : "Rate Limiting Policy", + "description" : "Enforces rate configurable request rate limits on an API. This ensures that consumers can't overload an API with too many requests.", + "icon" : "sliders", + "templates" : [ { + "template" : "Consumers are limited to ${limit} requests per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "IgnoredResourcesPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.IgnoredResourcesPolicy", + "name" : "Ignored Resources Policy", + "description" : "Requests satisfying the provided regular expression will be ignored.", + "icon" : "eye-slash", + "templates" : [ { + "template" : "Requests matching any of the ${rules.size()} regular expressions provided will receive a 404 error code." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "AuthorizationPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.AuthorizationPolicy", + "name" : "Authorization Policy", + "description" : "Enables fine grained authorization to API resources based on authenticated user roles.", + "icon" : "users", + "templates" : [ { + "template" : "Appropriate authorization roles are required. There are ${rules.size()} authorization rules defined." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "QuotaPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.QuotaPolicy", + "name" : "Quota Policy", + "description" : "Provides a way to limit the total number of requests that can be sent to an API.", + "icon" : "exchange", + "templates" : [ { + "template" : "Consumers cannot exceed their quota of ${limit} requests per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "CachingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.CachingPolicy", + "name" : "Caching Policy", + "description" : "Allows caching of API responses in the Gateway to reduce overall traffic to the back-end API.", + "icon" : "hdd-o", + "templates" : [ { + "template" : "API responses will be cached for ${ttl} seconds." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "TransferQuotaPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.TransferQuotaPolicy", + "name" : "Transfer Quota Policy", + "description" : "Provides a way to limit the total number of bytes that can be transferred from (or to) an API.", + "icon" : "download", + "templates" : [ { + "template" : "Consumers are limited to transferring ${limit} bytes per ${granularity} per ${period}." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "URLRewritingPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.URLRewritingPolicy", + "name" : "URL Rewriting Policy", + "description" : "Responses from the back-end API will be modified by fixing up any incorrect URLs found with modified ones. This is useful because apiman works through an API Gateway.", + "icon" : "pencil-square", + "templates" : [ { + "template" : "Responses will be modified by finding all text matching regular expression '${fromRegex}' with '${toReplacement}'." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "TimeRestrictedAccessPolicy", + "policyImpl" : "class:io.apiman.gateway.engine.policies.TimeRestrictedAccessPolicy", + "name" : "Time Restricted Access Policy", + "description" : "Requests matching the specified regular expression and made within the specified time period will be ignored.", + "icon" : "clock-o", + "templates" : [ { + "template" : "Requests matching the regular expression and made outside the specified time period will receive a 423 error code." + } ], + "formType" : "Default", + "deleted" : false + }, { + "id" : "log-headers-policy", + "policyImpl" : "plugin:io.apiman.plugins:apiman-plugins-log-policy:1.2.2.Final:war/io.apiman.plugins.log_policy.LogHeadersPolicy", + "name" : "Log Headers Policy", + "description" : "A policy that logs the headers to std out. Useful to analyse inbound HTTP traffic to the gateway when added as the first policy in the chain or to analyse outbound HTTP traffic from the gateway when added as the last policy in the chain.", + "icon" : "fire", + "templates" : [ ], + "pluginId" : 78, + "formType" : "JsonSchema", + "form" : "schemas/log-policyDef.schema", + "deleted" : false + }, { + "id" : "jsonp-policy", + "policyImpl" : "plugin:io.apiman.plugins:apiman-plugins-jsonp-policy:1.2.2.Final:war/io.apiman.plugins.jsonp_policy.JsonpPolicy", + "name" : "JSONP Policy", + "description" : "Turns an endpoint into a JSONP compatible endpoint.", + "icon" : "bars", + "templates" : [ ], + "pluginId" : 79, + "formType" : "JsonSchema", + "form" : "schemas/jsonp-policyDef.schema", + "deleted" : false + } ], + "Orgs" : [ { + "OrganizationBean" : { + "id" : "Test", + "name" : "Test", + "description" : "A test organization used by the full apiman smoke test suite.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:51Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:51Z" + }, + "Memberships" : [ { + "id" : 2, + "userId" : "admin", + "roleId" : "OrganizationOwner", + "organizationId" : "Test", + "createdOn" : "2016-03-17T09:47:51Z" + } ], + "Plans" : [ { + "PlanBean" : { + "id" : "Gold", + "name" : "Gold", + "description" : "The Gold plan allows users the highest level of API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 5, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "lockedOn" : "2016-03-17T09:47:52Z" + }, + "Policies" : [ { + "id" : 9, + "type" : "Plan", + "organizationId" : "Test", + "entityId" : "Gold", + "entityVersion" : "1.0", + "name" : "Rate Limiting Policy", + "configuration" : "{ \"limit\" : 100, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "definition" : { + "id" : "RateLimitingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + }, { + "PlanBean" : { + "id" : "Silver", + "name" : "Silver", + "description" : "The Silver plan allows users a lower level of API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 7, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "lockedOn" : "2016-03-17T09:47:52Z" + }, + "Policies" : [ { + "id" : 11, + "type" : "Plan", + "organizationId" : "Test", + "entityId" : "Silver", + "entityVersion" : "1.0", + "name" : "Rate Limiting Policy", + "configuration" : "{ \"limit\" : 5, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "definition" : { + "id" : "RateLimitingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Apis" : [ { + "ApiBean" : { + "id" : "echo", + "name" : "echo", + "description" : "A simple echo REST API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 16, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo/echo", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Gold", + "version" : "1.0" + }, { + "planId" : "Silver", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:52Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:52Z", + "publishedOn" : "2016-03-17T09:47:53Z" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "public-echo", + "name" : "public-echo", + "description" : "A public echo REST API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 21, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo/public-echo", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:47:53Z", + "publishedOn" : "2016-03-17T09:47:53Z" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "public-echo-two", + "name" : "public-echo-two", + "description" : "A second public echo API. Tests some plugin policies.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:50:35Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 81, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo", + "endpointType" : "rest", + "endpointContentType" : "json", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:50:35Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:51:01Z", + "publishedOn" : "2016-03-17T10:51:29Z" + }, + "Policies" : [ { + "id" : 85, + "type" : "Api", + "organizationId" : "Test", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "name" : "Log Headers Policy", + "configuration" : "{\"direction\":\"both\"}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:51:01Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:51:01Z", + "definition" : { + "id" : "log-headers-policy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Clients" : [ { + "ClientBean" : { + "id" : "client1", + "name" : "client1", + "description" : "A simple test client.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z" + }, + "Versions" : [ { + "ClientVersionBean" : { + "id" : 26, + "status" : "Registered", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:47:53Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:54:34Z", + "publishedOn" : "2016-03-17T09:54:40Z" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 28, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Gold" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:54:34Z", + "apikey" : "98571b7b-8fc7-4cce-b826-a8264020e211" + } ] + }, { + "ClientVersionBean" : { + "id" : 95, + "status" : "Ready", + "version" : "1.1", + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:05Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T13:28:22Z" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 100, + "api" : { + "api" : { + "organization" : { + "id" : "Foo" + }, + "id" : "foo-echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Foo" + }, + "id" : "Great" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:22Z", + "apikey" : "ac025635-e69d-49da-b9b8-4d960aa832cc" + }, { + "id" : 97, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Gold" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:28:05Z", + "apikey" : "4e9a4655-d6ee-4591-97fe-e8be5adfe5b0" + } ] + } ] + } ], + "Audits" : [ { + "id" : 1, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Organization", + "createdOn" : "2016-03-17T09:47:51Z", + "what" : "Create" + }, { + "id" : 3, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 4, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 6, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 8, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 10, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, { + "id" : 12, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, { + "id" : 13, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Gold", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Lock" + }, { + "id" : 14, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Plan", + "entityId" : "Silver", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Lock" + }, { + "id" : 15, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 17, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Create" + }, { + "id" : 18, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:52Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Gold:1.0, Silver:1.0\"},{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"}]}" + }, { + "id" : 19, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Publish" + }, { + "id" : 20, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 22, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 23, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/public-echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, { + "id" : 24, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Publish" + }, { + "id" : 25, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 27, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:47:53Z", + "what" : "Create" + }, { + "id" : 29, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:34Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 30, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:34Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 31, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:54:40Z", + "what" : "Register" + }, { + "id" : 80, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "createdOn" : "2016-03-17T10:50:35Z", + "what" : "Create" + }, { + "id" : 82, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:35Z", + "what" : "Create" + }, { + "id" : 83, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:40Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, { + "id" : 84, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:50:44Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, { + "id" : 86, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:51:01Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"log-headers-policy\"}" + }, { + "id" : 87, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "public-echo-two", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:51:29Z", + "what" : "Publish" + }, { + "id" : 93, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:51Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, { + "id" : 96, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "Create" + }, { + "id" : 98, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 99, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Api", + "entityId" : "echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:28:05Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, { + "id" : 101, + "who" : "admin", + "organizationId" : "Test", + "entityType" : "Client", + "entityId" : "client1", + "entityVersion" : "1.1", + "createdOn" : "2016-03-17T13:28:22Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } ] + }, { + "OrganizationBean" : { + "id" : "Foo", + "name" : "Foo", + "description" : "An amazing organization so that we have two for testing.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:54:54Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:54:54Z" + }, + "Memberships" : [ { + "id" : 33, + "userId" : "admin", + "roleId" : "OrganizationOwner", + "organizationId" : "Foo", + "createdOn" : "2016-03-17T09:54:54Z" + } ], + "Plans" : [ { + "PlanBean" : { + "id" : "Good", + "name" : "Good", + "description" : "A pretty good plan.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:06Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 35, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:06Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:55:14Z", + "lockedOn" : "2016-03-17T09:55:15Z" + }, + "Policies" : [ { + "id" : 37, + "type" : "Plan", + "organizationId" : "Foo", + "entityId" : "Good", + "entityVersion" : "1.0", + "name" : "Caching Policy", + "configuration" : "{\"ttl\":10}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:14Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:55:14Z", + "definition" : { + "id" : "CachingPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + }, { + "PlanBean" : { + "id" : "Great", + "name" : "Great", + "description" : "A really great plan.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:20Z" + }, + "Versions" : [ { + "PlanVersionBean" : { + "id" : 41, + "status" : "Locked", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:55:20Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:56:15Z", + "lockedOn" : "2016-03-17T09:56:26Z" + }, + "Policies" : [ { + "id" : 43, + "type" : "Plan", + "organizationId" : "Foo", + "entityId" : "Great", + "entityVersion" : "1.0", + "name" : "Time Restricted Access Policy", + "configuration" : "{\"rules\":[{\"timeStart\":\"2016-03-17T13:00:00.000Z\",\"timeEnd\":\"2016-03-17T21:00:00.000Z\",\"dayStart\":4,\"dayEnd\":5,\"pathPattern\":\".*\"}]}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:15Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:56:15Z", + "definition" : { + "id" : "TimeRestrictedAccessPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + } ] + } ] + } ], + "Apis" : [ { + "ApiBean" : { + "id" : "foo-echo", + "name" : "foo-echo", + "description" : "An echo service inside the Foo organization.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:33Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 47, + "status" : "Published", + "endpoint" : "http://localhost:8080/services/echo", + "endpointType" : "rest", + "endpointContentType" : "json", + "endpointProperties" : { + "authorization.type" : "basic", + "basic-auth.requireSSL" : "false", + "basic-auth.username" : "username", + "basic-auth.password" : "password" + }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:56:33Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:59:25Z", + "publishedOn" : "2016-03-17T10:03:01Z", + "definitionType" : "SwaggerJSON" + }, + "Policies" : [ { + "id" : 52, + "type" : "Api", + "organizationId" : "Foo", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "name" : "BASIC Authentication Policy", + "configuration" : "{\"realm\":\"Foo Echo\",\"forwardIdentityHttpHeader\":\"X-Identity\",\"requireBasicAuth\":true,\"staticIdentity\":{\"identities\":[{\"username\":\"user\",\"password\":\"user\"},{\"username\":\"user1\",\"password\":\"user1\"},{\"username\":\"user2\",\"password\":\"user2\"}]}}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:58:46Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:58:46Z", + "definition" : { + "id" : "BASICAuthenticationPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 1 + }, { + "id" : 54, + "type" : "Api", + "organizationId" : "Foo", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "name" : "Ignored Resources Policy", + "configuration" : "{\"rules\":[{\"verb\":\"*\",\"pathPattern\":\"/admin/.*\"}]}", + "createdBy" : "admin", + "createdOn" : "2016-03-17T09:59:25Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T09:59:25Z", + "definition" : { + "id" : "IgnoredResourcesPolicy", + "templates" : [ ], + "deleted" : false + }, + "orderIndex" : 2 + } ] + } ] + }, { + "ApiBean" : { + "id" : "FacebookAPI", + "name" : "Facebook API", + "description" : "The Facebook API is a platform for building applications that are available to the members of the social network of Facebook.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:54Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 65, + "status" : "Published", + "endpoint" : "http://api.facebook.com/restserver.php", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:54Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:05:54Z", + "publishedOn" : "2016-03-17T10:06:11Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "FlickrAPI", + "name" : "Flickr API", + "description" : "The Flickr API can be used to retrieve photos from the Flickr photo sharing service using a variety of feeds.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:55Z", + "numPublished" : 1 + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 68, + "status" : "Published", + "endpoint" : "http://api.flickr.com/services/rest/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : false, + "plans" : [ { + "planId" : "Great", + "version" : "1.0" + }, { + "planId" : "Good", + "version" : "1.0" + } ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:55Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:05:55Z", + "publishedOn" : "2016-03-17T10:06:15Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "TwitterAPI", + "name" : "Twitter API", + "description" : "The Twitter micro-blogging service includes two RESTful APIs.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:56Z" + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 73, + "status" : "Ready", + "endpoint" : "http://twitter.com/statuses/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:56Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:06:56Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + }, { + "ApiBean" : { + "id" : "YouTubeAPI", + "name" : "YouTube API", + "description" : "The Data API allows users to integrate their program with YouTube and allow it to perform many of the operations available on the website.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:57Z" + }, + "Versions" : [ { + "ApiVersionBean" : { + "id" : 76, + "status" : "Ready", + "endpoint" : "http://gdata.youtube.com/feeds/", + "endpointType" : "rest", + "endpointProperties" : { }, + "gateways" : [ { + "gatewayId" : "TheGateway" + } ], + "publicAPI" : true, + "plans" : [ ], + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:06:57Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T10:06:57Z", + "definitionType" : "External" + }, + "Policies" : [ ] + } ] + } ], + "Clients" : [ { + "ClientBean" : { + "id" : "foo-app", + "name" : "foo-app", + "description" : "The foo app! It probably uses the foo-echo API.", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:26Z" + }, + "Versions" : [ { + "ClientVersionBean" : { + "id" : 62, + "status" : "Registered", + "version" : "1.0", + "createdBy" : "admin", + "createdOn" : "2016-03-17T10:05:26Z", + "modifiedBy" : "admin", + "modifiedOn" : "2016-03-17T13:26:51Z", + "publishedOn" : "2016-03-17T13:26:57Z" + }, + "Policies" : [ ], + "Contracts" : [ { + "id" : 88, + "api" : { + "api" : { + "organization" : { + "id" : "Foo" + }, + "id" : "foo-echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Foo" + }, + "id" : "Good" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:26:43Z", + "apikey" : "8844afff-ba78-4910-a3a7-3cd5436e6d49" + }, { + "id" : 91, + "api" : { + "api" : { + "organization" : { + "id" : "Test" + }, + "id" : "echo" + }, + "endpointProperties" : { }, + "publicAPI" : false, + "version" : "1.0" + }, + "plan" : { + "plan" : { + "organization" : { + "id" : "Test" + }, + "id" : "Silver" + }, + "version" : "1.0" + }, + "createdBy" : "admin", + "createdOn" : "2016-03-17T13:26:51Z", + "apikey" : "db4c4bf5-153e-407e-9d3a-a28ad43c84c6" + } ] + } ] + } ], + "Audits" : [ { + "id" : 32, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Organization", + "createdOn" : "2016-03-17T09:54:54Z", + "what" : "Create" + }, { + "id" : 34, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "createdOn" : "2016-03-17T09:55:06Z", + "what" : "Create" + }, { + "id" : 36, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:06Z", + "what" : "Create" + }, { + "id" : 38, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:14Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"CachingPolicy\"}" + }, { + "id" : 39, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:15Z", + "what" : "Lock" + }, { + "id" : 40, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "createdOn" : "2016-03-17T09:55:20Z", + "what" : "Create" + }, { + "id" : 42, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:55:20Z", + "what" : "Create" + }, { + "id" : 44, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:15Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"TimeRestrictedAccessPolicy\"}" + }, { + "id" : 45, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:26Z", + "what" : "Lock" + }, { + "id" : 46, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "createdOn" : "2016-03-17T09:56:33Z", + "what" : "Create" + }, { + "id" : 48, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:56:33Z", + "what" : "Create" + }, { + "id" : 49, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:57:29Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, { + "id" : 50, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:06Z", + "what" : "UpdateDefinition" + }, { + "id" : 51, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:16Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Good:1.0, Great:1.0\"}]}" + }, { + "id" : 53, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:58:46Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"BASICAuthenticationPolicy\"}" + }, { + "id" : 55, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T09:59:25Z", + "what" : "AddPolicy", + "data" : "{\"policyDefId\":\"IgnoredResourcesPolicy\"}" + }, { + "id" : 56, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:03:01Z", + "what" : "Publish" + }, { + "id" : 57, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Organization", + "createdOn" : "2016-03-17T10:04:33Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An amazing organization so that we have two for testing.\"}]}" + }, { + "id" : 58, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Good", + "createdOn" : "2016-03-17T10:04:42Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A pretty good plan.\"}]}" + }, { + "id" : 59, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Plan", + "entityId" : "Great", + "createdOn" : "2016-03-17T10:04:49Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A really great plan.\"}]}" + }, { + "id" : 60, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "createdOn" : "2016-03-17T10:05:00Z", + "what" : "Update", + "data" : "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An echo service inside the Foo organization.\"}]}" + }, { + "id" : 61, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "createdOn" : "2016-03-17T10:05:26Z", + "what" : "Create" + }, { + "id" : 63, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:26Z", + "what" : "Create" + }, { + "id" : 64, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "createdOn" : "2016-03-17T10:05:54Z", + "what" : "Create" + }, { + "id" : 66, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:54Z", + "what" : "Create" + }, { + "id" : 67, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "createdOn" : "2016-03-17T10:05:55Z", + "what" : "Create" + }, { + "id" : 69, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:05:55Z", + "what" : "Create" + }, { + "id" : 70, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FacebookAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:11Z", + "what" : "Publish" + }, { + "id" : 71, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "FlickrAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:15Z", + "what" : "Publish" + }, { + "id" : 72, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "TwitterAPI", + "createdOn" : "2016-03-17T10:06:56Z", + "what" : "Create" + }, { + "id" : 74, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "TwitterAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:56Z", + "what" : "Create" + }, { + "id" : 75, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "YouTubeAPI", + "createdOn" : "2016-03-17T10:06:57Z", + "what" : "Create" + }, { + "id" : 77, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "YouTubeAPI", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T10:06:57Z", + "what" : "Create" + }, { + "id" : 89, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:43Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, { + "id" : 90, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:43Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, { + "id" : 92, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:51Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, { + "id" : 94, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Client", + "entityId" : "foo-app", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:26:57Z", + "what" : "Register" + }, { + "id" : 102, + "who" : "admin", + "organizationId" : "Foo", + "entityType" : "Api", + "entityId" : "foo-echo", + "entityVersion" : "1.0", + "createdOn" : "2016-03-17T13:28:22Z", + "what" : "CreateContract", + "data" : "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } ] + } ] +} +---- +200 +Content-Type: text/plain + +INFO: Migrating export data from old version 1.2.2.Final. +INFO: Migrating User: "admin" +INFO: Migrating Gateway: "The Gateway" +INFO: Migrating Plugin: "Log Policy Plugin" +INFO: Migrating Plugin: "JSONP Policy Plugin" +INFO: Migrating Role: "Organization Owner" +INFO: Migrating Role: "Client App Developer" +INFO: Migrating Role: "API Developer" +INFO: Migrating Role: "Plan Master" +INFO: Migrating Policy Def: "IP Whitelist Policy" +INFO: Migrating Policy Def: "IP Blacklist Policy" +INFO: Migrating Policy Def: "BASIC Authentication Policy" +INFO: Migrating Policy Def: "Rate Limiting Policy" +INFO: Migrating Policy Def: "Ignored Resources Policy" +INFO: Migrating Policy Def: "Authorization Policy" +INFO: Migrating Policy Def: "Quota Policy" +INFO: Migrating Policy Def: "Caching Policy" +INFO: Migrating Policy Def: "Transfer Quota Policy" +INFO: Migrating Policy Def: "URL Rewriting Policy" +INFO: Migrating Policy Def: "Time Restricted Access Policy" +INFO: Migrating Policy Def: "Log Headers Policy" +INFO: Migrating Policy Def: "JSONP Policy" +INFO: Migrating Organization: "Test" +INFO: Migrating Organization: "Foo" +INFO: ---------------------------- +INFO: Starting apiman data import. +INFO: Importing data from apiman version: 1.2.3-SNAPSHOT +INFO: Importing a user: admin +INFO: Importing a gateway: The Gateway +INFO: Importing a plugin: io.apiman.plugins/apiman-plugins-log-policy/1.2.2.Final +INFO: Importing a plugin: io.apiman.plugins/apiman-plugins-jsonp-policy/1.2.2.Final +INFO: Importing a role: Organization Owner +INFO: Importing a role: Client App Developer +INFO: Importing a role: API Developer +INFO: Importing a role: Plan Master +INFO: Importing a policy definition: IP Whitelist Policy +INFO: Importing a policy definition: IP Blacklist Policy +INFO: Importing a policy definition: BASIC Authentication Policy +INFO: Importing a policy definition: Rate Limiting Policy +INFO: Importing a policy definition: Ignored Resources Policy +INFO: Importing a policy definition: Authorization Policy +INFO: Importing a policy definition: Quota Policy +INFO: Importing a policy definition: Caching Policy +INFO: Importing a policy definition: Transfer Quota Policy +INFO: Importing a policy definition: URL Rewriting Policy +INFO: Importing a policy definition: Time Restricted Access Policy +INFO: Importing a policy definition: Log Headers Policy +INFO: Importing a policy definition: JSONP Policy +INFO: Importing an organization: Test +INFO: Importing a role membership: admin+OrganizationOwner=>Test +INFO: Importing a plan: Gold +INFO: Importing a plan version: 1.0 +INFO: Importing a plan policy: Rate Limiting Policy +INFO: Importing a plan: Silver +INFO: Importing a plan version: 1.0 +INFO: Importing a plan policy: Rate Limiting Policy +INFO: Importing an API: echo +INFO: Importing an API version: 1.0 +INFO: Importing an API: public-echo +INFO: Importing an API version: 1.0 +INFO: Importing an API: public-echo-two +INFO: Importing an API version: 1.0 +INFO: Importing an API policy: Log Headers Policy +INFO: Importing a client: client1 +INFO: Importing a client version: 1.0 +INFO: Importing a client version: 1.1 +INFO: Importing an audit entry: 1 +INFO: Importing an audit entry: 3 +INFO: Importing an audit entry: 4 +INFO: Importing an audit entry: 6 +INFO: Importing an audit entry: 8 +INFO: Importing an audit entry: 10 +INFO: Importing an audit entry: 12 +INFO: Importing an audit entry: 13 +INFO: Importing an audit entry: 14 +INFO: Importing an audit entry: 15 +INFO: Importing an audit entry: 17 +INFO: Importing an audit entry: 18 +INFO: Importing an audit entry: 19 +INFO: Importing an audit entry: 20 +INFO: Importing an audit entry: 22 +INFO: Importing an audit entry: 23 +INFO: Importing an audit entry: 24 +INFO: Importing an audit entry: 25 +INFO: Importing an audit entry: 27 +INFO: Importing an audit entry: 29 +INFO: Importing an audit entry: 30 +INFO: Importing an audit entry: 31 +INFO: Importing an audit entry: 80 +INFO: Importing an audit entry: 82 +INFO: Importing an audit entry: 83 +INFO: Importing an audit entry: 84 +INFO: Importing an audit entry: 86 +INFO: Importing an audit entry: 87 +INFO: Importing an audit entry: 93 +INFO: Importing an audit entry: 96 +INFO: Importing an audit entry: 98 +INFO: Importing an audit entry: 99 +INFO: Importing an audit entry: 101 +INFO: Importing an organization: Foo +INFO: Importing a role membership: admin+OrganizationOwner=>Foo +INFO: Importing a plan: Good +INFO: Importing a plan version: 1.0 +INFO: Importing a plan policy: Caching Policy +INFO: Importing a plan: Great +INFO: Importing a plan version: 1.0 +INFO: Importing a plan policy: Time Restricted Access Policy +INFO: Importing an API: foo-echo +INFO: Importing an API version: 1.0 +INFO: Importing an API policy: BASIC Authentication Policy +INFO: Importing an API policy: Ignored Resources Policy +INFO: Importing an API: Facebook API +INFO: Importing an API version: 1.0 +INFO: Importing an API: Flickr API +INFO: Importing an API version: 1.0 +INFO: Importing an API: Twitter API +INFO: Importing an API version: 1.0 +INFO: Importing an API: YouTube API +INFO: Importing an API version: 1.0 +INFO: Importing a client: foo-app +INFO: Importing a client version: 1.0 +INFO: Importing an audit entry: 32 +INFO: Importing an audit entry: 34 +INFO: Importing an audit entry: 36 +INFO: Importing an audit entry: 38 +INFO: Importing an audit entry: 39 +INFO: Importing an audit entry: 40 +INFO: Importing an audit entry: 42 +INFO: Importing an audit entry: 44 +INFO: Importing an audit entry: 45 +INFO: Importing an audit entry: 46 +INFO: Importing an audit entry: 48 +INFO: Importing an audit entry: 49 +INFO: Importing an audit entry: 50 +INFO: Importing an audit entry: 51 +INFO: Importing an audit entry: 53 +INFO: Importing an audit entry: 55 +INFO: Importing an audit entry: 56 +INFO: Importing an audit entry: 57 +INFO: Importing an audit entry: 58 +INFO: Importing an audit entry: 59 +INFO: Importing an audit entry: 60 +INFO: Importing an audit entry: 61 +INFO: Importing an audit entry: 63 +INFO: Importing an audit entry: 64 +INFO: Importing an audit entry: 66 +INFO: Importing an audit entry: 67 +INFO: Importing an audit entry: 69 +INFO: Importing an audit entry: 70 +INFO: Importing an audit entry: 71 +INFO: Importing an audit entry: 72 +INFO: Importing an audit entry: 74 +INFO: Importing an audit entry: 75 +INFO: Importing an audit entry: 77 +INFO: Importing an audit entry: 89 +INFO: Importing an audit entry: 90 +INFO: Importing an audit entry: 92 +INFO: Importing an audit entry: 94 +INFO: Importing an audit entry: 102 +INFO: Importing a client contract. +INFO: Importing a client contract. +INFO: Importing a client contract. +INFO: Importing a client contract. +INFO: Importing a client contract. +INFO: Publishing APIs to the gateway. +INFO: Publishing API: Foo / foo-echo -> 1.0 +INFO: Publishing API: Foo / FlickrAPI -> 1.0 +INFO: Publishing API: Foo / FacebookAPI -> 1.0 +INFO: Publishing API: Test / public-echo-two -> 1.0 +INFO: Publishing API: Test / echo -> 1.0 +INFO: Publishing API: Test / public-echo -> 1.0 +INFO: Registering clients in the gateway. +INFO: Registering app: Foo / foo-app -> 1.0 +INFO: Registering app: Test / client1 -> 1.0 +INFO: ----------------------------------- +INFO: Data import completed successfully! +INFO: ----------------------------------- diff --git a/manager/test/api/src/test/resources/test-plan-data/migrate/002_export.resttest b/manager/test/api/src/test/resources/test-plan-data/migrate/002_export.resttest new file mode 100644 index 0000000000..7733de2d03 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plan-data/migrate/002_export.resttest @@ -0,0 +1,1891 @@ +GET /system/export admin/admin +---- +200 +Content-Type: application/json + +{ + "Metadata": { + "exportedOn": "*", + "apimanVersion": "*" + }, + "Users": [ + { + "username": "admin", + "fullName": "Admin", + "email": "admin@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "admin2", + "fullName": "Admin 2", + "email": "admin2@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user1", + "fullName": "User 1", + "email": "user1@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user2", + "fullName": "User 2", + "email": "user2@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user3", + "fullName": "User 3", + "email": "user3@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user4", + "fullName": "User 4", + "email": "user4@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "user5", + "fullName": "User 5", + "email": "user5@example.org", + "joinedOn": "*", + "admin": false + }, + { + "username": "bwayne", + "fullName": "Bruce Wayne", + "email": "bwayne@wayne-enterprises.com", + "joinedOn": "*", + "admin": false + }, + { + "username": "ckent", + "fullName": "Clark Kent", + "email": "ckent@dailyplanet.com", + "joinedOn": "*", + "admin": false + }, + { + "username": "dprince", + "fullName": "Diana Prince", + "email": "dprince@themyscira.gov", + "joinedOn": "*", + "admin": false + } + ], + "Gateways": [ + { + "id": "TheGateway", + "name": "The Gateway", + "description": "This is the gateway.", + "createdBy": "admin", + "createdOn": "2015-10-27T19:13:25Z", + "modifiedBy": "admin", + "modifiedOn": "2015-10-27T19:13:25Z", + "type": "REST", + "configuration": "{\"endpoint\":\"http://localhost:7070/mock-gateway\",\"username\":\"admin\",\"password\":\"$CRYPT::j8rdW76Z5gUI0I+9c8/GrA==\"}" + } + ], + "Plugins": [ + { + "id": 1, + "groupId": "io.apiman.plugins", + "artifactId": "apiman-plugins-log-policy", + "version": "1.2.2.Final", + "name": "Log Policy Plugin", + "description": "This plugin has policies for logging to std out.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:49:39Z", + "deleted": false + }, + { + "id": 2, + "groupId": "io.apiman.plugins", + "artifactId": "apiman-plugins-jsonp-policy", + "version": "1.2.2.Final", + "name": "JSONP Policy Plugin", + "description": "A plugin that contributes a policy that turns a standard RESTful endpoint into a JSONP compatible endpoint.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:49:49Z", + "deleted": false + } + ], + "Roles": [ + { + "id": "OrganizationOwner", + "name": "Organization Owner", + "description": "Automatically granted to the user who creates an Organization. Grants all privileges.", + "createdBy": "admin", + "createdOn": "2016-02-29T13:43:23Z", + "autoGrant": true, + "permissions": [ + "orgView", + "orgAdmin", + "planAdmin", + "clientAdmin", + "orgEdit", + "apiEdit", + "apiView", + "clientView", + "clientEdit", + "apiAdmin", + "planView", + "planEdit" + ] + }, + { + "id": "ClientAppDeveloper", + "name": "Client App Developer", + "description": "Users responsible for creating and managing client apps should be granted this role within an Organization.", + "createdBy": "admin", + "createdOn": "2016-02-29T13:43:24Z", + "autoGrant": false, + "permissions": [ + "clientAdmin", + "clientView", + "clientEdit" + ] + }, + { + "id": "APIDeveloper", + "name": "API Developer", + "description": "Users responsible for creating and managing APIs should be granted this role within an Organization.", + "createdBy": "admin", + "createdOn": "2016-02-29T13:43:24Z", + "autoGrant": false, + "permissions": [ + "planAdmin", + "apiEdit", + "apiView", + "apiAdmin", + "planView", + "planEdit" + ] + }, + { + "id": "PlanMaster", + "name": "Plan Master", + "description": "The master of all plans!", + "createdBy": "admin", + "createdOn": "2016-03-17T10:49:20Z", + "autoGrant": false, + "permissions": [ + "planAdmin", + "planView", + "planEdit" + ] + } + ], + "PolicyDefinitions": [ + { + "id": "IPWhitelistPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.IPWhitelistPolicy", + "name": "IP Whitelist Policy", + "description": "Only requests that originate from a specified set of valid IP addresses will be allowed through.", + "icon": "filter", + "templates": [ + { + "template": "Only requests that originate from the set of configured IP address(es) will be allowed to invoke the managed API." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "IPBlacklistPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.IPBlacklistPolicy", + "name": "IP Blacklist Policy", + "description": "Requests that originate from a specified set of valid IP addresses will be denied access.", + "icon": "thumbs-down", + "templates": [ + { + "template": "Requests that originate from the set of configured IP address(es) will be denied access to the managed API." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "BASICAuthenticationPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.BasicAuthenticationPolicy", + "name": "BASIC Authentication Policy", + "description": "Enables HTTP BASIC Authentication on an API. Some configuration required.", + "icon": "lock", + "templates": [ + { + "template": "Access to the API is protected by BASIC Authentication through the '' authentication realm. @if{forwardIdentityHttpHeader != null}Successfully authenticated requests will forward the authenticated identity to the back end API via the '' custom HTTP header.@end{}" + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "RateLimitingPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.RateLimitingPolicy", + "name": "Rate Limiting Policy", + "description": "Enforces rate configurable request rate limits on an API. This ensures that consumers can't overload an API with too many requests.", + "icon": "sliders", + "templates": [ + { + "template": "Consumers are limited to requests per per ." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "IgnoredResourcesPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.IgnoredResourcesPolicy", + "name": "Ignored Resources Policy", + "description": "Requests satisfying the provided regular expression will be ignored.", + "icon": "eye-slash", + "templates": [ + { + "template": "Requests matching any of the regular expressions provided will receive a 404 error code." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "AuthorizationPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.AuthorizationPolicy", + "name": "Authorization Policy", + "description": "Enables fine grained authorization to API resources based on authenticated user roles.", + "icon": "users", + "templates": [ + { + "template": "Appropriate authorization roles are required. There are authorization rules defined." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "QuotaPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.QuotaPolicy", + "name": "Quota Policy", + "description": "Provides a way to limit the total number of requests that can be sent to an API.", + "icon": "exchange", + "templates": [ + { + "template": "Consumers cannot exceed their quota of requests per per ." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "CachingPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.CachingPolicy", + "name": "Caching Policy", + "description": "Allows caching of API responses in the Gateway to reduce overall traffic to the back-end API.", + "icon": "hdd-o", + "templates": [ + { + "template": "API responses will be cached for seconds." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "TransferQuotaPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.TransferQuotaPolicy", + "name": "Transfer Quota Policy", + "description": "Provides a way to limit the total number of bytes that can be transferred from (or to) an API.", + "icon": "download", + "templates": [ + { + "template": "Consumers are limited to transferring bytes per per ." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "URLRewritingPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.URLRewritingPolicy", + "name": "URL Rewriting Policy", + "description": "Responses from the back-end API will be modified by fixing up any incorrect URLs found with modified ones. This is useful because apiman works through an API Gateway.", + "icon": "pencil-square", + "templates": [ + { + "template": "Responses will be modified by finding all text matching regular expression '' with ''." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "TimeRestrictedAccessPolicy", + "policyImpl": "class:io.apiman.gateway.engine.policies.TimeRestrictedAccessPolicy", + "name": "Time Restricted Access Policy", + "description": "Requests matching the specified regular expression and made within the specified time period will be ignored.", + "icon": "clock-o", + "templates": [ + { + "template": "Requests matching the regular expression and made outside the specified time period will receive a 423 error code." + } + ], + "formType": "Default", + "deleted": false + }, + { + "id": "log-headers-policy", + "policyImpl": "plugin:io.apiman.plugins:apiman-plugins-log-policy:1.2.2.Final:war/io.apiman.plugins.log_policy.LogHeadersPolicy", + "name": "Log Headers Policy", + "description": "A policy that logs the headers to std out. Useful to analyse inbound HTTP traffic to the gateway when added as the first policy in the chain or to analyse outbound HTTP traffic from the gateway when added as the last policy in the chain.", + "icon": "fire", + "templates": [], + "pluginId": 78, + "formType": "JsonSchema", + "form": "schemas/log-policyDef.schema", + "deleted": false + }, + { + "id": "jsonp-policy", + "policyImpl": "plugin:io.apiman.plugins:apiman-plugins-jsonp-policy:1.2.2.Final:war/io.apiman.plugins.jsonp_policy.JsonpPolicy", + "name": "JSONP Policy", + "description": "Turns an endpoint into a JSONP compatible endpoint.", + "icon": "bars", + "templates": [], + "pluginId": 79, + "formType": "JsonSchema", + "form": "schemas/jsonp-policyDef.schema", + "deleted": false + } + ], + "Orgs": [ + { + "OrganizationBean": { + "id": "Test", + "name": "Test", + "description": "A test organization used by the full apiman smoke test suite.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:51Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:51Z" + }, + "Memberships": [ + { + "id": 3, + "userId": "admin", + "roleId": "OrganizationOwner", + "organizationId": "Test", + "createdOn": "2016-03-17T09:47:51Z" + } + ], + "Plans": [ + { + "PlanBean": { + "id": "Gold", + "name": "Gold", + "description": "The Gold plan allows users the highest level of API.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z" + }, + "Versions": [ + { + "PlanVersionBean": { + "id": 4, + "status": "Locked", + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:52Z", + "lockedOn": "2016-03-17T09:47:52Z" + }, + "Policies": [ + { + "id": 5, + "type": "Plan", + "organizationId": "Test", + "entityId": "Gold", + "entityVersion": "1.0", + "name": "Rate Limiting Policy", + "configuration": "{ \"limit\" : 100, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:52Z", + "definition": { + "id": "RateLimitingPolicy", + "templates": [], + "deleted": false + }, + "orderIndex": 1 + } + ] + } + ] + }, + { + "PlanBean": { + "id": "Silver", + "name": "Silver", + "description": "The Silver plan allows users a lower level of API.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z" + }, + "Versions": [ + { + "PlanVersionBean": { + "id": 6, + "status": "Locked", + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:52Z", + "lockedOn": "2016-03-17T09:47:52Z" + }, + "Policies": [ + { + "id": 7, + "type": "Plan", + "organizationId": "Test", + "entityId": "Silver", + "entityVersion": "1.0", + "name": "Rate Limiting Policy", + "configuration": "{ \"limit\" : 5, \"granularity\" : \"Client\", \"period\" : \"Minute\" }", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:52Z", + "definition": { + "id": "RateLimitingPolicy", + "templates": [], + "deleted": false + }, + "orderIndex": 1 + } + ] + } + ] + } + ], + "Apis": [ + { + "ApiBean": { + "id": "echo", + "name": "echo", + "description": "A simple echo REST API.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 8, + "status": "Published", + "endpoint": "http://localhost:8080/services/echo/echo", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": false, + "plans": [ + { + "planId": "Gold", + "version": "1.0" + }, + { + "planId": "Silver", + "version": "1.0" + } + ], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:52Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:52Z", + "publishedOn": "2016-03-17T09:47:53Z" + }, + "Policies": [] + } + ] + }, + { + "ApiBean": { + "id": "public-echo", + "name": "public-echo", + "description": "A public echo REST API.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:53Z", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 9, + "status": "Published", + "endpoint": "http://localhost:8080/services/echo/public-echo", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": true, + "plans": [], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:53Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:47:53Z", + "publishedOn": "2016-03-17T09:47:53Z" + }, + "Policies": [] + } + ] + }, + { + "ApiBean": { + "id": "public-echo-two", + "name": "public-echo-two", + "description": "A second public echo API. Tests some plugin policies.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:50:35Z", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 10, + "status": "Published", + "endpoint": "http://localhost:8080/services/echo", + "endpointType": "rest", + "endpointContentType": "json", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": true, + "plans": [], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T10:50:35Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T10:51:01Z", + "publishedOn": "2016-03-17T10:51:29Z" + }, + "Policies": [ + { + "id": 11, + "type": "Api", + "organizationId": "Test", + "entityId": "public-echo-two", + "entityVersion": "1.0", + "name": "Log Headers Policy", + "configuration": "{\"direction\":\"both\"}", + "createdBy": "admin", + "createdOn": "2016-03-17T10:51:01Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T10:51:01Z", + "definition": { + "id": "log-headers-policy", + "templates": [], + "deleted": false + }, + "orderIndex": 1 + } + ] + } + ] + } + ], + "Clients": [ + { + "ClientBean": { + "id": "client1", + "name": "client1", + "description": "A simple test client.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:53Z" + }, + "Versions": [ + { + "ClientVersionBean": { + "id": 12, + "status": "Registered", + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:47:53Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:54:34Z", + "publishedOn": "2016-03-17T09:54:40Z", + "apikey": "*" + }, + "Policies": [], + "Contracts": [ + { + "id": 98, + "api": { + "api": { + "organization": { + "id": "Test" + }, + "id": "echo" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Test" + }, + "id": "Gold" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "2016-03-17T09:54:34Z" + } + ] + }, + { + "ClientVersionBean": { + "id": 13, + "status": "Ready", + "version": "1.1", + "createdBy": "admin", + "createdOn": "2016-03-17T13:28:05Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T13:28:22Z", + "apikey": "*" + }, + "Policies": [], + "Contracts": [ + { + "id": 99, + "api": { + "api": { + "organization": { + "id": "Foo" + }, + "id": "foo-echo" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Foo" + }, + "id": "Great" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "2016-03-17T13:28:22Z" + }, + { + "id": 100, + "api": { + "api": { + "organization": { + "id": "Test" + }, + "id": "echo" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Test" + }, + "id": "Gold" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "2016-03-17T13:28:05Z" + } + ] + } + ] + } + ], + "Audits": [ + { + "id": 14, + "who": "admin", + "organizationId": "Test", + "entityType": "Organization", + "createdOn": "2016-03-17T09:47:51Z", + "what": "Create" + }, + { + "id": 15, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Gold", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Create" + }, + { + "id": 16, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Silver", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Create" + }, + { + "id": 17, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Gold", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Create" + }, + { + "id": 18, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Silver", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Create" + }, + { + "id": 19, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Gold", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, + { + "id": 20, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Silver", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"RateLimitingPolicy\"}" + }, + { + "id": 21, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Gold", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Lock" + }, + { + "id": 22, + "who": "admin", + "organizationId": "Test", + "entityType": "Plan", + "entityId": "Silver", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Lock" + }, + { + "id": 23, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Create" + }, + { + "id": 24, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Create" + }, + { + "id": 25, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:52Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Gold:1.0, Silver:1.0\"},{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"}]}" + }, + { + "id": 26, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Publish" + }, + { + "id": 27, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Create" + }, + { + "id": 28, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Create" + }, + { + "id": 29, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo/public-echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, + { + "id": 30, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Publish" + }, + { + "id": 31, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Create" + }, + { + "id": 32, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:47:53Z", + "what": "Create" + }, + { + "id": 33, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:54:34Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, + { + "id": 34, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:54:34Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, + { + "id": 35, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:54:40Z", + "what": "Register" + }, + { + "id": 36, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo-two", + "createdOn": "2016-03-17T10:50:35Z", + "what": "Create" + }, + { + "id": 37, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo-two", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:50:35Z", + "what": "Create" + }, + { + "id": 38, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo-two", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:50:40Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, + { + "id": 39, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo-two", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:50:44Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"publicAPI\",\"before\":\"false\",\"after\":\"true\"}]}" + }, + { + "id": 40, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo-two", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:51:01Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"log-headers-policy\"}" + }, + { + "id": 41, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "public-echo-two", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:51:29Z", + "what": "Publish" + }, + { + "id": 42, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:26:51Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, + { + "id": 43, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "entityVersion": "1.1", + "createdOn": "2016-03-17T13:28:05Z", + "what": "Create" + }, + { + "id": 44, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "entityVersion": "1.1", + "createdOn": "2016-03-17T13:28:05Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, + { + "id": 45, + "who": "admin", + "organizationId": "Test", + "entityType": "Api", + "entityId": "echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:28:05Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Gold\",\"planVersion\":\"1.0\"}" + }, + { + "id": 46, + "who": "admin", + "organizationId": "Test", + "entityType": "Client", + "entityId": "client1", + "entityVersion": "1.1", + "createdOn": "2016-03-17T13:28:22Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } + ] + }, + { + "OrganizationBean": { + "id": "Foo", + "name": "Foo", + "description": "An amazing organization so that we have two for testing.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:54:54Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:54:54Z" + }, + "Memberships": [ + { + "id": 47, + "userId": "admin", + "roleId": "OrganizationOwner", + "organizationId": "Foo", + "createdOn": "2016-03-17T09:54:54Z" + } + ], + "Plans": [ + { + "PlanBean": { + "id": "Good", + "name": "Good", + "description": "A pretty good plan.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:55:06Z" + }, + "Versions": [ + { + "PlanVersionBean": { + "id": 48, + "status": "Locked", + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:55:06Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:55:14Z", + "lockedOn": "2016-03-17T09:55:15Z" + }, + "Policies": [ + { + "id": 49, + "type": "Plan", + "organizationId": "Foo", + "entityId": "Good", + "entityVersion": "1.0", + "name": "Caching Policy", + "configuration": "{\"ttl\":10}", + "createdBy": "admin", + "createdOn": "2016-03-17T09:55:14Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:55:14Z", + "definition": { + "id": "CachingPolicy", + "templates": [], + "deleted": false + }, + "orderIndex": 1 + } + ] + } + ] + }, + { + "PlanBean": { + "id": "Great", + "name": "Great", + "description": "A really great plan.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:55:20Z" + }, + "Versions": [ + { + "PlanVersionBean": { + "id": 50, + "status": "Locked", + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:55:20Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:56:15Z", + "lockedOn": "2016-03-17T09:56:26Z" + }, + "Policies": [ + { + "id": 51, + "type": "Plan", + "organizationId": "Foo", + "entityId": "Great", + "entityVersion": "1.0", + "name": "Time Restricted Access Policy", + "configuration": "{\"rules\":[{\"timeStart\":\"2016-03-17T13:00:00.000Z\",\"timeEnd\":\"2016-03-17T21:00:00.000Z\",\"dayStart\":4,\"dayEnd\":5,\"pathPattern\":\".*\"}]}", + "createdBy": "admin", + "createdOn": "2016-03-17T09:56:15Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:56:15Z", + "definition": { + "id": "TimeRestrictedAccessPolicy", + "templates": [], + "deleted": false + }, + "orderIndex": 1 + } + ] + } + ] + } + ], + "Apis": [ + { + "ApiBean": { + "id": "foo-echo", + "name": "foo-echo", + "description": "An echo service inside the Foo organization.", + "createdBy": "admin", + "createdOn": "2016-03-17T09:56:33Z", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 52, + "status": "Published", + "endpoint": "http://localhost:8080/services/echo", + "endpointType": "rest", + "endpointContentType": "json", + "endpointProperties": { + "authorization.type": "basic", + "basic-auth.requireSSL": "false", + "basic-auth.username": "username", + "basic-auth.password": "password" + }, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": false, + "plans": [ + { + "planId": "Great", + "version": "1.0" + }, + { + "planId": "Good", + "version": "1.0" + } + ], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T09:56:33Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:59:25Z", + "publishedOn": "2016-03-17T10:03:01Z", + "definitionType": "SwaggerJSON" + }, + "Policies": [ + { + "id": 53, + "type": "Api", + "organizationId": "Foo", + "entityId": "foo-echo", + "entityVersion": "1.0", + "name": "BASIC Authentication Policy", + "configuration": "{\"realm\":\"Foo Echo\",\"forwardIdentityHttpHeader\":\"X-Identity\",\"requireBasicAuth\":true,\"staticIdentity\":{\"identities\":[{\"username\":\"user\",\"password\":\"user\"},{\"username\":\"user1\",\"password\":\"user1\"},{\"username\":\"user2\",\"password\":\"user2\"}]}}", + "createdBy": "admin", + "createdOn": "2016-03-17T09:58:46Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:58:46Z", + "definition": { + "id": "BASICAuthenticationPolicy", + "templates": [], + "deleted": false + }, + "orderIndex": 1 + }, + { + "id": 54, + "type": "Api", + "organizationId": "Foo", + "entityId": "foo-echo", + "entityVersion": "1.0", + "name": "Ignored Resources Policy", + "configuration": "{\"rules\":[{\"verb\":\"*\",\"pathPattern\":\"/admin/.*\"}]}", + "createdBy": "admin", + "createdOn": "2016-03-17T09:59:25Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T09:59:25Z", + "definition": { + "id": "IgnoredResourcesPolicy", + "templates": [], + "deleted": false + }, + "orderIndex": 2 + } + ] + } + ] + }, + { + "ApiBean": { + "id": "FacebookAPI", + "name": "Facebook API", + "description": "The Facebook API is a platform for building applications that are available to the members of the social network of Facebook.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:05:54Z", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 55, + "status": "Published", + "endpoint": "http://api.facebook.com/restserver.php", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": false, + "plans": [ + { + "planId": "Great", + "version": "1.0" + }, + { + "planId": "Good", + "version": "1.0" + } + ], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T10:05:54Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T10:05:54Z", + "publishedOn": "2016-03-17T10:06:11Z", + "definitionType": "External" + }, + "Policies": [] + } + ] + }, + { + "ApiBean": { + "id": "FlickrAPI", + "name": "Flickr API", + "description": "The Flickr API can be used to retrieve photos from the Flickr photo sharing service using a variety of feeds.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:05:55Z", + "numPublished": 1 + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 56, + "status": "Published", + "endpoint": "http://api.flickr.com/services/rest/", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": false, + "plans": [ + { + "planId": "Great", + "version": "1.0" + }, + { + "planId": "Good", + "version": "1.0" + } + ], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T10:05:55Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T10:05:55Z", + "publishedOn": "2016-03-17T10:06:15Z", + "definitionType": "External" + }, + "Policies": [] + } + ] + }, + { + "ApiBean": { + "id": "TwitterAPI", + "name": "Twitter API", + "description": "The Twitter micro-blogging service includes two RESTful APIs.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:06:56Z" + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 57, + "status": "Ready", + "endpoint": "http://twitter.com/statuses/", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": true, + "plans": [], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T10:06:56Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T10:06:56Z", + "definitionType": "External" + }, + "Policies": [] + } + ] + }, + { + "ApiBean": { + "id": "YouTubeAPI", + "name": "YouTube API", + "description": "The Data API allows users to integrate their program with YouTube and allow it to perform many of the operations available on the website.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:06:57Z" + }, + "Versions": [ + { + "ApiVersionBean": { + "id": 58, + "status": "Ready", + "endpoint": "http://gdata.youtube.com/feeds/", + "endpointType": "rest", + "endpointProperties": {}, + "gateways": [ + { + "gatewayId": "TheGateway" + } + ], + "publicAPI": true, + "plans": [], + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T10:06:57Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T10:06:57Z", + "definitionType": "External" + }, + "Policies": [] + } + ] + } + ], + "Clients": [ + { + "ClientBean": { + "id": "foo-app", + "name": "foo-app", + "description": "The foo app! It probably uses the foo-echo API.", + "createdBy": "admin", + "createdOn": "2016-03-17T10:05:26Z" + }, + "Versions": [ + { + "ClientVersionBean": { + "id": 59, + "status": "Registered", + "version": "1.0", + "createdBy": "admin", + "createdOn": "2016-03-17T10:05:26Z", + "modifiedBy": "admin", + "modifiedOn": "2016-03-17T13:26:51Z", + "publishedOn": "2016-03-17T13:26:57Z", + "apikey": "*" + }, + "Policies": [], + "Contracts": [ + { + "id": 101, + "api": { + "api": { + "organization": { + "id": "Foo" + }, + "id": "foo-echo" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Foo" + }, + "id": "Good" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "2016-03-17T13:26:43Z" + }, + { + "id": 102, + "api": { + "api": { + "organization": { + "id": "Test" + }, + "id": "echo" + }, + "endpointProperties": {}, + "publicAPI": false, + "version": "1.0" + }, + "plan": { + "plan": { + "organization": { + "id": "Test" + }, + "id": "Silver" + }, + "version": "1.0" + }, + "createdBy": "admin", + "createdOn": "2016-03-17T13:26:51Z" + } + ] + } + ] + } + ], + "Audits": [ + { + "id": 60, + "who": "admin", + "organizationId": "Foo", + "entityType": "Organization", + "createdOn": "2016-03-17T09:54:54Z", + "what": "Create" + }, + { + "id": 61, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Good", + "createdOn": "2016-03-17T09:55:06Z", + "what": "Create" + }, + { + "id": 62, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Good", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:55:06Z", + "what": "Create" + }, + { + "id": 63, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Good", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:55:14Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"CachingPolicy\"}" + }, + { + "id": 64, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Good", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:55:15Z", + "what": "Lock" + }, + { + "id": 65, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Great", + "createdOn": "2016-03-17T09:55:20Z", + "what": "Create" + }, + { + "id": 66, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Great", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:55:20Z", + "what": "Create" + }, + { + "id": 67, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Great", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:56:15Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"TimeRestrictedAccessPolicy\"}" + }, + { + "id": 68, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Great", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:56:26Z", + "what": "Lock" + }, + { + "id": 69, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "createdOn": "2016-03-17T09:56:33Z", + "what": "Create" + }, + { + "id": 70, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:56:33Z", + "what": "Create" + }, + { + "id": 71, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:57:29Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"endpoint\",\"before\":null,\"after\":\"http://localhost:8080/services/echo\"},{\"name\":\"endpointType\",\"before\":null,\"after\":\"rest\"},{\"name\":\"endpointContentType\",\"before\":null,\"after\":\"json\"}]}" + }, + { + "id": 72, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:58:06Z", + "what": "UpdateDefinition" + }, + { + "id": 73, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:58:16Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"plans\",\"before\":\"\",\"after\":\"Good:1.0, Great:1.0\"}]}" + }, + { + "id": 74, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:58:46Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"BASICAuthenticationPolicy\"}" + }, + { + "id": 75, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T09:59:25Z", + "what": "AddPolicy", + "data": "{\"policyDefId\":\"IgnoredResourcesPolicy\"}" + }, + { + "id": 76, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:03:01Z", + "what": "Publish" + }, + { + "id": 77, + "who": "admin", + "organizationId": "Foo", + "entityType": "Organization", + "createdOn": "2016-03-17T10:04:33Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An amazing organization so that we have two for testing.\"}]}" + }, + { + "id": 78, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Good", + "createdOn": "2016-03-17T10:04:42Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A pretty good plan.\"}]}" + }, + { + "id": 79, + "who": "admin", + "organizationId": "Foo", + "entityType": "Plan", + "entityId": "Great", + "createdOn": "2016-03-17T10:04:49Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"A really great plan.\"}]}" + }, + { + "id": 80, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "createdOn": "2016-03-17T10:05:00Z", + "what": "Update", + "data": "{\"changes\":[{\"name\":\"description\",\"before\":null,\"after\":\"An echo service inside the Foo organization.\"}]}" + }, + { + "id": 81, + "who": "admin", + "organizationId": "Foo", + "entityType": "Client", + "entityId": "foo-app", + "createdOn": "2016-03-17T10:05:26Z", + "what": "Create" + }, + { + "id": 82, + "who": "admin", + "organizationId": "Foo", + "entityType": "Client", + "entityId": "foo-app", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:05:26Z", + "what": "Create" + }, + { + "id": 83, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "FacebookAPI", + "createdOn": "2016-03-17T10:05:54Z", + "what": "Create" + }, + { + "id": 84, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "FacebookAPI", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:05:54Z", + "what": "Create" + }, + { + "id": 85, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "FlickrAPI", + "createdOn": "2016-03-17T10:05:55Z", + "what": "Create" + }, + { + "id": 86, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "FlickrAPI", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:05:55Z", + "what": "Create" + }, + { + "id": 87, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "FacebookAPI", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:06:11Z", + "what": "Publish" + }, + { + "id": 88, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "FlickrAPI", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:06:15Z", + "what": "Publish" + }, + { + "id": 89, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "TwitterAPI", + "createdOn": "2016-03-17T10:06:56Z", + "what": "Create" + }, + { + "id": 90, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "TwitterAPI", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:06:56Z", + "what": "Create" + }, + { + "id": 91, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "YouTubeAPI", + "createdOn": "2016-03-17T10:06:57Z", + "what": "Create" + }, + { + "id": 92, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "YouTubeAPI", + "entityVersion": "1.0", + "createdOn": "2016-03-17T10:06:57Z", + "what": "Create" + }, + { + "id": 93, + "who": "admin", + "organizationId": "Foo", + "entityType": "Client", + "entityId": "foo-app", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:26:43Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, + { + "id": 94, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:26:43Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Good\",\"planVersion\":\"1.0\"}" + }, + { + "id": 95, + "who": "admin", + "organizationId": "Foo", + "entityType": "Client", + "entityId": "foo-app", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:26:51Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Foo\",\"clientId\":\"foo-app\",\"clientVersion\":\"1.0\",\"apiOrgId\":\"Test\",\"apiId\":\"echo\",\"apiVersion\":\"1.0\",\"planId\":\"Silver\",\"planVersion\":\"1.0\"}" + }, + { + "id": 96, + "who": "admin", + "organizationId": "Foo", + "entityType": "Client", + "entityId": "foo-app", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:26:57Z", + "what": "Register" + }, + { + "id": 97, + "who": "admin", + "organizationId": "Foo", + "entityType": "Api", + "entityId": "foo-echo", + "entityVersion": "1.0", + "createdOn": "2016-03-17T13:28:22Z", + "what": "CreateContract", + "data": "{\"clientOrgId\":\"Test\",\"clientId\":\"client1\",\"clientVersion\":\"1.1\",\"apiOrgId\":\"Foo\",\"apiId\":\"foo-echo\",\"apiVersion\":\"1.0\",\"planId\":\"Great\",\"planVersion\":\"1.0\"}" + } + ] + } + ] +} diff --git a/manager/test/api/src/test/resources/test-plans/export-testPlan.xml b/manager/test/api/src/test/resources/test-plans/export-testPlan.xml index b351eada65..62c0929aac 100644 --- a/manager/test/api/src/test/resources/test-plans/export-testPlan.xml +++ b/manager/test/api/src/test/resources/test-plans/export-testPlan.xml @@ -2,26 +2,48 @@ - test-plan-data/export/creates/000_create-gateway.resttest - test-plan-data/export/creates/001_create_org.resttest - test-plan-data/export/creates/002_create-plan1.resttest - test-plan-data/export/creates/003_create-plan1-version-1.0.resttest - test-plan-data/export/publish/003_lock-plan-1.resttest - test-plan-data/export/creates/004_create-client1.resttest - test-plan-data/export/creates/005_create-client1-version-1.0.resttest - test-plan-data/export/creates/006_create-api1.resttest - test-plan-data/export/creates/007_create-api1-version-1.0.resttest - test-plan-data/export/creates/007.5_update-api1-version-1.0.resttest - test-plan-data/export/publish/001_publish-api-1.resttest - test-plan-data/export/creates/008_create-contract1.resttest - test-plan-data/export/publish/002_register-client-1.resttest + test-plan-data/export/creates-1/000_create-gateway.resttest + test-plan-data/export/creates-1/001_create_org.resttest + test-plan-data/export/creates-1/002_create-plan1.resttest + test-plan-data/export/creates-1/003_create-plan1-version-1.0.resttest + test-plan-data/export/creates-1/003.5_lock-plan-1.resttest + test-plan-data/export/creates-1/004_create-client1.resttest + test-plan-data/export/creates-1/005_create-client1-version-1.0.resttest + test-plan-data/export/creates-1/006_create-api1.resttest + test-plan-data/export/creates-1/007_create-api1-version-1.0.resttest + test-plan-data/export/creates-1/008_update-api1-version-1.0.resttest + test-plan-data/export/creates-1/009_publish-api-1.resttest + test-plan-data/export/creates-1/010_create-contract1.resttest + test-plan-data/export/creates-1/011_register-client-1.resttest - test-plan-data/export/export/001_export-1.resttest + test-plan-data/export/export/001_export-1.resttest test-plan-data/export/export/002_export-2-prepare.resttest test-plan-data/export/export/003_export-2-download.resttest + + test-plan-data/export/creates-2/001_create_org.resttest + test-plan-data/export/creates-2/002_create-plan1.resttest + test-plan-data/export/creates-2/003_create-plan1-version-1.0.resttest + test-plan-data/export/creates-2/003.5_lock-plan-1.resttest + test-plan-data/export/creates-2/004_create-client1.resttest + test-plan-data/export/creates-2/005_create-client1-version-1.0.resttest + test-plan-data/export/creates-2/006_create-api1.resttest + test-plan-data/export/creates-2/007_create-api1-version-1.0.resttest + test-plan-data/export/creates-2/008_update-api1-version-1.0.resttest + test-plan-data/export/creates-2/009_publish-api-1.resttest + test-plan-data/export/creates-2/010_create-contract1.resttest + test-plan-data/export/creates-2/011_register-client-1.resttest + test-plan-data/export/creates-2/012_create-plan1-version-1.1.resttest + test-plan-data/export/creates-2/013_create-plan1-version-1.2.resttest + + + + + test-plan-data/export/export/004_export-3.resttest + + diff --git a/manager/test/api/src/test/resources/test-plans/migrate-testPlan.xml b/manager/test/api/src/test/resources/test-plans/migrate-testPlan.xml new file mode 100644 index 0000000000..9e8348f9d8 --- /dev/null +++ b/manager/test/api/src/test/resources/test-plans/migrate-testPlan.xml @@ -0,0 +1,13 @@ + + + + + test-plan-data/migrate/001_import-1.2.2.Final.resttest + + + + + test-plan-data/migrate/002_export.resttest + + + diff --git a/pom.xml b/pom.xml index 35573debcb..8cdfe3d268 100644 --- a/pom.xml +++ b/pom.xml @@ -250,6 +250,11 @@ apiman-manager-api-export-import-api ${project.version} + + ${project.groupId} + apiman-manager-api-migrator + ${project.version} + ${project.groupId} apiman-manager-api-ispn diff --git a/test/common/pom.xml b/test/common/pom.xml index 2906fe2838..08efc459cc 100644 --- a/test/common/pom.xml +++ b/test/common/pom.xml @@ -44,6 +44,10 @@ commons-io commons-io + + commons-lang + commons-lang + org.slf4j slf4j-api diff --git a/test/common/src/main/java/io/apiman/test/common/json/JsonArrayOrderingType.java b/test/common/src/main/java/io/apiman/test/common/json/JsonArrayOrderingType.java new file mode 100644 index 0000000000..fbf7fc92a4 --- /dev/null +++ b/test/common/src/main/java/io/apiman/test/common/json/JsonArrayOrderingType.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.test.common.json; + +/** + * @author eric.wittmann@gmail.com + */ +public enum JsonArrayOrderingType { + + any, strict; + + public static JsonArrayOrderingType fromString(String string) { + if (string == null) { + return strict; + } else { + return JsonArrayOrderingType.valueOf(string); + } + } + +} diff --git a/test/common/src/main/java/io/apiman/test/common/json/JsonCompare.java b/test/common/src/main/java/io/apiman/test/common/json/JsonCompare.java new file mode 100644 index 0000000000..a6682878b2 --- /dev/null +++ b/test/common/src/main/java/io/apiman/test/common/json/JsonCompare.java @@ -0,0 +1,309 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.test.common.json; + +import java.io.InputStream; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Stack; + +import org.apache.commons.lang.StringUtils; +import org.junit.Assert; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.NullNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; + +/** + * Used to compare an expected JSON document to an actual one. + * @author eric.wittmann@gmail.com + */ +@SuppressWarnings("nls") +public class JsonCompare { + + private static final ObjectMapper jacksonParser = new ObjectMapper(); + + private JsonMissingFieldType missingField = JsonMissingFieldType.ignore; + private JsonArrayOrderingType arrayOrdering = JsonArrayOrderingType.strict; + private boolean ignoreCase; + private Stack currentPath = new Stack(); + + /** + * Constructor. + */ + public JsonCompare() { + } + + /** + * Asserts that the JSON document matches what we expected. + * + * Note: the input streams should be closed by the caller + * @param expectedJson + * @param actualJson + */ + public void assertJson(InputStream expectedJson, InputStream actualJson) throws Exception { + JsonNode expected = jacksonParser.readTree(expectedJson); + JsonNode actual = jacksonParser.readTree(actualJson); + assertJson(expected, actual); + } + + /** + * Asserts that the JSON document matches what we expected. + * @param expectedJson + * @param actualJson + */ + public void assertJson(JsonNode expectedJson, JsonNode actualJson) { + if (expectedJson instanceof ArrayNode) { + JsonNode actualValue = actualJson; + ArrayNode expectedArray = (ArrayNode) expectedJson; + Assert.assertEquals( + message("Expected JSON array but found non-array [{0}] instead.", + actualValue.getClass().getSimpleName()), + expectedJson.getClass(), actualValue.getClass()); + ArrayNode actualArray = (ArrayNode) actualValue; + Assert.assertEquals(message("Array size mismatch."), expectedArray.size(), actualArray.size()); + + JsonNode [] expected = new JsonNode[expectedArray.size()]; + JsonNode [] actual = new JsonNode[actualArray.size()]; + for (int idx = 0; idx < expected.length; idx++) { + expected[idx] = expectedArray.get(idx); + actual[idx] = actualArray.get(idx); + } + // If strict ordering is disabled, then sort both arrays + if (arrayOrdering == JsonArrayOrderingType.any) { + Comparator comparator = new Comparator() { + @Override + public int compare(JsonNode o1, JsonNode o2) { + int cmp = o1.toString().compareTo(o2.toString()); + if (cmp == 0) + cmp = 1; + return cmp; + } + }; + Arrays.sort(expected, comparator); + Arrays.sort(actual, comparator); + } + for (int idx = 0; idx < expected.length; idx++) { + currentPath.push(idx); + assertJson(expected[idx], actual[idx]); + currentPath.pop(); + } + } else { + Iterator> fields = expectedJson.fields(); + Set expectedFieldNames = new HashSet<>(); + while (fields.hasNext()) { + Entry entry = fields.next(); + String expectedFieldName = entry.getKey(); + expectedFieldNames.add(expectedFieldName); + JsonNode expectedValue = entry.getValue(); + currentPath.push(expectedFieldName); + if (expectedValue instanceof TextNode) { + TextNode tn = (TextNode) expectedValue; + String expected = tn.textValue(); + JsonNode actualValue = actualJson.get(expectedFieldName); + + if (isIgnoreCase()) { + expected = expected.toLowerCase(); + if (actualValue == null) { + actualValue = actualJson.get(expectedFieldName.toLowerCase()); + } + } + + Assert.assertNotNull( + message("Expected JSON text field \"{0}\" with value \"{1}\" but was not found.", + expectedFieldName, expected), + actualValue); + Assert.assertEquals( + message("Expected JSON text field \"{0}\" with value \"{1}\" but found non-text [{2}] field with that name instead.", + expectedFieldName, expected, actualValue.getClass().getSimpleName()), + TextNode.class, actualValue.getClass()); + String actual = ((TextNode) actualValue).textValue(); + + if (isIgnoreCase()) { + if (actual != null) { + actual = actual.toLowerCase(); + } + } + + if (!expected.equals("*")) { + Assert.assertEquals( + message("Value mismatch for text field \"{0}\".", expectedFieldName), + expected, actual); + } + } else if (expectedValue instanceof NumericNode) { + NumericNode numeric = (NumericNode) expectedValue; + Number expected = numeric.numberValue(); + JsonNode actualValue = actualJson.get(expectedFieldName); + Assert.assertNotNull( + message("Expected JSON numeric field \"{0}\" with value \"{1}\" but was not found.", + expectedFieldName, expected), + actualValue); + Assert.assertEquals( + message("Expected JSON numeric field \"{0}\" with value \"{1}\" but found non-numeric [{2}] field with that name instead.", + expectedFieldName, expected, actualValue.getClass().getSimpleName()), + expectedValue.getClass(), actualValue.getClass()); + Number actual = ((NumericNode) actualValue).numberValue(); + Assert.assertEquals(message("Value mismatch for numeric field \"{0}\".", expectedFieldName), expected, + actual); + } else if (expectedValue instanceof BooleanNode) { + BooleanNode bool = (BooleanNode) expectedValue; + Boolean expected = bool.booleanValue(); + JsonNode actualValue = actualJson.get(expectedFieldName); + Assert.assertNotNull( + message("Expected JSON boolean field \"{0}\" with value \"{1}\" but was not found.", + expectedFieldName, expected), + actualValue); + Assert.assertEquals( + message("Expected JSON boolean field \"{0}\" with value \"{1}\" but found non-boolean [{2}] field with that name instead.", + expectedFieldName, expected, actualValue.getClass().getSimpleName()), + expectedValue.getClass(), actualValue.getClass()); + Boolean actual = ((BooleanNode) actualValue).booleanValue(); + Assert.assertEquals( + message("Value mismatch for boolean field \"{0}\".", expectedFieldName), expected, + actual); + } else if (expectedValue instanceof ObjectNode) { + JsonNode actualValue = actualJson.get(expectedFieldName); + Assert.assertNotNull(message("Expected parent JSON field \"{0}\" but was not found.", + expectedFieldName), actualValue); + Assert.assertEquals( + message("Expected parent JSON field \"{0}\" but found field of type \"{1}\".", + expectedFieldName, actualValue.getClass().getSimpleName()), + ObjectNode.class, actualValue.getClass()); + assertJson(expectedValue, actualValue); + } else if (expectedValue instanceof ArrayNode) { + JsonNode actualValue = actualJson.get(expectedFieldName); + Assert.assertNotNull(message("Expected JSON array field \"{0}\" but was not found.", + expectedFieldName), actualValue); + ArrayNode expectedArray = (ArrayNode) expectedValue; + Assert.assertEquals( + message("Expected JSON array field \"{0}\" but found non-array [{1}] field with that name instead.", + expectedFieldName, actualValue.getClass().getSimpleName()), + expectedValue.getClass(), actualValue.getClass()); + ArrayNode actualArray = (ArrayNode) actualValue; + Assert.assertEquals(message("Field \"{0}\" array size mismatch.", expectedFieldName), + expectedArray.size(), actualArray.size()); + assertJson(expectedArray, actualArray); + } else if (expectedValue instanceof NullNode) { + JsonNode actualValue = actualJson.get(expectedFieldName); + Assert.assertNotNull( + message("Expected Null JSON field \"{0}\" but was not found.", expectedFieldName), + actualValue); + Assert.assertEquals( + message("Expected Null JSON field \"{0}\" but found field of type \"{0}\".", + expectedFieldName, actualValue.getClass().getSimpleName()), + NullNode.class, actualValue.getClass()); + } else { + Assert.fail(message("Unsupported field type: {0}", expectedValue.getClass().getSimpleName())); + } + currentPath.pop(); + } + + if (getMissingField() == JsonMissingFieldType.fail) { + Set actualFieldNames = new HashSet(); + Iterator names = actualJson.fieldNames(); + while (names.hasNext()) { + actualFieldNames.add(names.next()); + } + actualFieldNames.removeAll(expectedFieldNames); + Assert.assertTrue( + message("Found unexpected fields: {0}", StringUtils.join(actualFieldNames, ", ")), + actualFieldNames.isEmpty()); + } + } + } + + /** + * Format an assertion message, including the current path. + * @param pattern + * @param params + */ + private String message(String pattern, Object ... params) { + return path() + "::" + MessageFormat.format(pattern, params); + } + + /** + * Format the current path as a string. + */ + private String path() { + StringBuilder builder = new StringBuilder(); + builder.append("$ROOT"); + for (Object pathElement : currentPath) { + if (pathElement instanceof Integer) { + builder.append('['); + builder.append(pathElement); + builder.append(']'); + } else { + builder.append('.'); + builder.append(pathElement); + } + } + return builder.toString(); + } + + /** + * @return the arrayOrdering + */ + public JsonArrayOrderingType getArrayOrdering() { + return arrayOrdering; + } + + /** + * @param arrayOrdering the arrayOrdering to set + */ + public void setArrayOrdering(JsonArrayOrderingType arrayOrdering) { + this.arrayOrdering = arrayOrdering; + } + + /** + * @return the ignoreCase + */ + public boolean isIgnoreCase() { + return ignoreCase; + } + + /** + * @param ignoreCase the ignoreCase to set + */ + public void setIgnoreCase(boolean ignoreCase) { + this.ignoreCase = ignoreCase; + } + + /** + * @return the missingField + */ + public JsonMissingFieldType getMissingField() { + return missingField; + } + + /** + * @param missingField the missingField to set + */ + public void setMissingField(JsonMissingFieldType missingField) { + this.missingField = missingField; + } + +} diff --git a/test/common/src/main/java/io/apiman/test/common/json/JsonMissingFieldType.java b/test/common/src/main/java/io/apiman/test/common/json/JsonMissingFieldType.java new file mode 100644 index 0000000000..f7e758d916 --- /dev/null +++ b/test/common/src/main/java/io/apiman/test/common/json/JsonMissingFieldType.java @@ -0,0 +1,26 @@ +/* + * Copyright 2016 JBoss Inc + * + * 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.apiman.test.common.json; + +/** + * @author eric.wittmann@gmail.com + */ +public enum JsonMissingFieldType { + + fail, ignore + +} diff --git a/test/common/src/main/java/io/apiman/test/common/util/TestPlanRunner.java b/test/common/src/main/java/io/apiman/test/common/util/TestPlanRunner.java index 4e51caa959..e79c68e25d 100644 --- a/test/common/src/main/java/io/apiman/test/common/util/TestPlanRunner.java +++ b/test/common/src/main/java/io/apiman/test/common/util/TestPlanRunner.java @@ -15,14 +15,9 @@ */ package io.apiman.test.common.util; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.BooleanNode; -import com.fasterxml.jackson.databind.node.NullNode; -import com.fasterxml.jackson.databind.node.NumericNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; +import io.apiman.test.common.json.JsonArrayOrderingType; +import io.apiman.test.common.json.JsonCompare; +import io.apiman.test.common.json.JsonMissingFieldType; import io.apiman.test.common.plan.TestGroupType; import io.apiman.test.common.plan.TestPlan; import io.apiman.test.common.plan.TestType; @@ -34,9 +29,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.text.MessageFormat; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -59,6 +51,9 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.squareup.okhttp.MediaType; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; @@ -288,7 +283,13 @@ private void assertJsonPayload(RestTest restTest, Response response) { Assert.assertNotNull("REST Test missing expected JSON payload.", expectedPayload); JsonNode expectedJson = jacksonParser.readTree(expectedPayload); try { - assertJson(restTest, expectedJson, actualJson); + JsonCompare jsonCompare = new JsonCompare(); + jsonCompare.setArrayOrdering(JsonArrayOrderingType + .fromString(restTest.getExpectedResponseHeaders().get("X-RestTest-ArrayOrdering"))); + jsonCompare.setIgnoreCase("true" + .equals(restTest.getExpectedResponseHeaders().get("X-RestTest-Assert-IgnoreCase"))); + jsonCompare.setMissingField(JsonMissingFieldType.ignore); + jsonCompare.assertJson(expectedJson, actualJson); } catch (Error e) { System.out.println("--- START FAILED JSON PAYLOAD ---"); System.out.println(actualJson.toString()); @@ -428,147 +429,6 @@ public Object getProperty(String name, Object contextObj, VariableResolverFactor return String.valueOf(MVEL.eval(bindExpression, new TestVariableResolverFactory(json))); } - /** - * Asserts that the JSON payload matches what we expected, as defined - * in the configuration of the rest test. - * @param restTest - * @param expectedJson - * @param actualJson - */ - public void assertJson(RestTest restTest, JsonNode expectedJson, JsonNode actualJson) { - if (expectedJson instanceof ArrayNode) { - JsonNode actualValue = actualJson; - ArrayNode expectedArray = (ArrayNode) expectedJson; - Assert.assertEquals("Expected JSON array but found non-array [" - + actualValue.getClass().getSimpleName() + "] instead.", expectedJson.getClass(), - actualValue.getClass()); - ArrayNode actualArray = (ArrayNode) actualValue; - Assert.assertEquals("Array size mismatch.", expectedArray.size(), actualArray.size()); - String ordering = restTest.getExpectedResponseHeaders().get("X-RestTest-ArrayOrdering"); - - JsonNode [] expected = new JsonNode[expectedArray.size()]; - JsonNode [] actual = new JsonNode[actualArray.size()]; - for (int idx = 0; idx < expected.length; idx++) { - expected[idx] = expectedArray.get(idx); - actual[idx] = actualArray.get(idx); - } - // If strict ordering is disabled, then sort both arrays - if ("any".equals(ordering)) { - Comparator comparator = new Comparator() { - @Override - public int compare(JsonNode o1, JsonNode o2) { - int cmp = o1.toString().compareTo(o2.toString()); - if (cmp == 0) - cmp = 1; - return cmp; - } - }; - Arrays.sort(expected, comparator); - Arrays.sort(actual, comparator); - } - for (int idx = 0; idx < expected.length; idx++) { - assertJson(restTest, expected[idx], actual[idx]); - } - } else { - Iterator> fields = expectedJson.fields(); - while (fields.hasNext()) { - Entry entry = fields.next(); - String expectedFieldName = entry.getKey(); - JsonNode expectedValue = entry.getValue(); - if (expectedValue instanceof TextNode) { - TextNode tn = (TextNode) expectedValue; - String expected = tn.textValue(); - JsonNode actualValue = actualJson.get(expectedFieldName); - - if (isAssertionIgnoreCase(restTest)) { - expected = expected.toLowerCase(); - if (actualValue == null) { - actualValue = actualJson.get(expectedFieldName.toLowerCase()); - } - } - - Assert.assertNotNull("Expected JSON text field '" + expectedFieldName + "' with value '" - + expected + "' but was not found.", actualValue); - Assert.assertEquals("Expected JSON text field '" + expectedFieldName + "' with value '" - + expected + "' but found non-text [" + actualValue.getClass().getSimpleName() - + "] field with that name instead.", TextNode.class, actualValue.getClass()); - String actual = ((TextNode) actualValue).textValue(); - - if (isAssertionIgnoreCase(restTest)) { - if (actual != null) { - actual = actual.toLowerCase(); - } - } - - if (!expected.equals("*")) { - Assert.assertEquals("Value mismatch for text field '" + expectedFieldName + "'.", expected, - actual); - } - } else if (expectedValue instanceof NumericNode) { - NumericNode numeric = (NumericNode) expectedValue; - Number expected = numeric.numberValue(); - JsonNode actualValue = actualJson.get(expectedFieldName); - Assert.assertNotNull("Expected JSON numeric field '" + expectedFieldName + "' with value '" - + expected + "' but was not found.", actualValue); - Assert.assertEquals("Expected JSON numeric field '" + expectedFieldName + "' with value '" - + expected + "' but found non-numeric [" + actualValue.getClass().getSimpleName() - + "] field with that name instead.", expectedValue.getClass(), actualValue.getClass()); - Number actual = ((NumericNode) actualValue).numberValue(); - Assert.assertEquals("Value mismatch for numeric field '" + expectedFieldName + "'.", expected, - actual); - } else if (expectedValue instanceof BooleanNode) { - BooleanNode bool = (BooleanNode) expectedValue; - Boolean expected = bool.booleanValue(); - JsonNode actualValue = actualJson.get(expectedFieldName); - Assert.assertNotNull("Expected JSON boolean field '" + expectedFieldName + "' with value '" - + expected + "' but was not found.", actualValue); - Assert.assertEquals("Expected JSON boolean field '" + expectedFieldName + "' with value '" - + expected + "' but found non-boolean [" + actualValue.getClass().getSimpleName() - + "] field with that name instead.", expectedValue.getClass(), actualValue.getClass()); - Boolean actual = ((BooleanNode) actualValue).booleanValue(); - Assert.assertEquals("Value mismatch for boolean field '" + expectedFieldName + "'.", expected, - actual); - } else if (expectedValue instanceof ObjectNode) { - JsonNode actualValue = actualJson.get(expectedFieldName); - Assert.assertNotNull("Expected parent JSON field '" + expectedFieldName - + "' but was not found.", actualValue); - Assert.assertEquals("Expected parent JSON field '" + expectedFieldName - + "' but found field of type '" + actualValue.getClass().getSimpleName() + "'.", - ObjectNode.class, actualValue.getClass()); - assertJson(restTest, expectedValue, actualValue); - } else if (expectedValue instanceof ArrayNode) { - JsonNode actualValue = actualJson.get(expectedFieldName); - Assert.assertNotNull("Expected JSON array field '" + expectedFieldName - + "' but was not found.", actualValue); - ArrayNode expectedArray = (ArrayNode) expectedValue; - Assert.assertEquals("Expected JSON array field '" + expectedFieldName - + "' but found non-array [" + actualValue.getClass().getSimpleName() - + "] field with that name instead.", expectedValue.getClass(), actualValue.getClass()); - ArrayNode actualArray = (ArrayNode) actualValue; - Assert.assertEquals("Field '" + expectedFieldName + "' array size mismatch.", - expectedArray.size(), actualArray.size()); - assertJson(restTest, expectedArray, actualArray); - } else if (expectedValue instanceof NullNode) { - JsonNode actualValue = actualJson.get(expectedFieldName); - Assert.assertNotNull("Expected Null JSON field '" + expectedFieldName - + "' but was not found.", actualValue); - Assert.assertEquals("Expected Null JSON field '" + expectedFieldName - + "' but found field of type '" + actualValue.getClass().getSimpleName() + "'.", - NullNode.class, actualValue.getClass()); - } else { - Assert.fail("Unsupported field type: " + expectedValue.getClass().getSimpleName()); - } - } - } - } - - /** - * @param restTest - */ - private boolean isAssertionIgnoreCase(RestTest restTest) { - return "true".equals(restTest.getExpectedResponseHeaders().get("X-RestTest-Assert-IgnoreCase")); - } - /** * Assume the payload is Text and do some assertions based on the configuration * in the REST Test.