github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/permission/match.go (about)

     1  package permission
     2  
     3  import "strings"
     4  
     5  // Fetcher is an interface for an object to see if it matches a rule.
     6  type Fetcher interface {
     7  	ID() string
     8  	DocType() string
     9  	Fetch(field string) []string
    10  }
    11  
    12  func matchValues(r Rule, o Fetcher) bool {
    13  	// empty r.Values = any value
    14  	if len(r.Values) == 0 {
    15  		return true
    16  	}
    17  	if r.Selector == "" {
    18  		return r.ValuesContain(o.ID())
    19  	}
    20  	return r.ValuesMatch(o)
    21  }
    22  
    23  func matchOnFields(r Rule, o Fetcher, fields ...string) bool {
    24  	// in this case, if r.Values is empty the selector is considered too wide and
    25  	// is forbidden
    26  	if len(r.Values) == 0 || r.Selector == "" {
    27  		return false
    28  	}
    29  	var matchSelector bool
    30  	for _, f := range fields {
    31  		if r.Selector == f {
    32  			matchSelector = true
    33  			break
    34  		}
    35  	}
    36  	if !matchSelector {
    37  		return false
    38  	}
    39  	return r.ValuesMatch(o)
    40  }
    41  
    42  func matchVerb(r Rule, v Verb) bool {
    43  	return r.Verbs.Contains(v)
    44  }
    45  
    46  // MatchType returns true if the rule type matches the given doctype
    47  func MatchType(r Rule, doctype string) bool {
    48  	if r.Type == doctype || isMaximal(r.Type) {
    49  		return true
    50  	}
    51  	if !isWildcard(r.Type) {
    52  		return false
    53  	}
    54  	typ := TrimWildcard(r.Type)
    55  	return typ == doctype || strings.HasPrefix(doctype, typ+".")
    56  }
    57  
    58  func matchWholeType(r Rule) bool {
    59  	return len(r.Values) == 0
    60  }
    61  
    62  func matchID(r Rule, id string) bool {
    63  	return r.Selector == "" && r.ValuesContain(id)
    64  }
    65  
    66  // AllowWholeType returns true if the set allows to apply verb to every
    67  // document from the given doctypes (ie. r.values == 0)
    68  func (s Set) AllowWholeType(v Verb, doctype string) bool {
    69  	return s.Some(func(r Rule) bool {
    70  		return matchVerb(r, v) &&
    71  			MatchType(r, doctype) &&
    72  			matchWholeType(r)
    73  	})
    74  }
    75  
    76  // AllowID returns true if the set allows to apply verb to given type & id
    77  func (s Set) AllowID(v Verb, doctype, id string) bool {
    78  	return s.Some(func(r Rule) bool {
    79  		return matchVerb(r, v) &&
    80  			MatchType(r, doctype) &&
    81  			(matchWholeType(r) || matchID(r, id))
    82  	})
    83  }
    84  
    85  // Allow returns true if the set allows to apply verb to given doc
    86  func (s Set) Allow(v Verb, o Fetcher) bool {
    87  	return s.Some(func(r Rule) bool {
    88  		return matchVerb(r, v) &&
    89  			MatchType(r, o.DocType()) &&
    90  			matchValues(r, o)
    91  	})
    92  }
    93  
    94  // AllowOnFields returns true if the set allows to apply verb to given doc on
    95  // the specified fields.
    96  func (s Set) AllowOnFields(v Verb, o Fetcher, fields ...string) bool {
    97  	return s.Some(func(r Rule) bool {
    98  		return matchVerb(r, v) &&
    99  			MatchType(r, o.DocType()) &&
   100  			matchOnFields(r, o, fields...)
   101  	})
   102  }