From 2a59b4202c3540f741bf7fbad1a360d62afbd9d8 Mon Sep 17 00:00:00 2001 From: Titouan COMPIEGNE Date: Tue, 24 Dec 2019 10:27:57 +0100 Subject: [PATCH] feat(metadata): add EL support for the "email-support" API metadata closes gravitee-io/issues#3049 --- .../management/service/MetadataService.java | 3 + .../service/impl/ApiMetadataServiceImpl.java | 2 +- .../service/impl/ApiServiceImpl.java | 17 ++++- .../service/impl/MetadataServiceImpl.java | 33 +++++++--- .../service/impl/TicketServiceImpl.java | 13 +++- .../service/ApiService_CreateTest.java | 4 ++ .../ApiService_CreateWithDefinitionTest.java | 5 +- .../service/MetadataServiceTest.java | 63 +++++++++++++++++++ 8 files changed, 126 insertions(+), 14 deletions(-) create mode 100644 gravitee-management-api-service/src/test/java/io/gravitee/management/service/MetadataServiceTest.java diff --git a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/MetadataService.java b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/MetadataService.java index 0a26967295..6051e7d128 100644 --- a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/MetadataService.java +++ b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/MetadataService.java @@ -16,6 +16,7 @@ package io.gravitee.management.service; import io.gravitee.management.model.*; +import io.gravitee.management.model.api.ApiEntity; import java.util.List; @@ -35,5 +36,7 @@ public interface MetadataService { void checkMetadataFormat(MetadataFormat format, String value); + void checkMetadataFormat(MetadataFormat format, String value, ApiEntity apiEntity); + MetadataEntity findDefaultByKey(String key); } diff --git a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiMetadataServiceImpl.java b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiMetadataServiceImpl.java index f85ed4b5e4..06da72798d 100644 --- a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiMetadataServiceImpl.java +++ b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiMetadataServiceImpl.java @@ -165,7 +165,7 @@ public ApiMetadataEntity create(final NewApiMetadataEntity metadataEntity) { throw new DuplicateMetadataNameException(optionalMetadata.get().getName()); } - metadataService.checkMetadataFormat(metadataEntity.getFormat(), metadataEntity.getValue()); + metadataService.checkMetadataFormat(metadataEntity.getFormat(), metadataEntity.getValue(), apiEntity); try { final Metadata metadata = convertForAPI(metadataEntity); diff --git a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiServiceImpl.java b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiServiceImpl.java index 15bce27e1f..59bc502212 100644 --- a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiServiceImpl.java +++ b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/ApiServiceImpl.java @@ -30,6 +30,7 @@ import io.gravitee.definition.model.services.discovery.EndpointDiscoveryService; import io.gravitee.definition.model.services.healthcheck.HealthCheckService; import io.gravitee.management.model.EventType; +import io.gravitee.management.model.MetadataFormat; import io.gravitee.management.model.PageType; import io.gravitee.management.model.*; import io.gravitee.management.model.api.*; @@ -42,6 +43,7 @@ import io.gravitee.management.service.*; import io.gravitee.management.service.exceptions.*; import io.gravitee.management.service.impl.search.SearchResult; +import io.gravitee.management.service.impl.upgrade.DefaultMetadataUpgrader; import io.gravitee.management.service.jackson.ser.api.ApiSerializer; import io.gravitee.management.service.notification.ApiHook; import io.gravitee.management.service.notification.HookScope; @@ -148,6 +150,7 @@ public class ApiServiceImpl extends AbstractService implements ApiService { private static final Pattern LOGGING_MAX_DURATION_PATTERN = Pattern.compile("(?.*)\\#request.timestamp\\s*\\<\\=?\\s*(?\\d*)l(?.*)"); private static final String LOGGING_MAX_DURATION_CONDITION = "#request.timestamp <= %dl"; private static final String ENDPOINTS_DELIMITER = "\n"; + private static final String DEFAULT_API_METADATA_EMAIL_SUPPORT = "{#api.primaryOwner.email}"; @Override public ApiEntity create(final NewApiEntity newApiEntity, final String userId) throws ApiAlreadyExistsException { return create(newApiEntity, userId, null, null); @@ -308,6 +311,7 @@ private ApiEntity create(final NewApiEntity newApiEntity, final String userId, } pageService.createPage(createdApi.getId(), page); } + return createdApi; } @@ -317,10 +321,10 @@ private String addGraviteeUrl(String apiContextPath, String payload) { if (portalEntrypoint != null) { graviteeUrls.add(portalEntrypoint + apiContextPath); } - + List entrypoints = entrypointService.findAll(); entrypoints.stream().map(entrypoint -> entrypoint.getValue() + apiContextPath).forEach(graviteeUrls::add); - + return swaggerService.replaceServerList(payload, graviteeUrls); } @@ -407,6 +411,15 @@ private ApiEntity create0(UpdateApiEntity api, String userId) throws ApiAlreadyE notificationConfigEntity.setConfig("${api.primaryOwner.email}"); genericNotificationConfigService.create(notificationConfigEntity); + // create the default mail support metadata + NewApiMetadataEntity newApiMetadataEntity = new NewApiMetadataEntity(); + newApiMetadataEntity.setFormat(MetadataFormat.MAIL); + newApiMetadataEntity.setName(DefaultMetadataUpgrader.METADATA_EMAIL_SUPPORT_KEY); + newApiMetadataEntity.setDefaultValue(DEFAULT_API_METADATA_EMAIL_SUPPORT); + newApiMetadataEntity.setValue(DEFAULT_API_METADATA_EMAIL_SUPPORT); + newApiMetadataEntity.setApiId(createdApi.getId()); + apiMetadataService.create(newApiMetadataEntity); + //TODO add membership log ApiEntity apiEntity = convert(createdApi, primaryOwner); searchEngineService.index(apiEntity, false); diff --git a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/MetadataServiceImpl.java b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/MetadataServiceImpl.java index a86ee75408..7dd1055886 100644 --- a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/MetadataServiceImpl.java +++ b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/MetadataServiceImpl.java @@ -16,10 +16,12 @@ package io.gravitee.management.service.impl; import io.gravitee.common.utils.IdGenerator; +import io.gravitee.el.TemplateEngine; import io.gravitee.management.model.MetadataEntity; import io.gravitee.management.model.MetadataFormat; import io.gravitee.management.model.NewMetadataEntity; import io.gravitee.management.model.UpdateMetadataEntity; +import io.gravitee.management.model.api.ApiEntity; import io.gravitee.management.service.AuditService; import io.gravitee.management.service.MetadataService; import io.gravitee.management.service.exceptions.DuplicateMetadataNameException; @@ -199,29 +201,42 @@ public MetadataEntity findDefaultByKey(final String key) { } @Override - public void checkMetadataFormat(final MetadataFormat format, final String value) { - if (isBlank(value)) { - return; - } + public void checkMetadataFormat(MetadataFormat format, String value) { + checkMetadataFormat(format, value, null); + } + + @Override + public void checkMetadataFormat(final MetadataFormat format, final String value, final ApiEntity api) { try { + String decodedValue = value; + if (api != null && !isBlank(value) && value.startsWith("{#")) { + TemplateEngine templateEngine = TemplateEngine.templateEngine(); + templateEngine.getTemplateContext().setVariable("api", api); + decodedValue = templateEngine.getValue(value, String.class); + } + + if (isBlank(decodedValue)) { + return; + } + switch (format) { case BOOLEAN: - Boolean.valueOf(value); + Boolean.valueOf(decodedValue); break; case URL: - new URL(value); + new URL(decodedValue); break; case MAIL: - final InternetAddress email = new InternetAddress(value); + final InternetAddress email = new InternetAddress(decodedValue); email.validate(); break; case DATE: final SimpleDateFormat sdf = new SimpleDateFormat("YYYY-mm-dd"); sdf.setLenient(false); - sdf.parse(value); + sdf.parse(decodedValue); break; case NUMERIC: - Double.valueOf(value); + Double.valueOf(decodedValue); break; } } catch (final Exception e) { diff --git a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/TicketServiceImpl.java b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/TicketServiceImpl.java index 660d477778..12bddebee9 100644 --- a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/TicketServiceImpl.java +++ b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/TicketServiceImpl.java @@ -15,6 +15,7 @@ */ package io.gravitee.management.service.impl; +import io.gravitee.el.TemplateEngine; import io.gravitee.management.model.*; import io.gravitee.management.model.parameters.Key; import io.gravitee.management.service.*; @@ -91,7 +92,17 @@ public void create(final String userId, final NewTicketEntity ticketEntity) { emailTo = emailMetadata.getValue(); } else { api = apiService.findByIdForTemplates(ticketEntity.getApi()); - final String apiMetadataEmailSupport = api.getMetadata().get(DefaultMetadataUpgrader.METADATA_EMAIL_SUPPORT_KEY); + String apiMetadataEmailSupport = api.getMetadata().get(DefaultMetadataUpgrader.METADATA_EMAIL_SUPPORT_KEY); + if (apiMetadataEmailSupport != null && apiMetadataEmailSupport.startsWith("{#")) { + // email support metadata supports EL, parse EL expression if any + try { + TemplateEngine templateEngine = TemplateEngine.templateEngine(); + templateEngine.getTemplateContext().setVariable("api", api); + apiMetadataEmailSupport = templateEngine.getValue(apiMetadataEmailSupport, String.class); + } catch (Exception ex) { + throw new IllegalStateException("An error occurs while evaluating the support email API metadata", ex); + } + } if (apiMetadataEmailSupport == null) { throw new IllegalStateException("The support email API metadata has not been found"); } diff --git a/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateTest.java b/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateTest.java index ec817428f5..6706d0c4a8 100644 --- a/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateTest.java +++ b/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateTest.java @@ -95,6 +95,9 @@ public class ApiService_CreateTest { @Mock private GenericNotificationConfigService genericNotificationConfigService; + @Mock + private ApiMetadataService apiMetadataService; + @Before public void init() { final SecurityContext securityContext = mock(SecurityContext.class); @@ -207,6 +210,7 @@ private void testCreationWithContextPath(String existingContextPath, String cont verify(membershipRepository, times(1)).create(any()); verify(auditService, times(1)).createApiAuditLog(any(), any(), eq(API_CREATED), any(), eq(null) , any()); verify(searchEngineService, times(1)).index(any(), eq(false)); + verify(apiMetadataService, times(1)).create(any()); } @Test(expected = TechnicalManagementException.class) diff --git a/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateWithDefinitionTest.java b/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateWithDefinitionTest.java index 1cf8720d2a..fedce0cb51 100644 --- a/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateWithDefinitionTest.java +++ b/gravitee-management-api-service/src/test/java/io/gravitee/management/service/ApiService_CreateWithDefinitionTest.java @@ -106,7 +106,10 @@ public class ApiService_CreateWithDefinitionTest { private SearchEngineService searchEngineService; @Mock - private GenericNotificationConfigService genericNotificationConfigService; + private GenericNotificationConfigService genericNotificationConfigService; + + @Mock + private ApiMetadataService apiMetadataService; @Before public void init() { diff --git a/gravitee-management-api-service/src/test/java/io/gravitee/management/service/MetadataServiceTest.java b/gravitee-management-api-service/src/test/java/io/gravitee/management/service/MetadataServiceTest.java new file mode 100644 index 0000000000..f954dea653 --- /dev/null +++ b/gravitee-management-api-service/src/test/java/io/gravitee/management/service/MetadataServiceTest.java @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.management.service; + +import io.gravitee.management.model.MetadataFormat; +import io.gravitee.management.model.PrimaryOwnerEntity; +import io.gravitee.management.model.UserEntity; +import io.gravitee.management.model.api.ApiEntity; +import io.gravitee.management.service.exceptions.TechnicalManagementException; +import io.gravitee.management.service.impl.MetadataServiceImpl; +import org.junit.Test; + +/** + * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) + * @author GraviteeSource Team + */ +public class MetadataServiceTest { + + private MetadataService metadataService = new MetadataServiceImpl(); + + @Test(expected = TechnicalManagementException.class) + public void checkMetadataFormat_badEmailFormat() { + metadataService.checkMetadataFormat(MetadataFormat.MAIL, "test"); + } + + @Test(expected = TechnicalManagementException.class) + public void checkMetadataFormat_badURLFormat() { + metadataService.checkMetadataFormat(MetadataFormat.URL, "test"); + } + + @Test(expected = TechnicalManagementException.class) + public void checkMetadataFormat_badEmailFormat_EL() { + UserEntity userEntity = new UserEntity(); + userEntity.setEmail("test"); + PrimaryOwnerEntity primaryOwnerEntity = new PrimaryOwnerEntity(userEntity); + ApiEntity apiEntity = new ApiEntity(); + apiEntity.setPrimaryOwner(primaryOwnerEntity); + metadataService.checkMetadataFormat(MetadataFormat.MAIL, "{#api.primaryOwner.email}", apiEntity); + } + + @Test + public void checkMetadataFormat_nominalCase_EL() { + UserEntity userEntity = new UserEntity(); + userEntity.setEmail("gs@support.com"); + PrimaryOwnerEntity primaryOwnerEntity = new PrimaryOwnerEntity(userEntity); + ApiEntity apiEntity = new ApiEntity(); + apiEntity.setPrimaryOwner(primaryOwnerEntity); + metadataService.checkMetadataFormat(MetadataFormat.MAIL, "{#api.primaryOwner.email}", apiEntity); + } +}