A read-only clone of the dehub project, for until dehub.dev can be brought back online.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
dehub/accessctl/filter.go

124 lines
3.6 KiB

package accessctl
import (
"errors"
"fmt"
"dehub.dev/src/dehub.git/typeobj"
)
// ErrFilterNoMatch is returned from a FilterInterface's Match method when the
// given request was not matched to the filter due to the request itself (as
// opposed to some error in the filter's definition).
type ErrFilterNoMatch struct {
Err error
}
func (err ErrFilterNoMatch) Error() string {
return fmt.Sprintf("matching with filter: %s", err.Err.Error())
}
// Filter describes the methods that all Filters must implement.
type Filter interface {
// MatchCommit returns nil if the CommitRequest is matched by the filter,
// otherwise it returns an error (ErrFilterNoMatch if the error is due to
// the CommitRequest).
MatchCommit(CommitRequest) error
}
// FilterUnion represents an access control filter being defined in the Config.
// Only one of its fields may be filled at a time.
type FilterUnion struct {
Signature *FilterSignature `type:"signature"`
Branch *FilterBranch `type:"branch"`
FilesChanged *FilterFilesChanged `type:"files_changed"`
PayloadType *FilterPayloadType `type:"payload_type"`
CommitAttributes *FilterCommitAttributes `type:"commit_attributes"`
Not *FilterNot `type:"not"`
}
// MarshalYAML implements the yaml.Marshaler interface.
func (f FilterUnion) MarshalYAML() (interface{}, error) {
return typeobj.MarshalYAML(f)
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (f *FilterUnion) UnmarshalYAML(unmarshal func(interface{}) error) error {
return typeobj.UnmarshalYAML(f, unmarshal)
}
// Filter returns the Filter encapsulated by this FilterUnion.
//
// This method will panic if a Filter field is not populated.
func (f FilterUnion) Filter() Filter {
el, _, err := typeobj.Element(f)
if err != nil {
panic(err)
}
return el.(Filter)
}
// Type returns the Filter's type (as would be used in its YAML "type" field).
//
// This will panic if a Filter field is not populated.
func (f FilterUnion) Type() string {
_, typeStr, err := typeobj.Element(f)
if err != nil {
panic(err)
}
return typeStr
}
// FilterPayloadType filters by what type of payload is being requested. Exactly
// one of its fields should be filled.
type FilterPayloadType struct {
Type string `yaml:"payload_type"`
Types []string `yaml:"payload_types"`
}
var _ Filter = FilterPayloadType{}
// MatchCommit implements the method for FilterInterface.
func (f FilterPayloadType) MatchCommit(req CommitRequest) error {
switch {
case f.Type != "":
if f.Type != req.Type {
return ErrFilterNoMatch{
Err: fmt.Errorf("payload type %q does not match filter's type %q",
req.Type, f.Type),
}
}
return nil
case len(f.Types) > 0:
for _, typ := range f.Types {
if typ == req.Type {
return nil
}
}
return ErrFilterNoMatch{
Err: fmt.Errorf("payload type %q does not match any of filter's types %+v",
req.Type, f.Types),
}
default:
return errors.New(`one of the following fields must be set: "payload_type", "payload_types"`)
}
}
// FilterCommitAttributes filters by one more attributes a commit can have. If
// more than one field is filled in then all relevant attributes must be present
// on the commit for this filter to match.
type FilterCommitAttributes struct {
NonFastForward bool `yaml:"non_fast_forward"`
}
var _ Filter = FilterCommitAttributes{}
// MatchCommit implements the method for FilterInterface.
func (f FilterCommitAttributes) MatchCommit(req CommitRequest) error {
if f.NonFastForward && !req.NonFastForward {
return ErrFilterNoMatch{Err: errors.New("commit is a fast-forward")}
}
return nil
}