6dccf494f8
cleanup permit policies and correct documentation * docs * policy cleanup * refactor * Merge remote-tracking branch 'origin/feature/permit-policy-cleanup' into feature/permit-policy-cleanup * docs and edits
403 lines
10 KiB
Go
403 lines
10 KiB
Go
//go:build aws
|
|
|
|
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// Test configuration constants
|
|
const (
|
|
testProjectIDForRoles = "ebde1e1e9623491cab6f8112e67bd61c"
|
|
testEnvIDForRoles = "9d6801123cfd4a0ea2ef1df2f430e9d3"
|
|
)
|
|
|
|
// Replace the existing TestValidateCSVRoles function with these separate functions:
|
|
|
|
// setupTestConfig creates a test configuration for role validation tests
|
|
func setupTestConfig(t *testing.T) (AppConfig, *http.Client, bool) {
|
|
// Load environment variables
|
|
if err := godotenv.Overload(); err != nil {
|
|
t.Logf("Warning: problem loading .env file - ignoring: %v", err)
|
|
}
|
|
|
|
// Skip test if required environment variables are not set
|
|
if !checkRequiredEnvVarsForRoles(t) {
|
|
return AppConfig{}, nil, false
|
|
}
|
|
|
|
// Setup real HTTP client and configuration
|
|
httpClient := &http.Client{Timeout: 30 * time.Second}
|
|
config := AppConfig{
|
|
PermitAPIKey: os.Getenv("PERMIT_KEY"),
|
|
PermitProjectID: testProjectIDForRoles,
|
|
PermitEnvID: testEnvIDForRoles,
|
|
PermitBaseURL: "https://api.permit.io",
|
|
}
|
|
|
|
return config, httpClient, true
|
|
}
|
|
|
|
func TestValidateCSVRoles_MissingRoles(t *testing.T) {
|
|
config, httpClient, ok := setupTestConfig(t)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// Test CSV data with existing roles (admin, viewer, editor) and one non-existent role 'foo'
|
|
csvUsers := []map[string]string{
|
|
{
|
|
"email": "user1@example.com",
|
|
"first_name": "John",
|
|
"last_name": "Doe",
|
|
"roles": "admin,viewer",
|
|
},
|
|
{
|
|
"email": "user2@example.com",
|
|
"first_name": "Jane",
|
|
"last_name": "Smith",
|
|
"roles": "editor,foo", // 'foo' doesn't exist in real Permit.io
|
|
},
|
|
{
|
|
"email": "user3@example.com",
|
|
"first_name": "Bob",
|
|
"last_name": "Wilson",
|
|
"roles": "viewer",
|
|
},
|
|
}
|
|
|
|
// Call the function under test with real API
|
|
result, err := ValidateCSVRoles(httpClient, config, csvUsers)
|
|
|
|
// Verify that an error was returned for missing role 'foo'
|
|
if err == nil {
|
|
t.Fatalf("Expected error for missing role 'foo', but got nil. Returned roles: %v", result)
|
|
}
|
|
|
|
// Verify the error message mentions the missing role
|
|
if !strings.Contains(err.Error(), "foo") {
|
|
t.Errorf("Error message should mention missing role 'foo', got: %s", err.Error())
|
|
}
|
|
|
|
// Verify that 'foo' is in the list of missing roles
|
|
foundFoo := false
|
|
for _, role := range result {
|
|
if role == "foo" {
|
|
foundFoo = true
|
|
break
|
|
}
|
|
}
|
|
if !foundFoo {
|
|
t.Errorf("Expected 'foo' to be in missing roles list, got %v", result)
|
|
}
|
|
|
|
// Verify the error message format
|
|
if !strings.Contains(err.Error(), "the following roles do not exist in Permit.io") {
|
|
t.Errorf("Error message should contain expected prefix, got: %s", err.Error())
|
|
}
|
|
|
|
t.Logf("Successfully detected missing role 'foo'. Missing roles: %v", result)
|
|
}
|
|
|
|
func TestValidateCSVRoles_AllRolesExist(t *testing.T) {
|
|
config, httpClient, ok := setupTestConfig(t)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// Test CSV data with only roles that should exist (admin, viewer, editor)
|
|
csvUsers := []map[string]string{
|
|
{
|
|
"email": "user1@example.com",
|
|
"first_name": "John",
|
|
"last_name": "Doe",
|
|
"roles": "admin,viewer",
|
|
},
|
|
{
|
|
"email": "user2@example.com",
|
|
"first_name": "Jane",
|
|
"last_name": "Smith",
|
|
"roles": "editor,admin",
|
|
},
|
|
}
|
|
|
|
// Call the function under test with real API
|
|
result, err := ValidateCSVRoles(httpClient, config, csvUsers)
|
|
|
|
// Verify that no error was returned since all roles should exist
|
|
if err != nil {
|
|
t.Fatalf("Expected no error when all roles exist, but got: %v", err)
|
|
}
|
|
|
|
// Verify that all unique requested roles are returned
|
|
expectedRoleCount := 3 // admin, viewer, editor
|
|
if len(result) != expectedRoleCount {
|
|
t.Errorf("Expected %d unique roles, got %d: %v", expectedRoleCount, len(result), result)
|
|
}
|
|
|
|
// Verify expected roles are present
|
|
expectedRoles := map[string]bool{
|
|
"admin": false,
|
|
"viewer": false,
|
|
"editor": false,
|
|
}
|
|
|
|
for _, role := range result {
|
|
if _, exists := expectedRoles[role]; exists {
|
|
expectedRoles[role] = true
|
|
} else {
|
|
t.Errorf("Unexpected role in result: %s", role)
|
|
}
|
|
}
|
|
|
|
// Check that all expected roles were found
|
|
for role, found := range expectedRoles {
|
|
if !found {
|
|
t.Errorf("Expected role '%s' not found in result", role)
|
|
}
|
|
}
|
|
|
|
t.Logf("Successfully validated all existing roles: %v", result)
|
|
}
|
|
|
|
func TestValidateCSVRoles_EmptyCSV(t *testing.T) {
|
|
config, httpClient, ok := setupTestConfig(t)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// Empty CSV data
|
|
csvUsers := []map[string]string{}
|
|
|
|
// Call the function under test
|
|
result, err := ValidateCSVRoles(httpClient, config, csvUsers)
|
|
|
|
// Verify that no error was returned
|
|
if err != nil {
|
|
t.Fatalf("Expected no error for empty CSV, but got: %v", err)
|
|
}
|
|
|
|
// Verify that no roles are returned
|
|
if len(result) != 0 {
|
|
t.Errorf("Expected empty result for empty CSV, got %v", result)
|
|
}
|
|
|
|
t.Logf("Successfully handled empty CSV")
|
|
}
|
|
|
|
func TestValidateCSVRoles_NoRolesInCSV(t *testing.T) {
|
|
config, httpClient, ok := setupTestConfig(t)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// CSV data with users but no roles
|
|
csvUsers := []map[string]string{
|
|
{
|
|
"email": "user1@example.com",
|
|
"first_name": "John",
|
|
"last_name": "Doe",
|
|
"roles": "", // empty roles
|
|
},
|
|
{
|
|
"email": "user2@example.com",
|
|
"first_name": "Jane",
|
|
"last_name": "Smith",
|
|
// no roles field
|
|
},
|
|
}
|
|
|
|
// Call the function under test
|
|
result, err := ValidateCSVRoles(httpClient, config, csvUsers)
|
|
|
|
// Verify that no error was returned
|
|
if err != nil {
|
|
t.Fatalf("Expected no error when no roles specified, but got: %v", err)
|
|
}
|
|
|
|
// Verify that no roles are returned
|
|
if len(result) != 0 {
|
|
t.Errorf("Expected empty result when no roles specified, got %v", result)
|
|
}
|
|
|
|
t.Logf("Successfully handled CSV with no roles")
|
|
}
|
|
|
|
// TestExtractUniqueRolesFromCSV tests the role extraction helper function
|
|
func TestExtractUniqueRolesFromCSV(t *testing.T) {
|
|
t.Run("ExtractUniqueRoles_NormalCase", func(t *testing.T) {
|
|
csvUsers := []map[string]string{
|
|
{"roles": "admin,viewer"},
|
|
{"roles": "editor,admin"}, // admin is duplicate
|
|
{"roles": "viewer"}, // viewer is duplicate
|
|
{"roles": ""}, // empty roles
|
|
}
|
|
|
|
result := extractUniqueRolesFromCSV(csvUsers)
|
|
|
|
// Should get 3 unique roles
|
|
expectedCount := 3
|
|
if len(result) != expectedCount {
|
|
t.Errorf("Expected %d unique roles, got %d: %v", expectedCount, len(result), result)
|
|
}
|
|
|
|
// Check that all expected roles are present
|
|
expectedRoles := map[string]bool{
|
|
"admin": false,
|
|
"viewer": false,
|
|
"editor": false,
|
|
}
|
|
|
|
for _, role := range result {
|
|
if _, exists := expectedRoles[role]; exists {
|
|
expectedRoles[role] = true
|
|
} else {
|
|
t.Errorf("Unexpected role: %s", role)
|
|
}
|
|
}
|
|
|
|
// Verify all expected roles were found
|
|
for role, found := range expectedRoles {
|
|
if !found {
|
|
t.Errorf("Expected role '%s' not found", role)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("ExtractUniqueRoles_WithWhitespace", func(t *testing.T) {
|
|
csvUsers := []map[string]string{
|
|
{"roles": " admin , viewer "}, // roles with whitespace
|
|
{"roles": "editor, admin "}, // more whitespace
|
|
}
|
|
|
|
result := extractUniqueRolesFromCSV(csvUsers)
|
|
|
|
// Verify whitespace is trimmed and duplicates removed
|
|
expectedRoles := map[string]bool{
|
|
"admin": false,
|
|
"viewer": false,
|
|
"editor": false,
|
|
}
|
|
|
|
if len(result) != 3 {
|
|
t.Errorf("Expected 3 unique roles, got %d: %v", len(result), result)
|
|
}
|
|
|
|
for _, role := range result {
|
|
if _, exists := expectedRoles[role]; exists {
|
|
expectedRoles[role] = true
|
|
} else {
|
|
t.Errorf("Unexpected role: %s", role)
|
|
}
|
|
}
|
|
|
|
// Verify all expected roles were found
|
|
for role, found := range expectedRoles {
|
|
if !found {
|
|
t.Errorf("Expected role '%s' not found", role)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestFindMissingRoles tests the missing roles detection helper function
|
|
func TestFindMissingRoles(t *testing.T) {
|
|
t.Run("FindMissingRoles_SomeMissing", func(t *testing.T) {
|
|
requestedRoles := []string{"admin", "viewer", "foo", "bar"}
|
|
existingRoles := []string{"admin", "viewer", "editor"}
|
|
|
|
result := findMissingRoles(requestedRoles, existingRoles)
|
|
|
|
expectedMissing := map[string]bool{
|
|
"foo": false,
|
|
"bar": false,
|
|
}
|
|
|
|
if len(result) != 2 {
|
|
t.Errorf("Expected 2 missing roles, got %d: %v", len(result), result)
|
|
}
|
|
|
|
for _, role := range result {
|
|
if _, exists := expectedMissing[role]; exists {
|
|
expectedMissing[role] = true
|
|
} else {
|
|
t.Errorf("Unexpected missing role: %s", role)
|
|
}
|
|
}
|
|
|
|
// Verify all expected missing roles were found
|
|
for role, found := range expectedMissing {
|
|
if !found {
|
|
t.Errorf("Expected missing role '%s' not found", role)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("FindMissingRoles_NoneMissing", func(t *testing.T) {
|
|
requestedRoles := []string{"admin", "viewer"}
|
|
existingRoles := []string{"admin", "viewer", "editor"}
|
|
|
|
result := findMissingRoles(requestedRoles, existingRoles)
|
|
|
|
if len(result) != 0 {
|
|
t.Errorf("Expected no missing roles, got %v", result)
|
|
}
|
|
})
|
|
|
|
t.Run("FindMissingRoles_AllMissing", func(t *testing.T) {
|
|
requestedRoles := []string{"foo", "bar"}
|
|
existingRoles := []string{"admin", "viewer", "editor"}
|
|
|
|
result := findMissingRoles(requestedRoles, existingRoles)
|
|
|
|
if len(result) != 2 {
|
|
t.Errorf("Expected 2 missing roles, got %d: %v", len(result), result)
|
|
}
|
|
|
|
expectedMissing := map[string]bool{
|
|
"foo": false,
|
|
"bar": false,
|
|
}
|
|
|
|
for _, role := range result {
|
|
if _, exists := expectedMissing[role]; exists {
|
|
expectedMissing[role] = true
|
|
} else {
|
|
t.Errorf("Unexpected missing role: %s", role)
|
|
}
|
|
}
|
|
|
|
// Verify all expected missing roles were found
|
|
for role, found := range expectedMissing {
|
|
if !found {
|
|
t.Errorf("Expected missing role '%s' not found", role)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// checkRequiredEnvVarsForRoles checks if required environment variables are set for role validation tests
|
|
func checkRequiredEnvVarsForRoles(t *testing.T) bool {
|
|
required := []string{"PERMIT_KEY"}
|
|
missing := []string{}
|
|
|
|
for _, env := range required {
|
|
if os.Getenv(env) == "" {
|
|
missing = append(missing, env)
|
|
}
|
|
}
|
|
|
|
if len(missing) > 0 {
|
|
t.Skipf("Skipping role validation integration test - missing required environment variables: %v", missing)
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|