Thanks, that nudged me in the right direction.
I've opted to replace the IConnectionStringChecker
instead, seems to work
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IConnectionStringChecker), typeof(EncryptedConnectionStringChecker))]
public class EncryptedConnectionStringChecker : SqlServerConnectionStringChecker, IConnectionStringChecker, ITransientDependency
{
private readonly IStringEncryptionService _stringEncryptionService;
public EncryptedConnectionStringChecker(IStringEncryptionService stringEncryptionService)
{
_stringEncryptionService = stringEncryptionService ?? throw new ArgumentNullException(nameof(stringEncryptionService));
}
public override async Task<AbpConnectionStringCheckResult> CheckAsync(string connectionString)
{
if (string.IsNullOrWhiteSpace(connectionString))
{
throw new ArgumentException("Connection string cannot be null or empty.", nameof(connectionString));
}
try
{
var decryptedConnectionString = _stringEncryptionService.Decrypt(connectionString);
return await base.CheckAsync(decryptedConnectionString);
}
catch (Exception)
{
return new AbpConnectionStringCheckResult { Connected = false, DatabaseExists = false };
}
}
}
While I do get what you're telling me bot, I do think that overriding the actual Check logic should work in this case... So please let a human take this one :)
We currently got an error when trying to create a Tenant:
EXCEPTION: Volo.Abp.UserFriendlyException: The tenant connection string 'Default' is not valid at Volo.Saas.Host.TenantAppService.CheckConnectionStringAsync(Tenant tenant) at Volo.Saas.Host.TenantAppService.<>c__DisplayClass27_0.ETBg5kcYQAHiA0HJrJL.MoveNext() --- End of stack trace from previous location --- at Volo.Saas.Host.TenantAppService.CreateAsync(SaasTenantCreateDto input)
We think this started happening after upgrading to 9.2.0. We have changed ABP to store connection strings encrypted. For this, we assign an encrypted connection string to SaasTenantCreateDto.ConnectionString.Default. This used to work fine, but now results in the error message above.
We have found a method to override on the ITenantAppService which looked promising:
public override Task<bool> CheckConnectionStringAsync(string connectionString)
{
var decrypted = _stringEncryptionService.Decrypt(connectionString);
return base.CheckConnectionStringAsync(decrypted);
}
This however did not lead to success.
Any idea how we can fix this?
For further reference, this is how our overridden CreateAsync looks like:
public override async Task<SaasTenantDto> CreateAsync(SaasTenantCreateDto input)
{
var servers = await _availableSqlServerAppService.GetListAsync(new GetAvailableSqlServersInput {AvailableForTenantDatabase = true});
var first = servers.Items.OrderBy(i => i.NrOfTenants).First();
var defaultConnectionString = new SqlConnectionStringBuilder(DbConnectionOptions.ConnectionStrings.Default);
var baseDBName = string.Join('.', defaultConnectionString.InitialCatalog.Split(".").SkipLast(1));
var connectionString = new SqlConnectionStringBuilder {InitialCatalog = $"{baseDBName}.Tenant.{input.Name}", DataSource = first.SqlServerName, UserID = first.LoginUser, Password = _stringEncryptionService.Decrypt(first.EncryptedPassword), TrustServerCertificate = true};
input.ConnectionStrings.Default = _stringEncryptionService.Encrypt(connectionString.ConnectionString);
await CreateAzureDatabaseIfNotExists(connectionString);
return await base.CreateAsync(input);
}
Thx
Yes, that works! Thank you very much for the quick answer (Human, not the bot :) )
Hi
We are currently using ABP 9.2.0 with the Lepton Theme, Angular.
At some point probably during one of the last version updates (maybe 9.1.3?) it seems that our Homepage lost it's localizations.
Just the Homepage though (the one with the "LongWelcomeMessage
" localization) - all other pages are fine.
We're not aware of any changes from our side specifically to the Home Component, and we have no idea where to start looking for the error.
We rarely look at this page, I noticed it on the Update from 9.2.0, but we're also seeing it in an environment that still has 9.1.3...
There are no errors on the console, however we find these warnings: The localization source separator (::) not found.
hi
I think the ASP.NET Core only checks the
BindProperty
of the baseLoginModel
class.
Somehow I was under the impression that this should work, but if it's the expected behavior, then that's fine of course.
hi
[DisableAuditing] [Dependency(ReplaceServices = true)] [ExposeServices(typeof(LoginModel), typeof(OpenIddictSupportedLoginModel))] public class MyCustomLogin : OpenIddictSupportedLoginModel { public MyCustomLogin(IAuthenticationSchemeProvider schemeProvider, IOptions<AbpAccountOptions> accountOptions, IAbpRecaptchaValidatorFactory recaptchaValidatorFactory, IAccountExternalProviderAppService accountExternalProviderAppService, ICurrentPrincipalAccessor currentPrincipalAccessor, IOptions<IdentityOptions> identityOptions, IOptionsSnapshot<reCAPTCHAOptions> reCaptchaOptions, AbpOpenIddictRequestHelper openIddictRequestHelper) : base(schemeProvider, accountOptions, recaptchaValidatorFactory, accountExternalProviderAppService, currentPrincipalAccessor, identityOptions, reCaptchaOptions, openIddictRequestHelper) { } public override async Task<IActionResult> OnGetAsync() { var result = await base.OnGetAsync(); if (LoginInput.UserNameOrEmailAddress.IsNullOrWhiteSpace()) { LoginInput.UserNameOrEmailAddress = Request.Query["TestUrlParameter"]; } return result; } }
Yes, that is a workaround. But the default databinding of ASP.NET Core should also work, shouldn't it?
I have also created a PR to fix the overwriting of the Login Hint: https://github.com/abpframework/abp/pull/22887
I've shared a test project via E-Mail
We are trying to add a login hint to the login page on the Auth Server (MVC), and thought that's an easy task, but for some reason can't get it to work :(
We are overriding the Login.cs
page by having a OurProductLogin.cshtml.cs
file in /Pages/Account
(as well as the _ViewImports.cshtml
)
Content of OurProductLogin.cshtml.cs
:
using System.Threading.Tasks;
using company.Product.Saas;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Owl.reCAPTCHA;
using Volo.Abp.Account.ExternalProviders;
using Volo.Abp.Account.Public.Web;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Account.Security.Recaptcha;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
namespace company.Product.Pages.Account;
[DisableAuditing]
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(LoginModel))]
public class OurProductLoginModel: LoginModel
{
[BindProperty(SupportsGet = true)]
public string? test { get; set; }
public OurProductLoginModel(
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions,
IAbpRecaptchaValidatorFactory recaptchaValidatorFactory,
IAccountExternalProviderAppService accountExternalProviderAppService,
ICurrentPrincipalAccessor currentPrincipalAccessor,
IOptions<IdentityOptions> identityOptions,
IOptionsSnapshot<reCAPTCHAOptions> reCaptchaOptions) : base(schemeProvider, accountOptions, recaptchaValidatorFactory, accountExternalProviderAppService, currentPrincipalAccessor, identityOptions, reCaptchaOptions)
{
}
public override async Task<IActionResult> OnGetAsync()
{
var result = await base.OnGetAsync();
if (!string.IsNullOrEmpty(test))
{
LoginInput.UserNameOrEmailAddress = test;
}
return result;
}
}
As you can see, this seems as simple as it can get :)
However, when using a Browser GET
request to /Account/Login?test=test@test.com
, the Username field is not pre-filled as we'd expect.
What are we doing wrong?
(Note: We have also tried this permutation of the OnGetAsync()
function, without relying on the base.OnGetAsync()
):
public override async Task<IActionResult> OnGetAsync()
{
LoginInput = new LoginInputModel();
if (!string.IsNullOrEmpty(test))
{
LoginInput.UserNameOrEmailAddress = test;
}
var localLoginResult = await CheckLocalLoginAsync();
if (localLoginResult != null)
{
return localLoginResult;
}
IsSelfRegistrationEnabled = await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled);
UseCaptcha = await UseCaptchaOnLoginAsync();
IsLinkLogin = await VerifyLinkTokenAsync();
if (IsLinkLogin)
{
if (CurrentUser.IsAuthenticated)
{
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentitySecurityLogActionConsts.Logout
});
await SignInManager.SignOutAsync();
return Redirect(HttpContext.Request.GetDisplayUrl());
}
}
return Page();
}
Also note: While debugging, the Property test
is indeed null
in the OnGetAsync()
method.
Edit: The more I try to understand this, the more questions I have :)
What's the deal with OpenIddictSupportedLoginModel
, do I need to use this? (I can't really find any official documentation about this, so I assume not? If yes -> Documentation definitely needs to be improved).
In there, it seems that it <could> use a LoginHint
already, but the base.OnGetAsync()
overwrites the LoginInput property and would erase the value again, right?
Thanks Michel