Skip to content

Commit 83cd8f4

Browse files
committed
fixup! refactor: deduplicate / type license feature code
1 parent c2d044b commit 83cd8f4

File tree

4 files changed

+72
-124
lines changed

4 files changed

+72
-124
lines changed

codersdk/features.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const (
1616
)
1717

1818
// To add a new feature, modify this set of enums as well as the FeatureNames
19-
// array.
19+
// array below.
2020
type FeatureName string
2121

2222
const (
@@ -31,6 +31,19 @@ const (
3131
FeatureAppearance FeatureName = "appearance"
3232
)
3333

34+
// FeatureNames must be kept in-sync with the Feature enum above.
35+
var FeatureNames = []FeatureName{
36+
FeatureUserLimit,
37+
FeatureAuditLog,
38+
FeatureBrowserOnly,
39+
FeatureSCIM,
40+
FeatureTemplateRBAC,
41+
FeatureHighAvailability,
42+
FeatureMultipleGitAuth,
43+
FeatureExternalProvisionerDaemons,
44+
FeatureAppearance,
45+
}
46+
3447
// Humanize returns the feature name in a human-readable format.
3548
func (n FeatureName) Humanize() string {
3649
return strings.Title(strings.ReplaceAll(string(n), "_", " "))
@@ -48,18 +61,6 @@ func (n FeatureName) AlwaysEnable() bool {
4861
return m[n]
4962
}
5063

51-
var FeatureNames = []FeatureName{
52-
FeatureUserLimit,
53-
FeatureAuditLog,
54-
FeatureBrowserOnly,
55-
FeatureSCIM,
56-
FeatureTemplateRBAC,
57-
FeatureHighAvailability,
58-
FeatureMultipleGitAuth,
59-
FeatureExternalProvisionerDaemons,
60-
FeatureAppearance,
61-
}
62-
6364
type Feature struct {
6465
Entitlement Entitlement `json:"entitlement"`
6566
Enabled bool `json:"enabled"`

enterprise/coderd/coderdenttest/coderdenttest.go

Lines changed: 8 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,13 @@ func NewWithAPI(t *testing.T, options *Options) (*codersdk.Client, io.Closer, *c
9999
}
100100

101101
type LicenseOptions struct {
102-
AccountType string
103-
AccountID string
104-
Trial bool
105-
AllFeatures bool
106-
GraceAt time.Time
107-
ExpiresAt time.Time
108-
UserLimit int64
109-
AuditLog bool
110-
BrowserOnly bool
111-
SCIM bool
112-
TemplateRBAC bool
113-
HighAvailability bool
114-
MultipleGitAuth bool
115-
ExternalProvisionerDaemons bool
116-
ServiceBanners bool
102+
AccountType string
103+
AccountID string
104+
Trial bool
105+
AllFeatures bool
106+
GraceAt time.Time
107+
ExpiresAt time.Time
108+
Features license.Features
117109
}
118110

119111
// AddLicense generates a new license with the options provided and inserts it.
@@ -133,42 +125,6 @@ func GenerateLicense(t *testing.T, options LicenseOptions) string {
133125
if options.GraceAt.IsZero() {
134126
options.GraceAt = time.Now().Add(time.Hour)
135127
}
136-
var auditLog int64
137-
if options.AuditLog {
138-
auditLog = 1
139-
}
140-
var browserOnly int64
141-
if options.BrowserOnly {
142-
browserOnly = 1
143-
}
144-
var scim int64
145-
if options.SCIM {
146-
scim = 1
147-
}
148-
highAvailability := int64(0)
149-
if options.HighAvailability {
150-
highAvailability = 1
151-
}
152-
153-
rbacEnabled := int64(0)
154-
if options.TemplateRBAC {
155-
rbacEnabled = 1
156-
}
157-
158-
multipleGitAuth := int64(0)
159-
if options.MultipleGitAuth {
160-
multipleGitAuth = 1
161-
}
162-
163-
externalProvisionerDaemons := int64(0)
164-
if options.ExternalProvisionerDaemons {
165-
externalProvisionerDaemons = 1
166-
}
167-
168-
serviceBanners := int64(0)
169-
if options.ServiceBanners {
170-
serviceBanners = 1
171-
}
172128

173129
c := &license.Claims{
174130
RegisteredClaims: jwt.RegisteredClaims{
@@ -183,17 +139,7 @@ func GenerateLicense(t *testing.T, options LicenseOptions) string {
183139
Trial: options.Trial,
184140
Version: license.CurrentVersion,
185141
AllFeatures: options.AllFeatures,
186-
Features: license.Features{
187-
UserLimit: options.UserLimit,
188-
AuditLog: auditLog,
189-
BrowserOnly: browserOnly,
190-
SCIM: scim,
191-
HighAvailability: highAvailability,
192-
TemplateRBAC: rbacEnabled,
193-
MultipleGitAuth: multipleGitAuth,
194-
ExternalProvisionerDaemons: externalProvisionerDaemons,
195-
Appearance: serviceBanners,
196-
},
142+
Features: options.Features,
197143
}
198144
tok := jwt.NewWithClaims(jwt.SigningMethodEdDSA, c)
199145
tok.Header[license.HeaderKeyID] = testKeyID

enterprise/coderd/license/license.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ func Entitlements(
6868
entitlement = codersdk.EntitlementGracePeriod
6969
}
7070
for featureName, featureValue := range claims.Features {
71+
// Can this be negative?
72+
if featureValue <= 0 {
73+
continue
74+
}
75+
7176
switch featureName {
7277
// User limit has special treatment as our only non-boolean feature.
7378
case codersdk.FeatureUserLimit:
@@ -83,11 +88,9 @@ func Entitlements(
8388
Actual: &activeUserCount,
8489
}
8590
default:
86-
if featureValue > 0 {
87-
entitlements.Features[featureName] = codersdk.Feature{
88-
Entitlement: entitlement,
89-
Enabled: enablements[featureName] || featureName.AlwaysEnable(),
90-
}
91+
entitlements.Features[featureName] = codersdk.Feature{
92+
Entitlement: entitlement,
93+
Enabled: enablements[featureName] || featureName.AlwaysEnable(),
9194
}
9295
}
9396
}

enterprise/coderd/license/license_test.go

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,13 @@ func TestEntitlements(t *testing.T) {
5858
db := databasefake.New()
5959
db.InsertLicense(context.Background(), database.InsertLicenseParams{
6060
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
61-
UserLimit: 100,
62-
AuditLog: true,
63-
BrowserOnly: true,
64-
SCIM: true,
65-
HighAvailability: true,
66-
TemplateRBAC: true,
67-
MultipleGitAuth: true,
68-
ExternalProvisionerDaemons: true,
69-
ServiceBanners: true,
61+
Features: func() license.Features {
62+
f := make(license.Features)
63+
for _, name := range codersdk.FeatureNames {
64+
f[name] = 1
65+
}
66+
return f
67+
}(),
7068
}),
7169
Exp: time.Now().Add(time.Hour),
7270
})
@@ -83,37 +81,23 @@ func TestEntitlements(t *testing.T) {
8381
db := databasefake.New()
8482
db.InsertLicense(context.Background(), database.InsertLicenseParams{
8583
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
86-
UserLimit: 100,
87-
AuditLog: true,
88-
BrowserOnly: true,
89-
SCIM: true,
90-
HighAvailability: true,
91-
TemplateRBAC: true,
92-
ExternalProvisionerDaemons: true,
93-
ServiceBanners: true,
94-
GraceAt: time.Now().Add(-time.Hour),
95-
ExpiresAt: time.Now().Add(time.Hour),
84+
Features: license.Features{
85+
codersdk.FeatureUserLimit: 100,
86+
},
87+
88+
GraceAt: time.Now().Add(-time.Hour),
89+
ExpiresAt: time.Now().Add(time.Hour),
9690
}),
9791
Exp: time.Now().Add(time.Hour),
9892
})
9993
entitlements, err := license.Entitlements(context.Background(), db, slog.Logger{}, 1, 1, coderdenttest.Keys, all)
10094
require.NoError(t, err)
10195
require.True(t, entitlements.HasLicense)
10296
require.False(t, entitlements.Trial)
103-
for _, featureName := range codersdk.FeatureNames {
104-
if featureName == codersdk.FeatureUserLimit {
105-
continue
106-
}
107-
if featureName == codersdk.FeatureHighAvailability {
108-
continue
109-
}
110-
if featureName == codersdk.FeatureMultipleGitAuth {
111-
continue
112-
}
113-
niceName := featureName.Humanize()
114-
require.Equal(t, codersdk.EntitlementGracePeriod, entitlements.Features[featureName].Entitlement)
115-
require.Contains(t, entitlements.Warnings, fmt.Sprintf("%s is enabled but your license for this feature is expired.", niceName))
116-
}
97+
98+
require.Equal(t, codersdk.EntitlementGracePeriod, entitlements.Features[codersdk.FeatureUserLimit].Entitlement)
99+
require.Contains(t, entitlements.Warnings, fmt.Sprintf("%s is enabled but your license for this feature is expired.", codersdk.FeatureUserLimit.Humanize()))
100+
117101
})
118102
t.Run("SingleLicenseNotEntitled", func(t *testing.T) {
119103
t.Parallel()
@@ -154,7 +138,9 @@ func TestEntitlements(t *testing.T) {
154138
})
155139
db.InsertLicense(context.Background(), database.InsertLicenseParams{
156140
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
157-
UserLimit: 1,
141+
Features: license.Features{
142+
codersdk.FeatureUserLimit: 1,
143+
},
158144
}),
159145
Exp: time.Now().Add(time.Hour),
160146
})
@@ -170,13 +156,17 @@ func TestEntitlements(t *testing.T) {
170156
db.InsertUser(context.Background(), database.InsertUserParams{})
171157
db.InsertLicense(context.Background(), database.InsertLicenseParams{
172158
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
173-
UserLimit: 10,
159+
Features: license.Features{
160+
codersdk.FeatureUserLimit: 10,
161+
},
174162
}),
175163
Exp: time.Now().Add(time.Hour),
176164
})
177165
db.InsertLicense(context.Background(), database.InsertLicenseParams{
178166
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
179-
UserLimit: 1,
167+
Features: license.Features{
168+
codersdk.FeatureUserLimit: 1,
169+
},
180170
}),
181171
Exp: time.Now().Add(time.Hour),
182172
})
@@ -247,7 +237,9 @@ func TestEntitlements(t *testing.T) {
247237
db.InsertLicense(context.Background(), database.InsertLicenseParams{
248238
Exp: time.Now().Add(time.Hour),
249239
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
250-
AuditLog: true,
240+
Features: license.Features{
241+
codersdk.FeatureAuditLog: 1,
242+
},
251243
}),
252244
})
253245
entitlements, err := license.Entitlements(context.Background(), db, slog.Logger{}, 2, 1, coderdenttest.Keys, map[codersdk.FeatureName]bool{
@@ -264,9 +256,11 @@ func TestEntitlements(t *testing.T) {
264256
db := databasefake.New()
265257
db.InsertLicense(context.Background(), database.InsertLicenseParams{
266258
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
267-
HighAvailability: true,
268-
GraceAt: time.Now().Add(-time.Hour),
269-
ExpiresAt: time.Now().Add(time.Hour),
259+
Features: license.Features{
260+
codersdk.FeatureHighAvailability: 1,
261+
},
262+
GraceAt: time.Now().Add(-time.Hour),
263+
ExpiresAt: time.Now().Add(time.Hour),
270264
}),
271265
Exp: time.Now().Add(time.Hour),
272266
})
@@ -295,7 +289,9 @@ func TestEntitlements(t *testing.T) {
295289
db.InsertLicense(context.Background(), database.InsertLicenseParams{
296290
Exp: time.Now().Add(time.Hour),
297291
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
298-
AuditLog: true,
292+
Features: license.Features{
293+
codersdk.FeatureAuditLog: 1,
294+
},
299295
}),
300296
})
301297
entitlements, err := license.Entitlements(context.Background(), db, slog.Logger{}, 1, 2, coderdenttest.Keys, map[codersdk.FeatureName]bool{
@@ -312,9 +308,11 @@ func TestEntitlements(t *testing.T) {
312308
db := databasefake.New()
313309
db.InsertLicense(context.Background(), database.InsertLicenseParams{
314310
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
315-
MultipleGitAuth: true,
316-
GraceAt: time.Now().Add(-time.Hour),
317-
ExpiresAt: time.Now().Add(time.Hour),
311+
GraceAt: time.Now().Add(-time.Hour),
312+
ExpiresAt: time.Now().Add(time.Hour),
313+
Features: license.Features{
314+
codersdk.FeatureMultipleGitAuth: 1,
315+
},
318316
}),
319317
Exp: time.Now().Add(time.Hour),
320318
})

0 commit comments

Comments
 (0)