github.com/metacurrency/holochain@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/action_link.go (about)

     1  package holochain
     2  
     3  import (
     4  	"errors"
     5  	. "github.com/holochain/holochain-proto/hash"
     6  	peer "github.com/libp2p/go-libp2p-peer"
     7  )
     8  
     9  //------------------------------------------------------------
    10  // Link
    11  
    12  type ActionLink struct {
    13  	entryType      string
    14  	links          []Link
    15  	validationBase Hash
    16  }
    17  
    18  func NewLinkAction(entryType string, links []Link) *ActionLink {
    19  	a := ActionLink{entryType: entryType, links: links}
    20  	return &a
    21  }
    22  
    23  func (a *ActionLink) Name() string {
    24  	return "link"
    25  }
    26  
    27  func (a *ActionLink) SysValidation(h *Holochain, def *EntryDef, pkg *Package, sources []peer.ID) (err error) {
    28  	if def.DataFormat != DataFormatLinks {
    29  		err = errors.New("action only valid for links entry type")
    30  	}
    31  	//@TODO what sys level links validation?  That they are all valid hash format for the DNA?
    32  	return
    33  }
    34  
    35  func (a *ActionLink) Receive(dht *DHT, msg *Message) (response interface{}, err error) {
    36  	t := msg.Body.(HoldReq)
    37  	var holdResp *HoldResp
    38  
    39  	err = RunValidationPhase(dht.h, msg.From, VALIDATE_LINK_REQUEST, t.EntryHash, func(resp ValidateResponse) error {
    40  		var le LinksEntry
    41  		le, err = LinksEntryFromJSON(resp.Entry.Content().(string))
    42  		if err != nil {
    43  			return err
    44  		}
    45  
    46  		a := NewLinkAction(resp.Type, le.Links)
    47  		a.validationBase = t.RelatedHash
    48  		_, err = dht.h.ValidateAction(a, a.entryType, &resp.Package, []peer.ID{msg.From})
    49  		//@TODO this is "one bad apple spoils the lot" because the app
    50  		// has no way to tell us not to link certain of the links.
    51  		// we need to extend the return value of the app to be able to
    52  		// have it reject a subset of the links.
    53  		if err != nil {
    54  			// how do we record an invalid linking?
    55  			//@TODO store as REJECTED
    56  		} else {
    57  			base := t.RelatedHash.String()
    58  			for _, l := range le.Links {
    59  				if base == l.Base {
    60  					if l.LinkAction == DelLinkAction {
    61  						err = dht.DelLink(msg, base, l.Link, l.Tag)
    62  					} else {
    63  						err = dht.PutLink(msg, base, l.Link, l.Tag)
    64  					}
    65  				}
    66  			}
    67  			if err == nil {
    68  				holdResp, err = dht.MakeHoldResp(msg, StatusLive)
    69  			}
    70  		}
    71  		return err
    72  	})
    73  
    74  	if holdResp != nil {
    75  		response = *holdResp
    76  	}
    77  	return
    78  }
    79  
    80  func (a *ActionLink) CheckValidationRequest(def *EntryDef) (err error) {
    81  	if def.DataFormat != DataFormatLinks {
    82  		err = errors.New("hash not of a linking entry")
    83  	}
    84  	return
    85  }