Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[4.0.x] fix: check email opt in for trial instance #7060

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions gravitee-apim-console-webui/src/entities/consoleSettings.ts
Expand Up @@ -29,6 +29,11 @@ export interface ConsoleSettings {
theme?: ConsoleSettingsTheme;
emulateV4Engine?: ConsoleSettingsV4EmulationEngine;
alertEngine?: ConsoleSettingsAlertEngine;
<<<<<<< HEAD
=======
licenseExpirationNotification?: ConsoleSettingsLicenseExpirationNotification;
trialInstance?: ConsoleSettingsTrialInstance;
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
}

export interface ConsoleSettingsEmail {
Expand Down Expand Up @@ -143,3 +148,14 @@ export interface ConsoleSettingsV4EmulationEngine {
export interface ConsoleSettingsAlertEngine {
enabled?: boolean;
}
<<<<<<< HEAD
=======

export interface ConsoleSettingsLicenseExpirationNotification {
enabled?: boolean;
}

export interface ConsoleSettingsTrialInstance {
enabled?: boolean;
}
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
Expand Up @@ -269,8 +269,12 @@ <h2 gioTableOfContents>CORS</h2>
</mat-card-content>
</mat-card>

<<<<<<< HEAD
<mat-card class="settings-general__form__card" formGroupName="email">
<h2 gioTableOfContents>SMTP</h2>
=======
<mat-card *ngIf="!settings?.trialInstance?.enabled" class="settings-general__form__card" formGroupName="email">
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
<mat-card-content>
<gio-form-slide-toggle
[matTooltip]="providedConfigurationMessage"
Expand Down
Expand Up @@ -152,4 +152,9 @@ public String getDisplayName() {

return displayName;
}

@JsonIgnore
public boolean optedIn() {
return "ACTIVE".equalsIgnoreCase(status) && password != null || "memory".equalsIgnoreCase(source);
}
}
Expand Up @@ -246,17 +246,21 @@ public enum Key {
),
PORTAL_HTTP_CORS_MAX_AGE("http.api.portal.cors.max-age", "1728000", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),

EMAIL_ENABLED("email.enabled", "false", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_HOST("email.host", "smtp.my.domain", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_PORT("email.port", "587", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_USERNAME("email.username", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_PASSWORD("email.password", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_PROTOCOL("email.protocol", "smtp", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_SUBJECT("email.subject", "[Gravitee.io] %s", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_FROM("email.from", "noreply@my.domain", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_PROPERTIES_AUTH_ENABLED("email.properties.auth", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_PROPERTIES_STARTTLS_ENABLE("email.properties.starttls.enable", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_PROPERTIES_SSL_TRUST("email.properties.ssl.trust", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
EMAIL_ENABLED("email.enabled", "false", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_HOST("email.host", "smtp.my.domain", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_PORT("email.port", "587", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_USERNAME("email.username", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_PASSWORD("email.password", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_PROTOCOL("email.protocol", "smtp", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_SUBJECT("email.subject", "[Gravitee.io] %s", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_FROM("email.from", "noreply@my.domain", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_PROPERTIES_AUTH_ENABLED("email.properties.auth", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),
EMAIL_PROPERTIES_STARTTLS_ENABLE(
"email.properties.starttls.enable",
new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)),
true
),
EMAIL_PROPERTIES_SSL_TRUST("email.properties.ssl.trust", new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM)), true),

API_LABELS_DICTIONARY("api.labelsDictionary", List.class, new HashSet<>(Arrays.asList(ENVIRONMENT, ORGANIZATION, SYSTEM))),
API_PRIMARY_OWNER_MODE(
Expand Down Expand Up @@ -321,13 +325,21 @@ public enum Key {

V4_EMULATION_ENGINE_DEFAULT("api.v2.emulateV4Engine.default", "yes", Set.of(SYSTEM)),

<<<<<<< HEAD
ALERT_ENGINE_ENABLED("alerts.alert-engine.enabled", "false", Set.of(SYSTEM));
=======
ALERT_ENGINE_ENABLED("alerts.alert-engine.enabled", "false", Set.of(SYSTEM)),

INSTALLATION_TYPE("installation.type", "standalone", Set.of(SYSTEM)),
TRIAL_INSTANCE("trialInstance.enabled", "false", Set.of(SYSTEM));
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)

String key;
String defaultValue;
Class<?> type;
boolean isOverridable = true;
Set<KeyScope> scopes;
boolean isHiddenForTrial = false;

Key(String key, Set<KeyScope> scopes) {
this.key = key;
Expand Down Expand Up @@ -360,6 +372,19 @@ public enum Key {
this.scopes = scopes;
}

Key(String key, String defaultValue, Set<KeyScope> scopes, boolean isHiddenForTrial) {
this.key = key;
this.defaultValue = defaultValue;
this.scopes = scopes;
this.isHiddenForTrial = isHiddenForTrial;
}

Key(String key, Set<KeyScope> scopes, boolean isHiddenForTrial) {
this.key = key;
this.scopes = scopes;
this.isHiddenForTrial = isHiddenForTrial;
}

public static Key findByKey(String value) {
for (Key key : Key.values()) {
if (key.key.equals(value)) {
Expand All @@ -385,6 +410,10 @@ public boolean isOverridable() {
return isOverridable;
}

public boolean isHiddenForTrial() {
return isHiddenForTrial;
}

public Set<KeyScope> scopes() {
return scopes;
}
Expand Down
Expand Up @@ -35,6 +35,11 @@ public class ConsoleConfigEntity {
private Theme theme;
private V4EmulationEngine v4EmulationEngine;
private AlertEngine alertEngine;
<<<<<<< HEAD
=======
private LicenseExpirationNotification licenseExpirationNotification;
private TrialInstance trialInstance;
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)

public ConsoleConfigEntity() {
super();
Expand All @@ -50,5 +55,10 @@ public ConsoleConfigEntity() {
theme = new Theme();
v4EmulationEngine = new V4EmulationEngine();
alertEngine = new AlertEngine();
<<<<<<< HEAD
=======
licenseExpirationNotification = new LicenseExpirationNotification();
trialInstance = new TrialInstance();
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
}
}
Expand Up @@ -41,6 +41,11 @@ public class ConsoleSettingsEntity extends AbstractCommonSettingsEntity {
private Theme theme;
private V4EmulationEngine v4EmulationEngine;
private AlertEngine alertEngine;
<<<<<<< HEAD
=======
private LicenseExpirationNotification licenseExpirationNotification;
private TrialInstance trialInstance;
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)

public ConsoleSettingsEntity() {
super();
Expand All @@ -57,6 +62,11 @@ public ConsoleSettingsEntity() {
theme = new Theme();
v4EmulationEngine = new V4EmulationEngine();
alertEngine = new AlertEngine();
<<<<<<< HEAD
=======
licenseExpirationNotification = new LicenseExpirationNotification();
trialInstance = new TrialInstance();
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
}

//Classes
Expand Down
@@ -0,0 +1,35 @@
/*
* Copyright © 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.rest.api.model.settings;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.gravitee.rest.api.model.annotations.ParameterKey;
import io.gravitee.rest.api.model.parameters.Key;
import lombok.Getter;
import lombok.Setter;

/**
* @author Yann TAVERNIER (yann.tavernier at graviteesource.com)
* @author GraviteeSource Team
*/
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class TrialInstance {

@ParameterKey(Key.TRIAL_INSTANCE)
private Boolean enabled;
}
@@ -0,0 +1,41 @@
/*
* Copyright © 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.rest.api.service;

import io.gravitee.rest.api.service.common.ExecutionContext;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public interface EmailRecipientsService {
/**
* Process a list of templated recipients to extract it as a list of unique email addresses
*
* @param templatedRecipientsEmail a list of strings representing templated email. Each string can be itself a literal list of recipients separated by ' ' (whitespace) ',' or ';'. If an element contains '$', then it will be processed against templateData parameter with Freemarker processor
* @param templateData is the dateset used to process emails.
* @return a set of not empty emails.
*/
Set<String> processTemplatedRecipients(Collection<String> templatedRecipientsEmail, Map<String, Object> templateData);

/**
* Checks that each email has an opted-in user attached to it. If it is not the case, then the email is excluded from the result.
* @param executionContext
* @param recipientsEmail is the list of recipients to verify if attached user has opted-in. This method assumes emails are valids.
* @return a set of emails attached to an opted-in user.
*/
Set<String> filterRegisteredUser(ExecutionContext executionContext, Collection<String> recipientsEmail);
}
Expand Up @@ -303,6 +303,9 @@ public class ApiServiceImpl extends AbstractService implements ApiService {
@Autowired
private ApiSearchService apiSearchService;

@Autowired
private EmailRecipientsService emailRecipientsService;

@Override
public ApiEntity createFromSwagger(
ExecutionContext executionContext,
Expand Down Expand Up @@ -2163,6 +2166,8 @@ private ApiEntity updateWorkflowReview(

private List<String> findAllReviewersEmail(ExecutionContext executionContext, String apiId) {
final RolePermissionAction[] acls = { RolePermissionAction.UPDATE };
final boolean isTrialInstance = parameterService.findAsBoolean(executionContext, Key.TRIAL_INSTANCE, ParameterReferenceType.SYSTEM);
final Predicate<UserEntity> excludeIfTrialAndNotOptedIn = userEntity -> !isTrialInstance || userEntity.optedIn();

// find direct members of the API
Set<String> reviewerEmails = roleService
Expand All @@ -2176,6 +2181,7 @@ private List<String> findAllReviewersEmail(ExecutionContext executionContext, St
.map(MembershipEntity::getMemberId)
.distinct()
.map(id -> this.userService.findById(executionContext, id))
.filter(excludeIfTrialAndNotOptedIn)
.map(UserEntity::getEmail)
.filter(Objects::nonNull)
.collect(toSet());
Expand All @@ -2197,6 +2203,7 @@ private List<String> findAllReviewersEmail(ExecutionContext executionContext, St
.map(MembershipEntity::getMemberId)
.distinct()
.map(id -> this.userService.findById(executionContext, id))
.filter(excludeIfTrialAndNotOptedIn)
.map(UserEntity::getEmail)
.filter(Objects::nonNull)
.collect(toSet())
Expand Down
Expand Up @@ -118,6 +118,12 @@ public ConsoleSettingsEntity getConsoleSettings(ExecutionContext executionContex
);
enhanceFromConfigFile(consoleConfigEntity);

<<<<<<< HEAD
=======
enhanceFromRepository(executionContext, consoleConfigEntity);
hideForTrialInstance(consoleConfigEntity);

>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
return consoleConfigEntity;
}

Expand Down Expand Up @@ -272,6 +278,23 @@ private void enhanceFromConfigFile(ConsoleSettingsEntity consoleSettingsEntity)
consoleSettingsEntity.setNewsletter(newsletter);
}

<<<<<<< HEAD
=======
private void enhanceFromRepository(final ExecutionContext executionContext, final ConsoleSettingsEntity consoleConfigEntity) {
String consoleCustomUrl = installationAccessQueryService.getConsoleUrl(executionContext.getOrganizationId());
if (consoleCustomUrl != null) {
consoleConfigEntity.getManagement().setUrl(consoleCustomUrl);
consoleConfigEntity.getMetadata().add(PortalSettingsEntity.METADATA_READONLY, Key.MANAGEMENT_URL.key());
}
}

private void hideForTrialInstance(final ConsoleSettingsEntity consoleConfigEntity) {
if (Boolean.TRUE.equals(consoleConfigEntity.getTrialInstance().getEnabled())) {
consoleConfigEntity.setEmail(null);
}
}

>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
@Override
public void save(ExecutionContext executionContext, PortalSettingsEntity portalSettingsEntity) {
Object[] objects = getObjectArray(portalSettingsEntity);
Expand All @@ -281,19 +304,47 @@ public void save(ExecutionContext executionContext, PortalSettingsEntity portalS
@Override
public void save(ExecutionContext executionContext, ConsoleSettingsEntity consoleSettingsEntity) {
Object[] objects = getObjectArray(consoleSettingsEntity);
saveConfigByReference(executionContext, objects, executionContext.getOrganizationId(), ParameterReferenceType.ORGANIZATION);
saveConfigByReference(
executionContext,
objects,
executionContext.getOrganizationId(),
ParameterReferenceType.ORGANIZATION,
isTrialInstance(consoleSettingsEntity)
);
}

private boolean isTrialInstance(ConsoleSettingsEntity consoleSettings) {
return (
consoleSettings.getTrialInstance() != null &&
consoleSettings.getTrialInstance().getEnabled() != null &&
consoleSettings.getTrialInstance().getEnabled()
);
}

private void saveConfigByReference(
ExecutionContext executionContext,
Object[] objects,
String referenceId,
ParameterReferenceType referenceType
) {
saveConfigByReference(executionContext, objects, referenceId, referenceType, false);
}

private void saveConfigByReference(
ExecutionContext executionContext,
Object[] objects,
String referenceId,
ParameterReferenceType referenceType,
boolean isTrialInstance
) {
for (Object o : objects) {
for (Field f : o.getClass().getDeclaredFields()) {
ParameterKey parameterKey = f.getAnnotation(ParameterKey.class);
if (parameterKey != null) {
// do not save parameters that are hidden for trial instances
if (isTrialInstance && parameterKey.value().isHiddenForTrial()) {
continue;
}
boolean accessible = f.isAccessible();
f.setAccessible(true);
try {
Expand Down Expand Up @@ -399,6 +450,11 @@ private Object[] getObjectArray(ConsoleSettingsEntity consoleConfigEntity) {
consoleConfigEntity.getTheme(),
consoleConfigEntity.getV4EmulationEngine(),
consoleConfigEntity.getAlertEngine(),
<<<<<<< HEAD
=======
consoleConfigEntity.getLicenseExpirationNotification(),
consoleConfigEntity.getTrialInstance(),
>>>>>>> 6a6c2d18e3 (fix: prevent emails to be sent to non opted in user in trial instance)
};
}
}