diff options
Diffstat (limited to 'vendor/github.com/mattermost/mattermost-server/v5/model/remote_cluster.go')
-rw-r--r-- | vendor/github.com/mattermost/mattermost-server/v5/model/remote_cluster.go | 355 |
1 files changed, 0 insertions, 355 deletions
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/remote_cluster.go b/vendor/github.com/mattermost/mattermost-server/v5/model/remote_cluster.go deleted file mode 100644 index 2ec0cc9b..00000000 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/remote_cluster.go +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/json" - "errors" - "io" - "net/http" - "regexp" - "strings" - - "golang.org/x/crypto/scrypt" -) - -const ( - RemoteOfflineAfterMillis = 1000 * 60 * 5 // 5 minutes - RemoteNameMinLength = 1 - RemoteNameMaxLength = 64 -) - -var ( - validRemoteNameChars = regexp.MustCompile(`^[a-zA-Z0-9\.\-\_]+$`) -) - -type RemoteCluster struct { - RemoteId string `json:"remote_id"` - RemoteTeamId string `json:"remote_team_id"` - Name string `json:"name"` - DisplayName string `json:"display_name"` - SiteURL string `json:"site_url"` - CreateAt int64 `json:"create_at"` - LastPingAt int64 `json:"last_ping_at"` - Token string `json:"token"` - RemoteToken string `json:"remote_token"` - Topics string `json:"topics"` - CreatorId string `json:"creator_id"` -} - -func (rc *RemoteCluster) PreSave() { - if rc.RemoteId == "" { - rc.RemoteId = NewId() - } - - if rc.DisplayName == "" { - rc.DisplayName = rc.Name - } - - rc.Name = SanitizeUnicode(rc.Name) - rc.DisplayName = SanitizeUnicode(rc.DisplayName) - rc.Name = NormalizeRemoteName(rc.Name) - - if rc.Token == "" { - rc.Token = NewId() - } - - if rc.CreateAt == 0 { - rc.CreateAt = GetMillis() - } - rc.fixTopics() -} - -func (rc *RemoteCluster) IsValid() *AppError { - if !IsValidId(rc.RemoteId) { - return NewAppError("RemoteCluster.IsValid", "model.cluster.is_valid.id.app_error", nil, "id="+rc.RemoteId, http.StatusBadRequest) - } - - if !IsValidRemoteName(rc.Name) { - return NewAppError("RemoteCluster.IsValid", "model.cluster.is_valid.name.app_error", nil, "name="+rc.Name, http.StatusBadRequest) - } - - if rc.CreateAt == 0 { - return NewAppError("RemoteCluster.IsValid", "model.cluster.is_valid.create_at.app_error", nil, "create_at=0", http.StatusBadRequest) - } - - if !IsValidId(rc.CreatorId) { - return NewAppError("RemoteCluster.IsValid", "model.cluster.is_valid.id.app_error", nil, "creator_id="+rc.CreatorId, http.StatusBadRequest) - } - return nil -} - -func IsValidRemoteName(s string) bool { - if len(s) < RemoteNameMinLength || len(s) > RemoteNameMaxLength { - return false - } - return validRemoteNameChars.MatchString(s) -} - -func (rc *RemoteCluster) PreUpdate() { - if rc.DisplayName == "" { - rc.DisplayName = rc.Name - } - - rc.Name = SanitizeUnicode(rc.Name) - rc.DisplayName = SanitizeUnicode(rc.DisplayName) - rc.Name = NormalizeRemoteName(rc.Name) - rc.fixTopics() -} - -func (rc *RemoteCluster) IsOnline() bool { - return rc.LastPingAt > GetMillis()-RemoteOfflineAfterMillis -} - -// fixTopics ensures all topics are separated by one, and only one, space. -func (rc *RemoteCluster) fixTopics() { - trimmed := strings.TrimSpace(rc.Topics) - if trimmed == "" || trimmed == "*" { - rc.Topics = trimmed - return - } - - var sb strings.Builder - sb.WriteString(" ") - - ss := strings.Split(rc.Topics, " ") - for _, c := range ss { - cc := strings.TrimSpace(c) - if cc != "" { - sb.WriteString(cc) - sb.WriteString(" ") - } - } - rc.Topics = sb.String() -} - -func (rc *RemoteCluster) ToJSON() (string, error) { - b, err := json.Marshal(rc) - if err != nil { - return "", err - } - return string(b), nil -} - -func (rc *RemoteCluster) ToRemoteClusterInfo() RemoteClusterInfo { - return RemoteClusterInfo{ - Name: rc.Name, - DisplayName: rc.DisplayName, - CreateAt: rc.CreateAt, - LastPingAt: rc.LastPingAt, - } -} - -func NormalizeRemoteName(name string) string { - return strings.ToLower(name) -} - -func RemoteClusterFromJSON(data io.Reader) (*RemoteCluster, *AppError) { - var rc RemoteCluster - err := json.NewDecoder(data).Decode(&rc) - if err != nil { - return nil, NewAppError("RemoteClusterFromJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return &rc, nil -} - -// RemoteClusterInfo provides a subset of RemoteCluster fields suitable for sending to clients. -type RemoteClusterInfo struct { - Name string `json:"name"` - DisplayName string `json:"display_name"` - CreateAt int64 `json:"create_at"` - LastPingAt int64 `json:"last_ping_at"` -} - -// RemoteClusterFrame wraps a `RemoteClusterMsg` with credentials specific to a remote cluster. -type RemoteClusterFrame struct { - RemoteId string `json:"remote_id"` - Msg RemoteClusterMsg `json:"msg"` -} - -func (f *RemoteClusterFrame) IsValid() *AppError { - if !IsValidId(f.RemoteId) { - return NewAppError("RemoteClusterFrame.IsValid", "api.remote_cluster.invalid_id.app_error", nil, "RemoteId="+f.RemoteId, http.StatusBadRequest) - } - - if err := f.Msg.IsValid(); err != nil { - return err - } - - return nil -} - -func RemoteClusterFrameFromJSON(data io.Reader) (*RemoteClusterFrame, *AppError) { - var frame RemoteClusterFrame - err := json.NewDecoder(data).Decode(&frame) - if err != nil { - return nil, NewAppError("RemoteClusterFrameFromJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return &frame, nil -} - -// RemoteClusterMsg represents a message that is sent and received between clusters. -// These are processed and routed via the RemoteClusters service. -type RemoteClusterMsg struct { - Id string `json:"id"` - Topic string `json:"topic"` - CreateAt int64 `json:"create_at"` - Payload json.RawMessage `json:"payload"` -} - -func NewRemoteClusterMsg(topic string, payload json.RawMessage) RemoteClusterMsg { - return RemoteClusterMsg{ - Id: NewId(), - Topic: topic, - CreateAt: GetMillis(), - Payload: payload, - } -} - -func (m RemoteClusterMsg) IsValid() *AppError { - if !IsValidId(m.Id) { - return NewAppError("RemoteClusterMsg.IsValid", "api.remote_cluster.invalid_id.app_error", nil, "Id="+m.Id, http.StatusBadRequest) - } - - if m.Topic == "" { - return NewAppError("RemoteClusterMsg.IsValid", "api.remote_cluster.invalid_topic.app_error", nil, "Topic empty", http.StatusBadRequest) - } - - if len(m.Payload) == 0 { - return NewAppError("RemoteClusterMsg.IsValid", "api.context.invalid_body_param.app_error", map[string]interface{}{"Name": "PayLoad"}, "", http.StatusBadRequest) - } - - return nil -} - -func RemoteClusterMsgFromJSON(data io.Reader) (RemoteClusterMsg, *AppError) { - var msg RemoteClusterMsg - err := json.NewDecoder(data).Decode(&msg) - if err != nil { - return RemoteClusterMsg{}, NewAppError("RemoteClusterMsgFromJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return msg, nil -} - -// RemoteClusterPing represents a ping that is sent and received between clusters -// to indicate a connection is alive. This is the payload for a `RemoteClusterMsg`. -type RemoteClusterPing struct { - SentAt int64 `json:"sent_at"` - RecvAt int64 `json:"recv_at"` -} - -func RemoteClusterPingFromRawJSON(raw json.RawMessage) (RemoteClusterPing, *AppError) { - var ping RemoteClusterPing - err := json.Unmarshal(raw, &ping) - if err != nil { - return RemoteClusterPing{}, NewAppError("RemoteClusterPingFromRawJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return ping, nil -} - -// RemoteClusterInvite represents an invitation to establish a simple trust with a remote cluster. -type RemoteClusterInvite struct { - RemoteId string `json:"remote_id"` - RemoteTeamId string `json:"remote_team_id"` - SiteURL string `json:"site_url"` - Token string `json:"token"` -} - -func RemoteClusterInviteFromRawJSON(raw json.RawMessage) (*RemoteClusterInvite, *AppError) { - var invite RemoteClusterInvite - err := json.Unmarshal(raw, &invite) - if err != nil { - return nil, NewAppError("RemoteClusterInviteFromRawJSON", "model.utils.decode_json.app_error", nil, err.Error(), http.StatusBadRequest) - } - return &invite, nil -} - -func (rci *RemoteClusterInvite) Encrypt(password string) ([]byte, error) { - raw, err := json.Marshal(&rci) - if err != nil { - return nil, err - } - - // create random salt to be prepended to the blob. - salt := make([]byte, 16) - if _, err = io.ReadFull(rand.Reader, salt); err != nil { - return nil, err - } - - key, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) - if err != nil { - return nil, err - } - - block, err := aes.NewCipher(key[:]) - if err != nil { - return nil, err - } - - gcm, err := cipher.NewGCM(block) - if err != nil { - return nil, err - } - - // create random nonce - nonce := make([]byte, gcm.NonceSize()) - if _, err = io.ReadFull(rand.Reader, nonce); err != nil { - return nil, err - } - - // prefix the nonce to the cyphertext so we don't need to keep track of it. - sealed := gcm.Seal(nonce, nonce, raw, nil) - - return append(salt, sealed...), nil -} - -func (rci *RemoteClusterInvite) Decrypt(encrypted []byte, password string) error { - if len(encrypted) <= 16 { - return errors.New("invalid length") - } - - // first 16 bytes is the salt that was used to derive a key - salt := encrypted[:16] - encrypted = encrypted[16:] - - key, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) - if err != nil { - return err - } - - block, err := aes.NewCipher(key[:]) - if err != nil { - return err - } - - gcm, err := cipher.NewGCM(block) - if err != nil { - return err - } - - // nonce was prefixed to the cyphertext when encrypting so we need to extract it. - nonceSize := gcm.NonceSize() - nonce, cyphertext := encrypted[:nonceSize], encrypted[nonceSize:] - - plain, err := gcm.Open(nil, nonce, cyphertext, nil) - if err != nil { - return err - } - - // try to unmarshall the decrypted JSON to this invite struct. - return json.Unmarshal(plain, &rci) -} - -// RemoteClusterQueryFilter provides filter criteria for RemoteClusterStore.GetAll -type RemoteClusterQueryFilter struct { - ExcludeOffline bool - InChannel string - NotInChannel string - Topic string - CreatorId string - OnlyConfirmed bool -} |