7
7
8
8
"github.com/stretchr/testify/require"
9
9
10
- "github.com/coder/coder/v2/coderd/cel"
11
10
"github.com/coder/coder/v2/coderd/coderdtest"
11
+ "github.com/coder/coder/v2/coderd/expr"
12
12
"github.com/coder/coder/v2/codersdk"
13
13
"github.com/coder/serpent"
14
14
)
@@ -39,9 +39,9 @@ func createClientWithRoleTokenLifetimes(t *testing.T, roleTokenLifetimeExpressio
39
39
t .Logf ("MaximumTokenDuration: %v" ,api .DeploymentValues .Sessions .MaximumTokenDuration .Value ())
40
40
// Check if we have a compiled program
41
41
if program != nil {
42
- t .Logf ("CEL expression compiled successfully" )
42
+ t .Logf ("expr expression compiled successfully" )
43
43
}else {
44
- t .Logf ("NoCEL expression configured" )
44
+ t .Logf ("Noexpr expression configured" )
45
45
}
46
46
47
47
// Create the first user
@@ -53,29 +53,29 @@ func createClientWithRoleTokenLifetimes(t *testing.T, roleTokenLifetimeExpressio
53
53
func TestRoleBasedTokenLifetimes_Integration (t * testing.T ) {
54
54
t .Parallel ()
55
55
56
- t .Run ("ServerStartupWithValidCELExpressions " ,func (t * testing.T ) {
56
+ t .Run ("ServerStartupWithValidExprExpressions " ,func (t * testing.T ) {
57
57
t .Parallel ()
58
58
59
- // Test server starts successfully with validCEL expressions
59
+ // Test server starts successfully with validexpr expressions
60
60
testCases := []struct {
61
- name string
62
- celExpression string
61
+ name string
62
+ exprExpression string
63
63
}{
64
64
{
65
- name :"ValidRoleBasedExpression" ,
66
- celExpression :`subject.roles.exists(r, r.name == "owner") ? duration("168h") : subject.roles.exists(r, r.name == "user-admin") ? duration("72h") : duration("24h")` ,
65
+ name :"ValidRoleBasedExpression" ,
66
+ exprExpression :`any( subject.Roles, .Name == "owner") ? duration("168h") :any( subject.Roles, .Name == "user-admin") ? duration("72h") : duration("24h")` ,
67
67
},
68
68
{
69
- name :"ValidSimpleExpression" ,
70
- celExpression :`duration(globalMaxDuration)` ,
69
+ name :"ValidSimpleExpression" ,
70
+ exprExpression :`duration(globalMaxDuration)` ,
71
71
},
72
72
{
73
- name :"EmptyExpression" ,
74
- celExpression :`` ,
73
+ name :"EmptyExpression" ,
74
+ exprExpression :`` ,
75
75
},
76
76
{
77
- name :"EmailBasedExpression" ,
78
- celExpression :`subject.email. endsWith( "@company.com") ? duration("720h") : duration("24h")` ,
77
+ name :"EmailBasedExpression" ,
78
+ exprExpression :`subject.Email endsWith "@company.com") ? duration("720h") : duration("24h")` ,
79
79
},
80
80
}
81
81
@@ -85,7 +85,7 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
85
85
t .Parallel ()
86
86
87
87
dv := coderdtest .DeploymentValues (t )
88
- dv .Sessions .MaximumTokenDurationExpression = serpent .String (tc .celExpression )
88
+ dv .Sessions .MaximumTokenDurationExpression = serpent .String (tc .exprExpression )
89
89
90
90
// Should create successfully
91
91
client := coderdtest .New (t ,& coderdtest.Options {
@@ -96,21 +96,21 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
96
96
}
97
97
})
98
98
99
- t .Run ("InvalidCELExpressions " ,func (t * testing.T ) {
99
+ t .Run ("InvalidExprExpressions " ,func (t * testing.T ) {
100
100
t .Parallel ()
101
101
102
- // Test that invalidCEL expressions fail validation
102
+ // Test that invalidexpr expressions fail validation
103
103
testCases := []struct {
104
- name string
105
- celExpression string
104
+ name string
105
+ exprExpression string
106
106
}{
107
107
{
108
- name :"InvalidCELSyntax " ,
109
- celExpression :`subject.roles.exists(r, r.name == "owner" ? duration("168h")` ,// Missing closing parenthesis
108
+ name :"InvalidExprSyntax " ,
109
+ exprExpression :`any( subject.Roles, .Name == "owner" ? duration("168h")` ,// Missing closing parenthesis
110
110
},
111
111
{
112
- name :"UndefinedVariable" ,
113
- celExpression :`unknownVariable ? duration("720h") : duration("168h")` ,
112
+ name :"UndefinedVariable" ,
113
+ exprExpression :`unknownVariable ? duration("720h") : duration("168h")` ,
114
114
},
115
115
}
116
116
@@ -119,17 +119,14 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
119
119
t .Run (tc .name ,func (t * testing.T ) {
120
120
t .Parallel ()
121
121
122
- // For invalid CEL expressions, try to create the environment and compile
123
- env ,err := cel .NewTokenLifetimeEnvironment (cel.EnvironmentOptions {})
124
- require .NoError (t ,err )
125
-
126
- _ ,issues := env .Compile (tc .celExpression )
127
- if issues != nil && issues .Err ()!= nil {
128
- // CEL compilation failed as expected
122
+ // For invalid expr expressions, try to compile
123
+ _ ,err := expr .CompileTokenLifetimeExpression (tc .exprExpression )
124
+ if err != nil {
125
+ // expr compilation failed as expected
129
126
return
130
127
}
131
128
// If compilation succeeded but we expected failure, that's also a test failure
132
- t .Fatalf ("ExpectedCEL expression to fail compilation but it succeeded: %s" ,tc .celExpression )
129
+ t .Fatalf ("Expectedexpr expression to fail compilation but it succeeded: %s" ,tc .exprExpression )
133
130
})
134
131
}
135
132
})
@@ -139,8 +136,8 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
139
136
140
137
// Test actual token creation with various user role combinations
141
138
// Note: The first user created is an "Owner" (capital O)
142
- // Global max is 720h (30 days),CEL expression provides role-specific rules
143
- client := createClientWithRoleTokenLifetimes (t ,`subject.roles.exists(r, r.name == "owner") ? duration("168h") : subject.roles.exists(r, r.name == "user-admin") ? duration("72h") : subject.roles.exists(r, r.name == "member") ? duration("24h") : duration(globalMaxDuration)` ,720 * time .Hour )
139
+ // Global max is 720h (30 days),expr expression provides role-specific rules
140
+ client := createClientWithRoleTokenLifetimes (t ,`any( subject.Roles, .Name == "owner") ? duration("168h") :any( subject.Roles, .Name == "user-admin") ? duration("72h") :any( subject.Roles, .Name == "member") ? duration("24h") : duration(globalMaxDuration)` ,720 * time .Hour )
144
141
145
142
ctx := context .Background ()
146
143
@@ -149,13 +146,13 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
149
146
require .NoError (t ,err )
150
147
t .Logf ("Token config max lifetime: %v (expected 720h - global max)" ,tokenConfig .MaxTokenLifetime )
151
148
152
- // Test owner can create token up to what theCEL expression allows (168h)
149
+ // Test owner can create token up to what theexpr expression allows (168h)
153
150
_ ,err = client .CreateToken (ctx ,codersdk .Me , codersdk.CreateTokenRequest {
154
151
Lifetime :167 * time .Hour ,
155
152
})
156
153
require .NoError (t ,err )
157
154
158
- // Test owner cannot exceed what theCEL expression allows (168h)
155
+ // Test owner cannot exceed what theexpr expression allows (168h)
159
156
_ ,err = client .CreateToken (ctx ,codersdk .Me , codersdk.CreateTokenRequest {
160
157
Lifetime :169 * time .Hour ,
161
158
})
@@ -167,7 +164,7 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
167
164
t .Parallel ()
168
165
169
166
// Test that users without specific role configs fall back to global max
170
- client := createClientWithRoleTokenLifetimes (t ,`subject.roles.exists(r, r.name == "user-admin") ? duration("168h") : duration(globalMaxDuration)` ,48 * time .Hour )
167
+ client := createClientWithRoleTokenLifetimes (t ,`any( subject.Roles, .Name == "user-admin") ? duration("168h") : duration(globalMaxDuration)` ,48 * time .Hour )
171
168
172
169
ctx := context .Background ()
173
170
@@ -198,9 +195,9 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
198
195
t .Run ("RoleSpecificShorterThanGlobal" ,func (t * testing.T ) {
199
196
t .Parallel ()
200
197
201
- // TestCEL expression that chooses between role-specific and global max
198
+ // Testexpr expression that chooses between role-specific and global max
202
199
// Note: The first user created is an "Owner" (capital O)
203
- client := createClientWithRoleTokenLifetimes (t ,`subject.roles.exists(r, r.name == "owner") ? duration(globalMaxDuration) : duration("24h")` ,168 * time .Hour )// 7 days global
200
+ client := createClientWithRoleTokenLifetimes (t ,`any( subject.Roles, .Name == "owner") ? duration(globalMaxDuration) : duration("24h")` ,168 * time .Hour )// 7 days global
204
201
205
202
ctx := context .Background ()
206
203
@@ -214,7 +211,7 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
214
211
require .NoError (t ,err )
215
212
t .Logf ("User roles: %v" ,user .Roles )
216
213
217
- // Owner gets the global max (168h) because theCEL expression returns globalMaxDuration
214
+ // Owner gets the global max (168h) because theexpr expression returns globalMaxDuration
218
215
_ ,err = client .CreateToken (ctx ,codersdk .Me , codersdk.CreateTokenRequest {
219
216
Lifetime :167 * time .Hour ,
220
217
})
@@ -231,20 +228,20 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
231
228
t .Run ("OrganizationSpecificRoles" ,func (t * testing.T ) {
232
229
t .Parallel ()
233
230
234
- // This test verifies that organization-specific role configurations work withCEL expressions
231
+ // This test verifies that organization-specific role configurations work withexpr expressions
235
232
236
- // Set up a client with organization-specific role configurations usingCEL
237
- celExpression := `
238
- subject.roles.exists(r, r.name == "owner" &&r.orgID == "") ? duration("720h") :
239
- subject.roles.exists(r, r.name == "member" &&r.orgID == "") ? duration("24h") :
240
- subject.roles.exists(r, r.name == "organization-member" &&r.orgID != "") ? duration("48h") :
241
- subject.roles.exists(r, r.name == "organization-admin" &&r.orgID != "") ? duration("168h") :
233
+ // Set up a client with organization-specific role configurations usingexpr
234
+ exprExpression := `
235
+ any( subject.Roles, .Name == "owner" &&.OrgID == "") ? duration("720h") :
236
+ any( subject.Roles, .Name == "member" &&.OrgID == "") ? duration("24h") :
237
+ any( subject.Roles, .Name == "organization-member" &&.OrgID != "") ? duration("48h") :
238
+ any( subject.Roles, .Name == "organization-admin" &&.OrgID != "") ? duration("168h") :
242
239
duration(defaultDuration)
243
240
`
244
241
245
242
dv := coderdtest .DeploymentValues (t )
246
243
dv .Sessions .MaximumTokenDuration = serpent .Duration (720 * time .Hour )
247
- dv .Sessions .MaximumTokenDurationExpression = serpent .String (celExpression )
244
+ dv .Sessions .MaximumTokenDurationExpression = serpent .String (exprExpression )
248
245
249
246
// Create the client, database, and get the API instance
250
247
client ,closer ,api := coderdtest .NewWithAPI (t ,& coderdtest.Options {
@@ -254,15 +251,15 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
254
251
_ = closer .Close ()
255
252
})
256
253
257
- // Compile theCEL expression
254
+ // Compile theexpr expression
258
255
ctx := context .Background ()
259
256
_ ,err := api .DeploymentValues .Sessions .CompiledMaximumTokenDurationProgram ()
260
257
require .NoError (t ,err )
261
258
262
259
// Create the first user
263
260
_ = coderdtest .CreateFirstUser (t ,client )
264
261
265
- // Test that theCEL expression is working for the site-wide owner role
262
+ // Test that theexpr expression is working for the site-wide owner role
266
263
// The first user gets site-wide owner role, so should get 720h
267
264
_ ,err = client .CreateToken (ctx ,codersdk .Me , codersdk.CreateTokenRequest {
268
265
Lifetime :719 * time .Hour ,
@@ -280,21 +277,21 @@ func TestRoleBasedTokenLifetimes_Integration(t *testing.T) {
280
277
t .Run ("OrganizationRoleWithoutConfig" ,func (t * testing.T ) {
281
278
t .Parallel ()
282
279
283
- // TestCEL expression with fallback behavior for unconfigured roles
280
+ // Testexpr expression with fallback behavior for unconfigured roles
284
281
285
282
// Set up a client with only site-wide role configurations (no org-specific roles)
286
- client := createClientWithRoleTokenLifetimes (t ,`subject.roles.exists(r, r.name == "owner") ? duration("720h") : subject.roles.exists(r, r.name == "member") ? duration("24h") : duration(globalMaxDuration)` ,168 * time .Hour )
283
+ client := createClientWithRoleTokenLifetimes (t ,`any( subject.Roles, .Name == "owner") ? duration("720h") :any( subject.Roles, .Name == "member") ? duration("24h") : duration(globalMaxDuration)` ,168 * time .Hour )
287
284
288
285
ctx := context .Background ()
289
286
290
- // Test that the first user (owner) gets 720h according to theCEL expression,
287
+ // Test that the first user (owner) gets 720h according to theexpr expression,
291
288
// not the global max (168h)
292
289
_ ,err := client .CreateToken (ctx ,codersdk .Me , codersdk.CreateTokenRequest {
293
290
Lifetime :719 * time .Hour ,
294
291
})
295
292
require .NoError (t ,err )
296
293
297
- // Test that owner cannot exceed whatCEL expression allows (720h)
294
+ // Test that owner cannot exceed whatexpr expression allows (720h)
298
295
_ ,err = client .CreateToken (ctx ,codersdk .Me , codersdk.CreateTokenRequest {
299
296
Lifetime :721 * time .Hour ,
300
297
})