#nullable enable using System.Diagnostics.CodeAnalysis; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Localization.StringLists; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.PlayerData; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.PlayerData.Profiles.Email; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; public class SetEmailForm : BaseLayout { public SetEmailForm(Database database) : base(database) {} public EmailSetToken? EmailToken; public string? Error { get; private set; } public async Task OnGet(string? token = null) { if (!ServerConfiguration.Instance.Mail.MailEnabled) return this.NotFound(); if (token == null) return this.Redirect("/login"); EmailSetToken? emailToken = await this.Database.EmailSetTokens.FirstOrDefaultAsync(t => t.EmailToken == token); if (emailToken == null) return this.Redirect("/login"); this.EmailToken = emailToken; return this.Page(); } [SuppressMessage("ReSharper", "SpecifyStringComparison")] public async Task OnPost(string emailAddress, string token) { if (!ServerConfiguration.Instance.Mail.MailEnabled) return this.NotFound(); EmailSetToken? emailToken = await this.Database.EmailSetTokens.Include(t => t.User).FirstOrDefaultAsync(t => t.EmailToken == token); if (emailToken == null) return this.Redirect("/login"); if (await this.Database.Users.AnyAsync(u => u.EmailAddress != null && u.EmailAddress.ToLower() == emailAddress.ToLower())) { this.Error = this.Translate(ErrorStrings.EmailTaken); this.EmailToken = emailToken; return this.Page(); } emailToken.User.EmailAddress = emailAddress; this.Database.EmailSetTokens.Remove(emailToken); User user = emailToken.User; EmailVerificationToken emailVerifyToken = new() { UserId = user.UserId, User = user, EmailToken = CryptoHelper.GenerateAuthToken(), ExpiresAt = DateTime.Now + TimeSpan.FromHours(6), }; this.Database.EmailVerificationTokens.Add(emailVerifyToken); // The user just set their email address. Now, let's grant them a token to proceed with verifying the email. // TODO: insecure WebToken webToken = new() { UserId = user.UserId, UserToken = CryptoHelper.GenerateAuthToken(), ExpiresAt = DateTime.Now + TimeSpan.FromDays(7), }; this.Response.Cookies.Append ( "LighthouseToken", webToken.UserToken, new CookieOptions { Expires = DateTimeOffset.Now.AddDays(7), } ); Logger.Success($"User {user.Username} (id: {user.UserId}) successfully logged in on web after setting an email address", LogArea.Login); this.Database.WebTokens.Add(webToken); await this.Database.SaveChangesAsync(); return this.Redirect("/login/sendVerificationEmail"); } }