// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.WebUtilities; using System.ComponentModel.DataAnnotations; using System.Text; using System.Text.Encodings.Web; using TightWiki.Library.Interfaces; using TightWiki.Repository; namespace TightWiki.Areas.Identity.Pages.Account.Manage { public class EmailModel : PageModelBase { private readonly UserManager _userManager; private readonly SignInManager _signInManager; private readonly IWikiEmailSender _emailSender; public EmailModel( UserManager userManager, SignInManager signInManager, IWikiEmailSender emailSender) : base(signInManager) { _userManager = userManager; _signInManager = signInManager; _emailSender = emailSender; } /// /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// public string Email { get; set; } /// /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// public bool IsEmailConfirmed { get; set; } /// /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// [TempData] public string StatusMessage { get; set; } /// /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// [BindProperty] public InputModel Input { get; set; } /// /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// public class InputModel { /// /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// [Required] [EmailAddress] [Display(Name = "New email")] public string NewEmail { get; set; } } private async Task LoadAsync(IdentityUser user) { var email = await _userManager.GetEmailAsync(user); Email = email; Input = new InputModel { NewEmail = email, }; IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user); } public async Task OnGetAsync() { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } await LoadAsync(user); return Page(); } public async Task OnPostChangeEmailAsync() { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } if (!ModelState.IsValid) { await LoadAsync(user); return Page(); } var email = await _userManager.GetEmailAsync(user); if (Input.NewEmail != email) { var userId = await _userManager.GetUserIdAsync(user); var code = await _userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail); var encodedCode = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); var callbackUrl = Url.Page( "/Account/ConfirmEmailChange", pageHandler: null, values: new { area = "Identity", userId = userId, email = Input.NewEmail, code = encodedCode }, protocol: Request.Scheme); var emailTemplate = new StringBuilder(ConfigurationRepository.Get("Membership", "Template: Account Verification Email")); var basicConfig = ConfigurationRepository.GetConfigurationEntryValuesByGroupName("Basic"); var siteName = basicConfig.Value("Name"); var address = basicConfig.Value("Address"); var profile = UsersRepository.GetAccountProfileByUserId(Guid.Parse(userId)); var emailSubject = "Confirm your email"; emailTemplate.Replace("##SUBJECT##", emailSubject); emailTemplate.Replace("##ACCOUNTCOUNTRY##", profile.Country); emailTemplate.Replace("##ACCOUNTTIMEZONE##", profile.TimeZone); emailTemplate.Replace("##ACCOUNTLANGUAGE##", profile.Language); emailTemplate.Replace("##ACCOUNTEMAIL##", profile.EmailAddress); emailTemplate.Replace("##ACCOUNTNAME##", profile.AccountName); emailTemplate.Replace("##PERSONNAME##", $"{profile.FirstName} {profile.LastName}"); emailTemplate.Replace("##CODE##", code); emailTemplate.Replace("##USERID##", userId); emailTemplate.Replace("##SITENAME##", siteName); emailTemplate.Replace("##SITEADDRESS##", address); emailTemplate.Replace("##CALLBACKURL##", HtmlEncoder.Default.Encode(callbackUrl)); await _emailSender.SendEmailAsync(Input.NewEmail, emailSubject, emailTemplate.ToString()); StatusMessage = "Confirmation link to change email sent. Please check your email."; return RedirectToPage(); } StatusMessage = "Your email is unchanged."; return RedirectToPage(); } public async Task OnPostSendVerificationEmailAsync() { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } if (!ModelState.IsValid) { await LoadAsync(user); return Page(); } var userId = await _userManager.GetUserIdAsync(user); var email = await _userManager.GetEmailAsync(user); var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new { area = "Identity", userId = userId, code = code }, protocol: Request.Scheme); await _emailSender.SendEmailAsync( email, "Confirm your email", $"Please confirm your account by clicking here."); StatusMessage = "Verification email sent. Please check your email."; return RedirectToPage(); } } }