2020-03-18 22:35:32 +00:00
|
|
|
package accessctl
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2020-04-24 19:33:33 +00:00
|
|
|
|
|
|
|
"dehub.dev/src/dehub.git/typeobj"
|
2020-03-18 22:35:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// 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())
|
|
|
|
}
|
|
|
|
|
|
|
|
// FilterInterface describes the methods that all Filters must implement.
|
|
|
|
type FilterInterface 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// Filter represents an access control filter being defined in the Config. Only
|
|
|
|
// one of its fields may be filled at a time.
|
|
|
|
type Filter struct {
|
2020-04-24 19:33:33 +00:00
|
|
|
Signature *FilterSignature `type:"signature"`
|
|
|
|
Branch *FilterBranch `type:"branch"`
|
|
|
|
FilesChanged *FilterFilesChanged `type:"files_changed"`
|
|
|
|
CommitType *FilterCommitType `type:"commit_type"`
|
|
|
|
CommitAttributes *FilterCommitAttributes `type:"commit_attributes"`
|
|
|
|
Not *FilterNot `type:"not"`
|
2020-03-18 22:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalYAML implements the yaml.Marshaler interface.
|
|
|
|
func (f Filter) MarshalYAML() (interface{}, error) {
|
|
|
|
return typeobj.MarshalYAML(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
|
|
|
func (f *Filter) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
return typeobj.UnmarshalYAML(f, unmarshal)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Interface returns the FilterInterface encapsulated by this Filter.
|
|
|
|
func (f Filter) Interface() (FilterInterface, error) {
|
|
|
|
el, _, err := typeobj.Element(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return el.(FilterInterface), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type returns a string describing what type of Filter this object
|
|
|
|
// encapsulates, based on which of its fields are filled in.
|
|
|
|
func (f Filter) Type() (string, error) {
|
|
|
|
_, typeStr, err := typeobj.Element(f)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return typeStr, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FilterCommitType filters by what type of commit is being requested. Exactly
|
|
|
|
// one of its fields should be filled.
|
|
|
|
type FilterCommitType struct {
|
|
|
|
Type string `yaml:"commit_type"`
|
|
|
|
Types []string `yaml:"commit_types"`
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ FilterInterface = FilterCommitType{}
|
|
|
|
|
|
|
|
// MatchCommit implements the method for FilterInterface.
|
|
|
|
func (f FilterCommitType) MatchCommit(req CommitRequest) error {
|
|
|
|
switch {
|
|
|
|
case f.Type != "":
|
|
|
|
if f.Type != req.Type {
|
|
|
|
return ErrFilterNoMatch{
|
|
|
|
Err: fmt.Errorf("commit 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("commit 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: "commit_type", "commit_types"`)
|
|
|
|
}
|
|
|
|
}
|
2020-04-24 19:33:33 +00:00
|
|
|
|
|
|
|
// 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 _ FilterInterface = 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
|
|
|
|
}
|