mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-06 16:16:26 +00:00
138 lines
3.3 KiB
Go
138 lines
3.3 KiB
Go
package licensing
|
|
|
|
import "log"
|
|
|
|
// Evaluator is the canonical entitlement evaluator used by runtime surfaces.
|
|
type Evaluator struct {
|
|
source EntitlementSource
|
|
}
|
|
|
|
// NewEvaluator creates a new evaluator with the given source.
|
|
func NewEvaluator(source EntitlementSource) *Evaluator {
|
|
return &Evaluator{source: source}
|
|
}
|
|
|
|
// HasCapability checks if the given capability key is granted.
|
|
// It first checks the key directly, then tries resolving a legacy alias.
|
|
func (e *Evaluator) HasCapability(key string) bool {
|
|
if e == nil || e.source == nil {
|
|
return false
|
|
}
|
|
|
|
capabilities := e.source.Capabilities()
|
|
|
|
// Check the key directly first.
|
|
for _, cap := range capabilities {
|
|
if cap == key {
|
|
// Log deprecation warning if applicable.
|
|
if dep, ok := IsDeprecated(key); ok {
|
|
log.Printf("entitlements: deprecated capability %q used, replacement: %q (sunset: %s)",
|
|
key, dep.ReplacementKey, dep.SunsetAt.Format("2006-01-02"))
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Check alias resolution.
|
|
resolved := ResolveAlias(key)
|
|
if resolved != key {
|
|
for _, cap := range capabilities {
|
|
if cap == resolved {
|
|
log.Printf("entitlements: alias %q resolved to %q", key, resolved)
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// GetLimit returns the limit value for the given key and whether the limit exists.
|
|
func (e *Evaluator) GetLimit(key string) (int64, bool) {
|
|
if e == nil || e.source == nil {
|
|
return 0, false
|
|
}
|
|
|
|
limit, ok := e.source.Limits()[key]
|
|
return limit, ok
|
|
}
|
|
|
|
// CheckLimit evaluates observed value against the limit for the given key.
|
|
func (e *Evaluator) CheckLimit(key string, observed int64) LimitCheckResult {
|
|
limit, ok := e.GetLimit(key)
|
|
if !ok || limit <= 0 {
|
|
return LimitAllowed
|
|
}
|
|
|
|
if observed >= limit {
|
|
return LimitHardBlock
|
|
}
|
|
|
|
if observed*10 >= limit*9 {
|
|
return LimitSoftBlock
|
|
}
|
|
|
|
return LimitAllowed
|
|
}
|
|
|
|
// MeterEnabled checks if the given meter key is enabled.
|
|
func (e *Evaluator) MeterEnabled(key string) bool {
|
|
if e == nil || e.source == nil {
|
|
return false
|
|
}
|
|
|
|
for _, meter := range e.source.MetersEnabled() {
|
|
if meter == key {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// PlanVersion returns the current plan_version from the source.
|
|
func (e *Evaluator) PlanVersion() string {
|
|
if e == nil || e.source == nil {
|
|
return ""
|
|
}
|
|
return e.source.PlanVersion()
|
|
}
|
|
|
|
// SubscriptionState returns the current subscription state from the source.
|
|
func (e *Evaluator) SubscriptionState() SubscriptionState {
|
|
if e == nil || e.source == nil {
|
|
return SubStateActive
|
|
}
|
|
return e.source.SubscriptionState()
|
|
}
|
|
|
|
// TrialStartedAt returns the trial start timestamp (Unix seconds) when available.
|
|
func (e *Evaluator) TrialStartedAt() *int64 {
|
|
if e == nil || e.source == nil {
|
|
return nil
|
|
}
|
|
return cloneInt64Ptr(e.source.TrialStartedAt())
|
|
}
|
|
|
|
// TrialEndsAt returns the trial end timestamp (Unix seconds) when available.
|
|
func (e *Evaluator) TrialEndsAt() *int64 {
|
|
if e == nil || e.source == nil {
|
|
return nil
|
|
}
|
|
return cloneInt64Ptr(e.source.TrialEndsAt())
|
|
}
|
|
|
|
// OverflowGrantedAt returns the overflow grant timestamp (Unix seconds) when available.
|
|
func (e *Evaluator) OverflowGrantedAt() *int64 {
|
|
if e == nil || e.source == nil {
|
|
return nil
|
|
}
|
|
return cloneInt64Ptr(e.source.OverflowGrantedAt())
|
|
}
|
|
|
|
func cloneInt64Ptr(v *int64) *int64 {
|
|
if v == nil {
|
|
return nil
|
|
}
|
|
c := *v
|
|
return &c
|
|
}
|