github.com/s7techlab/cckit@v0.10.5/extensions/owner/chaincode_owner.go (about) 1 package owner 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 8 "github.com/golang/protobuf/ptypes/empty" 9 "google.golang.org/protobuf/types/known/timestamppb" 10 11 "github.com/s7techlab/cckit/identity" 12 "github.com/s7techlab/cckit/router" 13 ) 14 15 var ( 16 ErrTxInvokerIsNotOwner = errors.New(`tx invoker is not owner`) 17 ErrDeleteLastOwnerIsNotAllowed = errors.New(`delete last owner is not allowed`) 18 ErrNewCertSameAsOldCert = errors.New(`new cert same as old cert`) 19 ) 20 21 func (x *ChaincodeOwner) GetMSPIdentifier() string { 22 return x.MspId 23 } 24 25 func NewService() *ChaincodeOwnerService { 26 return &ChaincodeOwnerService{} 27 } 28 29 var _ ChaincodeOwnerServiceChaincode = &ChaincodeOwnerService{} 30 31 type ChaincodeOwnerService struct{} 32 33 // IsTxCreator - wrapper for TxCreatorIsOwner for local calls 34 func (c *ChaincodeOwnerService) IsTxCreator(ctx router.Context) (*ChaincodeOwner, error) { 35 return c.GetOwnerByTxCreator(ctx, &empty.Empty{}) 36 } 37 38 // RegisterTxCreator Wrapper for OwnerRegisterTxCreator 39 func (c *ChaincodeOwnerService) RegisterTxCreator(ctx router.Context) (*ChaincodeOwner, error) { 40 return c.CreateOwnerTxCreator(ctx, &empty.Empty{}) 41 } 42 43 func (c *ChaincodeOwnerService) GetOwnerByTxCreator(ctx router.Context, _ *empty.Empty) (*ChaincodeOwner, error) { 44 txCreator, err := identity.FromStub(ctx.Stub()) 45 if err != nil { 46 return nil, err 47 } 48 49 owner, err := c.GetOwner(ctx, &OwnerId{ 50 MspId: txCreator.GetMSPIdentifier(), 51 Subject: txCreator.GetSubject(), 52 }) 53 54 if err != nil { 55 return nil, fmt.Errorf(`find owner by tx creator's msp_id and cert subject: %w`, err) 56 } 57 58 if err = identity.Equal(txCreator, owner); err != nil { 59 return nil, fmt.Errorf(`owner with tx creator's' msp_id and cert subject found, but: %w`, err) 60 } 61 62 return owner, nil 63 } 64 65 func (c *ChaincodeOwnerService) ListOwners(ctx router.Context, _ *empty.Empty) (*ChaincodeOwners, error) { 66 if res, err := State(ctx).List(&ChaincodeOwner{}); err != nil { 67 return nil, err 68 } else { 69 return res.(*ChaincodeOwners), nil 70 } 71 } 72 73 func (c *ChaincodeOwnerService) GetOwner(ctx router.Context, id *OwnerId) (*ChaincodeOwner, error) { 74 if err := router.ValidateRequest(id); err != nil { 75 return nil, err 76 } 77 78 if res, err := State(ctx).Get(id, &ChaincodeOwner{}); err != nil { 79 return nil, err 80 } else { 81 return res.(*ChaincodeOwner), nil 82 } 83 } 84 85 func (c *ChaincodeOwnerService) allowToModifyBy(ctx router.Context, invoker identity.Identity) error { 86 currentOwners, err := c.ListOwners(ctx, &empty.Empty{}) 87 if err != nil { 88 return err 89 } 90 91 // no owners, allow registering 92 if len(currentOwners.Items) == 0 { 93 return nil 94 } 95 96 for _, owner := range currentOwners.Items { 97 if err = identity.Equal(owner, invoker); err == nil { 98 return nil 99 } 100 } 101 102 return ErrTxInvokerIsNotOwner 103 } 104 105 func (c *ChaincodeOwnerService) txCreatorAllowedToModify(ctx router.Context) (identity.Identity, error) { 106 txCreator, err := identity.FromStub(ctx.Stub()) 107 if err != nil { 108 return nil, err 109 } 110 111 return txCreator, c.allowToModifyBy(ctx, txCreator) 112 } 113 114 func (c *ChaincodeOwnerService) CreateOwnerTxCreator(ctx router.Context, _ *empty.Empty) (*ChaincodeOwner, error) { 115 txCreator, err := identity.FromStub(ctx.Stub()) 116 if err != nil { 117 return nil, err 118 } 119 120 return c.CreateOwner(ctx, &CreateOwnerRequest{ 121 MspId: txCreator.GetMSPIdentifier(), 122 Cert: txCreator.GetPEM(), 123 }) 124 } 125 126 func (c *ChaincodeOwnerService) CreateOwner(ctx router.Context, create *CreateOwnerRequest) (*ChaincodeOwner, error) { 127 if err := router.ValidateRequest(create); err != nil { 128 return nil, err 129 } 130 131 txCreator, err := c.txCreatorAllowedToModify(ctx) 132 if err != nil { 133 return nil, err 134 } 135 136 id, err := identity.New(create.MspId, create.Cert) 137 if err != nil { 138 return nil, fmt.Errorf(`parse certificate: %w`, err) 139 } 140 141 txTimestamp, _ := ctx.Stub().GetTxTimestamp() 142 chaincodeOwner := &ChaincodeOwner{ 143 MspId: id.GetMSPIdentifier(), 144 Subject: id.GetSubject(), 145 146 Issuer: id.GetIssuer(), 147 ExpiresAt: timestamppb.New(id.ExpiresAt()), 148 Cert: create.Cert, 149 UpdatedByMspId: txCreator.GetMSPIdentifier(), 150 UpdatedByCert: txCreator.GetPEM(), 151 UpdatedAt: txTimestamp, 152 } 153 154 if err = State(ctx).Insert(chaincodeOwner); err != nil { 155 return nil, err 156 } 157 158 if err = Event(ctx).Set(&ChaincodeOwnerCreated{ 159 MspId: chaincodeOwner.MspId, 160 Subject: chaincodeOwner.Subject, 161 Issuer: chaincodeOwner.Issuer, 162 ExpiresAt: chaincodeOwner.ExpiresAt, 163 }); err != nil { 164 return nil, err 165 } 166 167 return chaincodeOwner, nil 168 } 169 170 func (c ChaincodeOwnerService) UpdateOwner(ctx router.Context, updateRequest *UpdateOwnerRequest) (*ChaincodeOwner, error) { 171 if err := router.ValidateRequest(updateRequest); err != nil { 172 return nil, err 173 } 174 175 txCreator, err := c.txCreatorAllowedToModify(ctx) 176 if err != nil { 177 return nil, err 178 } 179 180 id, err := identity.New(updateRequest.MspId, updateRequest.Cert) 181 if err != nil { 182 return nil, fmt.Errorf(`parse certificate: %w`, err) 183 } 184 185 curOwner, err := c.GetOwner(ctx, &OwnerId{ 186 MspId: id.GetMSPIdentifier(), 187 Subject: id.GetSubject(), 188 }) 189 190 if err != nil { 191 return nil, fmt.Errorf(`current owner with equal msp_id and cert_subject: %w`, err) 192 } 193 194 if bytes.Equal(curOwner.Cert, updateRequest.Cert) { 195 return nil, ErrNewCertSameAsOldCert 196 } 197 198 if err = identity.Equal(curOwner, id); err != nil { 199 return nil, err 200 } 201 202 txTimestamp, _ := ctx.Stub().GetTxTimestamp() 203 chaincodeOwner := &ChaincodeOwner{ 204 MspId: id.GetMSPIdentifier(), 205 Subject: id.GetSubject(), 206 207 Issuer: id.GetIssuer(), 208 ExpiresAt: timestamppb.New(id.ExpiresAt()), 209 Cert: updateRequest.Cert, 210 UpdatedByMspId: txCreator.GetMSPIdentifier(), 211 UpdatedByCert: txCreator.GetPEM(), 212 UpdatedAt: txTimestamp, 213 } 214 215 if err = State(ctx).Put(chaincodeOwner); err != nil { 216 return nil, err 217 } 218 219 if err = Event(ctx).Set(&ChaincodeOwnerUpdated{ 220 MspId: chaincodeOwner.MspId, 221 Subject: chaincodeOwner.Subject, 222 ExpiresAt: chaincodeOwner.ExpiresAt, 223 }); err != nil { 224 return nil, err 225 } 226 227 return chaincodeOwner, nil 228 } 229 230 func (c ChaincodeOwnerService) DeleteOwner(ctx router.Context, id *OwnerId) (*ChaincodeOwner, error) { 231 if err := router.ValidateRequest(id); err != nil { 232 return nil, err 233 } 234 235 if _, err := c.txCreatorAllowedToModify(ctx); err != nil { 236 return nil, err 237 } 238 239 deletedOwner, err := c.GetOwner(ctx, id) 240 if err != nil { 241 return nil, err 242 } 243 244 currentOwners, err := c.ListOwners(ctx, &empty.Empty{}) 245 if err != nil { 246 return nil, err 247 } 248 249 if len(currentOwners.Items) == 1 { 250 return nil, ErrDeleteLastOwnerIsNotAllowed 251 } 252 253 if err = State(ctx).Delete(id); err != nil { 254 return nil, err 255 } 256 257 if err = Event(ctx).Set(&ChaincodeOwnerDeleted{ 258 MspId: id.MspId, 259 Subject: id.Subject, 260 }); err != nil { 261 return nil, err 262 } 263 264 return deletedOwner, nil 265 }