Пример #1
0
        public async Task <int> CreateWithAdminUserAsync(
            string tenancyName,
            string name,
            string adminPassword,
            string adminEmailAddress,
            string connectionString,
            bool isActive,
            int?editionId,
            bool shouldChangePasswordOnNextLogin,
            bool sendActivationEmail,
            DateTime?subscriptionEndDate,
            bool isInTrialPeriod,
            string emailActivationLink)
        {
            int  newTenantId;
            long newAdminId;

            await CheckEditionAsync(editionId, isInTrialPeriod);

            if (isInTrialPeriod && !subscriptionEndDate.HasValue)
            {
                throw new UserFriendlyException(LocalizationManager.GetString(LockthreatConsts.LocalizationSourceName, "TrialWithoutEndDateErrorMessage"));
            }

            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                //Create tenant
                var tenant = new Tenant(tenancyName, name)
                {
                    IsActive  = isActive,
                    EditionId = editionId,
                    SubscriptionEndDateUtc = subscriptionEndDate?.ToUniversalTime(),
                    IsInTrialPeriod        = isInTrialPeriod,
                    ConnectionString       = connectionString.IsNullOrWhiteSpace() ? null : SimpleStringCipher.Instance.Encrypt(connectionString)
                };

                await CreateAsync(tenant);

                await _unitOfWorkManager.Current.SaveChangesAsync(); //To get new tenant's id.

                //Create tenant database
                _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);

                //We are working entities of new tenant, so changing tenant filter
                using (_unitOfWorkManager.Current.SetTenantId(tenant.Id))
                {
                    //Create static roles for new tenant
                    CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));
                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get static role ids

                    //grant all permissions to admin role
                    var adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin);
                    await _roleManager.GrantAllPermissionsAsync(adminRole);

                    //User role should be default
                    var userRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.User);
                    userRole.IsDefault = true;
                    CheckErrors(await _roleManager.UpdateAsync(userRole));

                    //Create admin user for the tenant
                    var adminUser = User.CreateTenantAdminUser(tenant.Id, adminEmailAddress);
                    adminUser.ShouldChangePasswordOnNextLogin = shouldChangePasswordOnNextLogin;
                    adminUser.IsActive = true;

                    if (adminPassword.IsNullOrEmpty())
                    {
                        adminPassword = await _userManager.CreateRandomPassword();
                    }
                    else
                    {
                        await _userManager.InitializeOptionsAsync(AbpSession.TenantId);

                        foreach (var validator in _userManager.PasswordValidators)
                        {
                            CheckErrors(await validator.ValidateAsync(_userManager, adminUser, adminPassword));
                        }
                    }

                    adminUser.Password = _passwordHasher.HashPassword(adminUser, adminPassword);

                    CheckErrors(await _userManager.CreateAsync(adminUser));
                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get admin user's id

                    //Assign admin user to admin role!
                    CheckErrors(await _userManager.AddToRoleAsync(adminUser, adminRole.Name));

                    //Notifications
                    await _appNotifier.WelcomeToTheApplicationAsync(adminUser);

                    //Send activation email
                    if (sendActivationEmail)
                    {
                        adminUser.SetNewEmailConfirmationCode();
                        await _userEmailer.SendEmailActivationLinkAsync(adminUser, emailActivationLink, adminPassword);
                    }

                    await _unitOfWorkManager.Current.SaveChangesAsync();

                    await _demoDataBuilder.BuildForAsync(tenant);

                    newTenantId = tenant.Id;
                    newAdminId  = adminUser.Id;
                }

                await uow.CompleteAsync();
            }

            //Used a second UOW since UOW above sets some permissions and _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync needs these permissions to be saved.
            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                using (_unitOfWorkManager.Current.SetTenantId(newTenantId))
                {
                    await _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync(new UserIdentifier(newTenantId, newAdminId));

                    await _unitOfWorkManager.Current.SaveChangesAsync();

                    await uow.CompleteAsync();
                }
            }

            return(newTenantId);
        }
Пример #2
0
        public void Run(bool skipConnVerification)
        {
            var hostConnStr = _connectionStringResolver.GetNameOrConnectionString(new ConnectionStringResolveArgs(MultiTenancySides.Host));

            if (hostConnStr.IsNullOrWhiteSpace())
            {
                Log.Write("Configuration file should contain a connection string named 'Default'");
                return;
            }

            Log.Write("Host database: " + hostConnStr);
            if (!skipConnVerification)
            {
                Log.Write("Continue to migration for this host database and all tenants..? (Y/N): ");
                var command = Console.ReadLine();
                if (!command.IsIn("Y", "y"))
                {
                    Log.Write("Migration canceled.");
                    return;
                }
            }

            Log.Write("HOST database migration started...");

            try
            {
                _migrator.CreateOrMigrateForHost();
            }
            catch (Exception ex)
            {
                Log.Write("An error occured during migration of host database:");
                Log.Write(ex.ToString());
                Log.Write("Canceled migrations.");
                return;
            }

            Log.Write("HOST database migration completed.");
            Log.Write("--------------------------------------------------------");

            var migratedDatabases = new HashSet <string>();
            var tenants           = _tenantRepository.GetAllList(t => t.ConnectionString != null && t.ConnectionString != "");

            for (int i = 0; i < tenants.Count; i++)
            {
                var tenant = tenants[i];
                Log.Write(string.Format("Tenant database migration started... ({0} / {1})", (i + 1), tenants.Count));
                Log.Write("Name              : " + tenant.Name);
                Log.Write("TenancyName       : " + tenant.TenancyName);
                Log.Write("Tenant Id         : " + tenant.Id);
                Log.Write("Connection string : " + SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString));

                if (!migratedDatabases.Contains(tenant.ConnectionString))
                {
                    try
                    {
                        _migrator.CreateOrMigrateForTenant(tenant);
                    }
                    catch (Exception ex)
                    {
                        Log.Write("An error occured during migration of tenant database:");
                        Log.Write(ex.ToString());
                        Log.Write("Skipped this tenant and will continue for others...");
                    }

                    migratedDatabases.Add(tenant.ConnectionString);
                }
                else
                {
                    Log.Write("This database has already migrated before (you have more than one tenant in same database). Skipping it....");
                }

                Log.Write(string.Format("Tenant database migration completed. ({0} / {1})", (i + 1), tenants.Count));
                Log.Write("--------------------------------------------------------");
            }

            Log.Write("All databases have been migrated.");
        }
Пример #3
0
        public async Task <int> CreateWithAdminUserAsync(
            string tenantType,
            string tenancyName,
            string name,
            string hostAdminEmailAddress,
            string hostAdminPassword,
            string adminPassword,
            string adminEmailAddress,
            string connectionString,
            bool isActive,
            int?editionId,
            bool shouldChangePasswordOnNextLogin,
            bool sendActivationEmail,
            DateTime?subscriptionEndDate,
            bool isInTrialPeriod,
            string emailActivationLink)
        {
            int  newTenantId;
            long newAdminId;

            await CheckEditionAsync(editionId, isInTrialPeriod);

            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                //Create tenant
                var tenant = new Tenant(tenancyName, name)
                {
                    TenantType             = tenantType,
                    IsActive               = isActive,
                    EditionId              = editionId,
                    SubscriptionEndDateUtc = subscriptionEndDate?.ToUniversalTime(),
                    IsInTrialPeriod        = isInTrialPeriod,
                    ConnectionString       = connectionString.IsNullOrWhiteSpace() ? null : SimpleStringCipher.Instance.Encrypt(connectionString)
                };

                await CreateAsync(tenant);

                await _unitOfWorkManager.Current.SaveChangesAsync(); //To get new tenant's id.

                //Create tenant database
                _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);

                //We are working with entities of the new tenant, so changing tenant filter
                using (_unitOfWorkManager.Current.SetTenantId(tenant.Id))
                {
                    List <string> adminPermissions = new List <string>();
                    List <string> userPermissions  = new List <string>();

                    string staticAdminRoleName = string.Empty;
                    string staticUserRoleName  = string.Empty;

                    switch (tenantType)
                    {
                    case "A":
                        staticAdminRoleName = StaticRoleNames.Tenants.AssetOwnerAdmin;
                        staticUserRoleName  = StaticRoleNames.Tenants.AssetOwnerUser;
                        adminPermissions    = TenantPermissionConsts.AssetOwnerAdminPermissions.Split(',').ToList();
                        userPermissions     = TenantPermissionConsts.AssetOwnerUserPermissions.Split(',').ToList();
                        break;

                    case "C":
                        staticAdminRoleName = StaticRoleNames.Tenants.CustomerAdmin;
                        staticUserRoleName  = StaticRoleNames.Tenants.CustomerUser;
                        adminPermissions    = TenantPermissionConsts.CustomerAdminPermissions.Split(',').ToList();
                        userPermissions     = TenantPermissionConsts.CustomerUserPermissions.Split(',').ToList();
                        break;

                    case "V":
                        staticAdminRoleName = StaticRoleNames.Tenants.VendorAdmin;
                        staticUserRoleName  = StaticRoleNames.Tenants.VendorUser;
                        adminPermissions    = TenantPermissionConsts.VendorAdminPermissions.Split(',').ToList();
                        userPermissions     = TenantPermissionConsts.VendorUserPermissions.Split(',').ToList();
                        break;

                    default:
                        throw new Exception($"Cannot determine TenantType for {tenant.TenancyName}!");
                    }

                    //Create static roles for new tenant

                    var hostAdminRole = new Role()
                    {
                        TenantId = tenant.Id, IsDefault = false, IsStatic = true, Name = StaticRoleNames.Tenants.Admin, DisplayName = StaticRoleNames.Tenants.Admin, NormalizedName = StaticRoleNames.Tenants.Admin.ToUpper()
                    };
                    CheckErrors(await _roleManager.CreateAsync(hostAdminRole));

                    var adminRole = new Role()
                    {
                        TenantId = tenant.Id, IsDefault = false, IsStatic = true, Name = staticAdminRoleName, DisplayName = staticAdminRoleName, NormalizedName = staticAdminRoleName.ToUpper()
                    };
                    CheckErrors(await _roleManager.CreateAsync(adminRole));

                    var userRole = new Role()
                    {
                        TenantId = tenant.Id, IsDefault = true, IsStatic = true, Name = staticUserRoleName, DisplayName = staticUserRoleName, NormalizedName = staticUserRoleName.ToUpper()
                    };
                    CheckErrors(await _roleManager.CreateAsync(userRole));

                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get static role ids

                    // Grant permissions to the Admin role
                    foreach (var permission in adminPermissions)
                    {
                        if (permission != "")
                        {
                            await _rolePermissionStore.AddPermissionAsync(adminRole, new PermissionGrantInfo(permission, true));
                        }
                    }

                    // Grant permissions to the User role
                    foreach (var permission in userPermissions)
                    {
                        if (permission != "")
                        {
                            await _rolePermissionStore.AddPermissionAsync(userRole, new PermissionGrantInfo(permission, true));
                        }
                    }

                    //Create the host admin user for the tenant

                    var hostAdminUser = User.CreateTenantHostAdminUser(tenant.Id, hostAdminEmailAddress);
                    hostAdminUser.ShouldChangePasswordOnNextLogin = shouldChangePasswordOnNextLogin;
                    hostAdminUser.IsActive = true;

                    if (hostAdminPassword.IsNullOrEmpty())
                    {
                        hostAdminPassword = await _userManager.CreateRandomPassword();
                    }
                    else
                    {
                        await _userManager.InitializeOptionsAsync(AbpSession.TenantId);

                        foreach (var validator in _userManager.PasswordValidators)
                        {
                            CheckErrors(await validator.ValidateAsync(_userManager, hostAdminUser, hostAdminPassword));
                        }
                    }

                    hostAdminUser.Password = _passwordHasher.HashPassword(hostAdminUser, hostAdminPassword);

                    CheckErrors(await _userManager.CreateAsync(hostAdminUser));
                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get hostAdmin user's id

                    //Assign hostAdmin user to hostAdmin role!
                    CheckErrors(await _userManager.AddToRoleAsync(hostAdminUser, hostAdminRole.Name));


                    //Create admin user for the tenant

                    var firstName = adminEmailAddress.Split('@').ToList().FirstOrDefault();

                    Regex rgx         = new Regex("[^a-zA-Z0-9 -]");
                    var   newUserName = string.Format("{0}Admin", rgx.Replace(tenancyName, "").ToLower()).Replace(" ", "");

                    var adminUser = User.CreateTenantAdminUser(tenant.Id, adminEmailAddress, newUserName, firstName, "Admin");
                    adminUser.ShouldChangePasswordOnNextLogin = shouldChangePasswordOnNextLogin;
                    adminUser.IsActive = true;

                    if (adminPassword.IsNullOrEmpty())
                    {
                        adminPassword = await _userManager.CreateRandomPassword();
                    }
                    else
                    {
                        await _userManager.InitializeOptionsAsync(AbpSession.TenantId);

                        foreach (var validator in _userManager.PasswordValidators)
                        {
                            CheckErrors(await validator.ValidateAsync(_userManager, adminUser, adminPassword));
                        }
                    }

                    adminUser.Password = _passwordHasher.HashPassword(adminUser, adminPassword);

                    CheckErrors(await _userManager.CreateAsync(adminUser));
                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get admin user's id

                    //Assign admin user to admin role!
                    CheckErrors(await _userManager.AddToRoleAsync(adminUser, adminRole.Name));

                    //Notifications
                    await _appNotifier.WelcomeToTheApplicationAsync(adminUser);

                    //Send activation email
                    if (sendActivationEmail)
                    {
                        adminUser.SetNewEmailConfirmationCode();
                        await _userEmailer.SendEmailActivationLinkAsync(adminUser, emailActivationLink, adminPassword);
                    }

                    await _unitOfWorkManager.Current.SaveChangesAsync();

                    await _demoDataBuilder.BuildForAsync(tenant);

                    newTenantId = tenant.Id;
                    newAdminId  = adminUser.Id;
                }

                // Create the AssetOwner, Vendor or Customer

                switch (tenantType)
                {
                case "A":
                    AssetOwner assetOwner = new AssetOwner()
                    {
                        Reference = tenant.TenancyName, Identifier = tenant.TenancyName, Name = tenant.Name, TenantId = tenant.Id
                    };
                    _assetOwnerRepository.Insert(assetOwner);
                    break;

                case "C":

                    var defaultCustomerTypeId = _customerTypeRepository.GetAll().FirstOrDefault().Id;

                    Customer customer = new Customer()
                    {
                        CustomerTypeId = defaultCustomerTypeId, Reference = tenant.TenancyName, Identifier = tenant.TenancyName, Name = tenant.Name, TenantId = tenant.Id
                    };
                    _customerRepository.Insert(customer);
                    break;

                case "V":
                    Vendor vendor = new Vendor()
                    {
                        Reference = tenant.TenancyName, Identifier = tenant.TenancyName, Name = tenant.Name, TenantId = tenant.Id
                    };
                    _vendorRepository.Insert(vendor);
                    break;

                default:
                    throw new Exception($"Cannot determine TenantType for {tenant.TenancyName}!");
                }

                await uow.CompleteAsync();
            }

            // Used a second UOW since the UOW above sets some permissions and _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync needs these permissions to be saved.
            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                using (_unitOfWorkManager.Current.SetTenantId(newTenantId))
                {
                    await _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync(new UserIdentifier(newTenantId, newAdminId));

                    await _unitOfWorkManager.Current.SaveChangesAsync();

                    await uow.CompleteAsync();
                }
            }

            return(newTenantId);
        }
Пример #4
0
        public override async Task <TenantDto> Create(CreateTenantDto input)
        {
            CheckCreatePermission();

            var category = await _tenantCategoryManager.TenantCategories
                           .Where(x => x.Id == input.Category.Id)
                           .Include(x => x.SubCategories)
                           .OrderBy(x => x.Title).ToListAsync();

            input.Category = category.FirstOrDefault();
            // Create tenant
            var tenant = ObjectMapper.Map <Tenant>(input);

            tenant.ConnectionString = input.ConnectionString.IsNullOrEmpty()
                ? null
                : SimpleStringCipher.Instance.Encrypt(input.ConnectionString);

            var defaultEdition = await _editionManager.FindByNameAsync(EditionManager.DefaultEditionName);

            if (defaultEdition != null)
            {
                tenant.EditionId = defaultEdition.Id;
            }

            await _tenantManager.CreateAsync(tenant);

            await CurrentUnitOfWork.SaveChangesAsync(); // To get new tenant's id.

            foreach (var subcategory in category.FirstOrDefault().SubCategories.ToList())
            {
                if (input._subCategories.Exists(x => x.Title == subcategory.Title))
                {
                    var twsc = new TenantWithSubCategory(tenant, subcategory);
                    await CurrentUnitOfWork.SaveChangesAsync();

                    tenant.AddSubCategories(twsc);
                }
            }

            await CurrentUnitOfWork.SaveChangesAsync(); // To get new tenant's id.

            // Create tenant database
            _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);

            // We are working entities of new tenant, so changing tenant filter
            using (CurrentUnitOfWork.SetTenantId(tenant.Id))
            {
                // Create static roles for new tenant
                CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));

                await CurrentUnitOfWork.SaveChangesAsync(); // To get static role ids

                // Grant all permissions to admin role
                var adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin);
                await _roleManager.GrantAllPermissionsAsync(adminRole);

                // Create admin user for the tenant
                var adminUser = User.CreateTenantAdminUser(tenant.Id, input.AdminEmailAddress);
                await _userManager.InitializeOptionsAsync(tenant.Id);

                CheckErrors(await _userManager.CreateAsync(adminUser, User.DefaultPassword));
                await CurrentUnitOfWork.SaveChangesAsync(); // To get admin user's id

                // Assign admin user to role!
                CheckErrors(await _userManager.AddToRoleAsync(adminUser, adminRole.Name));
                await CurrentUnitOfWork.SaveChangesAsync();
            }

            var tenantDto = await GetTenant(new EntityDto <long>(tenant.Id));

            return(tenantDto);
        }
Пример #5
0
        public async Task <int> CreateWithAdminUserAsync(string tenancyName, string name, long?tinhId, string adminPassword, string adminEmailAddress, string connectionString, bool isActive, int?editionId, bool shouldChangePasswordOnNextLogin, bool sendActivationEmail)
        {
            int  newTenantId;
            long newAdminId;

            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                //Create tenant
                var tenant = new Tenant(tenancyName, name)
                {
                    IsActive         = isActive,
                    EditionId        = editionId,
                    ConnectionString = connectionString.IsNullOrWhiteSpace() ? null : SimpleStringCipher.Instance.Encrypt(connectionString)
                };
                tenant.TinhId = tinhId;
                await CreateAsync(tenant);

                await _unitOfWorkManager.Current.SaveChangesAsync(); //To get new tenant's id.

                //Create tenant database
                _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);

                //We are working entities of new tenant, so changing tenant filter
                using (_unitOfWorkManager.Current.SetTenantId(tenant.Id))
                {
                    //Create static roles for new tenant
                    CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));
                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get static role ids

                    //grant all permissions to admin role
                    var adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin);
                    await _roleManager.GrantAllPermissionsAsync(adminRole);

                    //User role should be default
                    var userRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.User);
                    userRole.IsDefault = true;
                    CheckErrors(await _roleManager.UpdateAsync(userRole));

                    //Create admin user for the tenant
                    if (adminPassword.IsNullOrEmpty())
                    {
                        adminPassword = User.CreateRandomPassword();
                    }

                    var adminUser = User.CreateTenantAdminUser(tenant.Id, adminEmailAddress, adminPassword);
                    adminUser.ShouldChangePasswordOnNextLogin = shouldChangePasswordOnNextLogin;
                    adminUser.IsActive = true;

                    CheckErrors(await _userManager.CreateAsync(adminUser));
                    await _unitOfWorkManager.Current.SaveChangesAsync(); //To get admin user's id

                    //Assign admin user to admin role!
                    CheckErrors(await _userManager.AddToRoleAsync(adminUser.Id, adminRole.Name));

                    //Notifications
                    await _appNotifier.WelcomeToTheApplicationAsync(adminUser);

                    //Send activation email
                    if (sendActivationEmail)
                    {
                        adminUser.SetNewEmailConfirmationCode();
                        await _userEmailer.SendEmailActivationLinkAsync(adminUser, adminPassword);
                    }

                    await _unitOfWorkManager.Current.SaveChangesAsync();

                    await _demoDataBuilder.BuildForAsync(tenant);

                    newTenantId = tenant.Id;
                    newAdminId  = adminUser.Id;
                }

                await uow.CompleteAsync();
            }

            //Used a second UOW since UOW above sets some permissions and _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync needs these permissions to be saved.
            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                using (_unitOfWorkManager.Current.SetTenantId(newTenantId))
                {
                    await _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync(new UserIdentifier(newTenantId, newAdminId));

                    await _unitOfWorkManager.Current.SaveChangesAsync();

                    await uow.CompleteAsync();
                }
            }

            return(newTenantId);
        }
Пример #6
0
        /// <summary>
        /// 注册租户信息
        /// </summary>
        /// <param name="Input"></param>
        /// <returns></returns>
        public async Task <RegisterTenantResultDto> RegisterTenantAsync(CreateTenantDto input)
        {
            // 检查验证码
            await CaptchaHelper.CheckVierificationCode(
                this._cacheManager,
                this.SettingManager,
                CaptchaType.HostTenantRegister,
                input.TenancyName,
                input.VerificationCode);


            //创建租户信息
            var tenant = new Tenant(input.TenancyName, input.Name)
            {
                // 激活根据系统配置
                IsActive = await SettingManager.GetSettingValueAsync <bool>(AppSettingNames.Host.AllowSelfRegistration)
            };

            tenant.ConnectionString = input.ConnectionString.IsNullOrEmpty() ? null : SimpleStringCipher.Instance.Encrypt(input.ConnectionString);

            Abp.Application.Editions.Edition defaultEdition = await _editionManager.FindByNameAsync(EditionManager.DefaultEditionName);

            if (defaultEdition != null)
            {
                tenant.EditionId = defaultEdition.Id;
            }
            await TenantManager.CreateAsync(tenant);

            // 保存以获取新租户的Id
            await CurrentUnitOfWork.SaveChangesAsync();

            // 创建租户数据库
            _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);
            //创建成功后,需要设置当前工作单元为当前登录后的租户信息
            using (CurrentUnitOfWork.SetTenantId(tenant.Id))
            {
                // 给新租户创建角色
                CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));
                // 保存,获取角色id
                await CurrentUnitOfWork.SaveChangesAsync();

                // 分配权限
                Role adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin);
                await _roleManager.GrantAllPermissionsAsync(adminRole);

                // 创建此租户的管理员用户
                var adminUser = User.CreateTenantAdminUser(tenant.Id, input.AdminEmailAddress, input.UserName);


                // 如果没有提交密码,那么走的是默认密码 123qwe
                adminUser.Password = _passwordHasher.HashPassword(adminUser, input.TenantAdminPassword.IsNullOrWhiteSpace() ? User.DefaultPassword : input.TenantAdminPassword);
                CheckErrors(await UserManager.CreateAsync(adminUser));

                // 保存,获取角色id
                await CurrentUnitOfWork.SaveChangesAsync();

                // 授权
                CheckErrors(await UserManager.AddToRoleAsync(adminUser, adminRole.Name));
                await CurrentUnitOfWork.SaveChangesAsync();
            }


            var resultDto = new RegisterTenantResultDto()
            {
                TenantId = tenant.Id,
                IsActive = tenant.IsActive,
                UseCaptchaOnUserLogin = await UseCaptchaOnLogin(tenant.Id)
            };

            return(resultDto);
        }