Skip to content

Commit e9077f3

Browse files
authored
fix: use AlwaysEnable for licenses with all features (coder#9808)
* fix: use AlwaysEnable for licenses with all features Signed-off-by: Spike Curtis <spike@coder.com> * use dbtime.Now() intead of time.Now() Signed-off-by: Spike Curtis <spike@coder.com> --------- Signed-off-by: Spike Curtis <spike@coder.com>
1 parent 94a0612 commit e9077f3

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

enterprise/coderd/license/license.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ func Entitlements(
6161
}
6262

6363
allFeatures := false
64+
allFeaturesEntitlement := codersdk.EntitlementNotEntitled
6465

6566
// Here we loop through licenses to detect enabled features.
6667
for _, l := range licenses {
@@ -117,14 +118,15 @@ func Entitlements(
117118
}
118119
default:
119120
entitlements.Features[featureName] = codersdk.Feature{
120-
Entitlement: entitlement,
121+
Entitlement: maxEntitlement(entitlements.Features[featureName].Entitlement, entitlement),
121122
Enabled: enablements[featureName] || featureName.AlwaysEnable(),
122123
}
123124
}
124125
}
125126

126127
if claims.AllFeatures {
127128
allFeatures = true
129+
allFeaturesEntitlement = maxEntitlement(allFeaturesEntitlement, entitlement)
128130
}
129131
entitlements.RequireTelemetry = entitlements.RequireTelemetry || claims.RequireTelemetry
130132
}
@@ -136,7 +138,8 @@ func Entitlements(
136138
continue
137139
}
138140
feature := entitlements.Features[featureName]
139-
feature.Entitlement = codersdk.EntitlementEntitled
141+
feature.Entitlement = maxEntitlement(feature.Entitlement, allFeaturesEntitlement)
142+
feature.Enabled = enablements[featureName] || featureName.AlwaysEnable()
140143
entitlements.Features[featureName] = feature
141144
}
142145
}
@@ -324,3 +327,14 @@ func keyFunc(keys map[string]ed25519.PublicKey) func(*jwt.Token) (interface{}, e
324327
return k, nil
325328
}
326329
}
330+
331+
// maxEntitlement is the "greater" entitlement between the given values
332+
func maxEntitlement(e1, e2 codersdk.Entitlement) codersdk.Entitlement {
333+
if e1 == codersdk.EntitlementEntitled || e2 == codersdk.EntitlementEntitled {
334+
return codersdk.EntitlementEntitled
335+
}
336+
if e1 == codersdk.EntitlementGracePeriod || e2 == codersdk.EntitlementGracePeriod {
337+
return codersdk.EntitlementGracePeriod
338+
}
339+
return codersdk.EntitlementNotEntitled
340+
}

enterprise/coderd/license/license_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,53 @@ func TestEntitlements(t *testing.T) {
378378
}
379379
})
380380

381+
t.Run("AllFeaturesAlwaysEnable", func(t *testing.T) {
382+
t.Parallel()
383+
db := dbfake.New()
384+
db.InsertLicense(context.Background(), database.InsertLicenseParams{
385+
Exp: dbtime.Now().Add(time.Hour),
386+
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
387+
AllFeatures: true,
388+
}),
389+
})
390+
entitlements, err := license.Entitlements(context.Background(), db, slog.Logger{}, 1, 1, coderdenttest.Keys, empty)
391+
require.NoError(t, err)
392+
require.True(t, entitlements.HasLicense)
393+
require.False(t, entitlements.Trial)
394+
for _, featureName := range codersdk.FeatureNames {
395+
if featureName == codersdk.FeatureUserLimit {
396+
continue
397+
}
398+
feature := entitlements.Features[featureName]
399+
require.Equal(t, featureName.AlwaysEnable(), feature.Enabled)
400+
require.Equal(t, codersdk.EntitlementEntitled, feature.Entitlement)
401+
}
402+
})
403+
404+
t.Run("AllFeaturesGrace", func(t *testing.T) {
405+
t.Parallel()
406+
db := dbfake.New()
407+
db.InsertLicense(context.Background(), database.InsertLicenseParams{
408+
Exp: dbtime.Now().Add(time.Hour),
409+
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
410+
AllFeatures: true,
411+
GraceAt: dbtime.Now().Add(-time.Hour),
412+
ExpiresAt: dbtime.Now().Add(time.Hour),
413+
}),
414+
})
415+
entitlements, err := license.Entitlements(context.Background(), db, slog.Logger{}, 1, 1, coderdenttest.Keys, all)
416+
require.NoError(t, err)
417+
require.True(t, entitlements.HasLicense)
418+
require.False(t, entitlements.Trial)
419+
for _, featureName := range codersdk.FeatureNames {
420+
if featureName == codersdk.FeatureUserLimit {
421+
continue
422+
}
423+
require.True(t, entitlements.Features[featureName].Enabled)
424+
require.Equal(t, codersdk.EntitlementGracePeriod, entitlements.Features[featureName].Entitlement)
425+
}
426+
})
427+
381428
t.Run("MultipleReplicasNoLicense", func(t *testing.T) {
382429
t.Parallel()
383430
db := dbfake.New()

0 commit comments

Comments
 (0)