github.com/cozy/cozy-stack@v0.0.0-20240327093429-939e4a21320e/model/permission/verbs.go (about)

     1  package permission
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  )
     7  
     8  const verbSep = ","
     9  const allVerbs = "ALL"
    10  const allVerbsLength = 5
    11  
    12  // Verb is one of GET,POST,PUT,PATCH,DELETE
    13  type Verb string
    14  
    15  // All possible Verbs, a subset of http methods
    16  const (
    17  	GET    = Verb("GET")
    18  	POST   = Verb("POST")
    19  	PUT    = Verb("PUT")
    20  	PATCH  = Verb("PATCH")
    21  	DELETE = Verb("DELETE")
    22  )
    23  
    24  var allVerbsOrder = []Verb{GET, POST, PUT, PATCH, DELETE}
    25  
    26  // VerbSet is a Set of Verbs
    27  type VerbSet map[Verb]struct{}
    28  
    29  // Contains check if VerbSet contains a Verb
    30  func (vs VerbSet) Contains(v Verb) bool {
    31  	if len(vs) == 0 {
    32  		return true // empty set = ALL
    33  	}
    34  	_, has := vs[v]
    35  	return has
    36  }
    37  
    38  // ContainsAll check if VerbSet contains all passed verbs
    39  func (vs VerbSet) ContainsAll(verbs VerbSet) bool {
    40  	if len(vs) == 0 {
    41  		return true // empty set = ALL
    42  	}
    43  
    44  	for v := range verbs {
    45  		_, has := vs[v]
    46  		if !has {
    47  			return false
    48  		}
    49  	}
    50  	return true
    51  }
    52  
    53  // ReadOnly returns true if the set contains only the verb GET
    54  func (vs VerbSet) ReadOnly() bool {
    55  	if len(vs) != 1 {
    56  		return false
    57  	}
    58  	_, has := vs[GET]
    59  	return has
    60  }
    61  
    62  func (vs VerbSet) String() string {
    63  	out := ""
    64  	if len(vs) == 0 || len(vs) == allVerbsLength {
    65  		return allVerbs
    66  	}
    67  	for _, v := range allVerbsOrder {
    68  		if _, has := vs[v]; has {
    69  			out += verbSep + string(v)
    70  		}
    71  	}
    72  	return out[1:]
    73  }
    74  
    75  // MarshalJSON implements json.Marshaller on VerbSet
    76  // the VerbSet is converted to a json array
    77  func (vs VerbSet) MarshalJSON() ([]byte, error) {
    78  	s := make([]string, len(vs))
    79  	i := 0
    80  	for _, v := range allVerbsOrder {
    81  		if _, has := vs[v]; has {
    82  			s[i] = string(v)
    83  			i++
    84  		}
    85  	}
    86  	return json.Marshal(s)
    87  }
    88  
    89  // UnmarshalJSON implements json.Unmarshaller on VerbSet
    90  // it expects a json array
    91  func (vs *VerbSet) UnmarshalJSON(b []byte) error {
    92  	*vs = make(VerbSet)
    93  	var s []string
    94  	err := json.Unmarshal(b, &s)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	// empty set means ALL
    99  	for _, v := range s {
   100  		if v == "ALL" {
   101  			return nil
   102  		}
   103  	}
   104  	for _, v := range s {
   105  		switch v {
   106  		case "GET", "POST", "PUT", "PATCH", "DELETE":
   107  			(*vs)[Verb(v)] = struct{}{}
   108  		default:
   109  			return ErrBadScope
   110  		}
   111  	}
   112  	return nil
   113  }
   114  
   115  // Merge add verbs to the set
   116  func (vs *VerbSet) Merge(verbs *VerbSet) {
   117  	for v := range *verbs {
   118  		(*vs)[v] = struct{}{}
   119  	}
   120  }
   121  
   122  // VerbSplit parse a string into a VerbSet
   123  // Note: this does not check if Verbs are proper HTTP Verbs
   124  // This behaviour is used in @event trigger
   125  func VerbSplit(in string) VerbSet {
   126  	if in == allVerbs {
   127  		return ALL
   128  	}
   129  	verbs := strings.Split(in, verbSep)
   130  	out := make(VerbSet, len(verbs))
   131  	for _, v := range verbs {
   132  		out[Verb(v)] = struct{}{}
   133  	}
   134  	return out
   135  }
   136  
   137  // Verbs is a utility function to create VerbSets
   138  func Verbs(verbs ...Verb) VerbSet {
   139  	vs := make(VerbSet, len(verbs))
   140  	for _, v := range verbs {
   141  		vs[v] = struct{}{}
   142  	}
   143  	return vs
   144  }
   145  
   146  // ALL : the default VerbSet allows all Verbs
   147  var ALL = Verbs(GET, POST, PUT, PATCH, DELETE)