github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/integration_action_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/masterhung0112/hk_server/v5/model"
    18  )
    19  
    20  type testHandler struct {
    21  	t *testing.T
    22  }
    23  
    24  func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    25  	bb, err := ioutil.ReadAll(r.Body)
    26  	assert.NoError(th.t, err)
    27  	assert.NotEmpty(th.t, string(bb))
    28  	poir := model.PostActionIntegrationRequestFromJson(bytes.NewReader(bb))
    29  	assert.NotEmpty(th.t, poir.UserId)
    30  	assert.NotEmpty(th.t, poir.UserName)
    31  	assert.NotEmpty(th.t, poir.ChannelId)
    32  	assert.NotEmpty(th.t, poir.ChannelName)
    33  	assert.NotEmpty(th.t, poir.TeamId)
    34  	assert.NotEmpty(th.t, poir.TeamName)
    35  	assert.NotEmpty(th.t, poir.PostId)
    36  	assert.NotEmpty(th.t, poir.TriggerId)
    37  	assert.Equal(th.t, "button", poir.Type)
    38  	assert.Equal(th.t, "test-value", poir.Context["test-key"])
    39  	w.Write([]byte("{}"))
    40  	w.WriteHeader(200)
    41  }
    42  
    43  func TestPostActionCookies(t *testing.T) {
    44  	th := Setup(t).InitBasic()
    45  	defer th.TearDown()
    46  	Client := th.Client
    47  
    48  	th.App.UpdateConfig(func(cfg *model.Config) {
    49  		*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
    50  	})
    51  
    52  	handler := &testHandler{t}
    53  	server := httptest.NewServer(handler)
    54  
    55  	for name, test := range map[string]struct {
    56  		Action             model.PostAction
    57  		ExpectedSucess     bool
    58  		ExpectedStatusCode int
    59  	}{
    60  		"32 character ID": {
    61  			Action: model.PostAction{
    62  				Id:   model.NewId(),
    63  				Name: "Test-action",
    64  				Type: model.POST_ACTION_TYPE_BUTTON,
    65  				Integration: &model.PostActionIntegration{
    66  					URL: server.URL,
    67  					Context: map[string]interface{}{
    68  						"test-key": "test-value",
    69  					},
    70  				},
    71  			},
    72  			ExpectedSucess:     true,
    73  			ExpectedStatusCode: http.StatusOK,
    74  		},
    75  		"6 character ID": {
    76  			Action: model.PostAction{
    77  				Id:   "someID",
    78  				Name: "Test-action",
    79  				Type: model.POST_ACTION_TYPE_BUTTON,
    80  				Integration: &model.PostActionIntegration{
    81  					URL: server.URL,
    82  					Context: map[string]interface{}{
    83  						"test-key": "test-value",
    84  					},
    85  				},
    86  			},
    87  			ExpectedSucess:     true,
    88  			ExpectedStatusCode: http.StatusOK,
    89  		},
    90  		"Empty ID": {
    91  			Action: model.PostAction{
    92  				Id:   "",
    93  				Name: "Test-action",
    94  				Type: model.POST_ACTION_TYPE_BUTTON,
    95  				Integration: &model.PostActionIntegration{
    96  					URL: server.URL,
    97  					Context: map[string]interface{}{
    98  						"test-key": "test-value",
    99  					},
   100  				},
   101  			},
   102  			ExpectedSucess:     false,
   103  			ExpectedStatusCode: http.StatusNotFound,
   104  		},
   105  	} {
   106  		t.Run(name, func(t *testing.T) {
   107  			post := &model.Post{
   108  				Id:        model.NewId(),
   109  				Type:      model.POST_EPHEMERAL,
   110  				UserId:    th.BasicUser.Id,
   111  				ChannelId: th.BasicChannel.Id,
   112  				CreateAt:  model.GetMillis(),
   113  				UpdateAt:  model.GetMillis(),
   114  				Props: map[string]interface{}{
   115  					"attachments": []*model.SlackAttachment{
   116  						{
   117  							Title:     "some-title",
   118  							TitleLink: "https://some-url.com",
   119  							Text:      "some-text",
   120  							ImageURL:  "https://some-other-url.com",
   121  							Actions:   []*model.PostAction{&test.Action},
   122  						},
   123  					},
   124  				},
   125  			}
   126  
   127  			assert.Equal(t, 32, len(th.App.PostActionCookieSecret()))
   128  			post = model.AddPostActionCookies(post, th.App.PostActionCookieSecret())
   129  
   130  			ok, resp := Client.DoPostActionWithCookie(post.Id, test.Action.Id, "", test.Action.Cookie)
   131  			require.NotNil(t, resp)
   132  			if test.ExpectedSucess {
   133  				assert.True(t, ok)
   134  				assert.Nil(t, resp.Error)
   135  			} else {
   136  				assert.False(t, ok)
   137  				assert.NotNil(t, resp.Error)
   138  			}
   139  			assert.Equal(t, test.ExpectedStatusCode, resp.StatusCode)
   140  			assert.NotNil(t, resp.RequestId)
   141  			assert.NotNil(t, resp.ServerVersion)
   142  		})
   143  	}
   144  }
   145  
   146  func TestOpenDialog(t *testing.T) {
   147  	th := Setup(t).InitBasic()
   148  	defer th.TearDown()
   149  	Client := th.Client
   150  
   151  	th.App.UpdateConfig(func(cfg *model.Config) {
   152  		*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
   153  	})
   154  
   155  	_, triggerId, err := model.GenerateTriggerId(th.BasicUser.Id, th.App.AsymmetricSigningKey())
   156  	require.Nil(t, err)
   157  
   158  	request := model.OpenDialogRequest{
   159  		TriggerId: triggerId,
   160  		URL:       "http://localhost:8065",
   161  		Dialog: model.Dialog{
   162  			CallbackId: "callbackid",
   163  			Title:      "Some Title",
   164  			Elements: []model.DialogElement{
   165  				{
   166  					DisplayName: "Element Name",
   167  					Name:        "element_name",
   168  					Type:        "text",
   169  					Placeholder: "Enter a value",
   170  				},
   171  			},
   172  			SubmitLabel:    "Submit",
   173  			NotifyOnCancel: false,
   174  			State:          "somestate",
   175  		},
   176  	}
   177  
   178  	pass, resp := Client.OpenInteractiveDialog(request)
   179  	CheckNoError(t, resp)
   180  	assert.True(t, pass)
   181  
   182  	// Should fail on bad trigger ID
   183  	request.TriggerId = "junk"
   184  	pass, resp = Client.OpenInteractiveDialog(request)
   185  	CheckBadRequestStatus(t, resp)
   186  	assert.False(t, pass)
   187  
   188  	// URL is required
   189  	request.TriggerId = triggerId
   190  	request.URL = ""
   191  	pass, resp = Client.OpenInteractiveDialog(request)
   192  	CheckBadRequestStatus(t, resp)
   193  	assert.False(t, pass)
   194  
   195  	// Should pass with markdown formatted introduction text
   196  	request.URL = "http://localhost:8065"
   197  	request.Dialog.IntroductionText = "**Some** _introduction text"
   198  	pass, resp = Client.OpenInteractiveDialog(request)
   199  	CheckNoError(t, resp)
   200  	assert.True(t, pass)
   201  
   202  	// Should pass with empty introduction text
   203  	request.Dialog.IntroductionText = ""
   204  	pass, resp = Client.OpenInteractiveDialog(request)
   205  	CheckNoError(t, resp)
   206  	assert.True(t, pass)
   207  
   208  	// Should pass with no elements
   209  	request.Dialog.Elements = nil
   210  	pass, resp = Client.OpenInteractiveDialog(request)
   211  	CheckNoError(t, resp)
   212  	assert.True(t, pass)
   213  	request.Dialog.Elements = []model.DialogElement{}
   214  	pass, resp = Client.OpenInteractiveDialog(request)
   215  	CheckNoError(t, resp)
   216  	assert.True(t, pass)
   217  }
   218  
   219  func TestSubmitDialog(t *testing.T) {
   220  	th := Setup(t).InitBasic()
   221  	defer th.TearDown()
   222  	Client := th.Client
   223  
   224  	th.App.UpdateConfig(func(cfg *model.Config) {
   225  		*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
   226  	})
   227  
   228  	submit := model.SubmitDialogRequest{
   229  		CallbackId: "callbackid",
   230  		State:      "somestate",
   231  		UserId:     th.BasicUser.Id,
   232  		ChannelId:  th.BasicChannel.Id,
   233  		TeamId:     th.BasicTeam.Id,
   234  		Submission: map[string]interface{}{"somename": "somevalue"},
   235  	}
   236  
   237  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   238  		var request model.SubmitDialogRequest
   239  		err := json.NewDecoder(r.Body).Decode(&request)
   240  		require.NoError(t, err)
   241  
   242  		assert.Equal(t, request.URL, "")
   243  		assert.Equal(t, request.UserId, submit.UserId)
   244  		assert.Equal(t, request.ChannelId, submit.ChannelId)
   245  		assert.Equal(t, request.TeamId, submit.TeamId)
   246  		assert.Equal(t, request.CallbackId, submit.CallbackId)
   247  		assert.Equal(t, request.State, submit.State)
   248  		val, ok := request.Submission["somename"].(string)
   249  		require.True(t, ok)
   250  		assert.Equal(t, "somevalue", val)
   251  	}))
   252  	defer ts.Close()
   253  
   254  	submit.URL = ts.URL
   255  
   256  	submitResp, resp := Client.SubmitInteractiveDialog(submit)
   257  	CheckNoError(t, resp)
   258  	assert.NotNil(t, submitResp)
   259  
   260  	submit.URL = ""
   261  	submitResp, resp = Client.SubmitInteractiveDialog(submit)
   262  	CheckBadRequestStatus(t, resp)
   263  	assert.Nil(t, submitResp)
   264  
   265  	submit.URL = ts.URL
   266  	submit.ChannelId = model.NewId()
   267  	submitResp, resp = Client.SubmitInteractiveDialog(submit)
   268  	CheckForbiddenStatus(t, resp)
   269  	assert.Nil(t, submitResp)
   270  
   271  	submit.URL = ts.URL
   272  	submit.ChannelId = th.BasicChannel.Id
   273  	submit.TeamId = model.NewId()
   274  	submitResp, resp = Client.SubmitInteractiveDialog(submit)
   275  	CheckForbiddenStatus(t, resp)
   276  	assert.Nil(t, submitResp)
   277  }