//go:build integration package admin_test import ( "testing" "time" "github.com/brianvoe/gofakeit/v6" "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/zitadel/zitadel/internal/integration" "github.com/zitadel/zitadel/pkg/grpc/admin" "github.com/zitadel/zitadel/pkg/grpc/management" v1 "github.com/zitadel/zitadel/pkg/grpc/v1" ) func TestServer_ImportData(t *testing.T) { orgIDs := generateIDs(10) projectIDs := generateIDs(10) userIDs := generateIDs(10) grantIDs := generateIDs(10) tests := []struct { name string req *admin.ImportDataRequest want *admin.ImportDataResponse wantErr bool }{ { name: "success", req: &admin.ImportDataRequest{ Data: &admin.ImportDataRequest_DataOrgs{ DataOrgs: &admin.ImportDataOrg{ Orgs: []*admin.DataOrg{ { OrgId: orgIDs[0], Org: &management.AddOrgRequest{ Name: gofakeit.ProductName(), }, Projects: []*v1.DataProject{ { ProjectId: projectIDs[0], Project: &management.AddProjectRequest{ Name: gofakeit.AppName(), ProjectRoleAssertion: true, }, }, { ProjectId: projectIDs[1], Project: &management.AddProjectRequest{ Name: gofakeit.AppName(), ProjectRoleAssertion: false, }, }, }, ProjectRoles: []*management.AddProjectRoleRequest{ { ProjectId: projectIDs[0], RoleKey: "role1", DisplayName: "role1", }, { ProjectId: projectIDs[0], RoleKey: "role2", DisplayName: "role2", }, { ProjectId: projectIDs[1], RoleKey: "role3", DisplayName: "role3", }, { ProjectId: projectIDs[1], RoleKey: "role4", DisplayName: "role4", }, }, HumanUsers: []*v1.DataHumanUser{ { UserId: userIDs[0], User: &management.ImportHumanUserRequest{ UserName: gofakeit.Username(), Profile: &management.ImportHumanUserRequest_Profile{ FirstName: gofakeit.FirstName(), LastName: gofakeit.LastName(), DisplayName: gofakeit.Username(), PreferredLanguage: gofakeit.LanguageBCP(), }, Email: &management.ImportHumanUserRequest_Email{ Email: gofakeit.Email(), IsEmailVerified: true, }, }, }, { UserId: userIDs[1], User: &management.ImportHumanUserRequest{ UserName: gofakeit.Username(), Profile: &management.ImportHumanUserRequest_Profile{ FirstName: gofakeit.FirstName(), LastName: gofakeit.LastName(), DisplayName: gofakeit.Username(), PreferredLanguage: gofakeit.LanguageBCP(), }, Email: &management.ImportHumanUserRequest_Email{ Email: gofakeit.Email(), IsEmailVerified: true, }, }, }, }, ProjectGrants: []*v1.DataProjectGrant{ { GrantId: grantIDs[0], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[0], GrantedOrgId: orgIDs[1], RoleKeys: []string{"role1", "role2"}, }, }, { GrantId: grantIDs[1], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[1], GrantedOrgId: orgIDs[1], RoleKeys: []string{"role3", "role4"}, }, }, { GrantId: grantIDs[2], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[0], GrantedOrgId: orgIDs[2], RoleKeys: []string{"role1", "role2"}, }, }, { GrantId: grantIDs[3], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[1], GrantedOrgId: orgIDs[2], RoleKeys: []string{"role3", "role4"}, }, }, }, }, { OrgId: orgIDs[1], Org: &management.AddOrgRequest{ Name: gofakeit.ProductName(), }, UserGrants: []*management.AddUserGrantRequest{ { UserId: userIDs[0], ProjectId: projectIDs[0], ProjectGrantId: grantIDs[0], }, { UserId: userIDs[0], ProjectId: projectIDs[1], ProjectGrantId: grantIDs[1], }, }, }, { OrgId: orgIDs[2], Org: &management.AddOrgRequest{ Name: gofakeit.ProductName(), }, UserGrants: []*management.AddUserGrantRequest{ { UserId: userIDs[1], ProjectId: projectIDs[0], ProjectGrantId: grantIDs[2], }, { UserId: userIDs[1], ProjectId: projectIDs[1], ProjectGrantId: grantIDs[3], }, }, }, }, }, }, Timeout: time.Minute.String(), }, want: &admin.ImportDataResponse{ Success: &admin.ImportDataSuccess{ Orgs: []*admin.ImportDataSuccessOrg{ { OrgId: orgIDs[0], ProjectIds: projectIDs[0:2], ProjectRoles: []string{ projectIDs[0] + "_role1", projectIDs[0] + "_role2", projectIDs[1] + "_role3", projectIDs[1] + "_role4", }, HumanUserIds: userIDs[0:2], ProjectGrants: []*admin.ImportDataSuccessProjectGrant{ { GrantId: grantIDs[0], ProjectId: projectIDs[0], OrgId: orgIDs[1], }, { GrantId: grantIDs[1], ProjectId: projectIDs[1], OrgId: orgIDs[1], }, { GrantId: grantIDs[2], ProjectId: projectIDs[0], OrgId: orgIDs[2], }, { GrantId: grantIDs[3], ProjectId: projectIDs[1], OrgId: orgIDs[2], }, }, }, { OrgId: orgIDs[1], UserGrants: []*admin.ImportDataSuccessUserGrant{ { ProjectId: projectIDs[0], UserId: userIDs[0], }, { UserId: userIDs[0], ProjectId: projectIDs[1], }, }, }, { OrgId: orgIDs[2], UserGrants: []*admin.ImportDataSuccessUserGrant{ { ProjectId: projectIDs[0], UserId: userIDs[1], }, { UserId: userIDs[1], ProjectId: projectIDs[1], }, }, }, }, }, }, }, { name: "duplicate project grant error", req: &admin.ImportDataRequest{ Data: &admin.ImportDataRequest_DataOrgs{ DataOrgs: &admin.ImportDataOrg{ Orgs: []*admin.DataOrg{ { OrgId: orgIDs[3], Org: &management.AddOrgRequest{ Name: gofakeit.ProductName(), }, Projects: []*v1.DataProject{ { ProjectId: projectIDs[2], Project: &management.AddProjectRequest{ Name: gofakeit.AppName(), ProjectRoleAssertion: true, }, }, { ProjectId: projectIDs[3], Project: &management.AddProjectRequest{ Name: gofakeit.AppName(), ProjectRoleAssertion: false, }, }, }, ProjectRoles: []*management.AddProjectRoleRequest{ { ProjectId: projectIDs[2], RoleKey: "role1", DisplayName: "role1", }, { ProjectId: projectIDs[2], RoleKey: "role2", DisplayName: "role2", }, { ProjectId: projectIDs[3], RoleKey: "role3", DisplayName: "role3", }, { ProjectId: projectIDs[3], RoleKey: "role4", DisplayName: "role4", }, }, ProjectGrants: []*v1.DataProjectGrant{ { GrantId: grantIDs[4], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[2], GrantedOrgId: orgIDs[4], RoleKeys: []string{"role1", "role2"}, }, }, { GrantId: grantIDs[4], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[2], GrantedOrgId: orgIDs[4], RoleKeys: []string{"role1", "role2"}, }, }, }, }, }, }, }, Timeout: time.Minute.String(), }, want: &admin.ImportDataResponse{ Errors: []*admin.ImportDataError{ { Type: "project_grant", Id: orgIDs[3] + "_" + projectIDs[2] + "_" + orgIDs[4], Message: "ID=V3-DKcYh Message=Errors.Project.Grant.AlreadyExists Parent=(ERROR: duplicate key value violates unique constraint \"unique_constraints_pkey\" (SQLSTATE 23505))", }, }, Success: &admin.ImportDataSuccess{ Orgs: []*admin.ImportDataSuccessOrg{ { OrgId: orgIDs[3], ProjectIds: projectIDs[2:4], ProjectRoles: []string{ projectIDs[2] + "_role1", projectIDs[2] + "_role2", projectIDs[3] + "_role3", projectIDs[3] + "_role4", }, ProjectGrants: []*admin.ImportDataSuccessProjectGrant{ { GrantId: grantIDs[4], ProjectId: projectIDs[2], OrgId: orgIDs[4], }, }, }, }, }, }, }, { name: "duplicate project grant member error", req: &admin.ImportDataRequest{ Data: &admin.ImportDataRequest_DataOrgs{ DataOrgs: &admin.ImportDataOrg{ Orgs: []*admin.DataOrg{ { OrgId: orgIDs[5], Org: &management.AddOrgRequest{ Name: gofakeit.ProductName(), }, Projects: []*v1.DataProject{ { ProjectId: projectIDs[4], Project: &management.AddProjectRequest{ Name: gofakeit.AppName(), ProjectRoleAssertion: true, }, }, }, ProjectRoles: []*management.AddProjectRoleRequest{ { ProjectId: projectIDs[4], RoleKey: "role1", DisplayName: "role1", }, }, HumanUsers: []*v1.DataHumanUser{ { UserId: userIDs[2], User: &management.ImportHumanUserRequest{ UserName: gofakeit.Username(), Profile: &management.ImportHumanUserRequest_Profile{ FirstName: gofakeit.FirstName(), LastName: gofakeit.LastName(), DisplayName: gofakeit.Username(), PreferredLanguage: gofakeit.LanguageBCP(), }, Email: &management.ImportHumanUserRequest_Email{ Email: gofakeit.Email(), IsEmailVerified: true, }, }, }, }, ProjectGrants: []*v1.DataProjectGrant{ { GrantId: grantIDs[5], ProjectGrant: &management.AddProjectGrantRequest{ ProjectId: projectIDs[4], GrantedOrgId: orgIDs[6], RoleKeys: []string{"role1", "role2"}, }, }, }, ProjectGrantMembers: []*management.AddProjectGrantMemberRequest{ { ProjectId: projectIDs[4], GrantId: grantIDs[5], UserId: userIDs[2], Roles: []string{"PROJECT_GRANT_OWNER"}, }, { ProjectId: projectIDs[4], GrantId: grantIDs[5], UserId: userIDs[2], Roles: []string{"PROJECT_GRANT_OWNER"}, }, }, }, }, }, }, Timeout: time.Minute.String(), }, want: &admin.ImportDataResponse{ Errors: []*admin.ImportDataError{ { Type: "project_grant_member", Id: orgIDs[5] + "_" + projectIDs[4] + "_" + grantIDs[5] + "_" + userIDs[2], Message: "ID=V3-DKcYh Message=Errors.Project.Member.AlreadyExists Parent=(ERROR: duplicate key value violates unique constraint \"unique_constraints_pkey\" (SQLSTATE 23505))", }, }, Success: &admin.ImportDataSuccess{ Orgs: []*admin.ImportDataSuccessOrg{ { OrgId: orgIDs[5], ProjectIds: projectIDs[4:5], ProjectRoles: []string{ projectIDs[4] + "_role1", }, HumanUserIds: userIDs[2:3], ProjectGrants: []*admin.ImportDataSuccessProjectGrant{ { GrantId: grantIDs[5], ProjectId: projectIDs[4], OrgId: orgIDs[6], }, }, ProjectGrantMembers: []*admin.ImportDataSuccessProjectGrantMember{ { ProjectId: projectIDs[4], GrantId: grantIDs[5], UserId: userIDs[2], }, }, }, }, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := Client.ImportData(AdminCTX, tt.req) if tt.wantErr { require.Error(t, err) return } require.NoError(t, err) integration.EqualProto(t, tt.want, got) }) } } func generateIDs(n int) []string { ids := make([]string, n) for i := range ids { ids[i] = uuid.NewString() } return ids }