diff options
Diffstat (limited to 'model')
-rw-r--r-- | model/manifest.go | 119 | ||||
-rw-r--r-- | model/manifest_test.go | 101 |
2 files changed, 212 insertions, 8 deletions
diff --git a/model/manifest.go b/model/manifest.go index 4352a2bd2..12f105aaa 100644 --- a/model/manifest.go +++ b/model/manifest.go @@ -1,4 +1,4 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package model @@ -13,20 +13,125 @@ import ( "gopkg.in/yaml.v2" ) +const ( + PLUGIN_CONFIG_TYPE_TEXT = "text" + PLUGIN_CONFIG_TYPE_BOOL = "bool" + PLUGIN_CONFIG_TYPE_RADIO = "radio" + PLUGIN_CONFIG_TYPE_DROPDOWN = "dropdown" + PLUGIN_CONFIG_TYPE_GENERATED = "generated" + PLUGIN_CONFIG_TYPE_USERNAME = "username" +) + +type PluginOption struct { + // The display name for the option. + DisplayName string `json:"display_name" yaml:"display_name"` + + // The string value for the option. + Value string `json:"value" yaml:"value"` +} + +type PluginSetting struct { + // The display name for the setting. + DisplayName string `json:"display_name" yaml:"display_name"` + + // The type of the setting. + // + // "bool" will result in a boolean true or false setting. + // + // "dropdown" will result in a string setting that allows the user to select from a list of + // pre-defined options. + // + // "generated" will result in a string setting that is set to a random, cryptographically secure + // string. + // + // "radio" will result in a string setting that allows the user to select from a short selection + // of pre-defined options. + // + // "text" will result in a string setting that can be typed in manually. + // + // "username" will result in a text setting that will autocomplete to a username. + Type string `json:"type" yaml:"type"` + + // The help text to display to the user. + HelpText string `json:"help_text" yaml:"help_text"` + + // The help text to display alongside the "Regenerate" button for settings of the "generated" type. + RegenerateHelpText string `json:"regenerate_help_text,omitempty" yaml:"regenerate_help_text,omitempty"` + + // The placeholder to display for "text", "generated" and "username" types when blank. + Placeholder string `json:"placeholder" yaml:"placeholder"` + + // The default value of the setting. + Default interface{} `json:"default" yaml:"default"` + + // For "radio" or "dropdown" settings, this is the list of pre-defined options that the user can choose + // from. + Options []*PluginOption `json:"options,omitempty" yaml:"options,omitempty"` +} + +type PluginSettingsSchema struct { + // Optional text to display above the settings. + Header string `json:"header" yaml:"header"` + + // Optional text to display below the settings. + Footer string `json:"footer" yaml:"footer"` + + // A mapping of setting keys to schema definitions. + Settings map[string]*PluginSetting `json:"settings" yaml:"settings"` +} + +// The plugin manifest defines the metadata required to load and present your plugin. The manifest +// file should be named plugin.json or plugin.yaml and placed in the top of your +// plugin bundle. +// +// Example plugin.yaml: +// +// id: com.mycompany.myplugin +// name: My Plugin +// description: This is my plugin. It does stuff. +// backend: +// executable: myplugin +// settings_schema: +// settings: +// enable_extra_thing: +// type: bool +// display_name: Enable Extra Thing +// help_text: When true, an extra thing will be enabled! +// default: false type Manifest struct { - Id string `json:"id" yaml:"id"` - Name string `json:"name,omitempty" yaml:"name,omitempty"` - Description string `json:"description,omitempty" yaml:"description,omitempty"` - Version string `json:"version" yaml:"version"` - Backend *ManifestBackend `json:"backend,omitempty" yaml:"backend,omitempty"` - Webapp *ManifestWebapp `json:"webapp,omitempty" yaml:"webapp,omitempty"` + // The id is a globally unique identifier that represents your plugin. Reverse-DNS notation + // using a name you control is a good option. For example, "com.mycompany.myplugin". + Id string `json:"id" yaml:"id"` + + // The name to be displayed for the plugin. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // A description of what your plugin is and does. + Description string `json:"description,omitempty" yaml:"description,omitempty"` + + // A version number for your plugin. Semantic versioning is recommended: http://semver.org + Version string `json:"version" yaml:"version"` + + // If your plugin extends the server, you'll need define backend. + Backend *ManifestBackend `json:"backend,omitempty" yaml:"backend,omitempty"` + + // If your plugin extends the web app, you'll need to define webapp. + Webapp *ManifestWebapp `json:"webapp,omitempty" yaml:"webapp,omitempty"` + + // To allow administrators to configure your plugin via the Mattermost system console, you can + // provide your settings schema. + SettingsSchema *PluginSettingsSchema `json:"settings_schema,omitempty" yaml:"settings_schema,omitempty"` } type ManifestBackend struct { + // The path to your executable binary. This should be relative to the root of your bundle and the + // location of the manifest file. Executable string `json:"executable" yaml:"executable"` } type ManifestWebapp struct { + // The path to your webapp bundle. This should be relative to the root of your bundle and the + // location of the manifest file. BundlePath string `json:"bundle_path" yaml:"bundle_path"` } diff --git a/model/manifest_test.go b/model/manifest_test.go index 1ec43a217..0edd1fed4 100644 --- a/model/manifest_test.go +++ b/model/manifest_test.go @@ -1,3 +1,6 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + package model import ( @@ -64,6 +67,26 @@ func TestManifestUnmarshal(t *testing.T) { Webapp: &ManifestWebapp{ BundlePath: "thebundlepath", }, + SettingsSchema: &PluginSettingsSchema{ + Header: "theheadertext", + Footer: "thefootertext", + Settings: map[string]*PluginSetting{ + "thesetting": &PluginSetting{ + DisplayName: "thedisplayname", + Type: PLUGIN_CONFIG_TYPE_DROPDOWN, + HelpText: "thehelptext", + RegenerateHelpText: "theregeneratehelptext", + Placeholder: "theplaceholder", + Options: []*PluginOption{ + &PluginOption{ + DisplayName: "theoptiondisplayname", + Value: "thevalue", + }, + }, + Default: "thedefault", + }, + }, + }, } var yamlResult Manifest @@ -73,6 +96,20 @@ backend: executable: theexecutable webapp: bundle_path: thebundlepath +settings_schema: + header: theheadertext + footer: thefootertext + settings: + thesetting: + display_name: thedisplayname + type: dropdown + help_text: thehelptext + regenerate_help_text: theregeneratehelptext + placeholder: theplaceholder + options: + - display_name: theoptiondisplayname + value: thevalue + default: thedefault `), &yamlResult)) assert.Equal(t, expected, yamlResult) @@ -84,7 +121,27 @@ webapp: }, "webapp": { "bundle_path": "thebundlepath" - } + }, + "settings_schema": { + "header": "theheadertext", + "footer": "thefootertext", + "settings": { + "thesetting": { + "display_name": "thedisplayname", + "type": "dropdown", + "help_text": "thehelptext", + "regenerate_help_text": "theregeneratehelptext", + "placeholder": "theplaceholder", + "options": [ + { + "display_name": "theoptiondisplayname", + "value": "thevalue" + } + ], + "default": "thedefault" + } + } + } }`), &jsonResult)) assert.Equal(t, expected, jsonResult) } @@ -115,6 +172,26 @@ func TestManifestJson(t *testing.T) { Webapp: &ManifestWebapp{ BundlePath: "thebundlepath", }, + SettingsSchema: &PluginSettingsSchema{ + Header: "theheadertext", + Footer: "thefootertext", + Settings: map[string]*PluginSetting{ + "thesetting": &PluginSetting{ + DisplayName: "thedisplayname", + Type: PLUGIN_CONFIG_TYPE_DROPDOWN, + HelpText: "thehelptext", + RegenerateHelpText: "theregeneratehelptext", + Placeholder: "theplaceholder", + Options: []*PluginOption{ + &PluginOption{ + DisplayName: "theoptiondisplayname", + Value: "thevalue", + }, + }, + Default: "thedefault", + }, + }, + }, } json := manifest.ToJson() @@ -159,6 +236,26 @@ func TestManifestClientManifest(t *testing.T) { Webapp: &ManifestWebapp{ BundlePath: "thebundlepath", }, + SettingsSchema: &PluginSettingsSchema{ + Header: "theheadertext", + Footer: "thefootertext", + Settings: map[string]*PluginSetting{ + "thesetting": &PluginSetting{ + DisplayName: "thedisplayname", + Type: PLUGIN_CONFIG_TYPE_DROPDOWN, + HelpText: "thehelptext", + RegenerateHelpText: "theregeneratehelptext", + Placeholder: "theplaceholder", + Options: []*PluginOption{ + &PluginOption{ + DisplayName: "theoptiondisplayname", + Value: "thevalue", + }, + }, + Default: "thedefault", + }, + }, + }, } sanitized := manifest.ClientManifest() @@ -166,6 +263,7 @@ func TestManifestClientManifest(t *testing.T) { assert.NotEmpty(t, sanitized.Id) assert.NotEmpty(t, sanitized.Version) assert.NotEmpty(t, sanitized.Webapp) + assert.NotEmpty(t, sanitized.SettingsSchema) assert.Empty(t, sanitized.Name) assert.Empty(t, sanitized.Description) assert.Empty(t, sanitized.Backend) @@ -176,4 +274,5 @@ func TestManifestClientManifest(t *testing.T) { assert.NotEmpty(t, manifest.Name) assert.NotEmpty(t, manifest.Description) assert.NotEmpty(t, manifest.Backend) + assert.NotEmpty(t, manifest.SettingsSchema) } |