Starts in:
2 DAYS
0 HR
46 MIN
48 SEC
Starts in:
2 D
0 H
46 M
48 S

Activities of "balessi75"

Abp Commercial 5.1.3 / EF / Non-Tiered / Blazor Server

Is there an expiration on the confirm email link, password reset link, or 2 factor code in Abp? If so what is it's default expiration time and how can it be changed and or implemented (if not provided by Abp)?

Could you spot where exactly input.DateOfBirth lose its value?

input.DateOfBirth never looses it's value, but the input UI is cleared.

So I am guessing you are non-tiered Blazor server application.

Doesn't matter, you can use Blazor.Server project instead of Web. Blazor-Server has similar structure with MVC/Razor web application. MVC cshtml pages can run along with razor pages. Same configurations for bundling applies. You will be overriding Account/Register page which is already an MVC page.

Yes, this is a non-tiered Blazor server application.

We are following the community article: https://community.abp.io/posts/how-to-integrate-the-telerik-ui-for-asp.net-core-kendo-components-with-the-abp-mvc-ui-u2voab2a

We are stuck at the step: In the abp.resourcemapping.js file, add the necessary entries that look like the following:

module.exports = {
    aliases: {
    },
    mappings: {
        "@node_modules/@progress/kendo-ui/css/**/*": "@libs/kendo/css",
        "@node_modules/@progress/kendo-ui/js/**/*": "@libs/kendo/js"
    }
};

... because our Blazor Server solution created from Abp Suite has no abp.resourcemapping.js file. If we attempt to create one in our Blazor project, we get compile time errors...

Error CS0103 The name 'module' does not exist in the current context

Any help is much appreciated.

hi

Is your SESEmailSender implement the IEmailSender and replace default one in the DI?

Account Pro will use IEmailSender to send emails by default.

https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/IEmailSender.cs#L9

When creating a custom email sender (SESEmailSender in this case) that implements IEmailSender, how does one have Account Pro register the custom email sender to the DI?

Does this issue occur when you use a simple <input type='date' .../> instead of <abp-input... />?

Interesting...

Yes it does also occur with a simple <input type='date' .../> and it also occurs with @Html.EditorFor(model => model.Input.DateOfBirth)

Any thoughts?

Can using Telerik UI for MVC/Razor be an option? If so Cusomize Login Page article may help.

Not sure this is possible with a Blazor Server Abp solution. In looking at this community article...

https://community.abp.io/posts/how-to-integrate-the-telerik-ui-for-asp.net-core-kendo-components-with-the-abp-mvc-ui-u2voab2a

...there seems to be a lot of configuration needed for a MVC solution. For example, creating .js and bundling configurations in the .Web project, but our Blazor Server templated Abp solution has no .Web project.

Thoughts?

Can using Telerik UI for MVC/Razor be an option? If so Cusomize Login Page article may help.

Thanks @gterdem. I will give that a try and post whether or not this solution works...

May it be related with the following code?

          Input.DateOfBirth = DateTime.Now; 
          return Page(); 

Hi @yekalkan, Unfortunately not. I had the assignment to DateTime.Now in there just for debugging purposes. When that assignment is removed, the date input still has it's value cleared when RegisterAsync returns a user friendly exception.

Before register button press:

After register button press:

Hi, We are using Abp Commercial 5.1.3 - Blazor Server. We need to override Abp's Register.cshtml page which we have successfully done.

We have a requirement, however, to utilize an existing Blazor Component (Telerik UI for Blazor) in the overriden Register.cshtml page in our Blazor Server solution. By default this does not appear to be possible because the Register page is an MVC page. Is it possible to accomplish this? And if so, what would be the steps to make this scenario work?

Thanks in advance, balessi75

Hi @balessi75,

Can you share the full content of Register.cshtml & Register.cshtml.cs files?

Also, what does the error/exception say?

Hi @yekalkan,

The user friendly message is our message from an overriden AccountAppService RegisterAsync method call.

Here is the Rgister.cshtml:

@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@using Volo.Abp.Account.Public.Web.Security.Recaptcha
@using Volo.Abp.Account.Security.Recaptcha
@using Volo.Abp.Account.Settings
@using Volo.Abp.Settings
@using Volo.Abp.BlazoriseUI.Components
@model FM.Timepiece.Blazor.Pages.Account.TimepieceRegisterModel
@*@model Volo.Abp.Account.Public.Web.Pages.Account.RegisterModel*@
@inject IHtmlLocalizer<AccountResource> L
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
@inject ISettingProvider SettingProvider
@{
    PageLayout.Content.Title = L["Register"].Value;
    var reCaptchaVersion = await SettingProvider.GetAsync<int>(AccountSettingNames.Captcha.Version);
}


@section scripts
{
    @if (Model.UseCaptcha)
    {
        if (reCaptchaVersion == 3)
        {
            <recaptcha-script-v3/>
            <recaptcha-script-v3-js action="register" callback="(function(){$('#@RecaptchaValidatorBase.RecaptchaResponseKey').val(token)})"/>
        }
        else
        {
            <recaptcha-script-v2/>
        }
    }


}

<div class="account-module-form">
    <form method="post">

        @if (Model.UseCaptcha)
        {
            <input type="hidden" name="@RecaptchaValidatorBase.RecaptchaResponseKey" id="@RecaptchaValidatorBase.RecaptchaResponseKey"/>
        }
 
        
        @if (!Model.IsExternalLogin)
        {
              <abp-row>
                <abp-column size="_6">
                    <abp-input asp-for="Input.UserName" label="User Name" auto-focus="true"/>
                </abp-column>
                <abp-column size="_6">
                     <abp-input asp-for="Input.Password" label="Password"/>
                </abp-column>     
            </abp-row>  
          
        }
        
        <abp-row>
            <abp-column size="_6">
                <abp-input asp-for="Input.EmailAddress" label="Email Address"/> 
            </abp-column>
            <abp-column size="_6">
                <abp-input asp-for="Input.EmployeeId" label="Employee Id"/> 
            </abp-column>
        </abp-row>
   
         <abp-row>
            <abp-column size="_6">
                  <abp-input asp-for="Input.FirstName" label="First Name"/>
            </abp-column>
            <abp-column size="_6">
                  <abp-input asp-for="Input.LastName" label="Last Name"/>
            </abp-column>
        </abp-row>

        <abp-row>
            <abp-column size="_6">
                  <abp-input asp-for="Input.ZipCode" label="Zip Code"/>
            </abp-column>
            <abp-column size="_6">

            
               <abp-input asp-for="Input.DateOfBirth" label="Date Of Birth"/>
                 
            </abp-column>
        </abp-row>


        @if (reCaptchaVersion == 2)
        {
            <recaptcha-div-v2 callback="(function(){$('#@RecaptchaValidatorBase.RecaptchaResponseKey').val(token)})" />
        }

        <div class="d-grid gap-2">
            <abp-button button-type="Primary" type="submit" class="mt-2 mb-3">@L["Register"]</abp-button>
        </div>
        @L["AlreadyRegistered"] <a href="@Url.Page("./Login", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Login"]</a>
    </form>
</div>

And register.chtml.cs

using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Owl.reCAPTCHA;
using Volo.Abp.Account.Public.Web.Security.Recaptcha;
using Volo.Abp.Account.Settings;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp;
using Volo.Abp.Account;
using FM.Timepiece.Identity;
using System;
using FM.Timepiece.Account;
using Volo.Abp.Data;
using FM.Timepiece.Employees;

//namespace Volo.Abp.Account.Public.Web.Pages.Account;
namespace FM.Timepiece.Blazor.Pages.Account;

public class TimepieceRegisterModel : AccountPageModel
{
    [BindProperty(SupportsGet = true)]
    public string ReturnUrl { get; set; }

    [BindProperty(SupportsGet = true)]
    public string ReturnUrlHash { get; set; }

    [BindProperty]
    public PostInput Input { get; set; }

    [BindProperty(SupportsGet = true)]
    public bool IsExternalLogin { get; set; }

    [BindProperty(SupportsGet = true)]
    public string ExternalLoginAuthSchema { get; set; }

    public bool UseCaptcha { get; set; }

    public virtual async Task<IActionResult> OnGetAsync()
    {
        await CheckSelfRegistrationAsync();
        await TrySetEmailAsync();
        await SetUseCaptchaAsync();

        return Page();
    }

    [UnitOfWork] //TODO: Will be removed when we implement action filter
    public virtual async Task<IActionResult> OnPostAsync()
    {
        try
        {
            await CheckSelfRegistrationAsync();
            await SetUseCaptchaAsync();

            IdentityUser user;
            if (IsExternalLogin)
            {
                var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
                if (externalLoginInfo == null)
                {
                    Logger.LogWarning("External login info is not available");
                    return RedirectToPage("./Login");
                }

                user = await RegisterExternalUserAsync(externalLoginInfo, Input.EmailAddress);
            }
            else
            {
                user = await RegisterLocalUserAsync();
            }

            //
            //Timepiece override to always require a confirmed email during the registration process for security reasons
            //

            //if (await SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail) && !user.EmailConfirmed ||
            //    await SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber) && !user.PhoneNumberConfirmed)
            //{
                await StoreConfirmUser(user);

                return RedirectToPage("./ConfirmUser", new {
                    returnUrl = ReturnUrl,
                    returnUrlHash = ReturnUrlHash
                });
           // }

            //await SignInManager.SignInAsync(user, isPersistent: true);

            //return Redirect(ReturnUrl ?? "/"); //TODO: How to ensure safety? IdentityServer requires it however it should be checked somehow!
        }
        catch (BusinessException e)
        {
            Alerts.Danger(GetLocalizeExceptionMessage(e));

            Input.DateOfBirth = DateTime.Now;
            return Page();
        }
    }

    protected virtual async Task<IdentityUser> RegisterLocalUserAsync()
    {
        ValidateModel();

        var captchaResponse = string.Empty;
        if (UseCaptcha)
        {
            captchaResponse = HttpContext.Request.Form[RecaptchaValidatorBase.RecaptchaResponseKey];
        }

        var registerDto = new RegisterDto
        {
            AppName = "MVC",
            EmailAddress = Input.EmailAddress,
            Password = Input.Password,
            UserName = Input.UserName,
            ReturnUrl = ReturnUrl,
            ReturnUrlHash = ReturnUrlHash,
            CaptchaResponse = captchaResponse
        };
        registerDto.SetProperty(EmployeeConsts.EmployeeId, Input.EmployeeId);
        registerDto.SetProperty(EmployeeConsts.FirstName, Input.FirstName);
        registerDto.SetProperty(EmployeeConsts.LastName, Input.LastName);
        registerDto.SetProperty(EmployeeConsts.ZipCode, Input.ZipCode);
        registerDto.SetProperty(EmployeeConsts.DateOfBirth, Input.DateOfBirth);

        var userDto = await AccountAppService.RegisterAsync(registerDto);

        return await UserManager.GetByIdAsync(userDto.Id);
    }

    protected virtual async Task<IdentityUser> RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress)
    {
        await IdentityOptions.SetAsync();

        var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);

        (await UserManager.CreateAsync(user)).CheckErrors();
        (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();

        if (!user.EmailConfirmed)
        {
            await AccountAppService.SendEmailConfirmationTokenAsync(
                new SendEmailConfirmationTokenDto
                {
                    AppName = "MVC",
                    UserId = user.Id,
                    ReturnUrl = ReturnUrl,
                    ReturnUrlHash = ReturnUrlHash
                }
            );
        }

        var userLoginAlreadyExists = user.Logins.Any(x =>
            x.TenantId == user.TenantId &&
            x.LoginProvider == externalLoginInfo.LoginProvider &&
            x.ProviderKey == externalLoginInfo.ProviderKey);

        if (!userLoginAlreadyExists)
        {
            user.AddLogin(new UserLoginInfo(
                    externalLoginInfo.LoginProvider,
                    externalLoginInfo.ProviderKey,
                    externalLoginInfo.ProviderDisplayName
                )
            );

            (await UserManager.UpdateAsync(user)).CheckErrors();
        }

        return user;
    }

    protected virtual async Task CheckSelfRegistrationAsync()
    {
        if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled) ||
            !await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin))
        {
            throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
        }
    }

    protected virtual async Task SetUseCaptchaAsync()
    {
        UseCaptcha = !IsExternalLogin && await SettingProvider.IsTrueAsync(AccountSettingNames.Captcha.UseCaptchaOnRegistration);
        if (UseCaptcha)
        {
            var reCaptchaVersion = await SettingProvider.GetAsync<int>(AccountSettingNames.Captcha.Version);
            await ReCaptchaOptions.SetAsync(reCaptchaVersion == 3 ? reCAPTCHAConsts.V3 : reCAPTCHAConsts.V2);
        }
    }

    protected virtual async Task StoreConfirmUser(IdentityUser user)
    {
        var identity = new ClaimsIdentity(ConfirmUserModel.ConfirmUserScheme);
        identity.AddClaim(new Claim(AbpClaimTypes.UserId, user.Id.ToString()));
        if (user.TenantId.HasValue)
        {
            identity.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.ToString()));
        }
        await HttpContext.SignInAsync(ConfirmUserModel.ConfirmUserScheme, new ClaimsPrincipal(identity));
    }

    private async Task TrySetEmailAsync()
    {
        if (IsExternalLogin)
        {
            var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
            if (externalLoginInfo == null)
            {
                return;
            }

            if (!externalLoginInfo.Principal.Identities.Any())
            {
                return;
            }

            var identity = externalLoginInfo.Principal.Identities.First();
            var emailClaim = identity.FindFirst(ClaimTypes.Email);

            if (emailClaim == null)
            {
                return;
            }

            Input = new PostInput { EmailAddress = emailClaim.Value };
        }
    }

    public class PostInput
    {
        [Required]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
        public string UserName { get; set; }

        [Required]
        [EmailAddress]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
        public string EmailAddress { get; set; }

        [Required]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
        [DataType(DataType.Password)]
        [DisableAuditing]
        public string Password { get; set; }

        //Added for Timepiece employee verification

        [Required(ErrorMessage = "Employee Id is required")]
        public int EmployeeId { get; set; }

        [Required(ErrorMessage = "First Name Name is required")]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxNameLength))]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "Last Name is required")]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxSurnameLength))]
        public string LastName { get; set; }

        [Required(ErrorMessage = "Zip Code is required")]
        [RegularExpression(@"(^\d{5}$)|(^\d{9}$)|(^\d{5}-\d{4}$)", ErrorMessage = "Invalid Zip Code")]
        [DynamicStringLength(typeof(UserConsts), nameof(UserConsts.MaxZipCodeLength))]
        public string ZipCode { get; set; }

        [Required(ErrorMessage = "Date Of Birth is required")]
        [DataType(DataType.Date)]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
        public DateTime DateOfBirth { get; set; }
    }
}

Showing 221 to 230 of 245 entries
Made with ❤️ on ABP v9.1.0-preview. Updated on November 20, 2024, 13:06