Full Mattermost server source with integrated Community Enterprise features. Includes vendor directory for offline/air-gapped builds. Structure: - enterprise-impl/: Enterprise feature implementations - enterprise-community/: Init files that register implementations - enterprise/: Bridge imports (community_imports.go) - vendor/: All dependencies for offline builds Build (online): go build ./cmd/mattermost Build (offline/air-gapped): go build -mod=vendor ./cmd/mattermost 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
263 lines
8.2 KiB
Go
263 lines
8.2 KiB
Go
package grammar
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/splitio/go-split-commons/v7/engine/grammar/datatypes"
|
|
"github.com/splitio/go-toolkit/v5/datastructures/set"
|
|
"github.com/splitio/go-toolkit/v5/logging"
|
|
)
|
|
|
|
// EqualToSemverMatcher struct to hold the semver to compare
|
|
type EqualToSemverMatcher struct {
|
|
Matcher
|
|
semver *datatypes.Semver
|
|
}
|
|
|
|
// Match will match if the comparisonValue is equal to the matchingValue
|
|
func (e *EqualToSemverMatcher) Match(key string, attributes map[string]interface{}, bucketingKey *string) bool {
|
|
if e.semver == nil {
|
|
return false
|
|
}
|
|
matchingKey, err := e.matchingKey(key, attributes)
|
|
if err != nil {
|
|
e.logger.Warning(fmt.Sprintf("EqualToSemverMatcher: %s", err.Error()))
|
|
return false
|
|
}
|
|
|
|
asString, ok := matchingKey.(string)
|
|
if !ok {
|
|
e.logger.Error("EqualToSemverMatcher: Error type-asserting string")
|
|
return false
|
|
}
|
|
|
|
semver, err := datatypes.BuildSemver(asString)
|
|
if err != nil {
|
|
e.logger.Error("EqualToSemverMatcher: Error parsing semver")
|
|
return false
|
|
}
|
|
|
|
result := semver.Version() == e.semver.Version()
|
|
e.logger.Debug(fmt.Sprintf("%s == %s | Result: %t", semver.Version(), e.semver.Version(), result))
|
|
return result
|
|
}
|
|
|
|
// NewEqualToSemverMatcher returns a pointer to a new instance of EqualToSemverMatcher
|
|
func NewEqualToSemverMatcher(cmpVal string, negate bool, attributeName *string, logger logging.LoggerInterface) *EqualToSemverMatcher {
|
|
semver, err := datatypes.BuildSemver(cmpVal)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("couldnt't build semver %s for EQUAL_TO_SEMVER matcher: %s", cmpVal, err.Error()))
|
|
}
|
|
return &EqualToSemverMatcher{
|
|
Matcher: Matcher{
|
|
negate: negate,
|
|
attributeName: attributeName,
|
|
},
|
|
semver: semver,
|
|
}
|
|
}
|
|
|
|
// GreaterThanOrEqualToSemverMatcher struct to hold the semver to compare
|
|
type GreaterThanOrEqualToSemverMatcher struct {
|
|
Matcher
|
|
semver *datatypes.Semver
|
|
}
|
|
|
|
// Match compares the semver of the key with the semver in the feature flag
|
|
func (g *GreaterThanOrEqualToSemverMatcher) Match(key string, attributes map[string]interface{}, bucketingKey *string) bool {
|
|
if g.semver == nil {
|
|
return false
|
|
}
|
|
matchingKey, err := g.matchingKey(key, attributes)
|
|
if err != nil {
|
|
g.logger.Warning(fmt.Sprintf("GreaterThanOrEqualToSemverMatcher: %s", err.Error()))
|
|
return false
|
|
}
|
|
|
|
asString, ok := matchingKey.(string)
|
|
if !ok {
|
|
g.logger.Error("GreaterThanOrEqualToSemverMatcher: Error type-asserting string")
|
|
return false
|
|
}
|
|
|
|
semver, err := datatypes.BuildSemver(asString)
|
|
if err != nil {
|
|
g.logger.Error("GreaterThanOrEqualToSemverMatcher: Error parsing semver")
|
|
return false
|
|
}
|
|
|
|
result := semver.Compare(*g.semver) >= 0
|
|
g.logger.Debug(fmt.Sprintf("%s >= %s | Result: %t", semver.Version(), g.semver.Version(), result))
|
|
return result
|
|
}
|
|
|
|
// NewGreaterThanOrEqualToSemverMatcher returns an instance of GreaterThanOrEqualToSemverMatcher
|
|
func NewGreaterThanOrEqualToSemverMatcher(negate bool, compareTo string, attributeName *string, logger logging.LoggerInterface) *GreaterThanOrEqualToSemverMatcher {
|
|
semver, err := datatypes.BuildSemver(compareTo)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("couldnt't build semver %s for GREATER_THAN_OR_EQUAL_TO_SEMVER matcher: %s", compareTo, err.Error()))
|
|
}
|
|
return &GreaterThanOrEqualToSemverMatcher{
|
|
Matcher: Matcher{
|
|
negate: negate,
|
|
attributeName: attributeName,
|
|
},
|
|
semver: semver,
|
|
}
|
|
}
|
|
|
|
// LessThanOrEqualToSemverMatcher struct to hold the semver to compare
|
|
type LessThanOrEqualToSemverMatcher struct {
|
|
Matcher
|
|
semver *datatypes.Semver
|
|
}
|
|
|
|
// Match will match if the comparisonValue is less or equal to the matchingValue
|
|
func (l *LessThanOrEqualToSemverMatcher) Match(key string, attributes map[string]interface{}, bucketingKey *string) bool {
|
|
if l.semver == nil {
|
|
return false
|
|
}
|
|
matchingKey, err := l.matchingKey(key, attributes)
|
|
if err != nil {
|
|
l.logger.Warning(fmt.Sprintf("LessThanOrEqualToSemverMatcher: %s", err.Error()))
|
|
return false
|
|
}
|
|
|
|
asString, ok := matchingKey.(string)
|
|
if !ok {
|
|
l.logger.Error("LessThanOrEqualToSemverMatcher: Error type-asserting string")
|
|
return false
|
|
}
|
|
|
|
semver, err := datatypes.BuildSemver(asString)
|
|
if err != nil {
|
|
l.logger.Error("LessThanOrEqualToSemverMatcher: Error parsing semver")
|
|
return false
|
|
}
|
|
|
|
result := semver.Compare(*l.semver) <= 0
|
|
l.logger.Debug(fmt.Sprintf("%s >= %s | Result: %t", semver.Version(), l.semver.Version(), result))
|
|
return result
|
|
}
|
|
|
|
// NewLessThanOrEqualToSemverMatcher returns a pointer to a new instance of LessThanOrEqualToSemverMatcher
|
|
func NewLessThanOrEqualToSemverMatcher(compareTo string, negate bool, attributeName *string, logger logging.LoggerInterface) *LessThanOrEqualToSemverMatcher {
|
|
semver, err := datatypes.BuildSemver(compareTo)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("couldnt't build semver %s for LESS_THAN_OR_EQUAL_TO_SEMVER matcher: %s", compareTo, err.Error()))
|
|
}
|
|
return &LessThanOrEqualToSemverMatcher{
|
|
Matcher: Matcher{
|
|
negate: negate,
|
|
attributeName: attributeName,
|
|
},
|
|
semver: semver,
|
|
}
|
|
}
|
|
|
|
// BetweenSemverMatcher struct to hold the semver to compare
|
|
type BetweenSemverMatcher struct {
|
|
Matcher
|
|
startSemver *datatypes.Semver
|
|
endSemver *datatypes.Semver
|
|
}
|
|
|
|
// Match will match if the comparisonValue is between to the matchingValue
|
|
func (b *BetweenSemverMatcher) Match(key string, attributes map[string]interface{}, bucketingKey *string) bool {
|
|
if b.startSemver == nil || b.endSemver == nil {
|
|
return false
|
|
}
|
|
matchingKey, err := b.matchingKey(key, attributes)
|
|
if err != nil {
|
|
b.logger.Warning(fmt.Sprintf("BetweenSemverMatcher: %s", err.Error()))
|
|
return false
|
|
}
|
|
|
|
asString, ok := matchingKey.(string)
|
|
if !ok {
|
|
b.logger.Error("BetweenSemverMatcher: Error type-asserting string")
|
|
return false
|
|
}
|
|
|
|
semver, err := datatypes.BuildSemver(asString)
|
|
if err != nil {
|
|
b.logger.Error("BetweenSemverMatcher: Error parsing semver")
|
|
return false
|
|
}
|
|
|
|
result := semver.Compare(*b.startSemver) >= 0 && semver.Compare(*b.endSemver) <= 0
|
|
b.logger.Debug(fmt.Sprintf("%s between %s and %s | Result: %t", semver.Version(), b.startSemver.Version(), b.endSemver.Version(), result))
|
|
return result
|
|
}
|
|
|
|
// NewBetweenSemverMatcher returns a pointer to a new instance of BetweenSemverMatcher
|
|
func NewBetweenSemverMatcher(startVal string, endVal string, negate bool, attributeName *string, logger logging.LoggerInterface) *BetweenSemverMatcher {
|
|
startSemver, err := datatypes.BuildSemver(startVal)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("couldnt't build semver %s for BETWEEN_SEMVER matcher, ignoring: %s", startVal, err.Error()))
|
|
}
|
|
endSemver, err := datatypes.BuildSemver(endVal)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("couldnt't build semver %s for BETWEEN_SEMVER matcher, ignoring: %s", endVal, err.Error()))
|
|
}
|
|
return &BetweenSemverMatcher{
|
|
Matcher: Matcher{
|
|
negate: negate,
|
|
attributeName: attributeName,
|
|
},
|
|
startSemver: startSemver,
|
|
endSemver: endSemver,
|
|
}
|
|
}
|
|
|
|
// InListSemverMatcher struct to hold the semver to compare
|
|
type InListSemverMatcher struct {
|
|
Matcher
|
|
semvers *set.ThreadUnsafeSet
|
|
}
|
|
|
|
// Match will match if the comparisonValue is in list to the matchingValue
|
|
func (i *InListSemverMatcher) Match(key string, attributes map[string]interface{}, bucketingKey *string) bool {
|
|
if i.semvers.IsEmpty() {
|
|
return false
|
|
}
|
|
matchingKey, err := i.matchingKey(key, attributes)
|
|
if err != nil {
|
|
i.logger.Warning(fmt.Sprintf("InListSemverMatcher: %s", err.Error()))
|
|
return false
|
|
}
|
|
|
|
asString, ok := matchingKey.(string)
|
|
if !ok {
|
|
i.logger.Error("InListSemverMatcher: Error type-asserting string")
|
|
return false
|
|
}
|
|
|
|
semver, err := datatypes.BuildSemver(asString)
|
|
if err != nil {
|
|
i.logger.Error("InListSemverMatcher: Error parsing semver")
|
|
return false
|
|
}
|
|
return i.semvers.Has(semver.Version())
|
|
}
|
|
|
|
// NewInListSemverMatcher returns a pointer to a new instance of InListSemverMatcher
|
|
func NewInListSemverMatcher(setVersions []string, negate bool, attributeName *string, logger logging.LoggerInterface) *InListSemverMatcher {
|
|
semvers := set.NewSet()
|
|
for _, version := range setVersions {
|
|
semver, err := datatypes.BuildSemver(version)
|
|
if err == nil {
|
|
semvers.Add(semver.Version())
|
|
} else {
|
|
logger.Error(fmt.Sprintf("couldnt't build semver %s for IN_LIST_SEMVER matcher, ignoring: %s", version, err.Error()))
|
|
}
|
|
}
|
|
return &InListSemverMatcher{
|
|
Matcher: Matcher{
|
|
negate: negate,
|
|
attributeName: attributeName,
|
|
},
|
|
semvers: semvers,
|
|
}
|
|
}
|