mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-23 16:27:35 +00:00
dd33538c0a
* feat: return 404 or 409 if org reg disallowed * fix: system limit permissions * feat: add iam limits api * feat: disallow public org registrations on default instance * add integration test * test: integration * fix test * docs: describe public org registrations * avoid updating docs deps * fix system limits integration test * silence integration tests * fix linting * ignore strange linter complaints * review * improve reset properties naming * redefine the api * use restrictions aggregate * test query * simplify and test projection * test commands * fix unit tests * move integration test * support restrictions on default instance * also test GetRestrictions * self review * lint * abstract away resource owner * fix tests * configure supported languages * fix allowed languages * fix tests * default lang must not be restricted * preferred language must be allowed * change preferred languages * check languages everywhere * lint * test command side * lint * add integration test * add integration test * restrict supported ui locales * lint * lint * cleanup * lint * allow undefined preferred language * fix integration tests * update main * fix env var * ignore linter * ignore linter * improve integration test config * reduce cognitive complexity * compile * check for duplicates * remove useless restriction checks * review * revert restriction renaming * fix language restrictions * lint * generate * allow custom texts for supported langs for now * fix tests * cleanup * cleanup * cleanup * lint * unsupported preferred lang is allowed * fix integration test * finish reverting to old property name * finish reverting to old property name * load languages * refactor(i18n): centralize translators and fs * lint * amplify no validations on preferred languages * fix integration test * lint * fix resetting allowed languages * test unchanged restrictions
1200 lines
48 KiB
Go
1200 lines
48 KiB
Go
package admin
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"strconv"
|
|
"time"
|
|
|
|
"cloud.google.com/go/storage"
|
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
|
"github.com/minio/minio-go/v7"
|
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
|
"github.com/zitadel/logging"
|
|
"google.golang.org/api/option"
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
|
action_grpc "github.com/zitadel/zitadel/internal/api/grpc/action"
|
|
"github.com/zitadel/zitadel/internal/api/grpc/authn"
|
|
"github.com/zitadel/zitadel/internal/api/grpc/management"
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
"github.com/zitadel/zitadel/internal/crypto"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
|
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
|
management_pb "github.com/zitadel/zitadel/pkg/grpc/management"
|
|
"github.com/zitadel/zitadel/pkg/grpc/policy"
|
|
v1_pb "github.com/zitadel/zitadel/pkg/grpc/v1"
|
|
)
|
|
|
|
type importResponse struct {
|
|
ret *admin_pb.ImportDataResponse
|
|
count *counts
|
|
err error
|
|
}
|
|
type counts struct {
|
|
humanUserCount int
|
|
humanUserLen int
|
|
machineUserCount int
|
|
machineUserLen int
|
|
userMetadataCount int
|
|
userMetadataLen int
|
|
userLinksCount int
|
|
userLinksLen int
|
|
projectCount int
|
|
projectLen int
|
|
oidcAppCount int
|
|
oidcAppLen int
|
|
apiAppCount int
|
|
apiAppLen int
|
|
actionCount int
|
|
actionLen int
|
|
projectRolesCount int
|
|
projectRolesLen int
|
|
projectGrantCount int
|
|
projectGrantLen int
|
|
userGrantCount int
|
|
userGrantLen int
|
|
projectMembersCount int
|
|
projectMembersLen int
|
|
orgMemberCount int
|
|
orgMemberLen int
|
|
projectGrantMemberCount int
|
|
projectGrantMemberLen int
|
|
appKeysCount int
|
|
machineKeysCount int
|
|
}
|
|
|
|
func (c *counts) getProgress() string {
|
|
return "progress:" +
|
|
"human_users " + strconv.Itoa(c.humanUserCount) + "/" + strconv.Itoa(c.humanUserLen) + ", " +
|
|
"machine_users " + strconv.Itoa(c.machineUserCount) + "/" + strconv.Itoa(c.machineUserLen) + ", " +
|
|
"user_metadata " + strconv.Itoa(c.userMetadataCount) + "/" + strconv.Itoa(c.userMetadataLen) + ", " +
|
|
"user_links " + strconv.Itoa(c.userLinksCount) + "/" + strconv.Itoa(c.userLinksLen) + ", " +
|
|
"projects " + strconv.Itoa(c.projectCount) + "/" + strconv.Itoa(c.projectLen) + ", " +
|
|
"oidc_apps " + strconv.Itoa(c.oidcAppCount) + "/" + strconv.Itoa(c.oidcAppLen) + ", " +
|
|
"api_apps " + strconv.Itoa(c.apiAppCount) + "/" + strconv.Itoa(c.apiAppLen) + ", " +
|
|
"actions " + strconv.Itoa(c.actionCount) + "/" + strconv.Itoa(c.actionLen) + ", " +
|
|
"project_roles " + strconv.Itoa(c.projectRolesCount) + "/" + strconv.Itoa(c.projectRolesLen) + ", " +
|
|
"project_grant " + strconv.Itoa(c.projectGrantCount) + "/" + strconv.Itoa(c.projectGrantLen) + ", " +
|
|
"user_grants " + strconv.Itoa(c.userGrantCount) + "/" + strconv.Itoa(c.userGrantLen) + ", " +
|
|
"project_members " + strconv.Itoa(c.projectMembersCount) + "/" + strconv.Itoa(c.projectMembersLen) + ", " +
|
|
"org_members " + strconv.Itoa(c.orgMemberCount) + "/" + strconv.Itoa(c.orgMemberLen) + ", " +
|
|
"project_grant_members " + strconv.Itoa(c.projectGrantMemberCount) + "/" + strconv.Itoa(c.projectGrantMemberLen)
|
|
}
|
|
|
|
func (s *Server) ImportData(ctx context.Context, req *admin_pb.ImportDataRequest) (_ *admin_pb.ImportDataResponse, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
if req.GetDataOrgs() != nil || req.GetDataOrgsv1() != nil {
|
|
timeoutDuration, err := time.ParseDuration(req.Timeout)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ch := make(chan importResponse, 1)
|
|
ctxTimeout, cancel := context.WithTimeout(ctx, timeoutDuration)
|
|
defer cancel()
|
|
|
|
go func() {
|
|
orgs := make([]*admin_pb.DataOrg, 0)
|
|
if req.GetDataOrgsv1() != nil {
|
|
dataOrgs, err := s.dataOrgsV1ToDataOrgs(ctx, req.GetDataOrgsv1())
|
|
if err != nil {
|
|
ch <- importResponse{ret: nil, err: err}
|
|
return
|
|
}
|
|
orgs = dataOrgs.GetOrgs()
|
|
} else {
|
|
orgs = req.GetDataOrgs().GetOrgs()
|
|
}
|
|
|
|
ret, count, err := s.importData(ctx, orgs)
|
|
ch <- importResponse{ret: ret, count: count, err: err}
|
|
}()
|
|
|
|
select {
|
|
case <-ctxTimeout.Done():
|
|
logging.Errorf("Import to response timeout: %v", ctxTimeout.Err())
|
|
return nil, ctxTimeout.Err()
|
|
case result := <-ch:
|
|
logging.OnError(result.err).Errorf("error while importing: %v", result.err)
|
|
logging.Infof("Import done: %s", result.count.getProgress())
|
|
return result.ret, result.err
|
|
}
|
|
} else {
|
|
v1Transformation := false
|
|
var gcsInput *admin_pb.ImportDataRequest_GCSInput
|
|
var s3Input *admin_pb.ImportDataRequest_S3Input
|
|
var localInput *admin_pb.ImportDataRequest_LocalInput
|
|
if req.GetDataOrgsGcs() != nil {
|
|
gcsInput = req.GetDataOrgsGcs()
|
|
}
|
|
if req.GetDataOrgsv1Gcs() != nil {
|
|
gcsInput = req.GetDataOrgsv1Gcs()
|
|
v1Transformation = true
|
|
}
|
|
if req.GetDataOrgsS3() != nil {
|
|
s3Input = req.GetDataOrgsS3()
|
|
}
|
|
if req.GetDataOrgsv1S3() != nil {
|
|
s3Input = req.GetDataOrgsv1S3()
|
|
v1Transformation = true
|
|
}
|
|
if req.GetDataOrgsLocal() != nil {
|
|
localInput = req.GetDataOrgsLocal()
|
|
}
|
|
if req.GetDataOrgsv1Local() != nil {
|
|
localInput = req.GetDataOrgsv1Local()
|
|
v1Transformation = true
|
|
}
|
|
|
|
timeoutDuration, err := time.ParseDuration(req.Timeout)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dctx := authz.Detach(ctx)
|
|
go func() {
|
|
ch := make(chan importResponse, 1)
|
|
ctxTimeout, cancel := context.WithTimeout(dctx, timeoutDuration)
|
|
defer cancel()
|
|
go func() {
|
|
dataOrgs, err := s.transportDataFromFile(ctxTimeout, v1Transformation, gcsInput, s3Input, localInput)
|
|
if err != nil {
|
|
ch <- importResponse{nil, nil, err}
|
|
return
|
|
}
|
|
resp, count, err := s.importData(ctxTimeout, dataOrgs)
|
|
if err != nil {
|
|
ch <- importResponse{nil, count, err}
|
|
return
|
|
}
|
|
ch <- importResponse{resp, count, nil}
|
|
}()
|
|
|
|
select {
|
|
case <-ctxTimeout.Done():
|
|
logging.Errorf("Export to response timeout: %v", ctxTimeout.Err())
|
|
return
|
|
case result := <-ch:
|
|
logging.OnError(result.err).Errorf("error while importing: %v", err)
|
|
if result.count != nil {
|
|
logging.Infof("Import done: %s", result.count.getProgress())
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
return &admin_pb.ImportDataResponse{}, nil
|
|
}
|
|
|
|
func (s *Server) transportDataFromFile(ctx context.Context, v1Transformation bool, gcsInput *admin_pb.ImportDataRequest_GCSInput, s3Input *admin_pb.ImportDataRequest_S3Input, localInput *admin_pb.ImportDataRequest_LocalInput) (_ []*admin_pb.DataOrg, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
|
|
dataOrgs := make([]*admin_pb.DataOrg, 0)
|
|
data := make([]byte, 0)
|
|
if gcsInput != nil {
|
|
gcsData, err := getFileFromGCS(ctx, gcsInput)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data = gcsData
|
|
}
|
|
if s3Input != nil {
|
|
s3Data, err := getFileFromS3(ctx, s3Input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data = s3Data
|
|
}
|
|
if localInput != nil {
|
|
localData, err := ioutil.ReadFile(localInput.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data = localData
|
|
}
|
|
|
|
jsonpb := &runtime.JSONPb{
|
|
UnmarshalOptions: protojson.UnmarshalOptions{
|
|
DiscardUnknown: true,
|
|
},
|
|
}
|
|
if v1Transformation {
|
|
dataImportV1 := new(v1_pb.ImportDataOrg)
|
|
if err := jsonpb.Unmarshal(data, dataImportV1); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dataImport, err := s.dataOrgsV1ToDataOrgs(ctx, dataImportV1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dataOrgs = dataImport.Orgs
|
|
} else {
|
|
dataImport := new(admin_pb.ImportDataOrg)
|
|
if err := jsonpb.Unmarshal(data, dataImport); err != nil {
|
|
return nil, err
|
|
}
|
|
dataOrgs = dataImport.Orgs
|
|
}
|
|
|
|
return dataOrgs, nil
|
|
}
|
|
|
|
func getFileFromS3(ctx context.Context, input *admin_pb.ImportDataRequest_S3Input) ([]byte, error) {
|
|
minioClient, err := minio.New(input.Endpoint, &minio.Options{
|
|
Creds: credentials.NewStaticV4(input.AccessKeyId, input.SecretAccessKey, ""),
|
|
Secure: input.Ssl,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
exists, err := minioClient.BucketExists(ctx, input.Bucket)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !exists {
|
|
return nil, fmt.Errorf("bucket not existing: %v", err)
|
|
}
|
|
|
|
object, err := minioClient.GetObject(ctx, input.Bucket, input.Path, minio.GetObjectOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer object.Close()
|
|
return ioutil.ReadAll(object)
|
|
}
|
|
|
|
func getFileFromGCS(ctx context.Context, input *admin_pb.ImportDataRequest_GCSInput) ([]byte, error) {
|
|
saJson, err := base64.StdEncoding.DecodeString(input.ServiceaccountJson)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client, err := storage.NewClient(ctx, option.WithCredentialsJSON(saJson))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bucket := client.Bucket(input.Bucket)
|
|
reader, err := bucket.Object(input.Path).NewReader(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer reader.Close()
|
|
return ioutil.ReadAll(reader)
|
|
}
|
|
|
|
func importOrg1(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, ctxData authz.CtxData, org *admin_pb.DataOrg, success *admin_pb.ImportDataSuccess, count *counts, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode, appSecretGenerator crypto.Generator) error {
|
|
_, err := s.command.AddOrgWithID(ctx, org.GetOrg().GetName(), ctxData.UserID, ctxData.ResourceOwner, org.GetOrgId(), []string{})
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "org", Id: org.GetOrgId(), Message: err.Error()})
|
|
if _, err := s.query.OrgByID(ctx, true, org.OrgId); err != nil {
|
|
// TODO: Only nil if err != not found
|
|
return nil
|
|
}
|
|
}
|
|
successOrg := &admin_pb.ImportDataSuccessOrg{
|
|
OrgId: org.GetOrgId(),
|
|
ProjectIds: []string{},
|
|
OidcAppIds: []string{},
|
|
ApiAppIds: []string{},
|
|
HumanUserIds: []string{},
|
|
MachineUserIds: []string{},
|
|
ActionIds: []string{},
|
|
ProjectGrants: []*admin_pb.ImportDataSuccessProjectGrant{},
|
|
UserGrants: []*admin_pb.ImportDataSuccessUserGrant{},
|
|
OrgMembers: []string{},
|
|
ProjectMembers: []*admin_pb.ImportDataSuccessProjectMember{},
|
|
ProjectGrantMembers: []*admin_pb.ImportDataSuccessProjectGrantMember{},
|
|
}
|
|
logging.Debugf("successful org: %s", successOrg.OrgId)
|
|
success.Orgs = append(success.Orgs, successOrg)
|
|
|
|
domainPolicy := org.GetDomainPolicy()
|
|
if org.DomainPolicy != nil {
|
|
_, err := s.command.AddOrgDomainPolicy(ctx, org.GetOrgId(), domainPolicy.UserLoginMustBeDomain, domainPolicy.ValidateOrgDomains, domainPolicy.SmtpSenderAddressMatchesInstanceDomain)
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "domain_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
}
|
|
}
|
|
return importResources(ctx, s, errors, successOrg, org, count, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode, appSecretGenerator)
|
|
}
|
|
|
|
func importLabelPolicy(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) error {
|
|
if org.LabelPolicy == nil {
|
|
return nil
|
|
}
|
|
_, err := s.command.AddLabelPolicy(ctx, org.GetOrgId(), management.AddLabelPolicyToDomain(org.GetLabelPolicy()))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "label_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
} else {
|
|
_, err = s.command.ActivateLabelPolicy(ctx, org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "label_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importLockoutPolicy(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.LockoutPolicy == nil {
|
|
return
|
|
}
|
|
_, err := s.command.AddLockoutPolicy(ctx, org.GetOrgId(), management.AddLockoutPolicyToDomain(org.GetLockoutPolicy()))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "lockout_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
}
|
|
}
|
|
|
|
func importOidcIdps(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg) error {
|
|
if org.OidcIdps == nil {
|
|
return nil
|
|
}
|
|
for _, idp := range org.OidcIdps {
|
|
logging.Debugf("import oidcidp: %s", idp.IdpId)
|
|
_, err := s.command.ImportIDPConfig(ctx, management.AddOIDCIDPRequestToDomain(idp.Idp), idp.IdpId, org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "oidc_idp", Id: idp.IdpId, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
logging.Debugf("successful oidcidp: %s", idp.GetIdpId())
|
|
successOrg.OidcIpds = append(successOrg.OidcIpds, idp.GetIdpId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importJwtIdps(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg) error {
|
|
if org.JwtIdps == nil {
|
|
return nil
|
|
}
|
|
for _, idp := range org.JwtIdps {
|
|
logging.Debugf("import jwtidp: %s", idp.IdpId)
|
|
_, err := s.command.ImportIDPConfig(ctx, management.AddJWTIDPRequestToDomain(idp.Idp), idp.IdpId, org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "jwt_idp", Id: idp.IdpId, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
logging.Debugf("successful jwtidp: %s", idp.GetIdpId())
|
|
successOrg.JwtIdps = append(successOrg.JwtIdps, idp.GetIdpId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importLoginPolicy(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.LoginPolicy == nil {
|
|
return
|
|
}
|
|
_, err := s.command.AddLoginPolicy(ctx, org.GetOrgId(), management.AddLoginPolicyToCommand(org.GetLoginPolicy()))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "login_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
}
|
|
}
|
|
|
|
func importPwComlexityPolicy(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.PasswordComplexityPolicy == nil {
|
|
return
|
|
}
|
|
_, err := s.command.AddPasswordComplexityPolicy(ctx, org.GetOrgId(), management.AddPasswordComplexityPolicyToDomain(org.GetPasswordComplexityPolicy()))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "password_complexity_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
}
|
|
}
|
|
|
|
func importPrivacyPolicy(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.PrivacyPolicy == nil {
|
|
return
|
|
}
|
|
_, err := s.command.AddPrivacyPolicy(ctx, org.GetOrgId(), management.AddPrivacyPolicyToDomain(org.GetPrivacyPolicy()))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "privacy_policy", Id: org.GetOrgId(), Message: err.Error()})
|
|
}
|
|
}
|
|
|
|
func importHumanUsers(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode crypto.Generator) error {
|
|
if org.HumanUsers == nil {
|
|
return nil
|
|
}
|
|
for _, user := range org.GetHumanUsers() {
|
|
logging.Debugf("import user: %s", user.GetUserId())
|
|
human, passwordless, links := management.ImportHumanUserRequestToDomain(user.User)
|
|
human.AggregateID = user.UserId
|
|
_, _, err := s.command.ImportHuman(ctx, org.GetOrgId(), human, passwordless, links, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode)
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "human_user", Id: user.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
} else {
|
|
count.humanUserCount += 1
|
|
logging.Debugf("successful user %d: %s", count.humanUserCount, user.GetUserId())
|
|
successOrg.HumanUserIds = append(successOrg.HumanUserIds, user.GetUserId())
|
|
}
|
|
|
|
if user.User.OtpCode != "" {
|
|
logging.Debugf("import user otp: %s", user.GetUserId())
|
|
if err := s.command.ImportHumanTOTP(ctx, user.UserId, "", org.GetOrgId(), user.User.OtpCode); err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "human_user_otp", Id: user.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
} else {
|
|
logging.Debugf("successful user otp: %s", user.GetUserId())
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importMachineUsers(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.MachineUsers == nil {
|
|
return nil
|
|
}
|
|
for _, user := range org.GetMachineUsers() {
|
|
logging.Debugf("import user: %s", user.GetUserId())
|
|
_, err := s.command.AddMachine(ctx, management.AddMachineUserRequestToCommand(user.GetUser(), org.GetOrgId()))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "machine_user", Id: user.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.machineUserCount += 1
|
|
logging.Debugf("successful user %d: %s", count.machineUserCount, user.GetUserId())
|
|
successOrg.MachineUserIds = append(successOrg.MachineUserIds, user.GetUserId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importUserMetadata(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.UserMetadata == nil {
|
|
return nil
|
|
}
|
|
for _, userMetadata := range org.GetUserMetadata() {
|
|
logging.Debugf("import usermetadata: %s", userMetadata.GetId()+"_"+userMetadata.GetKey())
|
|
_, err := s.command.SetUserMetadata(ctx, &domain.Metadata{Key: userMetadata.GetKey(), Value: userMetadata.GetValue()}, userMetadata.GetId(), org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "user_metadata", Id: userMetadata.GetId() + "_" + userMetadata.GetKey(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.userMetadataCount += 1
|
|
logging.Debugf("successful usermetadata %d: %s", count.userMetadataCount, userMetadata.GetId()+"_"+userMetadata.GetKey())
|
|
successOrg.UserMetadata = append(successOrg.UserMetadata, &admin_pb.ImportDataSuccessUserMetadata{UserId: userMetadata.GetId(), Key: userMetadata.GetKey()})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importMachineKeys(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.MachineKeys == nil {
|
|
return nil
|
|
}
|
|
for _, key := range org.GetMachineKeys() {
|
|
logging.Debugf("import machine_user_key: %s", key.KeyId)
|
|
_, err := s.command.AddUserMachineKey(ctx, &command.MachineKey{
|
|
ObjectRoot: models.ObjectRoot{
|
|
AggregateID: key.UserId,
|
|
ResourceOwner: org.GetOrgId(),
|
|
},
|
|
KeyID: key.KeyId,
|
|
Type: authn.KeyTypeToDomain(key.Type),
|
|
ExpirationDate: key.ExpirationDate.AsTime(),
|
|
PublicKey: key.PublicKey,
|
|
})
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "machine_user_key", Id: key.KeyId, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.machineKeysCount += 1
|
|
logging.Debugf("successful machine_user_key %d: %s", count.machineKeysCount, key.KeyId)
|
|
successOrg.MachineKeys = append(successOrg.MachineKeys, key.KeyId)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importUserLinks(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.UserLinks == nil {
|
|
return nil
|
|
}
|
|
for _, userLinks := range org.GetUserLinks() {
|
|
logging.Debugf("import userlink: %s", userLinks.GetUserId()+"_"+userLinks.GetIdpId()+"_"+userLinks.GetProvidedUserId()+"_"+userLinks.GetProvidedUserName())
|
|
externalIDP := &command.AddLink{
|
|
IDPID: userLinks.IdpId,
|
|
IDPExternalID: userLinks.ProvidedUserId,
|
|
DisplayName: userLinks.ProvidedUserName,
|
|
}
|
|
if _, err := s.command.AddUserIDPLink(ctx, userLinks.UserId, org.GetOrgId(), externalIDP); err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "user_link", Id: userLinks.UserId + "_" + userLinks.IdpId, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.userLinksCount += 1
|
|
logging.Debugf("successful userlink %d: %s", count.userLinksCount, userLinks.GetUserId()+"_"+userLinks.GetIdpId()+"_"+userLinks.GetProvidedUserId()+"_"+userLinks.GetProvidedUserName())
|
|
successOrg.UserLinks = append(successOrg.UserLinks, &admin_pb.ImportDataSuccessUserLinks{UserId: userLinks.GetUserId(), IdpId: userLinks.GetIdpId(), ExternalUserId: userLinks.GetProvidedUserId(), DisplayName: userLinks.GetProvidedUserName()})
|
|
}
|
|
return nil
|
|
|
|
}
|
|
|
|
func importProjects(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.Projects == nil {
|
|
return nil
|
|
}
|
|
for _, project := range org.GetProjects() {
|
|
logging.Debugf("import project: %s", project.GetProjectId())
|
|
_, err := s.command.AddProjectWithID(ctx, management.ProjectCreateToDomain(project.GetProject()), org.GetOrgId(), project.GetProjectId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "project", Id: project.GetProjectId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.projectCount += 1
|
|
logging.Debugf("successful project %d: %s", count.projectCount, project.GetProjectId())
|
|
successOrg.ProjectIds = append(successOrg.ProjectIds, project.GetProjectId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importOIDCApps(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts, appSecretGenerator crypto.Generator) error {
|
|
if org.OidcApps == nil {
|
|
return nil
|
|
}
|
|
for _, app := range org.GetOidcApps() {
|
|
logging.Debugf("import oidcapplication: %s", app.GetAppId())
|
|
_, err := s.command.AddOIDCApplicationWithID(ctx, management.AddOIDCAppRequestToDomain(app.App), org.GetOrgId(), app.GetAppId(), appSecretGenerator)
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "oidc_app", Id: app.GetAppId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.oidcAppCount += 1
|
|
logging.Debugf("successful oidcapplication %d: %s", count.oidcAppCount, app.GetAppId())
|
|
successOrg.OidcAppIds = append(successOrg.OidcAppIds, app.GetAppId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importAPIApps(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts, appSecretGenerator crypto.Generator) error {
|
|
if org.ApiApps == nil {
|
|
return nil
|
|
}
|
|
for _, app := range org.GetApiApps() {
|
|
logging.Debugf("import apiapplication: %s", app.GetAppId())
|
|
_, err := s.command.AddAPIApplicationWithID(ctx, management.AddAPIAppRequestToDomain(app.GetApp()), org.GetOrgId(), app.GetAppId(), appSecretGenerator)
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "api_app", Id: app.GetAppId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.apiAppCount += 1
|
|
logging.Debugf("successful apiapplication %d: %s", count.apiAppCount, app.GetAppId())
|
|
successOrg.ApiAppIds = append(successOrg.ApiAppIds, app.GetAppId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importAppKeys(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.AppKeys == nil {
|
|
return nil
|
|
}
|
|
for _, key := range org.GetAppKeys() {
|
|
logging.Debugf("import app_key: %s", key.Id)
|
|
_, err := s.command.AddApplicationKeyWithID(ctx, &domain.ApplicationKey{
|
|
ObjectRoot: models.ObjectRoot{
|
|
AggregateID: key.ProjectId,
|
|
ResourceOwner: org.GetOrgId(),
|
|
},
|
|
ApplicationID: key.AppId,
|
|
ClientID: key.ClientId,
|
|
KeyID: key.Id,
|
|
Type: authn.KeyTypeToDomain(key.Type),
|
|
ExpirationDate: key.ExpirationDate.AsTime(),
|
|
PublicKey: key.PublicKey,
|
|
}, org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "app_key", Id: key.Id, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.appKeysCount += 1
|
|
logging.Debugf("successful app_key %d: %s", count.appKeysCount, key.Id)
|
|
successOrg.AppKeys = append(successOrg.AppKeys, key.Id)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importActions(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.Actions == nil {
|
|
return nil
|
|
}
|
|
for _, action := range org.GetActions() {
|
|
logging.Debugf("import action: %s", action.GetActionId())
|
|
_, _, err := s.command.AddActionWithID(ctx, management.CreateActionRequestToDomain(action.GetAction()), org.GetOrgId(), action.GetActionId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "action", Id: action.GetActionId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.actionCount += 1
|
|
logging.Debugf("successful action %d: %s", count.actionCount, action.GetActionId())
|
|
successOrg.ActionIds = append(successOrg.ActionIds, action.ActionId)
|
|
}
|
|
return nil
|
|
}
|
|
func importProjectRoles(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts) error {
|
|
if org.ProjectRoles == nil {
|
|
return nil
|
|
}
|
|
for _, role := range org.GetProjectRoles() {
|
|
logging.Debugf("import projectroles: %s", role.ProjectId+"_"+role.RoleKey)
|
|
_, err := s.command.AddProjectRole(ctx, management.AddProjectRoleRequestToDomain(role), org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "project_role", Id: role.ProjectId + "_" + role.RoleKey, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.projectRolesCount += 1
|
|
logging.Debugf("successful projectroles %d: %s", count.projectRolesCount, role.ProjectId+"_"+role.RoleKey)
|
|
successOrg.ProjectRoles = append(successOrg.ProjectRoles, successOrg.ActionIds...)
|
|
successOrg.ProjectRoles = append(successOrg.ProjectRoles, role.ProjectId+"_"+role.RoleKey)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importResources(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg, count *counts, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode, appSecretGenerator crypto.Generator) error {
|
|
if err := importOrgDomains(ctx, s, errors, successOrg, org); err != nil {
|
|
return err
|
|
}
|
|
if err := importLabelPolicy(ctx, s, errors, org); err != nil {
|
|
return err
|
|
}
|
|
importLockoutPolicy(ctx, s, errors, org)
|
|
if err := importOidcIdps(ctx, s, errors, successOrg, org); err != nil {
|
|
return err
|
|
}
|
|
if err := importJwtIdps(ctx, s, errors, successOrg, org); err != nil {
|
|
return err
|
|
}
|
|
importLoginPolicy(ctx, s, errors, org)
|
|
importPwComlexityPolicy(ctx, s, errors, org)
|
|
importPrivacyPolicy(ctx, s, errors, org)
|
|
importLoginTexts(ctx, s, errors, org)
|
|
importInitMessageTexts(ctx, s, errors, org)
|
|
importPWResetMessageTexts(ctx, s, errors, org)
|
|
importVerifyEmailMessageTexts(ctx, s, errors, org)
|
|
importVerifyPhoneMessageTexts(ctx, s, errors, org)
|
|
importDomainClaimedMessageTexts(ctx, s, errors, org)
|
|
importPasswordlessRegistrationMessageTexts(ctx, s, errors, org)
|
|
if err := importHumanUsers(ctx, s, errors, successOrg, org, count, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode); err != nil {
|
|
return err
|
|
}
|
|
if err := importMachineUsers(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importUserMetadata(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importMachineKeys(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importUserLinks(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importProjects(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importOIDCApps(ctx, s, errors, successOrg, org, count, appSecretGenerator); err != nil {
|
|
return err
|
|
}
|
|
if err := importAPIApps(ctx, s, errors, successOrg, org, count, appSecretGenerator); err != nil {
|
|
return err
|
|
}
|
|
if err := importAppKeys(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importActions(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
if err := importProjectRoles(ctx, s, errors, successOrg, org, count); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importOrgDomains(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, org *admin_pb.DataOrg) error {
|
|
if org.Domains == nil {
|
|
return nil
|
|
}
|
|
for _, domainR := range org.Domains {
|
|
orgDomain := &domain.OrgDomain{
|
|
ObjectRoot: models.ObjectRoot{
|
|
AggregateID: org.GetOrgId(),
|
|
},
|
|
Domain: domainR.DomainName,
|
|
Verified: domainR.IsVerified,
|
|
Primary: domainR.IsPrimary,
|
|
}
|
|
_, err := s.command.AddOrgDomain(ctx, org.GetOrgId(), domainR.DomainName, []string{})
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "domain", Id: org.GetOrgId() + "_" + domainR.DomainName, Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
logging.Debugf("successful domain: %s", domainR.DomainName)
|
|
successOrg.Domains = append(successOrg.Domains, domainR.DomainName)
|
|
|
|
if domainR.IsVerified {
|
|
if _, err := s.command.VerifyOrgDomain(ctx, org.GetOrgId(), domainR.DomainName); err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "domain_isverified", Id: org.GetOrgId() + "_" + domainR.DomainName, Message: err.Error()})
|
|
}
|
|
}
|
|
if domainR.IsPrimary {
|
|
if _, err := s.command.SetPrimaryOrgDomain(ctx, orgDomain); err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "domain_isprimary", Id: org.GetOrgId() + "_" + domainR.DomainName, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importLoginTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.LoginTexts == nil {
|
|
return
|
|
}
|
|
for _, text := range org.GetLoginTexts() {
|
|
_, err := s.command.SetOrgLoginText(ctx, org.GetOrgId(), management.SetLoginCustomTextToDomain(text))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "login_texts", Id: org.GetOrgId() + "_" + text.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importInitMessageTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.InitMessages == nil {
|
|
return
|
|
}
|
|
for _, message := range org.GetInitMessages() {
|
|
_, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, management.SetInitCustomTextToDomain(message))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "init_message", Id: org.GetOrgId() + "_" + message.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importPWResetMessageTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.PasswordResetMessages == nil {
|
|
return
|
|
}
|
|
for _, message := range org.GetPasswordResetMessages() {
|
|
_, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, management.SetPasswordResetCustomTextToDomain(message))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "password_reset_message", Id: org.GetOrgId() + "_" + message.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importVerifyEmailMessageTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.VerifyEmailMessages == nil {
|
|
return
|
|
}
|
|
for _, message := range org.GetVerifyEmailMessages() {
|
|
_, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, management.SetVerifyEmailCustomTextToDomain(message))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "verify_email_message", Id: org.GetOrgId() + "_" + message.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importVerifyPhoneMessageTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.VerifyPhoneMessages != nil {
|
|
return
|
|
}
|
|
for _, message := range org.GetVerifyPhoneMessages() {
|
|
_, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, management.SetVerifyPhoneCustomTextToDomain(message))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "verify_phone_message", Id: org.GetOrgId() + "_" + message.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importDomainClaimedMessageTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.DomainClaimedMessages == nil {
|
|
return
|
|
}
|
|
for _, message := range org.GetDomainClaimedMessages() {
|
|
_, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, management.SetDomainClaimedCustomTextToDomain(message))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "domain_claimed_message", Id: org.GetOrgId() + "_" + message.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importPasswordlessRegistrationMessageTexts(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, org *admin_pb.DataOrg) {
|
|
if org.PasswordlessRegistrationMessages == nil {
|
|
return
|
|
}
|
|
for _, message := range org.GetPasswordlessRegistrationMessages() {
|
|
_, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, management.SetPasswordlessRegistrationCustomTextToDomain(message))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "passwordless_registration_message", Id: org.GetOrgId() + "_" + message.Language, Message: err.Error()})
|
|
}
|
|
}
|
|
}
|
|
|
|
func importOrg2(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, success *admin_pb.ImportDataSuccess, count *counts, org *admin_pb.DataOrg) error {
|
|
successOrg := findOldOrg(success, org.OrgId)
|
|
if successOrg == nil {
|
|
return nil
|
|
}
|
|
if org.TriggerActions != nil {
|
|
for _, triggerAction := range org.GetTriggerActions() {
|
|
_, err := s.command.SetTriggerActions(ctx, action_grpc.FlowTypeToDomain(triggerAction.FlowType), action_grpc.TriggerTypeToDomain(triggerAction.TriggerType), triggerAction.ActionIds, org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "trigger_action", Id: triggerAction.FlowType + "_" + triggerAction.TriggerType, Message: err.Error()})
|
|
continue
|
|
}
|
|
successOrg.TriggerActions = append(successOrg.TriggerActions, &management_pb.SetTriggerActionsRequest{FlowType: triggerAction.FlowType, TriggerType: triggerAction.TriggerType, ActionIds: triggerAction.GetActionIds()})
|
|
}
|
|
}
|
|
if org.ProjectGrants != nil {
|
|
for _, grant := range org.GetProjectGrants() {
|
|
logging.Debugf("import projectgrant: %s", grant.GetGrantId()+"_"+grant.GetProjectGrant().GetProjectId()+"_"+grant.GetProjectGrant().GetGrantedOrgId())
|
|
_, err := s.command.AddProjectGrantWithID(ctx, management.AddProjectGrantRequestToDomain(grant.GetProjectGrant()), grant.GetGrantId(), org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "project_grant", Id: org.GetOrgId() + "_" + grant.GetProjectGrant().GetProjectId() + "_" + grant.GetProjectGrant().GetGrantedOrgId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.projectGrantCount += 1
|
|
logging.Debugf("successful projectgrant %d: %s", count.projectGrantCount, grant.GetGrantId()+"_"+grant.GetProjectGrant().GetProjectId()+"_"+grant.GetProjectGrant().GetGrantedOrgId())
|
|
successOrg.ProjectGrants = append(successOrg.ProjectGrants, &admin_pb.ImportDataSuccessProjectGrant{GrantId: grant.GetGrantId(), ProjectId: grant.GetProjectGrant().GetProjectId(), OrgId: grant.GetProjectGrant().GetGrantedOrgId()})
|
|
}
|
|
}
|
|
if org.UserGrants != nil {
|
|
for _, grant := range org.GetUserGrants() {
|
|
logging.Debugf("import usergrant: %s", grant.GetProjectId()+"_"+grant.GetUserId())
|
|
_, err := s.command.AddUserGrant(ctx, management.AddUserGrantRequestToDomain(grant), org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "user_grant", Id: org.GetOrgId() + "_" + grant.GetProjectId() + "_" + grant.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.userGrantCount += 1
|
|
logging.Debugf("successful usergrant %d: %s", count.userGrantCount, grant.GetProjectId()+"_"+grant.GetUserId())
|
|
successOrg.UserGrants = append(successOrg.UserGrants, &admin_pb.ImportDataSuccessUserGrant{ProjectId: grant.GetProjectId(), UserId: grant.GetUserId()})
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importOrg3(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, success *admin_pb.ImportDataSuccess, count *counts, org *admin_pb.DataOrg) error {
|
|
successOrg := findOldOrg(success, org.OrgId)
|
|
if successOrg == nil {
|
|
return nil
|
|
}
|
|
if err := importOrgMembers(ctx, s, errors, successOrg, count, org); err != nil {
|
|
return err
|
|
}
|
|
if err := importProjectGrantMembers(ctx, s, errors, successOrg, count, org); err != nil {
|
|
return err
|
|
}
|
|
return importProjectMembers(ctx, s, errors, successOrg, count, org)
|
|
}
|
|
|
|
func importOrgMembers(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, count *counts, org *admin_pb.DataOrg) error {
|
|
if org.OrgMembers == nil {
|
|
return nil
|
|
}
|
|
for _, member := range org.GetOrgMembers() {
|
|
logging.Debugf("import orgmember: %s", member.GetUserId())
|
|
_, err := s.command.AddOrgMember(ctx, org.GetOrgId(), member.GetUserId(), member.GetRoles()...)
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "org_member", Id: org.GetOrgId() + "_" + member.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.orgMemberCount += 1
|
|
logging.Debugf("successful orgmember %d: %s", count.orgMemberCount, member.GetUserId())
|
|
successOrg.OrgMembers = append(successOrg.OrgMembers, member.GetUserId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importProjectGrantMembers(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, count *counts, org *admin_pb.DataOrg) error {
|
|
if org.ProjectGrantMembers == nil {
|
|
return nil
|
|
}
|
|
for _, member := range org.GetProjectGrantMembers() {
|
|
logging.Debugf("import projectgrantmember: %s", member.GetProjectId()+"_"+member.GetGrantId()+"_"+member.GetUserId())
|
|
_, err := s.command.AddProjectGrantMember(ctx, management.AddProjectGrantMemberRequestToDomain(member))
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "project_grant_member", Id: org.GetOrgId() + "_" + member.GetProjectId() + "_" + member.GetGrantId() + "_" + member.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.projectGrantMemberCount += 1
|
|
logging.Debugf("successful projectgrantmember %d: %s", count.projectGrantMemberCount, member.GetProjectId()+"_"+member.GetGrantId()+"_"+member.GetUserId())
|
|
successOrg.ProjectGrantMembers = append(successOrg.ProjectGrantMembers, &admin_pb.ImportDataSuccessProjectGrantMember{ProjectId: member.GetProjectId(), GrantId: member.GetGrantId(), UserId: member.GetUserId()})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func importProjectMembers(ctx context.Context, s *Server, errors *[]*admin_pb.ImportDataError, successOrg *admin_pb.ImportDataSuccessOrg, count *counts, org *admin_pb.DataOrg) error {
|
|
if org.ProjectMembers == nil {
|
|
return nil
|
|
}
|
|
for _, member := range org.GetProjectMembers() {
|
|
logging.Debugf("import orgmember: %s", member.GetProjectId()+"_"+member.GetUserId())
|
|
_, err := s.command.AddProjectMember(ctx, management.AddProjectMemberRequestToDomain(member), org.GetOrgId())
|
|
if err != nil {
|
|
*errors = append(*errors, &admin_pb.ImportDataError{Type: "project_member", Id: org.GetOrgId() + "_" + member.GetProjectId() + "_" + member.GetUserId(), Message: err.Error()})
|
|
if isCtxTimeout(ctx) {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
count.projectMembersCount += 1
|
|
logging.Debugf("successful orgmember %d: %s", count.projectMembersCount, member.GetProjectId()+"_"+member.GetUserId())
|
|
successOrg.ProjectMembers = append(successOrg.ProjectMembers, &admin_pb.ImportDataSuccessProjectMember{ProjectId: member.GetProjectId(), UserId: member.GetUserId()})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func findOldOrg(success *admin_pb.ImportDataSuccess, orgId string) *admin_pb.ImportDataSuccessOrg {
|
|
for _, oldOrd := range success.Orgs {
|
|
if orgId == oldOrd.OrgId {
|
|
return oldOrd
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*admin_pb.ImportDataResponse, *counts, error) {
|
|
errors := make([]*admin_pb.ImportDataError, 0)
|
|
success := &admin_pb.ImportDataSuccess{}
|
|
count := &counts{}
|
|
|
|
appSecretGenerator, err := s.query.InitHashGenerator(ctx, domain.SecretGeneratorTypeAppSecret, s.passwordHashAlg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
initCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeInitCode, s.userCodeAlg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.userCodeAlg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.userCodeAlg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
passwordlessInitCode, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, s.userCodeAlg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
ctxData := authz.GetCtxData(ctx)
|
|
for _, org := range orgs {
|
|
count.humanUserLen += len(org.GetHumanUsers())
|
|
count.machineUserLen += len(org.GetMachineUsers())
|
|
count.userMetadataLen += len(org.GetUserMetadata())
|
|
count.userLinksLen += len(org.GetUserLinks())
|
|
count.projectLen += len(org.GetProjects())
|
|
count.oidcAppLen += len(org.GetOidcApps())
|
|
count.apiAppLen += len(org.GetApiApps())
|
|
count.actionLen += len(org.GetActions())
|
|
count.projectRolesLen += len(org.GetProjectRoles())
|
|
count.projectGrantLen += len(org.GetProjectGrants())
|
|
count.userGrantLen += len(org.GetUserGrants())
|
|
count.projectMembersLen += len(org.GetProjectMembers())
|
|
count.orgMemberLen += len(org.GetOrgMembers())
|
|
count.projectGrantMemberLen += len(org.GetProjectGrantMembers())
|
|
count.machineKeysCount += len(org.GetMachineKeys())
|
|
count.appKeysCount += len(org.GetAppKeys())
|
|
}
|
|
for _, org := range orgs {
|
|
if err = importOrg1(ctx, s, &errors, ctxData, org, success, count, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessInitCode, appSecretGenerator); err != nil {
|
|
return &admin_pb.ImportDataResponse{Errors: errors, Success: success}, count, err
|
|
}
|
|
}
|
|
for _, org := range orgs {
|
|
if err = importOrg2(ctx, s, &errors, success, count, org); err != nil {
|
|
return &admin_pb.ImportDataResponse{Errors: errors, Success: success}, count, err
|
|
}
|
|
}
|
|
for _, org := range orgs {
|
|
if err = importOrg3(ctx, s, &errors, success, count, org); err != nil {
|
|
return &admin_pb.ImportDataResponse{Errors: errors, Success: success}, count, err
|
|
}
|
|
}
|
|
return &admin_pb.ImportDataResponse{
|
|
Errors: errors,
|
|
Success: success,
|
|
}, count, nil
|
|
}
|
|
|
|
func (s *Server) dataOrgsV1ToDataOrgs(ctx context.Context, dataOrgs *v1_pb.ImportDataOrg) (_ *admin_pb.ImportDataOrg, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
|
|
orgs := make([]*admin_pb.DataOrg, 0)
|
|
for _, orgV1 := range dataOrgs.Orgs {
|
|
triggerActions := make([]*management_pb.SetTriggerActionsRequest, 0)
|
|
for _, action := range orgV1.GetTriggerActions() {
|
|
triggerActions = append(triggerActions, &management_pb.SetTriggerActionsRequest{
|
|
FlowType: strconv.Itoa(int(action.GetFlowType().Number())),
|
|
TriggerType: strconv.Itoa(int(action.GetTriggerType().Number())),
|
|
ActionIds: action.ActionIds,
|
|
})
|
|
}
|
|
|
|
org := &admin_pb.DataOrg{
|
|
OrgId: orgV1.GetOrgId(),
|
|
Org: orgV1.GetOrg(),
|
|
DomainPolicy: nil,
|
|
LabelPolicy: orgV1.GetLabelPolicy(),
|
|
LockoutPolicy: orgV1.GetLockoutPolicy(),
|
|
LoginPolicy: orgV1.GetLoginPolicy(),
|
|
PasswordComplexityPolicy: orgV1.GetPasswordComplexityPolicy(),
|
|
PrivacyPolicy: orgV1.GetPrivacyPolicy(),
|
|
Projects: orgV1.GetProjects(),
|
|
ProjectRoles: orgV1.GetProjectRoles(),
|
|
ApiApps: orgV1.GetApiApps(),
|
|
OidcApps: orgV1.GetOidcApps(),
|
|
HumanUsers: orgV1.GetHumanUsers(),
|
|
MachineUsers: orgV1.GetMachineUsers(),
|
|
TriggerActions: triggerActions,
|
|
Actions: orgV1.GetActions(),
|
|
ProjectGrants: orgV1.GetProjectGrants(),
|
|
UserGrants: orgV1.GetUserGrants(),
|
|
OrgMembers: orgV1.GetOrgMembers(),
|
|
ProjectMembers: orgV1.GetProjectMembers(),
|
|
ProjectGrantMembers: orgV1.GetProjectGrantMembers(),
|
|
UserMetadata: orgV1.GetUserMetadata(),
|
|
LoginTexts: orgV1.GetLoginTexts(),
|
|
InitMessages: orgV1.GetInitMessages(),
|
|
PasswordResetMessages: orgV1.GetPasswordResetMessages(),
|
|
VerifyEmailMessages: orgV1.GetVerifyEmailMessages(),
|
|
VerifyPhoneMessages: orgV1.GetVerifyPhoneMessages(),
|
|
DomainClaimedMessages: orgV1.GetDomainClaimedMessages(),
|
|
PasswordlessRegistrationMessages: orgV1.GetPasswordlessRegistrationMessages(),
|
|
OidcIdps: orgV1.GetOidcIdps(),
|
|
JwtIdps: orgV1.GetJwtIdps(),
|
|
UserLinks: orgV1.GetUserLinks(),
|
|
Domains: orgV1.GetDomains(),
|
|
AppKeys: orgV1.GetAppKeys(),
|
|
MachineKeys: orgV1.GetMachineKeys(),
|
|
}
|
|
if orgV1.IamPolicy != nil {
|
|
defaultDomainPolicy, err := s.query.DefaultDomainPolicy(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
org.DomainPolicy = &admin_pb.AddCustomDomainPolicyRequest{
|
|
UserLoginMustBeDomain: orgV1.IamPolicy.UserLoginMustBeDomain,
|
|
ValidateOrgDomains: defaultDomainPolicy.ValidateOrgDomains,
|
|
SmtpSenderAddressMatchesInstanceDomain: defaultDomainPolicy.SMTPSenderAddressMatchesInstanceDomain,
|
|
}
|
|
}
|
|
if org.LoginPolicy != nil {
|
|
defaultLoginPolicy, err := s.query.DefaultLoginPolicy(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
org.LoginPolicy.ExternalLoginCheckLifetime = durationpb.New(defaultLoginPolicy.ExternalLoginCheckLifetime)
|
|
org.LoginPolicy.MultiFactorCheckLifetime = durationpb.New(defaultLoginPolicy.MultiFactorCheckLifetime)
|
|
org.LoginPolicy.SecondFactorCheckLifetime = durationpb.New(defaultLoginPolicy.SecondFactorCheckLifetime)
|
|
org.LoginPolicy.PasswordCheckLifetime = durationpb.New(defaultLoginPolicy.PasswordCheckLifetime)
|
|
org.LoginPolicy.MfaInitSkipLifetime = durationpb.New(defaultLoginPolicy.MFAInitSkipLifetime)
|
|
|
|
if orgV1.SecondFactors != nil {
|
|
org.LoginPolicy.SecondFactors = make([]policy.SecondFactorType, len(orgV1.SecondFactors))
|
|
for i, factor := range orgV1.SecondFactors {
|
|
org.LoginPolicy.SecondFactors[i] = factor.GetType()
|
|
}
|
|
}
|
|
if orgV1.MultiFactors != nil {
|
|
org.LoginPolicy.MultiFactors = make([]policy.MultiFactorType, len(orgV1.MultiFactors))
|
|
for i, factor := range orgV1.MultiFactors {
|
|
org.LoginPolicy.MultiFactors[i] = factor.GetType()
|
|
}
|
|
}
|
|
if orgV1.Idps != nil {
|
|
org.LoginPolicy.Idps = make([]*management_pb.AddCustomLoginPolicyRequest_IDP, len(orgV1.Idps))
|
|
for i, idpR := range orgV1.Idps {
|
|
org.LoginPolicy.Idps[i] = &management_pb.AddCustomLoginPolicyRequest_IDP{
|
|
IdpId: idpR.GetIdpId(),
|
|
OwnerType: idpR.GetOwnerType(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
orgs = append(orgs, org)
|
|
}
|
|
|
|
return &admin_pb.ImportDataOrg{
|
|
Orgs: orgs,
|
|
}, nil
|
|
}
|
|
|
|
func isCtxTimeout(ctx context.Context) bool {
|
|
select {
|
|
case <-ctx.Done():
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|