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

org.graylog.events.processor.systemnotification.SystemNotificationRenderService Maven / Gradle / Ivy

There is a newer version: 6.1.4
Show newest version
/*
 * Copyright (C) 2020 Graylog, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program. If not, see
 * .
 */
package org.graylog.events.processor.systemnotification;

import freemarker.cache.ConditionalTemplateConfigurationFactory;
import freemarker.cache.PathGlobMatcher;
import freemarker.core.HTMLOutputFormat;
import freemarker.core.TemplateConfiguration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.graylog2.notifications.Notification;
import org.graylog2.notifications.NotificationService;

import javax.inject.Inject;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import static org.apache.commons.lang.CharEncoding.UTF_8;
import static org.graylog2.shared.utilities.StringUtils.f;

public class SystemNotificationRenderService {
    public enum Format {HTML, PLAINTEXT}

    private static final String KEY_NODE_ID = "node_id";
    private static final String KEY_TITLE = "_title";
    private static final String KEY_DESCRIPTION = "_description";
    private static final String KEY_CLOUD = "_cloud";
    public static final String TEMPLATE_BASE_PATH = "/org/graylog2/freemarker/templates/";
    private NotificationService notificationService;
    private org.graylog2.Configuration graylogConfig;
    private static final freemarker.template.Configuration cfg =
            new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_28);

    @Inject
    public SystemNotificationRenderService(NotificationService notificationService,
                                           org.graylog2.Configuration graylogConfig) {
        this.notificationService = notificationService;
        this.graylogConfig = graylogConfig;

        cfg.setDefaultEncoding(UTF_8);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        cfg.setLogTemplateExceptions(false);
        cfg.setClassForTemplateLoading(SystemNotificationRenderService.class, TEMPLATE_BASE_PATH);

        TemplateConfiguration tcHTML = new TemplateConfiguration();
        tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
        cfg.setTemplateConfigurations(
                new ConditionalTemplateConfigurationFactory(
                        new PathGlobMatcher(Format.HTML.name() + "/**"),
                        tcHTML));
    }

    public RenderResponse render(Notification.Type type, String key, Format format, Map values) {
        Notification notification = notificationService.getByTypeAndKey(type, key)
                .orElseThrow(() -> new NotFoundException(f("Event type <%s/%s> is not currently active", type, key)));
        return render(notification, format, values);
    }

    public RenderResponse render(Notification notification) {
        return render(notification, Format.PLAINTEXT, null);
    }

    public RenderResponse render(Notification notification, Format format, Map values) {
        // Add top level data for template expansion into the details map
        if (values == null) {
            values = new HashMap<>();
        }
        if (notification.getDetails() != null) {
            values.putAll(notification.getDetails());
        }
        if (notification.getNodeId() != null) {
            values.put(KEY_NODE_ID, notification.getNodeId());
        }
        values.put(KEY_CLOUD, graylogConfig.isCloud());

        final String templateRelPath = format.toString() + "/" + notification.getType().toString().toLowerCase(Locale.ENGLISH) + ".ftl";
        try (StringWriter writer = new StringWriter()) {
            Template template = cfg.getTemplate(templateRelPath);

            values.put(KEY_TITLE, true);
            values.put(KEY_DESCRIPTION, false);
            template.process(values, writer);
            String title = writer.toString();

            writer.getBuffer().setLength(0);
            values.put(KEY_TITLE, false);
            values.put(KEY_DESCRIPTION, true);
            template.process(values, writer);
            String description = writer.toString();

            return new RenderResponse(title, description);
        } catch (TemplateException e) {
            throw new BadRequestException("Unable to render template " + notification.getType().toString() + ": " + e.getMessage());
        } catch (IOException e) {
            throw new BadRequestException("Unable to locate template " + notification.getType().toString() + ": " + e.getMessage());
        }
    }

    public class RenderResponse {
        public String title;
        public String description;
        public RenderResponse(String title, String description) {
            this.title = title;
            this.description = description;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy