package accessctl import ( "dehub.dev/src/dehub.git/typeobj" "errors" "fmt" ) // 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 { Signature *FilterSignature `type:"signature"` Branch *FilterBranch `type:"branch"` FilesChanged *FilterFilesChanged `type:"files_changed"` CommitType *FilterCommitType `type:"commit_type"` Not *FilterNot `type:"not"` } // 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"`) } }