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

Commit

Permalink
feat: Lifecycle - allows to deprecate an API
Browse files Browse the repository at this point in the history
  • Loading branch information
aelamrani committed Nov 4, 2019
1 parent e36b8bf commit 5e453fd
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 22 deletions.
Expand Up @@ -111,7 +111,8 @@ public enum EmailTemplate {
GROUP_INVITATION("groupInvitation.html"),
ASK_FOR_REVIEW("askForReview.html"),
REQUEST_FOR_CHANGES("requestForChanges.html"),
REVIEW_OK("reviewOk.html");
REVIEW_OK("reviewOk.html"),
API_DEPRECATED("apiDeprecated.html");

private String template;

Expand Down
@@ -0,0 +1,43 @@
/**
* 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.exceptions;

import io.gravitee.common.http.HttpStatusCode;

import static java.lang.String.format;

/**
* @author Azize ELAMRANI (azize.elamrani at graviteesource.com)
* @author GraviteeSource Team
*/
public class ApiDeprecatedException extends AbstractManagementException {

private final String api;

public ApiDeprecatedException(String api) {
this.api = api;
}

@Override
public String getMessage() {
return format("The api %s is deprecated and can not be modified.", api);
}

@Override
public int getHttpStatusCode() {
return HttpStatusCode.BAD_REQUEST_400;
}
}
Expand Up @@ -755,7 +755,7 @@ public ApiEntity update(String apiId, UpdateApiEntity updateApiEntity) {
// if user changes sharding tags, then check if he is allowed to do it
checkShardingTags(updateApiEntity, apiToCheck);

// if lifecycle state not provide, set the saved one
// if lifecycle state not provided, set the saved one
if (updateApiEntity.getLifecycleState() == null) {
updateApiEntity.setLifecycleState(apiToCheck.getLifecycleState());
}
Expand Down Expand Up @@ -795,7 +795,19 @@ public ApiEntity update(String apiId, UpdateApiEntity updateApiEntity) {
if (updateApiEntity.getViews() == null) {
api.setViews(apiToUpdate.getViews());
}


if (ApiLifecycleState.DEPRECATED.equals(api.getApiLifecycleState())) {
planService.findByApi(api.getId()).forEach(plan -> {
if (PlanStatus.PUBLISHED.equals(plan.getStatus()) || PlanStatus.STAGING.equals(plan.getStatus())) {
planService.depreciate(plan.getId());
}
});
notifierService.trigger(ApiHook.API_DEPRECATED, apiId,
new NotificationParamsBuilder()
.api(apiToCheck)
.user(userService.findById(getAuthenticatedUsername()))
.build());
}

Api updatedApi = apiRepository.update(api);

Expand Down Expand Up @@ -874,17 +886,16 @@ private void validateRegexfields(final UpdateApiEntity updateApiEntity) {
}

private void checkLifecycleState(final UpdateApiEntity updateApiEntity, final ApiEntity existingAPI) {
if (io.gravitee.management.model.api.ApiLifecycleState.DEPRECATED.equals(existingAPI.getLifecycleState())) {
throw new LifecycleStateChangeNotAllowedException(updateApiEntity.getLifecycleState().name());
}
if (existingAPI.getLifecycleState().name().equals(updateApiEntity.getLifecycleState().name())) {
return;
}
if (io.gravitee.management.model.api.ApiLifecycleState.ARCHIVED.equals(existingAPI.getLifecycleState())) {
if (!io.gravitee.management.model.api.ApiLifecycleState.ARCHIVED.equals(updateApiEntity.getLifecycleState())) {
throw new LifecycleStateChangeNotAllowedException(updateApiEntity.getLifecycleState().name());
}
} else if (io.gravitee.management.model.api.ApiLifecycleState.DEPRECATED.equals(existingAPI.getLifecycleState())) {
if (!io.gravitee.management.model.api.ApiLifecycleState.UNPUBLISHED.equals(updateApiEntity.getLifecycleState())) {
throw new LifecycleStateChangeNotAllowedException(updateApiEntity.getLifecycleState().name());
}
} else if (io.gravitee.management.model.api.ApiLifecycleState.UNPUBLISHED.equals(existingAPI.getLifecycleState())) {
if (io.gravitee.management.model.api.ApiLifecycleState.CREATED.equals(updateApiEntity.getLifecycleState())) {
throw new LifecycleStateChangeNotAllowedException(updateApiEntity.getLifecycleState().name());
Expand Down
Expand Up @@ -21,12 +21,11 @@
import io.gravitee.common.utils.UUID;
import io.gravitee.definition.model.Path;
import io.gravitee.management.model.*;
import io.gravitee.management.model.api.ApiEntity;
import io.gravitee.management.model.api.ApiLifecycleState;
import io.gravitee.management.model.parameters.Key;
import io.gravitee.management.model.plan.PlanQuery;
import io.gravitee.management.service.AuditService;
import io.gravitee.management.service.ParameterService;
import io.gravitee.management.service.PlanService;
import io.gravitee.management.service.SubscriptionService;
import io.gravitee.management.service.*;
import io.gravitee.management.service.exceptions.*;
import io.gravitee.management.service.processor.PlanSynchronizationProcessor;
import io.gravitee.repository.exceptions.TechnicalException;
Expand All @@ -53,28 +52,22 @@
@Component
public class PlanServiceImpl extends TransactionalService implements PlanService {

/**
* Logger.
*/
private final Logger logger = LoggerFactory.getLogger(PlanServiceImpl.class);

@Autowired
private PlanRepository planRepository;

@Autowired
private SubscriptionService subscriptionService;

@Autowired
private ObjectMapper objectMapper;

@Autowired
private AuditService auditService;

@Autowired
private ParameterService parameterService;

@Autowired
private PlanSynchronizationProcessor planSynchronizationProcessor;
@Autowired
private ApiService apiService;

private static final List<PlanSecurityEntity> DEFAULT_SECURITY_LIST =
Collections.unmodifiableList(Arrays.asList(
Expand Down Expand Up @@ -151,6 +144,12 @@ public PlanEntity create(NewPlanEntity newPlan) {
logger.debug("Create a new plan {} for API {}", newPlan.getName(), newPlan.getApi());

assertPlanSecurityIsAllowed(newPlan.getSecurity());

final ApiEntity api = apiService.findById(newPlan.getApi());
if (ApiLifecycleState.DEPRECATED.equals(api.getLifecycleState())) {
throw new ApiDeprecatedException(api.getName());
}

Plan plan = new Plan();

plan.setId(UUID.toString(UUID.random()));
Expand Down
Expand Up @@ -39,7 +39,8 @@ public enum ApiHook implements Hook {
MESSAGE(null, null, null, true),
ASK_FOR_REVIEW("Ask for API review", "Triggered when an API can be reviewed", "REVIEW"),
REVIEW_OK("Accept API review", "Triggered when an API's review has been accepted", "REVIEW"),
REQUEST_FOR_CHANGES("Reject API review", "Triggered when an API's review has been rejected", "REVIEW");
REQUEST_FOR_CHANGES("Reject API review", "Triggered when an API's review has been rejected", "REVIEW"),
API_DEPRECATED("API Deprecated", "Triggered when an API is deprecated", "LIFECYCLE");

private String label;
private String description;
Expand Down
Expand Up @@ -125,6 +125,9 @@ else if (hook.equals(ApiHook.REQUEST_FOR_CHANGES)) {
else if (hook.equals(ApiHook.REVIEW_OK)) {
return EmailNotificationBuilder.EmailTemplate.REVIEW_OK;
}
else if (hook.equals(API_DEPRECATED)) {
return EmailNotificationBuilder.EmailTemplate.API_DEPRECATED;
}

// Application Hook
else if (hook.equals(ApplicationHook.SUBSCRIPTION_NEW)) {
Expand Down Expand Up @@ -250,6 +253,9 @@ else if (hook.equals(ApiHook.REQUEST_FOR_CHANGES)) {
else if (hook.equals(ApiHook.REVIEW_OK)) {
return "API review accepted";
}
else if (hook.equals(API_DEPRECATED)) {
return "API deprecated";
}

// Application Hook
else if (hook.equals(ApplicationHook.SUBSCRIPTION_NEW)) {
Expand Down
Expand Up @@ -316,12 +316,13 @@ public void shouldNotChangeLifecycleStateFromUnpublishedToCreated() throws Techn
}

@Test
public void shouldOnlyUnpublishADeprecatedApi() throws TechnicalException {
public void shouldNotUpdateADeprecatedApi() throws TechnicalException {
prepareUpdate();
assertUpdate(ApiLifecycleState.DEPRECATED, CREATED, true);
assertUpdate(ApiLifecycleState.DEPRECATED, PUBLISHED, true);
assertUpdate(ApiLifecycleState.DEPRECATED, UNPUBLISHED, false);
assertUpdate(ApiLifecycleState.DEPRECATED, UNPUBLISHED, true);
assertUpdate(ApiLifecycleState.DEPRECATED, ARCHIVED, true);
assertUpdate(ApiLifecycleState.DEPRECATED, DEPRECATED, true);
}

@Test
Expand Down
@@ -0,0 +1,13 @@
<html>
<body style="text-align: center;">
<header>
<#include "header.html" />
</header>
<div style="margin-top: 50px; color: #424e5a;">
<h3>Hi,</h3>
<p>
The API <b><code>${api.name}</code></b> was deprecated by ${user.displayName}.
</p>
</div>
</body>
</html>
@@ -0,0 +1,3 @@
title: API deprecated
message: |
"${api.name}" was deprecated by ${user.displayName}.

0 comments on commit 5e453fd

Please sign in to comment.