Send email on account creation

This commit is contained in:
jvyden 2022-03-01 15:06:12 -05:00
commit 7c98b1eca3
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
7 changed files with 1074 additions and 6 deletions

View file

@ -45,7 +45,8 @@ public class Database : DbContext
protected override void OnConfiguring(DbContextOptionsBuilder options) protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion); => options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
public async Task<User> CreateUser(string username, string password) #nullable enable
public async Task<User> CreateUser(string username, string password, string? emailAddress = null)
{ {
if (!password.StartsWith('$')) throw new ArgumentException(nameof(password) + " is not a BCrypt hash"); if (!password.StartsWith('$')) throw new ArgumentException(nameof(password) + " is not a BCrypt hash");
@ -59,8 +60,8 @@ public class Database : DbContext
if (!regex.IsMatch(username)) throw new ArgumentException(nameof(username) + " does not match the username regex"); if (!regex.IsMatch(username)) throw new ArgumentException(nameof(username) + " does not match the username regex");
} }
User user; User? user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync();
if ((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null) return user; if (user != null) return user;
Location l = new(); // store to get id after submitting Location l = new(); // store to get id after submitting
this.Locations.Add(l); // add to table this.Locations.Add(l); // add to table
@ -77,10 +78,17 @@ public class Database : DbContext
await this.SaveChangesAsync(); await this.SaveChangesAsync();
if (emailAddress != null && ServerSettings.Instance.SMTPEnabled)
{
string body = "An account for Project Lighthouse has been registered with this email address.\n\n" +
$"You can login at {ServerSettings.Instance.ExternalUrl}.";
SMTPHelper.SendEmail(emailAddress, "Account Created: " + username, body);
}
return user; return user;
} }
#nullable enable
public async Task<GameToken?> AuthenticateUser(NPTicket npTicket, string userLocation) public async Task<GameToken?> AuthenticateUser(NPTicket npTicket, string userLocation)
{ {
User? user = await this.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username); User? user = await this.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddEmailAddressToUser : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "EmailAddress",
table: "Users",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "EmailAddress",
table: "Users");
}
}
}

View file

@ -669,6 +669,9 @@ namespace ProjectLighthouse.Migrations
b.Property<string>("BooHash") b.Property<string>("BooHash")
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<string>("EmailAddress")
.HasColumnType("longtext");
b.Property<int>("Game") b.Property<int>("Game")
.HasColumnType("int"); .HasColumnType("int");

View file

@ -43,6 +43,14 @@
</div> </div>
</div> </div>
<div class="field">
<label>Email address</label>
<div class="ui left icon input">
<input type="email" name="emailAddress" id="emailAddress" placeholder="Email Address">
<i class="mail icon"></i>
</div>
</div>
<div class="field"> <div class="field">
<label>Password</label> <label>Password</label>
<div class="ui left icon input"> <div class="ui left icon input">

View file

@ -21,7 +21,7 @@ public class RegisterForm : BaseLayout
[UsedImplicitly] [UsedImplicitly]
[SuppressMessage("ReSharper", "SpecifyStringComparison")] [SuppressMessage("ReSharper", "SpecifyStringComparison")]
public async Task<IActionResult> OnPost(string username, string password, string confirmPassword) public async Task<IActionResult> OnPost(string username, string password, string confirmPassword, string emailAddress)
{ {
if (!ServerSettings.Instance.RegistrationEnabled) return this.NotFound(); if (!ServerSettings.Instance.RegistrationEnabled) return this.NotFound();
@ -37,6 +37,12 @@ public class RegisterForm : BaseLayout
return this.Page(); return this.Page();
} }
if (string.IsNullOrWhiteSpace(emailAddress))
{
this.Error = "Email address field is required.";
return this.Page();
}
if (password != confirmPassword) if (password != confirmPassword)
{ {
this.Error = "Passwords do not match!"; this.Error = "Passwords do not match!";
@ -55,7 +61,7 @@ public class RegisterForm : BaseLayout
return this.Page(); return this.Page();
} }
User user = await this.Database.CreateUser(username, HashHelper.BCryptHash(password)); User user = await this.Database.CreateUser(username, HashHelper.BCryptHash(password), emailAddress);
WebToken webToken = new() WebToken webToken = new()
{ {

View file

@ -13,6 +13,11 @@ public class User
public int UserId { get; set; } public int UserId { get; set; }
public string Username { get; set; } public string Username { get; set; }
#nullable enable
[JsonIgnore]
public string? EmailAddress { get; set; } = null;
#nullable disable
[JsonIgnore] [JsonIgnore]
public string Password { get; set; } public string Password { get; set; }