All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.am.management.service.impl.EmailManagerImpl Maven / Gradle / Ivy

There is a newer version: 4.6.0-alpha.3
Show newest version
/**
 * 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.am.management.service.impl;

import freemarker.cache.StringTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import io.gravitee.am.common.event.EmailEvent;
import io.gravitee.am.management.service.EmailManager;
import io.gravitee.am.model.Email;
import io.gravitee.am.model.ReferenceType;
import io.gravitee.am.model.Template;
import io.gravitee.am.model.User;
import io.gravitee.am.model.common.event.Payload;
import io.gravitee.am.service.EmailTemplateService;
import io.gravitee.common.event.Event;
import io.gravitee.common.event.EventListener;
import io.gravitee.common.event.EventManager;
import io.gravitee.common.service.AbstractService;
import io.reactivex.rxjava3.core.Maybe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static java.lang.String.format;

/**
 * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com)
 * @author GraviteeSource Team
 */
@Component
public class EmailManagerImpl extends AbstractService implements EmailManager, EventListener {

    private static final Logger logger = LoggerFactory.getLogger(EmailManagerImpl.class);
    private static final String TEMPLATE_SUFFIX = ".html";
    private ConcurrentMap emailTemplates = new ConcurrentHashMap<>();

    @Value("${email.from:#{null}}")
    private String defaultFrom;

    @Value("${email.subject:[Gravitee.io] %s}")
    private String subject;

    @Autowired
    private TemplateLoader templateLoader;

    @Autowired
    private Configuration configuration;

    @Autowired
    private EmailTemplateService emailTemplateService;

    @Autowired
    private EventManager eventManager;

    @Override
    protected void doStart() throws Exception {
        super.doStart();

        logger.info("Register event listener for email events for the management API");
        eventManager.subscribeForEvents(this, EmailEvent.class);

        logger.info("Initializing emails");
        emailTemplateService.findAll()
                .filter(Email::isEnabled)
                .blockingIterable()
                .forEach(this::loadEmail);
    }

    @Override
    public void onEvent(Event event) {
        if (Objects.requireNonNull(event.type()) == EmailEvent.UNDEPLOY) {
            removeEmail(event.content().getId());
        } else {
            logger.debug("{} event received for EmailTemplate {}, ignore it as it will be loaded on demand", event.type(), event.content().getId());
        }
    }

    @Override
    public Maybe getEmail(io.gravitee.am.model.Template templateDef, User user, String defaultSubject, int defaultExpiresAfter) {
        return getEmail0(templateDef, user.getReferenceType(), user.getReferenceId(), user, defaultSubject, defaultExpiresAfter);
    }

    @Override
    public Maybe getEmail(Template template, ReferenceType referenceType, String referenceId, User user, String defaultSubject, int defaultExpiresAfter) {
        return getEmail0(template, referenceType, referenceId, user, defaultSubject, defaultExpiresAfter);
    }

    private Maybe getEmail0(Template template, ReferenceType referenceType, String referenceId, User user, String defaultSubject, int defaultExpiresAfter) {
        // Since https://github.com/gravitee-io/issues/issues/6590 we have to read the record in Email repository
        return innerGetEmail(template, referenceType, referenceId, user)
                .map(customEmail -> {
                    // try to found email template in the local map
                    final String templateName = getTemplateName(customEmail);
                    final Email localEmailTemplate = emailTemplates.get(templateName);
                    if (localEmailTemplate != null && localEmailTemplate.getUpdatedAt().getTime() >= customEmail.getUpdatedAt().getTime()) {
                        return create(templateName, localEmailTemplate.getFrom(), localEmailTemplate.getFromName(), localEmailTemplate.getSubject(), localEmailTemplate.getExpiresAfter());
                    }
                    // else, reload the local map and return the database copy one
                    loadEmail(customEmail);
                    return create(templateName, customEmail.getFrom(), customEmail.getFromName(), customEmail.getSubject(), customEmail.getExpiresAfter());

                })
                // if there is nothing in database, return the classpath copy one
                .defaultIfEmpty(create(template.template(), defaultFrom, null, format(subject, defaultSubject), defaultExpiresAfter))
                .toMaybe();
    }

    private void removeEmail(String email) {
        logger.info("Management API has received a undeploy email event for {}", email);
        Optional emailOptional = emailTemplates.values().stream().filter(email1 -> email.equals(email1.getId())).findFirst();
        if (emailOptional.isPresent()) {
            Email emailToRemove = emailOptional.get();
            emailTemplates.remove(getTemplateName(emailToRemove));
            ((StringTemplateLoader) templateLoader).removeTemplate(getTemplateName(emailToRemove) + TEMPLATE_SUFFIX);
        }
    }

    public void loadEmail(Email email) {
        final String templateName = getTemplateName(email);
        if (email.isEnabled()) {
            reloadTemplate(templateName + TEMPLATE_SUFFIX, email.getContent());
            emailTemplates.put(templateName, email);
        } else {
            // remove email who has been disabled
            emailTemplates.remove(templateName);
            ((StringTemplateLoader) templateLoader).removeTemplate(templateName + TEMPLATE_SUFFIX);
        }
    }

    private Email create(String template, String from, String fromName, String subject, int expiresAt) {
        Email email = new Email();
        email.setTemplate(template);
        email.setFrom(from);
        email.setFromName(fromName);
        email.setSubject(subject);
        email.setExpiresAfter(expiresAt);
        return email;
    }

    private void reloadTemplate(String templateName, String content) {
        ((StringTemplateLoader) templateLoader).putTemplate(templateName, content, System.currentTimeMillis());
        configuration.clearTemplateCache();
    }

    private String getTemplateName(Email email) {
        return email.getTemplate()
                + TEMPLATE_NAME_SEPARATOR
                + email.getReferenceType() + email.getReferenceId()
                + ((email.getClient() != null) ? TEMPLATE_NAME_SEPARATOR + email.getClient() : "");
    }

    private Maybe innerGetEmail(io.gravitee.am.model.Template templateDef, ReferenceType refType, String referenceId, User user) {
        if (user.getClient() == null) {
            return emailTemplateService.findByTemplate(refType, referenceId, templateDef.template())
                    .filter(Email::isEnabled);
        }

        return emailTemplateService.findByClientAndTemplate(refType, referenceId, user.getClient(), templateDef.template())
                .filter(Email::isEnabled)
                .switchIfEmpty(Maybe.defer(() -> emailTemplateService.findByTemplate(refType, referenceId, templateDef.template())))
                .filter(Email::isEnabled);
    }

    public void setDefaultFrom(String defaultFrom) {
        this.defaultFrom = defaultFrom;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy