github.com/nmintoh/dserver@v5.11.1+incompatible/app/plugin_test.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"bytes"
     8  	"crypto/sha256"
     9  	"encoding/base64"
    10  	"io/ioutil"
    11  	"net/http"
    12  	"net/http/httptest"
    13  	"testing"
    14  
    15  	"github.com/gorilla/mux"
    16  	"github.com/mattermost/mattermost-server/model"
    17  	"github.com/mattermost/mattermost-server/plugin"
    18  	"github.com/stretchr/testify/assert"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  func getHashedKey(key string) string {
    23  	hash := sha256.New()
    24  	hash.Write([]byte(key))
    25  	return base64.StdEncoding.EncodeToString(hash.Sum(nil))
    26  }
    27  
    28  func TestPluginKeyValueStore(t *testing.T) {
    29  	th := Setup(t).InitBasic()
    30  	defer th.TearDown()
    31  
    32  	pluginId := "testpluginid"
    33  
    34  	defer func() {
    35  		assert.Nil(t, th.App.DeletePluginKey(pluginId, "key"))
    36  		assert.Nil(t, th.App.DeletePluginKey(pluginId, "key2"))
    37  		assert.Nil(t, th.App.DeletePluginKey(pluginId, "key3"))
    38  		assert.Nil(t, th.App.DeletePluginKey(pluginId, "key4"))
    39  	}()
    40  
    41  	assert.Nil(t, th.App.SetPluginKey(pluginId, "key", []byte("test")))
    42  	ret, err := th.App.GetPluginKey(pluginId, "key")
    43  	assert.Nil(t, err)
    44  	assert.Equal(t, []byte("test"), ret)
    45  
    46  	// Test inserting over existing entries
    47  	assert.Nil(t, th.App.SetPluginKey(pluginId, "key", []byte("test2")))
    48  	ret, err = th.App.GetPluginKey(pluginId, "key")
    49  	assert.Nil(t, err)
    50  	assert.Equal(t, []byte("test2"), ret)
    51  
    52  	// Test getting non-existent key
    53  	ret, err = th.App.GetPluginKey(pluginId, "notakey")
    54  	assert.Nil(t, err)
    55  	assert.Nil(t, ret)
    56  
    57  	// Test deleting non-existent keys.
    58  	assert.Nil(t, th.App.DeletePluginKey(pluginId, "notrealkey"))
    59  
    60  	// Verify behaviour for the old approach that involved storing the hashed keys.
    61  	hashedKey2 := getHashedKey("key2")
    62  	kv := &model.PluginKeyValue{
    63  		PluginId: pluginId,
    64  		Key:      hashedKey2,
    65  		Value:    []byte("test"),
    66  		ExpireAt: 0,
    67  	}
    68  
    69  	result := <-th.App.Srv.Store.Plugin().SaveOrUpdate(kv)
    70  	assert.Nil(t, result.Err)
    71  
    72  	// Test fetch by keyname (this key does not exist but hashed key will be used for lookup)
    73  	ret, err = th.App.GetPluginKey(pluginId, "key2")
    74  	assert.Nil(t, err)
    75  	assert.Equal(t, kv.Value, ret)
    76  
    77  	// Test fetch by hashed keyname
    78  	ret, err = th.App.GetPluginKey(pluginId, hashedKey2)
    79  	assert.Nil(t, err)
    80  	assert.Equal(t, kv.Value, ret)
    81  
    82  	// Test ListKeys
    83  	assert.Nil(t, th.App.SetPluginKey(pluginId, "key3", []byte("test3")))
    84  	assert.Nil(t, th.App.SetPluginKey(pluginId, "key4", []byte("test4")))
    85  
    86  	list, err := th.App.ListPluginKeys(pluginId, 0, 1)
    87  	assert.Nil(t, err)
    88  	assert.Equal(t, []string{"key"}, list)
    89  
    90  	list, err = th.App.ListPluginKeys(pluginId, 1, 1)
    91  	assert.Nil(t, err)
    92  	assert.Equal(t, []string{"key3"}, list)
    93  
    94  	list, err = th.App.ListPluginKeys(pluginId, 0, 4)
    95  	assert.Nil(t, err)
    96  	assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
    97  
    98  	list, err = th.App.ListPluginKeys(pluginId, 0, 2)
    99  	assert.Nil(t, err)
   100  	assert.Equal(t, []string{"key", "key3"}, list)
   101  
   102  	list, err = th.App.ListPluginKeys(pluginId, 1, 2)
   103  	assert.Nil(t, err)
   104  	assert.Equal(t, []string{"key4", hashedKey2}, list)
   105  
   106  	list, err = th.App.ListPluginKeys(pluginId, 2, 2)
   107  	assert.Nil(t, err)
   108  	assert.Equal(t, []string{}, list)
   109  
   110  	// List Keys bad input
   111  	list, err = th.App.ListPluginKeys(pluginId, 0, 0)
   112  	assert.Nil(t, err)
   113  	assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
   114  
   115  	list, err = th.App.ListPluginKeys(pluginId, 0, -1)
   116  	assert.Nil(t, err)
   117  	assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
   118  
   119  	list, err = th.App.ListPluginKeys(pluginId, -1, 1)
   120  	assert.Nil(t, err)
   121  	assert.Equal(t, []string{"key"}, list)
   122  
   123  	list, err = th.App.ListPluginKeys(pluginId, -1, 0)
   124  	assert.Nil(t, err)
   125  	assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
   126  }
   127  
   128  func TestServePluginRequest(t *testing.T) {
   129  	th := Setup(t).InitBasic()
   130  	defer th.TearDown()
   131  
   132  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false })
   133  
   134  	w := httptest.NewRecorder()
   135  	r := httptest.NewRequest("GET", "/plugins/foo/bar", nil)
   136  	th.App.ServePluginRequest(w, r)
   137  	assert.Equal(t, http.StatusNotImplemented, w.Result().StatusCode)
   138  }
   139  
   140  func TestPrivateServePluginRequest(t *testing.T) {
   141  	th := Setup(t).InitBasic()
   142  	defer th.TearDown()
   143  
   144  	testCases := []struct {
   145  		Description string
   146  		ConfigFunc  func(cfg *model.Config)
   147  		URL         string
   148  		ExpectedURL string
   149  	}{
   150  		{
   151  			"no subpath",
   152  			func(cfg *model.Config) {},
   153  			"/plugins/id/endpoint",
   154  			"/endpoint",
   155  		},
   156  		{
   157  			"subpath",
   158  			func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL += "/subpath" },
   159  			"/subpath/plugins/id/endpoint",
   160  			"/endpoint",
   161  		},
   162  	}
   163  
   164  	for _, testCase := range testCases {
   165  		t.Run(testCase.Description, func(t *testing.T) {
   166  			th.App.UpdateConfig(testCase.ConfigFunc)
   167  			expectedBody := []byte("body")
   168  			request := httptest.NewRequest(http.MethodGet, testCase.URL, bytes.NewReader(expectedBody))
   169  			recorder := httptest.NewRecorder()
   170  
   171  			handler := func(context *plugin.Context, w http.ResponseWriter, r *http.Request) {
   172  				assert.Equal(t, testCase.ExpectedURL, r.URL.Path)
   173  
   174  				body, _ := ioutil.ReadAll(r.Body)
   175  				assert.Equal(t, expectedBody, body)
   176  			}
   177  
   178  			request = mux.SetURLVars(request, map[string]string{"plugin_id": "id"})
   179  
   180  			th.App.servePluginRequest(recorder, request, handler)
   181  		})
   182  	}
   183  
   184  }
   185  
   186  func TestHandlePluginRequest(t *testing.T) {
   187  	th := Setup(t).InitBasic()
   188  	defer th.TearDown()
   189  
   190  	th.App.UpdateConfig(func(cfg *model.Config) {
   191  		*cfg.PluginSettings.Enable = false
   192  		*cfg.ServiceSettings.EnableUserAccessTokens = true
   193  	})
   194  
   195  	token, err := th.App.CreateUserAccessToken(&model.UserAccessToken{
   196  		UserId: th.BasicUser.Id,
   197  	})
   198  	require.Nil(t, err)
   199  
   200  	var assertions func(*http.Request)
   201  	router := mux.NewRouter()
   202  	router.HandleFunc("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}/{anything:.*}", func(_ http.ResponseWriter, r *http.Request) {
   203  		th.App.servePluginRequest(nil, r, func(_ *plugin.Context, _ http.ResponseWriter, r *http.Request) {
   204  			assertions(r)
   205  		})
   206  	})
   207  
   208  	r := httptest.NewRequest("GET", "/plugins/foo/bar", nil)
   209  	r.Header.Add("Authorization", "Bearer "+token.Token)
   210  	assertions = func(r *http.Request) {
   211  		assert.Equal(t, "/bar", r.URL.Path)
   212  		assert.Equal(t, th.BasicUser.Id, r.Header.Get("Mattermost-User-Id"))
   213  	}
   214  	router.ServeHTTP(nil, r)
   215  
   216  	r = httptest.NewRequest("GET", "/plugins/foo/bar?a=b&access_token="+token.Token+"&c=d", nil)
   217  	assertions = func(r *http.Request) {
   218  		assert.Equal(t, "/bar", r.URL.Path)
   219  		assert.Equal(t, "a=b&c=d", r.URL.RawQuery)
   220  		assert.Equal(t, th.BasicUser.Id, r.Header.Get("Mattermost-User-Id"))
   221  	}
   222  	router.ServeHTTP(nil, r)
   223  
   224  	r = httptest.NewRequest("GET", "/plugins/foo/bar?a=b&access_token=asdf&c=d", nil)
   225  	assertions = func(r *http.Request) {
   226  		assert.Equal(t, "/bar", r.URL.Path)
   227  		assert.Equal(t, "a=b&c=d", r.URL.RawQuery)
   228  		assert.Empty(t, r.Header.Get("Mattermost-User-Id"))
   229  	}
   230  	router.ServeHTTP(nil, r)
   231  }
   232  
   233  func TestGetPluginStatusesDisabled(t *testing.T) {
   234  	th := Setup(t).InitBasic()
   235  	defer th.TearDown()
   236  
   237  	th.App.UpdateConfig(func(cfg *model.Config) {
   238  		*cfg.PluginSettings.Enable = false
   239  	})
   240  
   241  	_, err := th.App.GetPluginStatuses()
   242  	require.NotNil(t, err)
   243  	require.EqualError(t, err, "GetPluginStatuses: Plugins have been disabled. Please check your logs for details., ")
   244  }
   245  
   246  func TestGetPluginStatuses(t *testing.T) {
   247  	th := Setup(t).InitBasic()
   248  	defer th.TearDown()
   249  
   250  	th.App.UpdateConfig(func(cfg *model.Config) {
   251  		*cfg.PluginSettings.Enable = true
   252  	})
   253  
   254  	pluginStatuses, err := th.App.GetPluginStatuses()
   255  	require.Nil(t, err)
   256  	require.NotNil(t, pluginStatuses)
   257  }