mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-06 20:08:40 +00:00
Add prompt for users without an email address set so they can set & verify one
This commit is contained in:
parent
7c98b1eca3
commit
cc2159d539
12 changed files with 370 additions and 8 deletions
|
@ -8,6 +8,7 @@ using LBPUnion.ProjectLighthouse.Types;
|
|||
using LBPUnion.ProjectLighthouse.Types.Categories;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles.Email;
|
||||
using LBPUnion.ProjectLighthouse.Types.Reports;
|
||||
using LBPUnion.ProjectLighthouse.Types.Reviews;
|
||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
|
@ -41,6 +42,8 @@ public class Database : DbContext
|
|||
public DbSet<DatabaseCategory> CustomCategories { get; set; }
|
||||
public DbSet<Reaction> Reactions { get; set; }
|
||||
public DbSet<GriefReport> Reports { get; set; }
|
||||
public DbSet<EmailVerificationToken> EmailVerificationTokens { get; set; }
|
||||
public DbSet<EmailSetToken> EmailSetTokens { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
=> options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
using LBPUnion.ProjectLighthouse;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20220301204930_AddEmailVerificationTokens")]
|
||||
public partial class AddEmailVerificationTokens : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EmailVerificationToken",
|
||||
columns: table => new
|
||||
{
|
||||
EmailVerificationTokenId = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
EmailToken = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EmailVerificationToken", x => x.EmailVerificationTokenId);
|
||||
table.ForeignKey(
|
||||
name: "FK_EmailVerificationToken_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EmailVerificationToken_UserId",
|
||||
table: "EmailVerificationToken",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "EmailVerificationToken");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
using LBPUnion.ProjectLighthouse;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20220301212120_SplitSetAndVerificationTokenTypes")]
|
||||
public partial class SplitSetAndVerificationTokenTypes : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "EmailVerificationToken");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EmailSetTokens",
|
||||
columns: table => new
|
||||
{
|
||||
EmailSetTokenId = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
EmailToken = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EmailSetTokens", x => x.EmailSetTokenId);
|
||||
table.ForeignKey(
|
||||
name: "FK_EmailSetTokens_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EmailVerificationTokens",
|
||||
columns: table => new
|
||||
{
|
||||
EmailVerificationTokenId = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
EmailToken = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EmailVerificationTokens", x => x.EmailVerificationTokenId);
|
||||
table.ForeignKey(
|
||||
name: "FK_EmailVerificationTokens_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EmailSetTokens_UserId",
|
||||
table: "EmailSetTokens",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EmailVerificationTokens_UserId",
|
||||
table: "EmailVerificationTokens",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "EmailSetTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "EmailVerificationTokens");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EmailVerificationToken",
|
||||
columns: table => new
|
||||
{
|
||||
EmailVerificationTokenId = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
EmailToken = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EmailVerificationToken", x => x.EmailVerificationTokenId);
|
||||
table.ForeignKey(
|
||||
name: "FK_EmailVerificationToken_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EmailVerificationToken_UserId",
|
||||
table: "EmailVerificationToken",
|
||||
column: "UserId");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -452,6 +452,44 @@ namespace ProjectLighthouse.Migrations
|
|||
b.ToTable("Comments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Email.EmailSetToken", b =>
|
||||
{
|
||||
b.Property<int>("EmailSetTokenId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("EmailToken")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("EmailSetTokenId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("EmailSetTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Email.EmailVerificationToken", b =>
|
||||
{
|
||||
b.Property<int>("EmailVerificationTokenId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("EmailToken")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("EmailVerificationTokenId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("EmailVerificationTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastContact", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
|
@ -923,6 +961,28 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("Poster");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Email.EmailSetToken", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Email.EmailVerificationToken", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reports.GriefReport", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "ReportingPlayer")
|
||||
|
|
|
@ -8,6 +8,8 @@ using LBPUnion.ProjectLighthouse.Helpers.Extensions;
|
|||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles.Email;
|
||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -64,6 +66,23 @@ public class LoginForm : BaseLayout
|
|||
return this.Page();
|
||||
}
|
||||
|
||||
if (user.EmailAddress == null && ServerSettings.Instance.SMTPEnabled)
|
||||
{
|
||||
Logger.Log($"User {user.Username} (id: {user.UserId}) failed to login; email not set", LoggerLevelLogin.Instance);
|
||||
|
||||
EmailSetToken emailSetToken = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
User = user,
|
||||
EmailToken = HashHelper.GenerateAuthToken(),
|
||||
};
|
||||
|
||||
this.Database.EmailSetTokens.Add(emailSetToken);
|
||||
await this.Database.SaveChangesAsync();
|
||||
|
||||
return this.Redirect("/login/setEmail?token=" + emailSetToken.EmailToken);
|
||||
}
|
||||
|
||||
WebToken webToken = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
|
|
|
@ -43,13 +43,16 @@
|
|||
</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>
|
||||
@if (ServerSettings.Instance.SMTPEnabled)
|
||||
{
|
||||
<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>
|
||||
}
|
||||
|
||||
<div class="field">
|
||||
<label>Password</label>
|
||||
|
|
|
@ -17,7 +17,6 @@ public class RegisterForm : BaseLayout
|
|||
{}
|
||||
|
||||
public string Error { get; private set; }
|
||||
public bool WasRegisterRequest { get; private set; }
|
||||
|
||||
[UsedImplicitly]
|
||||
[SuppressMessage("ReSharper", "SpecifyStringComparison")]
|
||||
|
@ -37,7 +36,7 @@ public class RegisterForm : BaseLayout
|
|||
return this.Page();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(emailAddress))
|
||||
if (string.IsNullOrWhiteSpace(emailAddress) && ServerSettings.Instance.SMTPEnabled)
|
||||
{
|
||||
this.Error = "Email address field is required.";
|
||||
return this.Page();
|
||||
|
|
29
ProjectLighthouse/Pages/SetEmailForm.cshtml
Normal file
29
ProjectLighthouse/Pages/SetEmailForm.cshtml
Normal file
|
@ -0,0 +1,29 @@
|
|||
@page "/login/setEmail"
|
||||
@using LBPUnion.ProjectLighthouse.Types.Settings
|
||||
@model LBPUnion.ProjectLighthouse.Pages.SetEmailForm
|
||||
|
||||
@{
|
||||
Layout = "Layouts/BaseLayout";
|
||||
Model.Title = "Set an Email Address";
|
||||
}
|
||||
|
||||
<p>This instance requires email verification. As your account was created before this was a requirement, you must now set an email for your account before continuing.</p>
|
||||
|
||||
<form class="ui form" onsubmit="return onSubmit(this)" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
|
||||
@if (ServerSettings.Instance.SMTPEnabled)
|
||||
{
|
||||
<div class="field">
|
||||
<label>Please type a valid email address and verify it:</label>
|
||||
<div class="ui left icon input">
|
||||
<input type="email" name="emailAddress" id="emailAddress" placeholder="Email Address">
|
||||
<i class="mail icon"></i>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="token" id="token" value="@Model.EmailToken.EmailToken">
|
||||
</div>
|
||||
}
|
||||
|
||||
<input type="submit" value="Verify Email Address" id="submit" class="ui blue button">
|
||||
</form>
|
51
ProjectLighthouse/Pages/SetEmailForm.cshtml.cs
Normal file
51
ProjectLighthouse/Pages/SetEmailForm.cshtml.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles.Email;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Pages;
|
||||
|
||||
public class SetEmailForm : BaseLayout
|
||||
{
|
||||
public SetEmailForm(Database database) : base(database)
|
||||
{}
|
||||
|
||||
public EmailSetToken EmailToken;
|
||||
|
||||
public async Task<IActionResult> OnGet(string? token = null)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost(string emailAddress, string token)
|
||||
{
|
||||
EmailSetToken? emailToken = await this.Database.EmailSetTokens.Include(t => t.User).FirstOrDefaultAsync(t => t.EmailToken == token);
|
||||
if (emailToken == null) return this.Redirect("/login");
|
||||
|
||||
emailToken.User.EmailAddress = emailAddress;
|
||||
this.Database.EmailSetTokens.Remove(emailToken);
|
||||
|
||||
EmailVerificationToken emailVerifyToken = new()
|
||||
{
|
||||
UserId = emailToken.UserId,
|
||||
User = emailToken.User,
|
||||
EmailToken = HashHelper.GenerateAuthToken(),
|
||||
};
|
||||
|
||||
this.Database.EmailVerificationTokens.Add(emailVerifyToken);
|
||||
|
||||
await this.Database.SaveChangesAsync();
|
||||
|
||||
return this.Redirect("/login/verify?token=" + emailVerifyToken.EmailToken);
|
||||
}
|
||||
}
|
|
@ -51,6 +51,10 @@
|
|||
<None Remove="r.tar.gz"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Migrations\20220301204930_AddEmailVerificationTokens.Designer.cs"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
<Exec Command="git describe --long --always --dirty --exclude=\* --abbrev=8 > "$(ProjectDir)/gitVersion.txt""/>
|
||||
<Exec Command="git branch --show-current > "$(ProjectDir)/gitBranch.txt""/>
|
||||
|
|
17
ProjectLighthouse/Types/Profiles/Email/EmailSetToken.cs
Normal file
17
ProjectLighthouse/Types/Profiles/Email/EmailSetToken.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles.Email;
|
||||
|
||||
public class EmailSetToken
|
||||
{
|
||||
[Key]
|
||||
public int EmailSetTokenId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public string EmailToken { get; set; }
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles.Email;
|
||||
|
||||
public class EmailVerificationToken
|
||||
{
|
||||
[Key]
|
||||
public int EmailVerificationTokenId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public string EmailToken { get; set; }
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue