[PLUGIN] Set a configuration section

Hi !

I’m trying develop a configuration section in my plugin.

The configuration section is shown but my “edit configuration” button does not show the bootstrap modal on click. In fact nothing happen and no javascript error is raised.

The code:

Settings.jsx


import React, { useState } from 'react';
import { useStore } from 'stores/connect';
import { StreamsStore } from 'views/stores/StreamsStore';
import { defaultCompare } from 'logic/DefaultCompare'
import { BootstrapModalForm, Button, Input } from 'components/bootstrap';
import IfPermitted from 'components/common/IfPermitted';
import Select from 'components/common/Select';
import Spinner from 'components/common/Spinner';

const DEFAULT_CONFIG = {
    graylog_endpoint: 'https://127.0.0.1:9000',
    example_service_token: 'XXX',
};

const _formatOption = (key, value) => {
    return { value: value, label: key };
};

const _displayOptionalConfigurationValue = (value) => {
    if (!value) {
        return '[not set]';
    }
    return value;
};

const Settings = ({ config = DEFAULT_CONFIG, updateConfig }) => {
    const [nextConfiguration, setNextConfiguration] = useState(config);
    const [showModal, setShowModal] = useState(false);
    const { streams: streamList = [] } = useStore(StreamsStore);

    const _openModal = () => {
        setShowModal(true);
    };

    const _closeModal = () => {
        setShowModal(false);
    };

    /* TODO is this necessary?
        useEffect(() => {
            setNextConfiguration({ ...config });
        }, [config]);
    */

    const _saveConfiguration = () => {
        updateConfig(nextConfiguration).then(() => {
            _closeModal();
        })
    };

    const _resetConfiguration = () => {
        setNextConfiguration(config);
    };

    const _updateConfigurationField = (field, value) => {
        const newConfiguration = {...nextConfiguration};
        newConfiguration[field] = value;
        setNextConfiguration(newConfiguration);
    };

    const _onUpdate = (field) => {
        return e => {
            _updateConfigurationField(field, e.target.value);
        };
    };

    if (!streamList) {
        return <Spinner />;
    }

    const formattedStreams = streamList
        .map(stream => _formatOption(stream.title, stream.id))
        .sort((s1, s2) => defaultCompare(s1.label.toLowerCase(), s2.label.toLowerCase()));

    return (
        <div>
            <h3>ExampleConfiguration</h3>

            <p>
                Example needs two parameters:\n
                Graylog endpoint : The SIEM endpoint for API requesting\n
                Example service token: A graylog service token for API authentication
            </p>
            <dl className="deflist">
                <dt>Graylog endpoint: </dt>
                <dd>
                    {_displayOptionalConfigurationValue(config.graylog_endpoint)}
                </dd>
            </dl>
            <dl className="deflist">
                <dt>Example service token: </dt>
                <dd>
                    {_displayOptionalConfigurationValue(config.example_service_token)}
                </dd>
            </dl>

            <IfPermitted permissions="clusterconfigentry:edit">
                <Button bsStyle="info" bsSize="xs" onClick={_openModal}>
                    Edit configuration test
                </Button>
            </IfPermitted>

            <BootstrapModalForm
                show={showModal}
                title="Update example Configuration"
                onSubmitForm={_saveConfiguration}
                onCancel={_resetConfiguration}
                submitButtonText="Save">

                <fieldset>
                    <Input
                        id="graylog_endpoint"
                        type="text"
                        label="Graylog endpoint"
                        name="graylog_endpoint"
                        help="Graylog endpoint for API requesting."
                        value={nextConfiguration.graylog_endpoint}
                        onChange={_onUpdate('graylog_endpoint')}
                    />
                    <Input
                        id="example_service_token"
                        type="text"
                        label="example service token"
                        name="example_service_token"
                        help="example service token for API authentication."
                        value={nextConfiguration.example_service_token}
                        onChange={_onUpdate('example_service_token')}
                    />
                </fieldset>
            </BootstrapModalForm>
        </div>
    );
};

export default Settings;

Settings.java

package com.package.graylog;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.auto.value.AutoValue;

import javax.annotation.Nullable;

import static org.graylog2.plugin.streams.Stream.DEFAULT_STREAM_ID;

/**
 * This is the general configuration of the plugin (see System/Configurations)
 * It is probably linked to the IHM, just by the configuration in the web index.jsx.
 */
@JsonAutoDetect
@AutoValue
public abstract class Settings {
    
    @JsonProperty("graylog_endpoint")
    public abstract String accessGraylogEndpoint();

    @JsonProperty("example_service_token")
    public abstract String accessexampleServiceToken();

    @JsonCreator
    public static Settings create(
            @JsonProperty("graylog_endpoint") String graylog_endpoint,
            @JsonProperty("example_service_token") String examplel_service_token){
        return builder()
                .accessGraylogEndpoint(graylog_endpoint)
                .accessExampleServiceToken(examplel_service_token)
                .build();
    }

    public static Settings createDefault() {
        return builder()
                .accessGraylogEndpoint("https://127.0.0.1:9000")
                .accessExampleServiceToken("XXX")
                .build();
    }

    public static Builder builder() {
        return new AutoValue_Settings.Builder();
    }


    public abstract Builder toBuilder();

    @AutoValue.Builder
    public abstract static class Builder {

        public abstract Builder accessGraylogEndpoint(String accessGraylogEndpoint);
        public abstract Builder accessExampleServiceToken(String accessExampleServiceToken);

        public abstract Settings build();
    }
}

Index.jsx

import packageJson from '../../package.json';
import { PluginManifest, PluginStore } from 'graylog-web-plugin/plugin';
import SamplePage from 'pages/SamplePage';
import Settings from "./components/settings";

PluginStore.register(new PluginManifest(packageJson, {
  /* This is the place where you define which entities you are providing to the web interface.
     Right now you can add routes and navigation elements to it. */

  systemConfigurations: [
    {
      component: Settings,
      configType: 'com.package.graylog.Settings',
    },
  ],

  routes: [
        {path: '/example', component: SamplePage},

    ],

    navigation: [
        {
            path: '/example', description: 'Example'
        },
    ],
}));

Using Modal works instead of BootstrapModalForm.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.