package tests import ( "testing" ) // TestMultiTenantIsolation 测试多租户数据隔离 func TestMultiTenantIsolation(t *testing.T) { ensureUsers(t) var org1ID, org2ID string // User1 创建组织1 t.Run("User1 creates Organization 1", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "tenant_test_org1", "name": "Tenant Test Org 1", }, User1Token) if resp.Code == 200 { var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) org1ID = data.ID } else { // 可能已经存在,尝试获取 resp = doRequest(t, "GET", "/api/orgs", nil, User1Token) assertStatus(t, resp, 200) } }) // User2 创建组织2 t.Run("User2 creates Organization 2", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "tenant_test_org2", "name": "Tenant Test Org 2", }, User2Token) if resp.Code == 200 { var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) org2ID = data.ID } }) if org1ID == "" || org2ID == "" { t.Skip("Failed to create test orgs") } // 测试:User1 不能访问 User2 的组织 t.Run("User1 cannot access User2's organization", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+org2ID, nil, User1Token) if resp.Code == 200 { t.Errorf("User1 should not be able to access User2's org, got 200") } }) // 测试:User2 不能访问 User1 的组织 t.Run("User2 cannot access User1's organization", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+org1ID, nil, User2Token) if resp.Code == 200 { t.Errorf("User2 should not be able to access User1's org, got 200") } }) // 测试:User1 添加 User2 到组织1后,User2 可以访问 t.Run("User1 adds User2 to Org1", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs/"+org1ID+"/members", map[string]string{ "user_id": User2ID, "role": "member", }, User1Token) assertStatus(t, resp, 200) }) // User2 现在应该能访问组织1 t.Run("User2 can now access Org1 as member", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+org1ID, nil, User2Token) assertStatus(t, resp, 200) }) // 但 User2 不应该能修改组织1(只有 owner 可以) t.Run("User2 cannot update Org1 as member", func(t *testing.T) { resp := doRequest(t, "PATCH", "/api/orgs/"+org1ID, map[string]string{ "name": "Hacked by User2", }, User2Token) // 应该失败,因为需要 org:update 权限 if resp.Code == 200 { t.Errorf("User2 should not be able to update Org1, got 200") } }) } // TestOrgMemberPermission 测试组织成员权限 func TestOrgMemberPermission(t *testing.T) { ensureUsers(t) var orgID string // User1 创建组织 t.Run("User1 creates org", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "member_perm_test", "name": "Member Permission Test", }, User1Token) if resp.Code == 200 { var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) orgID = data.ID } }) if orgID == "" { t.Skip("Failed to create org") } // User1 添加 User2 为成员 t.Run("Add User2 as member", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs/"+orgID+"/members", map[string]string{ "user_id": User2ID, "role": "member", }, User1Token) assertStatus(t, resp, 200) }) // User2 可以查看成员列表 t.Run("Member can view member list", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID+"/members", nil, User2Token) assertStatus(t, resp, 200) }) // User2 不能添加新成员(需要 org:update 权限) t.Run("Member cannot add new members", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs/"+orgID+"/members", map[string]string{ "user_id": AdminID, "role": "member", }, User2Token) if resp.Code == 200 { t.Errorf("Member should not be able to add new members, got 200") } }) // 清理 t.Run("Cleanup", func(t *testing.T) { resp := doRequest(t, "DELETE", "/api/orgs/"+orgID, nil, User1Token) assertStatus(t, resp, 200) }) } // TestCrossOrgDataLeak 测试跨组织数据泄漏 func TestCrossOrgDataLeak(t *testing.T) { ensureUsers(t) var orgID string // User1 创建组织 t.Run("User1 creates org", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "data_leak_test", "name": "Data Leak Test", }, User1Token) if resp.Code == 200 { var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) orgID = data.ID } }) if orgID == "" { t.Skip("Failed to create org") } // User1 添加 User2 为成员 t.Run("Add User2 as member", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs/"+orgID+"/members", map[string]string{ "user_id": User2ID, "role": "member", }, User1Token) assertStatus(t, resp, 200) }) // User2 获取组织详情 t.Run("User2 gets org details", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID, nil, User2Token) assertStatus(t, resp, 200) }) // User2 不应该能看到其他组织的成员 // 注意:这里假设 orgID+1 是另一个不存在的组织ID t.Run("User2 cannot access non-existent org", func(t *testing.T) { fakeOrgID := "non-existent-org-id-12345" resp := doRequest(t, "GET", "/api/orgs/"+fakeOrgID, nil, User2Token) if resp.Code == 200 { t.Errorf("Should not be able to access non-existent org, got 200") } }) // 清理 t.Run("Cleanup", func(t *testing.T) { resp := doRequest(t, "DELETE", "/api/orgs/"+orgID, nil, User1Token) assertStatus(t, resp, 200) }) } // TestOrgIDHeaderManipulation 测试 X-Org-ID 头部操作 func TestOrgIDHeaderManipulation(t *testing.T) { ensureUsers(t) var orgID string // User1 创建组织 t.Run("User1 creates org", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "header_test_org", "name": "Header Test Org", }, User1Token) if resp.Code == 200 { var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) orgID = data.ID } }) if orgID == "" { t.Skip("Failed to create org") } // 测试:User2 尝试通过伪造 X-Org-ID 访问组织 // 注意:这需要修改 doRequest 函数来支持自定义 header // 目前测试表明 User2 无法访问 t.Run("User2 cannot access org without membership", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID, nil, User2Token) if resp.Code == 200 { t.Errorf("User2 should not be able to access org without membership, got 200") } }) // 清理 t.Run("Cleanup", func(t *testing.T) { resp := doRequest(t, "DELETE", "/api/orgs/"+orgID, nil, User1Token) assertStatus(t, resp, 200) }) }