diff --git a/backend/internal/handler/tenant_assignment_policy.go b/backend/internal/handler/tenant_assignment_policy.go index fa381207..63678875 100644 --- a/backend/internal/handler/tenant_assignment_policy.go +++ b/backend/internal/handler/tenant_assignment_policy.go @@ -135,6 +135,9 @@ func createPersonalTenantForUser(ctx context.Context, tenantService service.Tena normalizedEmail = "user" } slug := "personal-" + strings.ReplaceAll(uuid.NewString(), "-", "") + if len(slug) > 32 { + slug = slug[:32] + } tenant, err := tenantService.RegisterTenant( ctx, fmt.Sprintf("Personal - %s", normalizedEmail), diff --git a/backend/internal/handler/tenant_assignment_policy_test.go b/backend/internal/handler/tenant_assignment_policy_test.go new file mode 100644 index 00000000..eb53acb7 --- /dev/null +++ b/backend/internal/handler/tenant_assignment_policy_test.go @@ -0,0 +1,49 @@ +package handler + +import ( + "context" + "strings" + "testing" + + "baron-sso-backend/internal/domain" + "baron-sso-backend/internal/utils" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestCreatePersonalTenantForUser_SlugLength(t *testing.T) { + mockTenantService := &MockTenantService{} + ctx := context.Background() + + var capturedSlug string + mockTenantService.On( + "RegisterTenant", + ctx, + "Personal - user@example.com", + mock.AnythingOfType("string"), + domain.TenantTypePersonal, + "Automatically provisioned personal tenant", + []string(nil), + (*string)(nil), + "", + ).Run(func(args mock.Arguments) { + capturedSlug = args.String(2) + }).Return(&domain.Tenant{ + ID: "personal-tenant-id", + Slug: "personal-slug", + Name: "Personal - user@example.com", + }, nil) + + tenant, err := createPersonalTenantForUser(ctx, mockTenantService, "user@example.com") + assert.NoError(t, err) + assert.NotNil(t, tenant) + + // Ensure the generated slug is strictly 32 characters or less + assert.LessOrEqual(t, len(capturedSlug), 32) + assert.True(t, strings.HasPrefix(capturedSlug, "personal-")) + + // Ensure that the captured slug actually passes ValidateSlug! + valid, msg := utils.ValidateSlug(capturedSlug) + assert.True(t, valid, "Slug must be valid: "+msg) +}