Hi,
Because two applications are running on the localhost domain, the browser will share the cookies.
you can try put the abp.swagger.js file in wwwroot/swagger/ui, It refreshes the CSRF token for every request。
var abp = abp || {};
(function() {
abp.SwaggerUIBundle = function(configObject) {
var excludeUrl = ["swagger.json", "connect/token"]
var firstRequest = true;
abp.appPath = configObject.baseUrl || abp.appPath;
var requestInterceptor = configObject.requestInterceptor;
configObject.requestInterceptor = async function(request) {
if (request.url.includes(excludeUrl[1])) {
firstRequest = true;
}
if (!excludeUrl.some(url => request.url.includes(url))) {
await fetch(`${abp.appPath}abp/Swashbuckle/SetCsrfCookie`, {
headers: request.headers
});
}
var antiForgeryToken = abp.security.antiForgery.getToken();
if (antiForgeryToken) {
request.headers[abp.security.antiForgery.tokenHeaderName] = antiForgeryToken;
}
if (!request.headers["X-Requested-With"]) {
request.headers["X-Requested-With"] = "XMLHttpRequest";
}
if (requestInterceptor) {
requestInterceptor(request);
}
return request;
};
return SwaggerUIBundle(configObject);
}
})();
Hi @cellero
You can try to change the namespace Volo.Abp.AspNetCore........ApplicationLayout.TopMenu to Volo.Abp.AspNetCore........ApplicationLayout.SideMenu
You can remove the file when the next patch(7.0.2) version is released.
See: https://support.abp.io/QA/Questions/4469/Entering-invalid-phone-number-locks-you-out-of-the-system#answer-e1ededc6-2ed4-c0e9-61dd-3a09383bd39e
Hi,
Yes, it's a problem. we will fix it in the next version.
You can try put the Default.js file in your Pages\Account\Components\ProfileManagementGroup\\PersonalInfo path.
Default.js
(function ($) {
$(function () {
var l = abp.localization.getResource("AbpAccount");
var _profileService = volo.abp.account.profile;
var _accountService = volo.abp.account.account;
var _confirmPhoneNumberModal = new abp.ModalManager(
abp.appPath + "Account/Components/ProfileManagementGroup/PersonalInfo/ConfirmPhoneNumberModal"
);
var $email = $('#PersonalSettingsForm').find("#Email");
var $verifyEmail = $("#VerifyEmailButton");
var $emailVerified = $("#EmailVerified");
var $emailNotVerified = $("#EmailNotVerified");
var $phone = $('#PersonalSettingsForm').find("#PhoneNumber");
var $verifyPhone = $("#VerifyPhoneButton");
var $phoneVerified = $("#PhoneVerified");
var $phoneNotVerified = $("#PhoneNotVerified");
$('#PersonalSettingsForm').find("#Email").keyup(function () {
if ($(this).val() !== $(this).attr("data-saved-email")) {
$("#VerifyEmailButton").hide();
$("#EmailVerified").hide();
$("#EmailNotVerified").show();
} else if ($(this).attr("data-email-verified") === "False") {
$("#VerifyEmailButton").show();
$("#EmailNotVerified").hide();
} else if ($(this).attr("data-email-verified") === "True") {
$("#EmailVerified").show();
$("#EmailNotVerified").hide();
}
});
$('#PersonalSettingsForm').find("#PhoneNumber").keyup(function () {
if ($(this).val() !== $(this).attr("data-saved-phone")) {
$("#VerifyPhoneButton").hide();
$("#PhoneVerified").hide();
if ($(this).val() !== "") {
$("#PhoneNotVerified").show();
} else {
$("#PhoneNotVerified").hide();
}
} else if ($(this).attr("data-phone-verified") === "False") {
if ($(this).val() !== "") {
$("#VerifyPhoneButton").show();
}
$("#PhoneNotVerified").hide();
} else if ($(this).attr("data-phone-verified") === "True") {
if ($(this).val() !== "") {
$("#PhoneVerified").show();
}
$("#PhoneNotVerified").hide();
}
});
$("#VerifyEmailButton").on("click", "", function () {
var returnUrl = "/";
var returnUrlLink = $("#returnUrlLink");
if(returnUrlLink.length === 1){
returnUrl = returnUrlLink.attr("href");
}
_accountService
.sendEmailConfirmationToken({
userId: $('#CurrentUserId').val(),
appName: "MVC",
returnUrl:returnUrl,
returnUrlHash: "",
})
.then(function () {
abp.notify.success(
l(
"EmailConfirmationSentMessage",
$('#PersonalSettingsForm').find("#Email").val()
)
);
$("#VerifyEmailButton").hide();
});
});
$("#VerifyPhoneButton").on("click", "", function () {
_confirmPhoneNumberModal.open();
});
var askForVerify = function () {
abp.message.confirm(
" ",
l("DoYouWantToVerifyPhoneNumberMessage"),
function (isConfirmed) {
if (isConfirmed) {
$("#VerifyPhoneButton").click();
}
}
);
};
$("#PersonalSettingsForm").submit(function (e) {
e.preventDefault();
if (!$("#PersonalSettingsForm").valid()) {
return false;
}
var input = $("#PersonalSettingsForm").serializeFormToObject(false);
_profileService.update(input).then(function (result) {
abp.notify.success(l("PersonalSettingsSaved"));
if (input.Email !== $email.attr("data-saved-email")) {
$verifyEmail.show();
$emailVerified.hide();
$email.attr("data-email-verified", "False");
}
$email.attr("data-saved-email", $email.val());
$emailNotVerified.hide();
if (!input.PhoneNumber || input.PhoneNumber === "") {
$verifyPhone.hide();
$phoneVerified.hide();
$phoneNotVerified.hide();
$phone.attr("data-saved-phone", input.PhoneNumber);
return;
}
if (
$phone.attr("data-saved-phone") === input.PhoneNumber ||
$verifyPhone.length < 1
) {
return;
}
$verifyPhone.show();
$phoneVerified.hide();
$phoneNotVerified.hide();
$phone.attr("data-saved-phone", input.PhoneNumber);
$phone.attr("data-phone-verified", "False");
askForVerify();
});
});
_confirmPhoneNumberModal.onResult(function () {
$verifyPhone.hide();
$phoneNotVerified.hide();
$phoneVerified.show();
$phone.attr("data-phone-verified", "True");
});
});
})(jQuery);
Hi,
Ok, I think the merchant is a user right? you need to custom the text template module.
EfCoreTextTemplateContentRepository to change the GetAsync and FindAsync methods.For example:
[ExposeServices(typeof(IEfCoreTextTemplateContentRepository))]
public class MyEfCoreTextTemplateContentRepository : EfCoreTextTemplateContentRepository
{
public override async Task<TextTemplateContent> GetAsync(
string name,
string cultureName = null,
CancellationToken cancellationToken = default)
{
// You need to care if the user is logged in or not
var userId = currentUser.GetId();
return await GetAsync(x => x.Name == name && x.CultureName == cultureName && x.CreatorId == userId, cancellationToken: GetCancellationToken(cancellationToken));
}
//......
}
Configure<TextTemplateManagementOptions>(options =>
{
options.MinimumCacheDuration = TimeSpan.Zero; // use zero to avoid caching
});
Hi,
Can you share the .csproj file content?
BTW, it's working for me:
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(TokenController))]
public class MyTokenController : Volo.Abp.OpenIddict.Controllers.TokenController
{
protected override Task<IActionResult> HandlePasswordAsync(OpenIddictRequest request)
{
return base.HandlePasswordAsync(request);
}
}
Hi,
The Text Template is tenant-isolated, and each tenant can customize the template.
Hi,
You can implement a simple news system.
For example, create a table News:
Use the layout hook system to create a NewsComponent to display the news.
PS: News systems can get very complex based on your use case. you can add type for news(release, information etc...) and separate display logic for each type
Hi,
You can try to override the SendPasswordResetCodeAsync method to handle the exception.
For example:
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IAccountAppService))]
public class MyAccountAppService: AccountAppService
{
public MyAccountAppService(
IdentityUserManager userManager,
IAccountEmailer accountEmailer,
IAccountPhoneService phoneService,
IIdentityRoleRepository roleRepository,
IdentitySecurityLogManager identitySecurityLogManager,
IBlobContainer<AccountProfilePictureContainer> accountProfilePictureContainer,
ISettingManager settingManager,
IOptions<IdentityOptions> identityOptions,
IIdentitySecurityLogRepository securityLogRepository) : base(userManager, accountEmailer, phoneService, roleRepository, identitySecurityLogManager, accountProfilePictureContainer, settingManager, identityOptions, securityLogRepository)
{
}
public override async Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto input)
{
try
{
var user = await GetUserByEmail(input.Email);
var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user);
await AccountEmailer.SendPasswordResetLinkAsync(user, resetToken, input.AppName, input.ReturnUrl, input.ReturnUrlHash);
}
catch (Exception e)
{
throw new UserFriendlyException("custom message");
}
}
}