@@ -38,11 +38,13 @@ func New(ctx context.Context, options *Options) (*API, error) {
38
38
AGPL : coderd .New (options .Options ),
39
39
Options : options ,
40
40
41
- activeUsers : codersdk.Feature {
42
- Entitlement : codersdk .EntitlementNotEntitled ,
43
- Enabled : false ,
41
+ entitlements : entitlements {
42
+ activeUsers : codersdk.Feature {
43
+ Entitlement : codersdk .EntitlementNotEntitled ,
44
+ Enabled : false ,
45
+ },
46
+ auditLogs : codersdk .EntitlementNotEntitled ,
44
47
},
45
- auditLogs : codersdk .EntitlementNotEntitled ,
46
48
cancelEntitlementsLoop : cancelFunc ,
47
49
}
48
50
oauthConfigs := & httpmw.OAuth2Configs {
@@ -52,7 +54,7 @@ func New(ctx context.Context, options *Options) (*API, error) {
52
54
apiKeyMiddleware := httpmw .ExtractAPIKey (options .Database , oauthConfigs , false )
53
55
54
56
api .AGPL .APIHandler .Group (func (r chi.Router ) {
55
- r .Get ("/entitlements" , api .entitlements )
57
+ r .Get ("/entitlements" , api .serveEntitlements )
56
58
r .Route ("/licenses" , func (r chi.Router ) {
57
59
r .Use (apiKeyMiddleware )
58
60
r .Post ("/" , api .postLicense )
@@ -83,10 +85,14 @@ type API struct {
83
85
* Options
84
86
85
87
cancelEntitlementsLoop func ()
86
- mutex sync.RWMutex
87
- hasLicense bool
88
- activeUsers codersdk.Feature
89
- auditLogs codersdk.Entitlement
88
+ entitlementsMu sync.RWMutex
89
+ entitlements entitlements
90
+ }
91
+
92
+ type entitlements struct {
93
+ hasLicense bool
94
+ activeUsers codersdk.Feature
95
+ auditLogs codersdk.Entitlement
90
96
}
91
97
92
98
func (api * API ) Close () error {
@@ -99,17 +105,19 @@ func (api *API) updateEntitlements(ctx context.Context) error {
99
105
if err != nil {
100
106
return err
101
107
}
102
- api .mutex .Lock ()
103
- defer api .mutex .Unlock ()
108
+ api .entitlementsMu .Lock ()
109
+ defer api .entitlementsMu .Unlock ()
104
110
now := time .Now ()
105
111
106
112
// Default all entitlements to be disabled.
107
- hasLicense := false
108
- activeUsers := codersdk.Feature {
109
- Enabled : false ,
110
- Entitlement : codersdk .EntitlementNotEntitled ,
113
+ entitlements := entitlements {
114
+ hasLicense : false ,
115
+ activeUsers : codersdk.Feature {
116
+ Enabled : false ,
117
+ Entitlement : codersdk .EntitlementNotEntitled ,
118
+ },
119
+ auditLogs : codersdk .EntitlementNotEntitled ,
111
120
}
112
- auditLogs := codersdk .EntitlementNotEntitled
113
121
114
122
// Here we loop through licenses to detect enabled features.
115
123
for _ , l := range licenses {
@@ -119,33 +127,35 @@ func (api *API) updateEntitlements(ctx context.Context) error {
119
127
slog .F ("id" , l .ID ), slog .Error (err ))
120
128
continue
121
129
}
122
- hasLicense = true
130
+ entitlements . hasLicense = true
123
131
entitlement := codersdk .EntitlementEntitled
124
132
if now .After (claims .LicenseExpires .Time ) {
125
133
// if the grace period were over, the validation fails, so if we are after
126
134
// LicenseExpires we must be in grace period.
127
135
entitlement = codersdk .EntitlementGracePeriod
128
136
}
129
137
if claims .Features .UserLimit > 0 {
130
- activeUsers .Enabled = true
131
- activeUsers .Entitlement = entitlement
138
+ entitlements .activeUsers = codersdk.Feature {
139
+ Enabled : true ,
140
+ Entitlement : entitlement ,
141
+ }
132
142
currentLimit := int64 (0 )
133
- if activeUsers .Limit != nil {
134
- currentLimit = * activeUsers .Limit
143
+ if entitlements . activeUsers .Limit != nil {
144
+ currentLimit = * entitlements . activeUsers .Limit
135
145
}
136
146
limit := max (currentLimit , claims .Features .UserLimit )
137
- activeUsers .Limit = & limit
147
+ entitlements . activeUsers .Limit = & limit
138
148
}
139
149
if claims .Features .AuditLog > 0 {
140
- auditLogs = entitlement
150
+ entitlements . auditLogs = entitlement
141
151
}
142
152
}
143
153
144
- if auditLogs != api .auditLogs {
154
+ if entitlements . auditLogs != api . entitlements .auditLogs {
145
155
auditor := agplaudit .NewNop ()
146
156
// A flag could be added to the options that would allow disabling
147
157
// enhanced audit logging here!
148
- if auditLogs == codersdk .EntitlementEntitled && api .AuditLogging {
158
+ if entitlements . auditLogs == codersdk .EntitlementEntitled && api .AuditLogging {
149
159
auditor = audit .NewAuditor (
150
160
audit .DefaultFilter ,
151
161
backends .NewPostgres (api .Database , true ),
@@ -155,27 +165,23 @@ func (api *API) updateEntitlements(ctx context.Context) error {
155
165
api .AGPL .Auditor .Store (& auditor )
156
166
}
157
167
158
- api .hasLicense = hasLicense
159
- api .activeUsers = activeUsers
160
- api .auditLogs = auditLogs
168
+ api .entitlements = entitlements
161
169
162
170
return nil
163
171
}
164
172
165
- func (api * API ) entitlements (rw http.ResponseWriter , r * http.Request ) {
166
- api .mutex .RLock ()
167
- hasLicense := api .hasLicense
168
- activeUsers := api .activeUsers
169
- auditLogs := api .auditLogs
170
- api .mutex .RUnlock ()
173
+ func (api * API ) serveEntitlements (rw http.ResponseWriter , r * http.Request ) {
174
+ api .entitlementsMu .RLock ()
175
+ entitlements := api .entitlements
176
+ api .entitlementsMu .RUnlock ()
171
177
172
178
resp := codersdk.Entitlements {
173
179
Features : make (map [string ]codersdk.Feature ),
174
180
Warnings : make ([]string , 0 ),
175
- HasLicense : hasLicense ,
181
+ HasLicense : entitlements . hasLicense ,
176
182
}
177
183
178
- if activeUsers .Limit != nil {
184
+ if entitlements . activeUsers .Limit != nil {
179
185
activeUserCount , err := api .Database .GetActiveUserCount (r .Context ())
180
186
if err != nil {
181
187
httpapi .Write (rw , http .StatusInternalServerError , codersdk.Response {
@@ -184,22 +190,22 @@ func (api *API) entitlements(rw http.ResponseWriter, r *http.Request) {
184
190
})
185
191
return
186
192
}
187
- activeUsers .Actual = & activeUserCount
188
- if activeUserCount > * activeUsers .Limit {
193
+ entitlements . activeUsers .Actual = & activeUserCount
194
+ if activeUserCount > * entitlements . activeUsers .Limit {
189
195
resp .Warnings = append (resp .Warnings ,
190
196
fmt .Sprintf (
191
197
"Your deployment has %d active users but is only licensed for %d." ,
192
- activeUserCount , * activeUsers .Limit ))
198
+ activeUserCount , * entitlements . activeUsers .Limit ))
193
199
}
194
200
}
195
- resp .Features [codersdk .FeatureUserLimit ] = activeUsers
201
+ resp .Features [codersdk .FeatureUserLimit ] = entitlements . activeUsers
196
202
197
203
// Audit logs
198
204
resp .Features [codersdk .FeatureAuditLog ] = codersdk.Feature {
199
- Entitlement : auditLogs ,
205
+ Entitlement : entitlements . auditLogs ,
200
206
Enabled : api .AuditLogging ,
201
207
}
202
- if auditLogs == codersdk .EntitlementGracePeriod && api .AuditLogging {
208
+ if entitlements . auditLogs == codersdk .EntitlementGracePeriod && api .AuditLogging {
203
209
resp .Warnings = append (resp .Warnings ,
204
210
"Audit logging is enabled but your license for this feature is expired." )
205
211
}
0 commit comments