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  }