Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc3fe251

Browse files
rodrimaiamtojek
andauthored
feat: add license expiration warning (#7264)
* wip: add expiration warning* Use GraceAt* show expiration warning for trial accounts* fix test* only show license banner for users with deployment permission---------Co-authored-by: Marcin Tojek <marcin@coder.com>
1 parent3eb7f06 commitc3fe251

File tree

4 files changed

+143
-3
lines changed

4 files changed

+143
-3
lines changed

‎enterprise/coderd/coderd_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func TestEntitlements(t *testing.T) {
5555
codersdk.FeatureAdvancedTemplateScheduling:1,
5656
codersdk.FeatureWorkspaceProxy:1,
5757
},
58+
GraceAt:time.Now().Add(59*24*time.Hour),
5859
})
5960
res,err:=client.Entitlements(context.Background())
6061
require.NoError(t,err)

‎enterprise/coderd/license/license.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto/ed25519"
66
"fmt"
7+
"math"
78
"time"
89

910
"github.com/golang-jwt/jwt/v4"
@@ -70,6 +71,23 @@ func Entitlements(
7071
// LicenseExpires we must be in grace period.
7172
entitlement=codersdk.EntitlementGracePeriod
7273
}
74+
75+
// Add warning if license is expiring soon
76+
daysToExpire:=int(math.Ceil(claims.LicenseExpires.Sub(now).Hours()/24))
77+
isTrial:=entitlements.Trial
78+
showWarningDays:=30
79+
ifisTrial {
80+
showWarningDays=7
81+
}
82+
isExpiringSoon:=daysToExpire>0&&daysToExpire<showWarningDays
83+
ifisExpiringSoon {
84+
day:="day"
85+
ifdaysToExpire>1 {
86+
day="days"
87+
}
88+
entitlements.Warnings=append(entitlements.Warnings,fmt.Sprintf("Your license expires in %d %s.",daysToExpire,day))
89+
}
90+
7391
forfeatureName,featureValue:=rangeclaims.Features {
7492
// Can this be negative?
7593
iffeatureValue<=0 {

‎enterprise/coderd/license/license_test.go

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,123 @@ func TestEntitlements(t *testing.T) {
102102
fmt.Sprintf("%s is enabled but your license for this feature is expired.",codersdk.FeatureAuditLog.Humanize()),
103103
)
104104
})
105+
t.Run("Expiration warning",func(t*testing.T) {
106+
t.Parallel()
107+
db:=dbfake.New()
108+
db.InsertLicense(context.Background(), database.InsertLicenseParams{
109+
JWT:coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
110+
Features: license.Features{
111+
codersdk.FeatureUserLimit:100,
112+
codersdk.FeatureAuditLog:1,
113+
},
114+
115+
GraceAt:time.Now().AddDate(0,0,2),
116+
ExpiresAt:time.Now().AddDate(0,0,5),
117+
}),
118+
Exp:time.Now().AddDate(0,0,5),
119+
})
120+
121+
entitlements,err:=license.Entitlements(context.Background(),db, slog.Logger{},1,1,coderdenttest.Keys,all)
122+
123+
require.NoError(t,err)
124+
require.True(t,entitlements.HasLicense)
125+
require.False(t,entitlements.Trial)
126+
127+
require.Equal(t,codersdk.EntitlementEntitled,entitlements.Features[codersdk.FeatureAuditLog].Entitlement)
128+
require.Contains(
129+
t,entitlements.Warnings,
130+
"Your license expires in 2 days.",
131+
)
132+
})
133+
134+
t.Run("Expiration warning for license expiring in 1 day",func(t*testing.T) {
135+
t.Parallel()
136+
db:=dbfake.New()
137+
db.InsertLicense(context.Background(), database.InsertLicenseParams{
138+
JWT:coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
139+
Features: license.Features{
140+
codersdk.FeatureUserLimit:100,
141+
codersdk.FeatureAuditLog:1,
142+
},
143+
144+
GraceAt:time.Now().AddDate(0,0,1),
145+
ExpiresAt:time.Now().AddDate(0,0,5),
146+
}),
147+
Exp:time.Now().AddDate(0,0,5),
148+
})
149+
150+
entitlements,err:=license.Entitlements(context.Background(),db, slog.Logger{},1,1,coderdenttest.Keys,all)
151+
152+
require.NoError(t,err)
153+
require.True(t,entitlements.HasLicense)
154+
require.False(t,entitlements.Trial)
155+
156+
require.Equal(t,codersdk.EntitlementEntitled,entitlements.Features[codersdk.FeatureAuditLog].Entitlement)
157+
require.Contains(
158+
t,entitlements.Warnings,
159+
"Your license expires in 1 day.",
160+
)
161+
})
162+
163+
t.Run("Expiration warning for trials",func(t*testing.T) {
164+
t.Parallel()
165+
db:=dbfake.New()
166+
db.InsertLicense(context.Background(), database.InsertLicenseParams{
167+
JWT:coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
168+
Features: license.Features{
169+
codersdk.FeatureUserLimit:100,
170+
codersdk.FeatureAuditLog:1,
171+
},
172+
173+
Trial:true,
174+
GraceAt:time.Now().AddDate(0,0,8),
175+
ExpiresAt:time.Now().AddDate(0,0,5),
176+
}),
177+
Exp:time.Now().AddDate(0,0,5),
178+
})
179+
180+
entitlements,err:=license.Entitlements(context.Background(),db, slog.Logger{},1,1,coderdenttest.Keys,all)
181+
182+
require.NoError(t,err)
183+
require.True(t,entitlements.HasLicense)
184+
require.True(t,entitlements.Trial)
185+
186+
require.Equal(t,codersdk.EntitlementEntitled,entitlements.Features[codersdk.FeatureAuditLog].Entitlement)
187+
require.NotContains(// it should not contain a warning since it is a trial license
188+
t,entitlements.Warnings,
189+
"Your license expires in 8 days.",
190+
)
191+
})
192+
193+
t.Run("Expiration warning for non trials",func(t*testing.T) {
194+
t.Parallel()
195+
db:=dbfake.New()
196+
db.InsertLicense(context.Background(), database.InsertLicenseParams{
197+
JWT:coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
198+
Features: license.Features{
199+
codersdk.FeatureUserLimit:100,
200+
codersdk.FeatureAuditLog:1,
201+
},
202+
203+
GraceAt:time.Now().AddDate(0,0,30),
204+
ExpiresAt:time.Now().AddDate(0,0,5),
205+
}),
206+
Exp:time.Now().AddDate(0,0,5),
207+
})
208+
209+
entitlements,err:=license.Entitlements(context.Background(),db, slog.Logger{},1,1,coderdenttest.Keys,all)
210+
211+
require.NoError(t,err)
212+
require.True(t,entitlements.HasLicense)
213+
require.False(t,entitlements.Trial)
214+
215+
require.Equal(t,codersdk.EntitlementEntitled,entitlements.Features[codersdk.FeatureAuditLog].Entitlement)
216+
require.NotContains(// it should not contain a warning since it is a trial license
217+
t,entitlements.Warnings,
218+
"Your license expires in 30 days.",
219+
)
220+
})
221+
105222
t.Run("SingleLicenseNotEntitled",func(t*testing.T) {
106223
t.Parallel()
107224
db:=dbfake.New()
@@ -164,16 +281,18 @@ func TestEntitlements(t *testing.T) {
164281
Features: license.Features{
165282
codersdk.FeatureUserLimit:10,
166283
},
284+
GraceAt:time.Now().Add(59*24*time.Hour),
167285
}),
168-
Exp:time.Now().Add(time.Hour),
286+
Exp:time.Now().Add(60*24*time.Hour),
169287
})
170288
db.InsertLicense(context.Background(), database.InsertLicenseParams{
171289
JWT:coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
172290
Features: license.Features{
173291
codersdk.FeatureUserLimit:1,
174292
},
293+
GraceAt:time.Now().Add(59*24*time.Hour),
175294
}),
176-
Exp:time.Now().Add(time.Hour),
295+
Exp:time.Now().Add(60*24*time.Hour),
177296
})
178297
entitlements,err:=license.Entitlements(context.Background(),db, slog.Logger{},1,1,coderdenttest.Keys,empty)
179298
require.NoError(t,err)

‎site/src/components/Dashboard/DashboardLayout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ export const DashboardLayout: FC = () => {
2525
})
2626
const{error:updateCheckError, updateCheck}=updateCheckState.context
2727

28+
constcanViewDeployment=Boolean(permissions.viewDeploymentValues)
29+
2830
return(
2931
<DashboardProvider>
3032
<ServiceBanner/>
31-
<LicenseBanner/>
33+
{canViewDeployment&&<LicenseBanner/>}
3234

3335
<divclassName={styles.site}>
3436
<Navbar/>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp