diff --git a/cli/cliui/table.go b/cli/cliui/table.go index cd26c43182..cd417641f6 100644 --- a/cli/cliui/table.go +++ b/cli/cliui/table.go @@ -158,6 +158,10 @@ func DisplayTable(out any, sort string, filterColumns []string) (string, error) if val != nil { v = val.Format(time.RFC3339) } + case *int64: + if val != nil { + v = *val + } case fmt.Stringer: if val != nil { v = val.String() diff --git a/enterprise/coderd/license/license.go b/enterprise/coderd/license/license.go index 213d5dafb8..55a62eee17 100644 --- a/enterprise/coderd/license/license.go +++ b/enterprise/coderd/license/license.go @@ -60,17 +60,17 @@ func Entitlements(ctx context.Context, db database.Store, logger slog.Logger, ke entitlement = codersdk.EntitlementGracePeriod } if claims.Features.UserLimit > 0 { + limit := claims.Features.UserLimit + priorLimit := entitlements.Features[codersdk.FeatureUserLimit] + if priorLimit.Limit != nil && *priorLimit.Limit > limit { + limit = *priorLimit.Limit + } entitlements.Features[codersdk.FeatureUserLimit] = codersdk.Feature{ Enabled: true, Entitlement: entitlement, - Limit: &claims.Features.UserLimit, + Limit: &limit, Actual: &activeUserCount, } - if activeUserCount > claims.Features.UserLimit { - entitlements.Warnings = append(entitlements.Warnings, fmt.Sprintf( - "Your deployment has %d active users but is only licensed for %d.", - activeUserCount, claims.Features.UserLimit)) - } } if claims.Features.AuditLog > 0 { entitlements.Features[codersdk.FeatureAuditLog] = codersdk.Feature{ @@ -114,6 +114,13 @@ func Entitlements(ctx context.Context, db database.Store, logger slog.Logger, ke } if entitlements.HasLicense { + userLimit := entitlements.Features[codersdk.FeatureUserLimit].Limit + if userLimit != nil && activeUserCount > *userLimit { + entitlements.Warnings = append(entitlements.Warnings, fmt.Sprintf( + "Your deployment has %d active users but is only licensed for %d.", + activeUserCount, *userLimit)) + } + for _, featureName := range codersdk.FeatureNames { // The user limit has it's own warnings! if featureName == codersdk.FeatureUserLimit { diff --git a/enterprise/coderd/license/license_test.go b/enterprise/coderd/license/license_test.go index 04141718e6..85958fbf4f 100644 --- a/enterprise/coderd/license/license_test.go +++ b/enterprise/coderd/license/license_test.go @@ -141,6 +141,28 @@ func TestEntitlements(t *testing.T) { require.True(t, entitlements.HasLicense) require.Contains(t, entitlements.Warnings, "Your deployment has 2 active users but is only licensed for 1.") }) + t.Run("MaximizeUserLimit", func(t *testing.T) { + t.Parallel() + db := databasefake.New() + db.InsertUser(context.Background(), database.InsertUserParams{}) + db.InsertUser(context.Background(), database.InsertUserParams{}) + db.InsertLicense(context.Background(), database.InsertLicenseParams{ + JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{ + UserLimit: 10, + }), + Exp: time.Now().Add(time.Hour), + }) + db.InsertLicense(context.Background(), database.InsertLicenseParams{ + JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{ + UserLimit: 1, + }), + Exp: time.Now().Add(time.Hour), + }) + entitlements, err := license.Entitlements(context.Background(), db, slog.Logger{}, coderdenttest.Keys, map[string]bool{}) + require.NoError(t, err) + require.True(t, entitlements.HasLicense) + require.Empty(t, entitlements.Warnings) + }) t.Run("MultipleLicenseEnabled", func(t *testing.T) { t.Parallel() db := databasefake.New()