diff --git a/server/channels/app/remote_cluster.go b/server/channels/app/remote_cluster.go index a5090dd08e..3aa338a0ee 100644 --- a/server/channels/app/remote_cluster.go +++ b/server/channels/app/remote_cluster.go @@ -204,6 +204,10 @@ func (a *App) CreateRemoteClusterInvite(remoteId, siteURL, token, password strin Token: token, } + if err := invite.IsValid(); err != nil { + return "", model.NewAppError("CreateRemoteClusterInvite", "api.remote_cluster.create_invite_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + encrypted, err := invite.Encrypt(password) if err != nil { return "", model.NewAppError("CreateRemoteClusterInvite", "api.remote_cluster.encrypt_invite_error", nil, "", http.StatusInternalServerError).Wrap(err) diff --git a/server/i18n/en.json b/server/i18n/en.json index 393a4ae39b..fa24a131bb 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -2754,6 +2754,10 @@ "id": "api.remote_cluster.cluster_not_deleted", "translation": "Remote cluster has not been deleted" }, + { + "id": "api.remote_cluster.create_invite_error", + "translation": "Could not create remote cluster invite" + }, { "id": "api.remote_cluster.delete.app_error", "translation": "We encountered an error deleting the secure connection." @@ -9614,6 +9618,18 @@ "id": "model.reaction.is_valid.user_id.app_error", "translation": "Invalid user id." }, + { + "id": "model.remote_cluster_invite.is_valid.remote_id.app_error", + "translation": "Invalid remote id." + }, + { + "id": "model.remote_cluster_invite.is_valid.site_url.app_error", + "translation": "Invalid site url." + }, + { + "id": "model.remote_cluster_invite.is_valid.token.app_error", + "translation": "Invalid token." + }, { "id": "model.reporting_base_options.is_valid.bad_date_range", "translation": "Date range provided is invalid." diff --git a/server/public/model/remote_cluster.go b/server/public/model/remote_cluster.go index fd6aeba617..4140cab043 100644 --- a/server/public/model/remote_cluster.go +++ b/server/public/model/remote_cluster.go @@ -13,6 +13,7 @@ import ( "errors" "io" "net/http" + "net/url" "regexp" "strings" @@ -368,6 +369,22 @@ type RemoteClusterInvite struct { Token string `json:"token"` } +func (rci *RemoteClusterInvite) IsValid() *AppError { + if !IsValidId(rci.RemoteId) { + return NewAppError("RemoteClusterInvite.IsValid", "model.remote_cluster_invite.is_valid.remote_id.app_error", nil, "id="+rci.RemoteId, http.StatusBadRequest) + } + + if rci.Token == "" { + return NewAppError("RemoteClusterInvite.IsValid", "model.remote_cluster_invite.is_valid.token.app_error", nil, "Token empty", http.StatusBadRequest) + } + + if _, err := url.ParseRequestURI(rci.SiteURL); err != nil { + return NewAppError("RemoteClusterInvite.IsValid", "model.remote_cluster_invite.is_valid.site_url.app_error", nil, "", http.StatusBadRequest).Wrap(err) + } + + return nil +} + func (rci *RemoteClusterInvite) Encrypt(password string) ([]byte, error) { raw, err := json.Marshal(&rci) if err != nil { diff --git a/server/public/model/remote_cluster_test.go b/server/public/model/remote_cluster_test.go index cdb1019d19..497882ba87 100644 --- a/server/public/model/remote_cluster_test.go +++ b/server/public/model/remote_cluster_test.go @@ -78,6 +78,34 @@ func TestRemoteClusterMsgIsValid(t *testing.T) { } } +func TestRemoteClusterInviteIsValid(t *testing.T) { + id := NewId() + url := "https://localhost:8080/test" + token := NewId() + + data := []struct { + name string + invite *RemoteClusterInvite + valid bool + }{ + {name: "Zero value", invite: &RemoteClusterInvite{}, valid: false}, + {name: "Missing remote id", invite: &RemoteClusterInvite{Token: token, SiteURL: url}, valid: false}, + {name: "Missing site url", invite: &RemoteClusterInvite{RemoteId: id, Token: token}, valid: false}, + {name: "Bad site url", invite: &RemoteClusterInvite{RemoteId: id, Token: token, SiteURL: ":/localhost"}, valid: false}, + {name: "Missing token", invite: &RemoteClusterInvite{RemoteId: id, SiteURL: url}, valid: false}, + {name: "RemoteClusterInvite valid", invite: &RemoteClusterInvite{RemoteId: id, Token: token, SiteURL: url}, valid: true}, + } + + for _, item := range data { + appErr := item.invite.IsValid() + if item.valid { + assert.Nil(t, appErr, item.name) + } else { + assert.NotNil(t, appErr, item.name) + } + } +} + func TestFixTopics(t *testing.T) { testData := []struct { topics string