Skip to content

Commit 6c26592

Browse files
BRBussyclaude
andauthored
Expand role resource name validation to support full enum range (#56)
Updates role validation pattern from [123456][0-9]{6} to [1-9][0-9]{6} to allow role enum values across the full [1000000, 9999999] range, supporting future role additions beyond the 6000000 limit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 169a022 commit 6c26592

13 files changed

Lines changed: 80 additions & 90 deletions

File tree

go/iam/api_user/v1/api_user.pb.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/iam/api_user/v1/api_user_validation_test.go

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,25 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
2121
{
2222
name: "valid API user with all fields",
2323
apiUser: &APIUser{
24-
Owner: "groups/test-group-123",
24+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
2525
DisplayName: "Test API User",
2626
State: APIUserState_API_USER_STATE_ACTIVE,
27-
Roles: []string{"groups/test-group-123/ROLE_IAM_VIEWER"},
27+
Roles: []string{"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/3000001"},
2828
},
2929
wantValid: true,
3030
},
3131
{
3232
name: "valid API user with minimal required fields",
3333
apiUser: &APIUser{
34-
Owner: "groups/test-group-123",
34+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
3535
DisplayName: "Test API User",
3636
},
3737
wantValid: true,
3838
},
3939
{
4040
name: "valid API user with empty system-set fields",
4141
apiUser: &APIUser{
42-
Owner: "groups/test-group-123",
42+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
4343
DisplayName: "Test API User",
4444
State: APIUserState_API_USER_STATE_UNSPECIFIED, // System set, can be unspecified
4545
Roles: []string{}, // Can be empty (0 roles allowed)
@@ -49,7 +49,7 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
4949
{
5050
name: "valid API user with no roles",
5151
apiUser: &APIUser{
52-
Owner: "groups/test-group-123",
52+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
5353
DisplayName: "Test API User",
5454
Roles: []string{}, // 0 roles allowed
5555
},
@@ -62,7 +62,7 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
6262
DisplayName: "Test API User",
6363
},
6464
wantValid: false,
65-
wantError: "owner is required",
65+
wantError: "required",
6666
},
6767
{
6868
name: "invalid owner format - missing groups prefix",
@@ -71,7 +71,7 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
7171
DisplayName: "Test API User",
7272
},
7373
wantValid: false,
74-
wantError: "owner must be in format groups/{group_id}",
74+
wantError: "pattern",
7575
},
7676
{
7777
name: "invalid owner format - invalid group ID characters",
@@ -80,37 +80,37 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
8080
DisplayName: "Test API User",
8181
},
8282
wantValid: false,
83-
wantError: "group_id contains only alphanumeric characters",
83+
wantError: "pattern",
8484
},
8585
{
86-
name: "valid owner with underscores and hyphens",
86+
name: "valid owner with proper ULIDv2 format",
8787
apiUser: &APIUser{
88-
Owner: "groups/test_group-123",
88+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
8989
DisplayName: "Test API User",
9090
},
9191
wantValid: true,
9292
},
9393
{
9494
name: "owners field accepts any values since no validation defined",
9595
apiUser: &APIUser{
96-
Owner: "groups/test-group-123",
96+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
9797
DisplayName: "Test API User",
9898
},
9999
wantValid: true, // No validation rules defined for owners field in proto
100100
},
101101
{
102102
name: "empty display name - should fail (required field)",
103103
apiUser: &APIUser{
104-
Owner: "groups/test-group-123",
104+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
105105
DisplayName: "",
106106
},
107107
wantValid: false,
108-
wantError: "display name is required",
108+
wantError: "required",
109109
},
110110
{
111111
name: "display name too long",
112112
apiUser: &APIUser{
113-
Owner: "groups/test-group-123",
113+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
114114
DisplayName: string(make([]byte, 256)), // 256 characters
115115
},
116116
wantValid: false,
@@ -119,7 +119,7 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
119119
{
120120
name: "valid state when specified",
121121
apiUser: &APIUser{
122-
Owner: "groups/test-group-123",
122+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
123123
DisplayName: "Test API User",
124124
State: APIUserState_API_USER_STATE_ACTIVE,
125125
},
@@ -128,7 +128,7 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
128128
{
129129
name: "valid unspecified state (system can set this)",
130130
apiUser: &APIUser{
131-
Owner: "groups/test-group-123",
131+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
132132
DisplayName: "Test API User",
133133
State: APIUserState_API_USER_STATE_UNSPECIFIED,
134134
},
@@ -137,20 +137,21 @@ func TestAPIUser_ValidationUpdated(t *testing.T) {
137137
{
138138
name: "multiple valid roles",
139139
apiUser: &APIUser{
140-
Owner: "groups/test-group-123",
140+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
141141
DisplayName: "Test API User",
142-
Roles: []string{"groups/test-group-123/ROLE_IAM_VIEWER", "groups/test-group-123/ROLE_IAM_ADMIN"},
142+
Roles: []string{"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/3000001", "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/3000000"},
143143
},
144144
wantValid: true,
145145
},
146146
{
147147
name: "invalid role format when roles provided",
148148
apiUser: &APIUser{
149-
Owner: "groups/test-group-123",
149+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
150150
DisplayName: "Test API User",
151-
Roles: []string{"invalid-role-format"}, // Invalid role format
151+
Roles: []string{"invalid-role-format"},
152152
},
153-
wantValid: true, // Currently no validation on role format in proto
153+
wantValid: false, // Role validation is enforced
154+
wantError: "pattern",
154155
},
155156
}
156157

@@ -174,29 +175,21 @@ func TestAPIUser_ValidationOwnerFormatsUpdated(t *testing.T) {
174175
validator, err := protovalidate.New()
175176
require.NoError(t, err)
176177

178+
// Valid ULIDv2 formats
177179
validOwnerFormats := []string{
178-
"groups/a", // single character
179-
"groups/abc123", // alphanumeric
180-
"groups/test-group-123", // with hyphens
181-
"groups/test_group_123", // with underscores
182-
"groups/group-with_mixed-123", // mixed separators
183-
"groups/ABC123", // uppercase
184-
"groups/a1b2c3", // mixed case
180+
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV", // Standard ULIDv2
181+
"groups/01BX5ZZKBKACTAV9WEVGEMMVRZ", // Another valid ULIDv2
185182
}
186183

184+
// Invalid owner formats
187185
invalidOwnerFormats := []string{
188-
"", // empty (required field)
189-
"groups/", // missing group ID
190-
"groups/-invalid", // starts with hyphen
191-
"groups/invalid-", // ends with hyphen
192-
"groups/_invalid", // starts with underscore
193-
"groups/invalid_", // ends with underscore
194-
"groups/inv@lid", // invalid character @
195-
"groups/inv!lid", // invalid character !
196-
"groups/inv lid", // space
197-
"groups/inv.lid", // dot
198-
"group/test", // wrong prefix
199-
"test-group-123", // no prefix
186+
"", // empty (required field)
187+
"groups/", // missing group ID
188+
"groups/01ARZ3NDEKTSV4RRFFQ69G5FIL", // Contains 'I' and 'L' (invalid in ULIDv2)
189+
"groups/01ARZ3NDEKTSV4RRFFQ69G5FA", // Too short (25 chars instead of 26)
190+
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAVX", // Too long (27 chars instead of 26)
191+
"group/01ARZ3NDEKTSV4RRFFQ69G5FAV", // Wrong prefix (missing 's')
192+
"test-group-123", // No prefix
200193
}
201194

202195
// Test valid formats
@@ -233,7 +226,7 @@ func TestAPIUser_SystemSetFieldsOptional(t *testing.T) {
233226
t.Run("all system-set fields can be empty/unspecified", func(t *testing.T) {
234227
apiUser := &APIUser{
235228
// Only required fields
236-
Owner: "groups/test-group-123",
229+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
237230
DisplayName: "Test API User",
238231

239232
// System-set fields can be empty/unspecified
@@ -249,7 +242,7 @@ func TestAPIUser_SystemSetFieldsOptional(t *testing.T) {
249242

250243
t.Run("system-set fields are validated when present", func(t *testing.T) {
251244
apiUser := &APIUser{
252-
Owner: "groups/test-group-123",
245+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
253246
DisplayName: "Test API User",
254247
}
255248

go/iam/api_user/v1/service.pb.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/iam/api_user/v1/service_validation_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -568,13 +568,13 @@ func TestAssignRoleToAPIUserRequest_Validation(t *testing.T) {
568568
},
569569
// name field tests
570570
{
571-
name: "empty name - should fail due to length validation",
571+
name: "empty name - should fail (required field)",
572572
request: &AssignRoleToAPIUserRequest{
573573
Name: "",
574574
Role: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/1234567",
575575
},
576-
wantValid: false, // Empty string fails length validation (expects exactly 36 chars)
577-
wantError: "len",
576+
wantValid: false,
577+
wantError: "required",
578578
},
579579
{
580580
name: "invalid name format - users prefix (wrong resource type)",
@@ -650,13 +650,12 @@ func TestAssignRoleToAPIUserRequest_Validation(t *testing.T) {
650650
wantError: "len",
651651
},
652652
{
653-
name: "invalid role format - role_id doesn't start with 1",
653+
name: "valid role format - role_id starts with 2",
654654
request: &AssignRoleToAPIUserRequest{
655655
Name: "api_users/01ARZ3NDEKTSV4RRFFQ69G5FAV", // Corrected to api_users/
656-
Role: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/2234567", // Must start with 1
656+
Role: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/2234567", // Valid under new pattern [1-9][0-9]{6}
657657
},
658-
wantValid: false,
659-
wantError: "pattern",
658+
wantValid: true,
660659
},
661660
{
662661
name: "invalid role format - role_id contains letters",

go/iam/user/v1/service.pb.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/iam/user/v1/service_validation_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,12 @@ func TestAssignRoleToUserRequest_Validation(t *testing.T) {
164164
wantError: "pattern",
165165
},
166166
{
167-
name: "invalid role format - wrong role ID format (not starting with 1)",
167+
name: "valid role format - role ID starting with 2",
168168
request: &AssignRoleToUserRequest{
169169
Name: "users/01ARZ3NDEKTSV4RRFFQ69G5FAV",
170-
Role: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/2234567", // Starts with 2, 41 chars
170+
Role: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/2234567", // Starts with 2, valid under new pattern [1-9][0-9]{6}
171171
},
172-
wantValid: false,
173-
wantError: "pattern",
172+
wantValid: true,
174173
},
175174
{
176175
name: "invalid role format - wrong role ID format (non-numeric)",
@@ -326,7 +325,6 @@ func TestAssignRoleToUserRequest_RoleFieldValidation(t *testing.T) {
326325
"groups/01arz3ndektsv4rrffq69g5fav/1234567", // Lowercase not allowed
327326
"groups/01ARZ3NDEKTSV4RRFFQ69G5FA/1234567", // Group too short (40 chars total)
328327
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAVX/1234567", // Too long overall (42 chars)
329-
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/2234567", // Role ID starts with 2
330328
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/0234567", // Role ID starts with 0
331329
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/123456A", // Non-numeric role ID
332330
"groups/01ARZ3NDEKTSV4RRFFQ69G5FAV/123456", // Role ID too short (6 digits)

go/iam/user/v1/user.pb.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/iam/user/v1/user_validation_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,18 @@ func TestUser_Validation(t *testing.T) {
143143
wantValid: true,
144144
},
145145
{
146-
name: "invalid owners item - wrong format",
146+
name: "invalid owner - wrong format",
147147
user: &User{
148-
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
148+
Owner: "group/01ARZ3NDEKTSV4RRFFQ69G5FAV", // Missing 's' in 'groups'
149149
Email: "test@example.com",
150150
},
151151
wantValid: false,
152152
wantError: "pattern",
153153
},
154154
{
155-
name: "invalid owners item - wrong length",
155+
name: "invalid owner - wrong length",
156156
user: &User{
157-
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FAV",
157+
Owner: "groups/01ARZ3NDEKTSV4RRFFQ69G5FA", // 32 chars instead of 33
158158
Email: "test@example.com",
159159
},
160160
wantValid: false,

java/src/main/java/co/meshtrade/api/iam/api_user/v1/ApiUser.java

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)