From 7c98b1eca32ffbcd048ee71b0002a2bdbabd1cd4 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 1 Mar 2022 15:06:12 -0500 Subject: [PATCH] Send email on account creation --- ProjectLighthouse/Database.cs | 16 +- ...01195426_AddEmailAddressToUser.Designer.cs | 1012 +++++++++++++++++ .../20220301195426_AddEmailAddressToUser.cs | 26 + .../Migrations/DatabaseModelSnapshot.cs | 3 + ProjectLighthouse/Pages/RegisterForm.cshtml | 8 + .../Pages/RegisterForm.cshtml.cs | 10 +- ProjectLighthouse/Types/User.cs | 5 + 7 files changed, 1074 insertions(+), 6 deletions(-) create mode 100644 ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.Designer.cs create mode 100644 ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.cs diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index 0ae12fde..bf8bbef8 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -45,7 +45,8 @@ public class Database : DbContext protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion); - public async Task CreateUser(string username, string password) + #nullable enable + public async Task CreateUser(string username, string password, string? emailAddress = null) { 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"); } - User user; - if ((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null) return user; + User? user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync(); + if (user != null) return user; Location l = new(); // store to get id after submitting this.Locations.Add(l); // add to table @@ -77,10 +78,17 @@ public class Database : DbContext 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; } - #nullable enable public async Task AuthenticateUser(NPTicket npTicket, string userLocation) { User? user = await this.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username); diff --git a/ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.Designer.cs b/ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.Designer.cs new file mode 100644 index 00000000..1cef4223 --- /dev/null +++ b/ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.Designer.cs @@ -0,0 +1,1012 @@ +// +using LBPUnion.ProjectLighthouse; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20220301195426_AddEmailAddressToUser")] + partial class AddEmailAddressToUser + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b => + { + b.Property("AuthenticationAttemptId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameTokenId") + .HasColumnType("int"); + + b.Property("IPAddress") + .HasColumnType("longtext"); + + b.Property("Platform") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("AuthenticationAttemptId"); + + b.HasIndex("GameTokenId"); + + b.ToTable("AuthenticationAttempts"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Categories.DatabaseCategory", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Endpoint") + .HasColumnType("longtext"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("SlotIdsCollection") + .HasColumnType("longtext"); + + b.HasKey("CategoryId"); + + b.ToTable("CustomCategories"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("Platform") + .HasColumnType("int"); + + b.Property("Used") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserLocation") + .HasColumnType("longtext"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.HasIndex("UserId"); + + b.ToTable("GameTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => + { + b.Property("HeartedProfileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("HeartedUserId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("HeartedProfileId"); + + b.HasIndex("HeartedUserId"); + + b.HasIndex("UserId"); + + b.ToTable("HeartedProfiles"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b => + { + b.Property("HeartedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("HeartedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("HeartedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b => + { + b.Property("QueuedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("QueuedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("QueuedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b => + { + b.Property("RatedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("RatingLBP1") + .HasColumnType("double"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("RatedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.Property("SlotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuthorLabels") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("BackgroundHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("CrossControllerRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstUploaded") + .HasColumnType("bigint"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("IconHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InitiallyLocked") + .HasColumnType("tinyint(1)"); + + b.Property("LastUpdated") + .HasColumnType("bigint"); + + b.Property("Lbp1Only") + .HasColumnType("tinyint(1)"); + + b.Property("LevelType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("MaximumPlayers") + .HasColumnType("int"); + + b.Property("MinimumPlayers") + .HasColumnType("int"); + + b.Property("MoveRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PlaysLBP1") + .HasColumnType("int"); + + b.Property("PlaysLBP1Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP1Unique") + .HasColumnType("int"); + + b.Property("PlaysLBP2") + .HasColumnType("int"); + + b.Property("PlaysLBP2Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP2Unique") + .HasColumnType("int"); + + b.Property("PlaysLBP3") + .HasColumnType("int"); + + b.Property("PlaysLBP3Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP3Unique") + .HasColumnType("int"); + + b.Property("PlaysLBPVita") + .HasColumnType("int"); + + b.Property("PlaysLBPVitaComplete") + .HasColumnType("int"); + + b.Property("PlaysLBPVitaUnique") + .HasColumnType("int"); + + b.Property("ResourceCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RootLevel") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Shareable") + .HasColumnType("int"); + + b.Property("SubLevel") + .HasColumnType("tinyint(1)"); + + b.Property("TeamPick") + .HasColumnType("tinyint(1)"); + + b.HasKey("SlotId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("LocationId"); + + b.ToTable("Slots"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b => + { + b.Property("VisitedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PlaysLBP1") + .HasColumnType("int"); + + b.Property("PlaysLBP2") + .HasColumnType("int"); + + b.Property("PlaysLBP3") + .HasColumnType("int"); + + b.Property("PlaysLBPVita") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("VisitedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("VisitedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.Property("PhotoId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("LargeHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MediumHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhotoSubjectCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PlanHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SmallHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("PhotoId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Photos"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.Property("PhotoSubjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Bounds") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("PhotoSubjectId"); + + b.HasIndex("UserId"); + + b.ToTable("PhotoSubjects"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.Property("CommentId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("DeletedBy") + .HasColumnType("longtext"); + + b.Property("DeletedType") + .HasColumnType("longtext"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("PosterUserId") + .HasColumnType("int"); + + b.Property("TargetId") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("CommentId"); + + b.HasIndex("PosterUserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastContact", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("Platform") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("UserId"); + + b.ToTable("LastContacts"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("int"); + + b.Property("Y") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reaction", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("TargetId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatingId"); + + b.ToTable("Reactions"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reports.GriefReport", b => + { + b.Property("ReportId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Bounds") + .HasColumnType("longtext"); + + b.Property("GriefStateHash") + .HasColumnType("longtext"); + + b.Property("InitialStateHash") + .HasColumnType("longtext"); + + b.Property("JpegHash") + .HasColumnType("longtext"); + + b.Property("LevelId") + .HasColumnType("int"); + + b.Property("LevelOwner") + .HasColumnType("longtext"); + + b.Property("LevelType") + .HasColumnType("longtext"); + + b.Property("Players") + .HasColumnType("longtext"); + + b.Property("ReportingPlayerId") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("ReportId"); + + b.HasIndex("ReportingPlayerId"); + + b.ToTable("Reports"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b => + { + b.Property("RatedReviewId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ReviewId") + .HasColumnType("int"); + + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatedReviewId"); + + b.HasIndex("ReviewId"); + + b.HasIndex("UserId"); + + b.ToTable("RatedReviews"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b => + { + b.Property("ReviewId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("DeletedBy") + .HasColumnType("int"); + + b.Property("LabelCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReviewerId") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("ReviewId"); + + b.HasIndex("ReviewerId"); + + b.HasIndex("SlotId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => + { + b.Property("ScoreId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PlayerIdCollection") + .HasColumnType("longtext"); + + b.Property("Points") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("ScoreId"); + + b.HasIndex("SlotId"); + + b.ToTable("Scores"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Banned") + .HasColumnType("tinyint(1)"); + + b.Property("BannedReason") + .HasColumnType("longtext"); + + b.Property("Biography") + .HasColumnType("longtext"); + + b.Property("BooHash") + .HasColumnType("longtext"); + + b.Property("EmailAddress") + .HasColumnType("longtext"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("IsAdmin") + .HasColumnType("tinyint(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("MehHash") + .HasColumnType("longtext"); + + b.Property("Password") + .HasColumnType("longtext"); + + b.Property("PasswordResetRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Pins") + .HasColumnType("longtext"); + + b.Property("PlanetHashLBP2") + .HasColumnType("longtext"); + + b.Property("PlanetHashLBP3") + .HasColumnType("longtext"); + + b.Property("PlanetHashLBPVita") + .HasColumnType("longtext"); + + b.Property("Username") + .HasColumnType("longtext"); + + b.Property("YayHash") + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.HasIndex("LocationId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.UserApprovedIpAddress", b => + { + b.Property("UserApprovedIpAddressId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("IpAddress") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("UserApprovedIpAddressId"); + + b.HasIndex("UserId"); + + b.ToTable("UserApprovedIpAddresses"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.ToTable("WebTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken") + .WithMany() + .HasForeignKey("GameTokenId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameToken"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser") + .WithMany() + .HasForeignKey("HeartedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("HeartedUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster") + .WithMany() + .HasForeignKey("PosterUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Poster"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reports.GriefReport", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "ReportingPlayer") + .WithMany() + .HasForeignKey("ReportingPlayerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportingPlayer"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Reviews.Review", "Review") + .WithMany() + .HasForeignKey("ReviewId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Review"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Reviewer") + .WithMany() + .HasForeignKey("ReviewerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Reviewer"); + + b.Navigation("Slot"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.UserApprovedIpAddress", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.cs b/ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.cs new file mode 100644 index 00000000..d30d4f9d --- /dev/null +++ b/ProjectLighthouse/Migrations/20220301195426_AddEmailAddressToUser.cs @@ -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( + name: "EmailAddress", + table: "Users", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EmailAddress", + table: "Users"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 23e9069d..4afda237 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -669,6 +669,9 @@ namespace ProjectLighthouse.Migrations b.Property("BooHash") .HasColumnType("longtext"); + b.Property("EmailAddress") + .HasColumnType("longtext"); + b.Property("Game") .HasColumnType("int"); diff --git a/ProjectLighthouse/Pages/RegisterForm.cshtml b/ProjectLighthouse/Pages/RegisterForm.cshtml index 93e9dfd5..025cb0f7 100644 --- a/ProjectLighthouse/Pages/RegisterForm.cshtml +++ b/ProjectLighthouse/Pages/RegisterForm.cshtml @@ -43,6 +43,14 @@ +
+ +
+ + +
+
+
diff --git a/ProjectLighthouse/Pages/RegisterForm.cshtml.cs b/ProjectLighthouse/Pages/RegisterForm.cshtml.cs index a7945459..ab42a197 100644 --- a/ProjectLighthouse/Pages/RegisterForm.cshtml.cs +++ b/ProjectLighthouse/Pages/RegisterForm.cshtml.cs @@ -21,7 +21,7 @@ public class RegisterForm : BaseLayout [UsedImplicitly] [SuppressMessage("ReSharper", "SpecifyStringComparison")] - public async Task OnPost(string username, string password, string confirmPassword) + public async Task OnPost(string username, string password, string confirmPassword, string emailAddress) { if (!ServerSettings.Instance.RegistrationEnabled) return this.NotFound(); @@ -37,6 +37,12 @@ public class RegisterForm : BaseLayout return this.Page(); } + if (string.IsNullOrWhiteSpace(emailAddress)) + { + this.Error = "Email address field is required."; + return this.Page(); + } + if (password != confirmPassword) { this.Error = "Passwords do not match!"; @@ -55,7 +61,7 @@ public class RegisterForm : BaseLayout 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() { diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index 2599681e..35e7a7cc 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -13,6 +13,11 @@ public class User public int UserId { get; set; } public string Username { get; set; } + #nullable enable + [JsonIgnore] + public string? EmailAddress { get; set; } = null; + #nullable disable + [JsonIgnore] public string Password { get; set; }