github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/pkg/fftypes/group.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package fftypes 18 19 import ( 20 "context" 21 "crypto/sha256" 22 "encoding/json" 23 "fmt" 24 25 "github.com/kaleido-io/firefly/internal/i18n" 26 ) 27 28 type GroupIdentity struct { 29 Ledger *UUID `json:"ledger,omitempty"` 30 Namespace string `json:"namespace,omitempty"` 31 Name string `json:"name"` 32 Members Members `json:"members"` 33 } 34 35 type Group struct { 36 GroupIdentity 37 Message *UUID `json:"message,omitempty"` 38 Hash *Bytes32 `json:"hash,omitempty"` 39 Created *FFTime `json:"created,omitempty"` 40 } 41 42 type Members []*Member 43 44 type Member struct { 45 Identity string `json:"identity,omitempty"` 46 Node *UUID `json:"node,omitempty"` 47 } 48 49 type MemberInput struct { 50 Identity string `json:"identity,omitempty"` 51 Node string `json:"node,omitempty"` 52 } 53 54 func (man *GroupIdentity) Hash() *Bytes32 { 55 b, _ := json.Marshal(&man) 56 hash := Bytes32(sha256.Sum256(b)) 57 return &hash 58 } 59 60 func (group *Group) Validate(ctx context.Context, existing bool) (err error) { 61 // We allow a blank name for a group (for auto creation) 62 if group.Name != "" { 63 if err = ValidateFFNameField(ctx, group.Namespace, "namespace"); err != nil { 64 return err 65 } 66 } 67 if len(group.Members) == 0 { 68 return i18n.NewError(ctx, i18n.MsgGroupMustHaveMembers) 69 } 70 dupCheck := make(map[string]bool) 71 for i, r := range group.Members { 72 if r.Identity == "" { 73 return i18n.NewError(ctx, i18n.MsgEmptyMemberIdentity, i) 74 } 75 if err = ValidateLength(ctx, r.Identity, "identity", 1024); err != nil { 76 return err 77 } 78 if r.Node == nil { 79 return i18n.NewError(ctx, i18n.MsgEmptyMemberNode, i) 80 } 81 key := fmt.Sprintf("%s:%s", r.Node, r.Identity) 82 if dupCheck[key] { 83 return i18n.NewError(ctx, i18n.MsgDuplicateMember, i) 84 } 85 dupCheck[key] = true 86 } 87 if existing { 88 hash := group.GroupIdentity.Hash() 89 if !group.Hash.Equals(hash) { 90 return i18n.NewError(ctx, i18n.MsgGroupInvalidHash, group.Hash, hash) 91 } 92 } 93 return nil 94 } 95 96 func (group *Group) Seal() { 97 group.Hash = group.GroupIdentity.Hash() 98 } 99 100 func (group *Group) Topic() string { 101 return group.Hash.String() 102 } 103 104 func (group *Group) SetBroadcastMessage(msgID *UUID) { 105 group.Message = msgID 106 }