github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/graveler/branch/protection_manager.go (about)

     1  package branch
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"time"
     7  
     8  	"github.com/gobwas/glob"
     9  	"github.com/treeverse/lakefs/pkg/cache"
    10  	"github.com/treeverse/lakefs/pkg/graveler"
    11  	"github.com/treeverse/lakefs/pkg/graveler/settings"
    12  )
    13  
    14  const ProtectionSettingKey = "protected_branches"
    15  
    16  const (
    17  	matcherCacheSize   = 100_000
    18  	matcherCacheExpiry = 1 * time.Hour
    19  	matcherCacheJitter = 1 * time.Minute
    20  )
    21  
    22  type ProtectionManager struct {
    23  	settingManager *settings.Manager
    24  	matchers       cache.Cache
    25  }
    26  
    27  func NewProtectionManager(settingManager *settings.Manager) *ProtectionManager {
    28  	return &ProtectionManager{settingManager: settingManager, matchers: cache.NewCache(matcherCacheSize, matcherCacheExpiry, cache.NewJitterFn(matcherCacheJitter))}
    29  }
    30  
    31  func (m *ProtectionManager) GetRules(ctx context.Context, repository *graveler.RepositoryRecord) (*graveler.BranchProtectionRules, *string, error) {
    32  	rulesMsg := &graveler.BranchProtectionRules{}
    33  	checksum, err := m.settingManager.GetLatest(ctx, repository, ProtectionSettingKey, rulesMsg)
    34  	if err != nil {
    35  		return nil, nil, err
    36  	}
    37  	return rulesMsg, checksum, nil
    38  }
    39  
    40  func (m *ProtectionManager) SetRules(ctx context.Context, repository *graveler.RepositoryRecord, rules *graveler.BranchProtectionRules, lastKnownChecksum *string) error {
    41  	return m.settingManager.Save(ctx, repository, ProtectionSettingKey, rules, lastKnownChecksum)
    42  }
    43  
    44  func (m *ProtectionManager) IsBlocked(ctx context.Context, repository *graveler.RepositoryRecord, branchID graveler.BranchID, action graveler.BranchProtectionBlockedAction) (bool, error) {
    45  	rules := &graveler.BranchProtectionRules{}
    46  	err := m.settingManager.Get(ctx, repository, ProtectionSettingKey, rules)
    47  	if errors.Is(err, graveler.ErrNotFound) {
    48  		return false, nil
    49  	}
    50  	if err != nil {
    51  		return false, err
    52  	}
    53  	for pattern, blockedActions := range rules.BranchPatternToBlockedActions {
    54  		pattern := pattern
    55  		matcher, err := m.matchers.GetOrSet(pattern, func() (v interface{}, err error) {
    56  			return glob.Compile(pattern)
    57  		})
    58  		if err != nil {
    59  			return false, err
    60  		}
    61  		if !matcher.(glob.Glob).Match(string(branchID)) {
    62  			continue
    63  		}
    64  		for _, c := range blockedActions.GetValue() {
    65  			if c == action {
    66  				return true, nil
    67  			}
    68  		}
    69  	}
    70  	return false, nil
    71  }