aboutsummaryrefslogtreecommitdiff
path: root/weed/iam/helpers_test.go
diff options
context:
space:
mode:
authorchrislu <chris.lu@gmail.com>2025-12-14 16:08:56 -0800
committerchrislu <chris.lu@gmail.com>2025-12-14 16:08:56 -0800
commitf734b2d4bf154b372d382283a8ef09fe1c808154 (patch)
tree85d2e06d14257051a3e57da1d6ee773a401113fe /weed/iam/helpers_test.go
parentf41925b60bd066048217a6de23185a6e6cfb75a7 (diff)
downloadseaweedfs-f734b2d4bf154b372d382283a8ef09fe1c808154.tar.xz
seaweedfs-f734b2d4bf154b372d382283a8ef09fe1c808154.zip
Refactor: Extract common IAM logic into shared weed/iam package (#7747)
This resolves GitHub issue #7747 by extracting duplicated IAM code into a shared package that both the embedded S3 IAM and standalone IAM use. New shared package (weed/iam/): - constants.go: Common constants (charsets, action strings, error messages) - helpers.go: Shared helper functions (Hash, GenerateRandomString, GenerateAccessKeyId, GenerateSecretAccessKey, StringSlicesEqual, MapToStatementAction, MapToIdentitiesAction, MaskAccessKey) - responses.go: Common IAM response structs (CommonResponse, ListUsersResponse, CreateUserResponse, etc.) - helpers_test.go: Unit tests for shared helpers Updated files: - weed/s3api/s3api_embedded_iam.go: Use type aliases and function wrappers to the shared package, removing ~200 lines of duplicated code - weed/iamapi/iamapi_management_handlers.go: Use shared package for constants and helper functions, removing ~100 lines of duplicated code - weed/iamapi/iamapi_response.go: Re-export types from shared package for backwards compatibility Benefits: - Single source of truth for IAM constants and helpers - Easier maintenance - changes only need to be made in one place - Reduced risk of inconsistencies between embedded and standalone IAM - Better test coverage through shared test suite
Diffstat (limited to 'weed/iam/helpers_test.go')
-rw-r--r--weed/iam/helpers_test.go135
1 files changed, 135 insertions, 0 deletions
diff --git a/weed/iam/helpers_test.go b/weed/iam/helpers_test.go
new file mode 100644
index 000000000..c9913d28a
--- /dev/null
+++ b/weed/iam/helpers_test.go
@@ -0,0 +1,135 @@
+package iam
+
+import (
+ "testing"
+
+ "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestHash(t *testing.T) {
+ input := "test"
+ result := Hash(&input)
+ assert.NotEmpty(t, result)
+ assert.Len(t, result, 40) // SHA1 hex is 40 chars
+
+ // Same input should produce same hash
+ result2 := Hash(&input)
+ assert.Equal(t, result, result2)
+
+ // Different input should produce different hash
+ different := "different"
+ result3 := Hash(&different)
+ assert.NotEqual(t, result, result3)
+}
+
+func TestGenerateRandomString(t *testing.T) {
+ // Valid generation
+ result, err := GenerateRandomString(10, CharsetUpper)
+ assert.NoError(t, err)
+ assert.Len(t, result, 10)
+
+ // Different calls should produce different results (with high probability)
+ result2, err := GenerateRandomString(10, CharsetUpper)
+ assert.NoError(t, err)
+ assert.NotEqual(t, result, result2)
+
+ // Invalid length
+ _, err = GenerateRandomString(0, CharsetUpper)
+ assert.Error(t, err)
+
+ _, err = GenerateRandomString(-1, CharsetUpper)
+ assert.Error(t, err)
+
+ // Empty charset
+ _, err = GenerateRandomString(10, "")
+ assert.Error(t, err)
+}
+
+func TestGenerateAccessKeyId(t *testing.T) {
+ keyId, err := GenerateAccessKeyId()
+ assert.NoError(t, err)
+ assert.Len(t, keyId, AccessKeyIdLength)
+}
+
+func TestGenerateSecretAccessKey(t *testing.T) {
+ secretKey, err := GenerateSecretAccessKey()
+ assert.NoError(t, err)
+ assert.Len(t, secretKey, SecretAccessKeyLength)
+}
+
+func TestStringSlicesEqual(t *testing.T) {
+ tests := []struct {
+ a []string
+ b []string
+ expected bool
+ }{
+ {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, true},
+ {[]string{"c", "b", "a"}, []string{"a", "b", "c"}, true}, // Order independent
+ {[]string{"a", "b"}, []string{"a", "b", "c"}, false},
+ {[]string{}, []string{}, true},
+ {nil, nil, true},
+ {[]string{"a"}, []string{"b"}, false},
+ }
+
+ for _, test := range tests {
+ result := StringSlicesEqual(test.a, test.b)
+ assert.Equal(t, test.expected, result)
+ }
+}
+
+func TestMapToStatementAction(t *testing.T) {
+ tests := []struct {
+ input string
+ expected string
+ }{
+ {StatementActionAdmin, s3_constants.ACTION_ADMIN},
+ {StatementActionWrite, s3_constants.ACTION_WRITE},
+ {StatementActionRead, s3_constants.ACTION_READ},
+ {StatementActionList, s3_constants.ACTION_LIST},
+ {StatementActionDelete, s3_constants.ACTION_DELETE_BUCKET},
+ {"unknown", ""},
+ }
+
+ for _, test := range tests {
+ result := MapToStatementAction(test.input)
+ assert.Equal(t, test.expected, result)
+ }
+}
+
+func TestMapToIdentitiesAction(t *testing.T) {
+ tests := []struct {
+ input string
+ expected string
+ }{
+ {s3_constants.ACTION_ADMIN, StatementActionAdmin},
+ {s3_constants.ACTION_WRITE, StatementActionWrite},
+ {s3_constants.ACTION_READ, StatementActionRead},
+ {s3_constants.ACTION_LIST, StatementActionList},
+ {s3_constants.ACTION_DELETE_BUCKET, StatementActionDelete},
+ {"unknown", ""},
+ }
+
+ for _, test := range tests {
+ result := MapToIdentitiesAction(test.input)
+ assert.Equal(t, test.expected, result)
+ }
+}
+
+func TestMaskAccessKey(t *testing.T) {
+ tests := []struct {
+ input string
+ expected string
+ }{
+ {"AKIAIOSFODNN7EXAMPLE", "AKIA***"},
+ {"AKIA", "AKIA"},
+ {"AKI", "AKI"},
+ {"", ""},
+ }
+
+ for _, test := range tests {
+ result := MaskAccessKey(test.input)
+ assert.Equal(t, test.expected, result)
+ }
+}
+