ok I will check the code and try to find the reason.
Do you have a online website to reproduce?
If you think your problem is in Login.cs, I think you can reproduce the problem in a new template project and share it with us.
Can you share the DevExpress
nuget source?
So I need to change the connection string and run DbMigrator
to initialize the database
Then run CFData.Structure.AuthServer
, CFData.Structure.HttpApi.Host
and CFData.Structure.Blazor
Log in to Blazor -> AuthServer to reproduce the problem?
Are those steps correct?
Thanks.
hi
You can add a new JSON file for IdentityResource
or use the language-management module to add texts.
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<IdentityResource>()
.AddVirtualJson("Your_Localization_Json_File_Path");
});
https://abp.io/docs/latest/modules/language-management#language-texts
hi
Can you share the steps to reproduce your problem with the Integration-BugFixes
code?
Thanks.
hi
You can inject the IAuditLogRepository
to query the audit logs. It's the same as EfCoreAuditLogRepository
Use IAuditLogRepository
will be fine.
https://github.com/abpframework/abp/blob/dev/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
hi
so I updated to it to test and the issue I described above still persists in 9.2.0. The article you linked is the same one I linked.
Can you share some screenshots?
Have you added the UseAbpTimeZone
middleware?
Thanks.
hi
Tenant will work as expected when tenant claim is set correctly.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Owl.reCAPTCHA;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.ExternalProviders;
using Volo.Abp.Account.Public.Web;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Account.Public.Web.Security.Recaptcha;
using Volo.Abp.Account.Security.Recaptcha;
using Volo.Abp.Account.Settings;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.Identity.Settings;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
using Volo.Saas.Tenants;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace CFData.Structure.Web.Pages.Account;
[DisableAuditing]
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(MyLoginModel), typeof(LoginModel))]
public class MyLoginModel : LoginModel
{
[Inject]
public ICurrentTenantAccessor CurrentTenantAccessor { get; set; }
[Inject]
public ITenantStore TenantStore { get; set; }
private readonly ITenantRepository _tenantRepository;
protected IDataFilter DataFilter { get; }
public MyLoginModel(
IAuthenticationSchemeProvider schemeProvider,
IOptions accountOptions,
IAbpRecaptchaValidatorFactory recaptchaValidatorFactory,
IAccountExternalProviderAppService accountExternalProviderAppService,
ICurrentPrincipalAccessor currentPrincipalAccessor,
IOptions identityOptions,
IOptionsSnapshot reCaptchaOptions,
ITenantRepository tenantRepository,
DataFilter dataFilter) : base(
schemeProvider,
accountOptions,
recaptchaValidatorFactory,
accountExternalProviderAppService,
currentPrincipalAccessor,
identityOptions,
reCaptchaOptions)
{
//ReCaptchaOptions = reCaptchaOptions;
_tenantRepository = tenantRepository;
DataFilter = dataFilter;
}
public override async Task OnGetAsync()
{
return await base.OnGetAsync();
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public override async Task OnPostAsync(string action)
{
try
{
await ReCaptchaVerification();
}
catch (UserFriendlyException e)
{
if (e is ScoreBelowThresholdException)
{
var onScoreBelowThresholdResult = OnRecaptchaScoreBelowThreshold();
if (onScoreBelowThresholdResult != null)
{
return await onScoreBelowThresholdResult;
}
}
Alerts.Danger(GetLocalizeExceptionMessage(e));
return Page();
}
//ValidateModel();
await IdentityOptions.SetAsync();
var localLoginResult = await CheckLocalLoginAsync();
if (localLoginResult != null)
{
return localLoginResult;
}
IsSelfRegistrationEnabled = false; //await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled);
await ReplaceEmailToUsernameOfInputIfNeeds();
var getUser = await FindUserAsync(LoginInput.UserNameOrEmailAddress);
if (getUser == null)
{
Alerts.Danger("User does not exist");
return Page();
}
TenantConfiguration tenant = null;
if (getUser.TenantId is not null)
{
tenant = await TenantStore.FindAsync((Guid)getUser.TenantId);
}
using (CurrentTenant.Change(tenant?.Id))
{
IsLinkLogin = await VerifyLinkTokenAsync();
var result = new Microsoft.AspNetCore.Identity.SignInResult();
using (DataFilter.Disable())
{
result = await SignInManager.PasswordSignInAsync(
LoginInput.UserNameOrEmailAddress,
LoginInput.Password,
LoginInput.RememberMe,
true);
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(),
UserName = LoginInput.UserNameOrEmailAddress
});
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./SendSecurityCode", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = LoginInput.RememberMe,
linkUserId = LinkUserId,
linkTenantId = LinkTenantId,
linkToken = LinkToken
});
}
if (result.IsLockedOut)
{
var lockedUser = await FindUserAsync(LoginInput.UserNameOrEmailAddress);
await StoreLockedUser(lockedUser);
return RedirectToPage("./LockedOut", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash
});
}
if (result.IsNotAllowed)
{
var notAllowedUser = await FindUserAsync(LoginInput.UserNameOrEmailAddress);
if (!await UserManager.CheckPasswordAsync(notAllowedUser, LoginInput.Password))
{
Alerts.Danger(L["InvalidUserNameOrPassword"]);
return Page();
}
if (notAllowedUser.ShouldChangePasswordOnNextLogin || await UserManager.ShouldPeriodicallyChangePasswordAsync(notAllowedUser))
{
await StoreChangePasswordUser(notAllowedUser);
return RedirectToPage("./ChangePassword", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
RememberMe = LoginInput.RememberMe
});
}
if (notAllowedUser.IsActive)
{
await StoreConfirmUser(notAllowedUser);
return RedirectToPage("./ConfirmUser", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash
});
}
Alerts.Danger(L["LoginIsNotAllowed"]);
return Page();
}
if (!result.Succeeded)
{
Alerts.Danger(L["InvalidUserNameOrPassword"]);
return Page();
}
var user = await FindUserAsync(LoginInput.UserNameOrEmailAddress);
if (IsLinkLogin)
{
using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(user)))
{
await IdentityLinkUserAppService.LinkAsync(new LinkUserInput
{
UserId = LinkUserId.Value,
TenantId = LinkTenantId,
Token = LinkToken
});
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentityProSecurityLogActionConsts.LinkUser,
UserName = user.UserName,
ExtraProperties =
{
{ IdentityProSecurityLogActionConsts.LinkTargetTenantId, LinkTenantId },
{ IdentityProSecurityLogActionConsts.LinkTargetUserId, LinkUserId }
}
});
using (CurrentTenant.Change(LinkTenantId))
{
var targetUser = await UserManager.GetByIdAsync(LinkUserId.Value);
using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(targetUser)))
{
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentityProSecurityLogActionConsts.LinkUser,
UserName = targetUser.UserName,
ExtraProperties =
{
{ IdentityProSecurityLogActionConsts.LinkTargetTenantId, targetUser.TenantId },
{ IdentityProSecurityLogActionConsts.LinkTargetUserId, targetUser.Id }
}
});
}
}
return RedirectToPage("./LinkLogged", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
targetLinkUserId = LinkUserId,
targetLinkTenantId = LinkTenantId
});
}
}
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash);
}
}
protected override async Task ReplaceEmailToUsernameOfInputIfNeeds()
{
if (!ValidationHelper.IsValidEmailAddress(LoginInput.UserNameOrEmailAddress))
{
return;
}
var userByUsername = await FindUserAsync(LoginInput.UserNameOrEmailAddress);
if (userByUsername != null)
{
return;
}
var userByEmail = await FindUserAsync(LoginInput.UserNameOrEmailAddress);
if (userByEmail == null)
{
return;
}
LoginInput.UserNameOrEmailAddress = userByEmail.UserName;
}
protected override async Task GetIdentityUser(string userNameOrEmailAddress)
{
IdentityUser identityUser = null;
using (CurrentTenant.Change(null))
{
identityUser = await base.UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress);
if (identityUser == null)
{
identityUser = await base.UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
}
}
IdentityUser user = identityUser;
Debug.Assert(user != null, "user != null");
return user;
}
protected virtual async Task FindUserAsync(string uniqueUserNameOrEmailAddress)
{
IdentityUser user = null;
using (CurrentTenant.Change(null))
{
user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
if (user != null)
{
return user;
}
}
foreach (var tenant in await _tenantRepository.GetListAsync())
{
using (CurrentTenant.Change(tenant.Id))
{
user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
if (user != null)
{
return user;
}
}
}
return null;
}
}
hi
Try using Change
method instead of set CurrentTenantAccessor.Current
TenantConfiguration tenant = null;
if (getUser.TenantId is not null)
{
tenant = await TenantStore.FindAsync((Guid)getUser.TenantId);
CurrentTenantAccessor.Current = new BasicTenantInfo(
tenant?.Id,
tenant?.Name);
}
using (CurrentTenant.Change(tenant?.Id))
{
// Add all the code following this to this scope
}