github.com/s7techlab/cckit@v0.10.5/extensions/owner/owner.go (about)

     1  // Package owner provides method for storing in chaincode state information about chaincode owner
     2  package owner
     3  
     4  import (
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/s7techlab/cckit/identity"
     9  	r "github.com/s7techlab/cckit/router"
    10  )
    11  
    12  var (
    13  	// ErrOwnerNotProvided occurs when providing owner identity in init arguments
    14  	ErrOwnerNotProvided = errors.New(`owner not provided`)
    15  
    16  	// ErrOwnerAlreadySet owner already set
    17  	ErrOwnerAlreadySet = errors.New(`owner already set`)
    18  )
    19  
    20  func IsSet(c r.Context) (bool, error) {
    21  	return c.State().Exists(OwnerStateKey)
    22  }
    23  
    24  // Get returns current chaincode owner identity.Entry
    25  // Service implementation recommended, see chaincode_owner.proto
    26  func Get(c r.Context) (*identity.Entry, error) {
    27  	ownerEntry, err := c.State().Get(OwnerStateKey, &identity.Entry{})
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	o := ownerEntry.(identity.Entry)
    33  	return &o, nil
    34  }
    35  
    36  // SetFromCreator sets chain code owner from stub creator
    37  // Service implementation recommended, see chaincode_owner.proto
    38  func SetFromCreator(c r.Context) (*identity.Entry, error) {
    39  	if ownerSet, err := IsSet(c); err != nil {
    40  		return nil, err
    41  	} else if ownerSet {
    42  		return Get(c)
    43  	}
    44  
    45  	creator, err := identity.FromStub(c.Stub())
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	identityEntry, err := identity.CreateEntry(creator)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	return identityEntry, c.State().Insert(OwnerStateKey, identityEntry)
    56  }
    57  
    58  // SetFromArgs set owner from first args
    59  func SetFromArgs(c r.Context) (*identity.Entry, error) {
    60  	args := c.Stub().GetArgs()
    61  
    62  	if len(args) == 2 {
    63  		return Insert(c, string(args[0]), args[1])
    64  	}
    65  
    66  	if isSet, err := IsSet(c); err != nil {
    67  		return nil, err
    68  	} else if !isSet {
    69  		return nil, ErrOwnerNotProvided
    70  	}
    71  
    72  	return Get(c)
    73  }
    74  
    75  // Insert information about owner to chaincode state
    76  func Insert(c r.Context, mspID string, cert []byte) (*identity.Entry, error) {
    77  	if ownerSet, err := IsSet(c); err != nil {
    78  		return nil, fmt.Errorf(`check owner is set: %w`, err)
    79  	} else if ownerSet {
    80  		return nil, ErrOwnerAlreadySet
    81  	}
    82  
    83  	id, err := identity.New(mspID, cert)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	identityEntry, err := identity.CreateEntry(id)
    89  	if err != nil {
    90  		return nil, fmt.Errorf(`create owner entry: %w`, err)
    91  	}
    92  	return identityEntry, c.State().Insert(OwnerStateKey, identityEntry)
    93  }
    94  
    95  // IsInvokerOr checks tx creator and compares with owner of another identity
    96  // Service implementation recommended, see chaincode_owner.proto
    97  func IsInvokerOr(c r.Context, allowedTo ...identity.Identity) (bool, error) {
    98  	if err := IsTxCreator(c); err == nil {
    99  		return true, nil
   100  	}
   101  	if len(allowedTo) == 0 {
   102  		return false, nil
   103  	}
   104  	invoker, err := identity.FromStub(c.Stub())
   105  	if err != nil {
   106  		return false, err
   107  	}
   108  	for _, allowed := range allowedTo {
   109  		if allowed.GetMSPIdentifier() == invoker.GetMSPIdentifier() &&
   110  			allowed.GetSubject() == invoker.GetSubject() {
   111  			return true, nil
   112  		}
   113  	}
   114  	return false, nil
   115  }
   116  
   117  // IdentityEntryFromState returns identity.Entry with chaincode owner certificate
   118  // Service implementation recommended, see chaincode_owner.proto
   119  func IdentityEntryFromState(c r.Context) (identity.Entry, error) {
   120  	res, err := c.State().Get(OwnerStateKey, &identity.Entry{})
   121  	if err != nil {
   122  		return identity.Entry{}, err
   123  	}
   124  
   125  	return res.(identity.Entry), nil
   126  }
   127  
   128  // IsInvoker checks than tx creator is chain code owner
   129  // Service implementation recommended, see chaincode_owner.proto
   130  func IsInvoker(ctx r.Context) (bool, error) {
   131  	if err := IsTxCreator(ctx); err != nil {
   132  		return false, err
   133  	}
   134  
   135  	return true, nil
   136  }
   137  
   138  // IsTxCreator returns error if owner identity  (msp_id + certificate) did not match tx creator identity
   139  // Service implementation recommended, see chaincode_owner.proto
   140  func IsTxCreator(ctx r.Context) error {
   141  	invoker, err := identity.FromStub(ctx.Stub())
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	ownerEntry, err := IdentityEntryFromState(ctx)
   147  	if err != nil {
   148  		return err
   149  	}
   150  
   151  	if err = identity.Equal(invoker, ownerEntry); err != nil {
   152  		return fmt.Errorf(`%s : %w`, err, ErrOwnerOnly)
   153  	}
   154  
   155  	return nil
   156  }