summaryrefslogtreecommitdiffstats
path: root/model
diff options
context:
space:
mode:
Diffstat (limited to 'model')
-rw-r--r--model/manifest.go119
-rw-r--r--model/manifest_test.go101
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)
}