diff --git a/FoodPicker.Infrastructure/Models/ApplicationUser.cs b/FoodPicker.Infrastructure/Models/ApplicationUser.cs index b3a971e..1b95d8e 100644 --- a/FoodPicker.Infrastructure/Models/ApplicationUser.cs +++ b/FoodPicker.Infrastructure/Models/ApplicationUser.cs @@ -8,5 +8,6 @@ public class ApplicationUser : IdentityUser [Required] public string Name { get; set; } public bool VoteIsRequired { get; set; } = true; + public bool IsActive { get; set; } = true; } } \ No newline at end of file diff --git a/FoodPicker.Migrations/Migrations/20230907201038_Add user active bool.Designer.cs b/FoodPicker.Migrations/Migrations/20230907201038_Add user active bool.Designer.cs new file mode 100644 index 0000000..1f7d52f --- /dev/null +++ b/FoodPicker.Migrations/Migrations/20230907201038_Add user active bool.Designer.cs @@ -0,0 +1,555 @@ +// +using System; +using FoodPicker.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FoodPicker.Migrations.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20230907201038_Add user active bool")] + partial class Adduseractivebool + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.21") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("VoteIsRequired") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.AutoVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Keyword") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("longtext"); + + b.Property("VoteOptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("VoteOptionId"); + + b.ToTable("AutoVotes"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .HasColumnType("longtext"); + + b.Property("MealWeekId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SelectedForOrder") + .HasColumnType("tinyint(1)"); + + b.Property("Tags") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealWeekId"); + + b.ToTable("Meals"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.MealRating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("RatingComment") + .HasColumnType("longtext"); + + b.Property("RatingTime") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("MealId") + .IsUnique(); + + b.ToTable("MealRatings"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.MealVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteOptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VoteOptionId"); + + b.HasIndex("MealId", "UserId") + .IsUnique(); + + b.ToTable("MealVotes"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.MealWeek", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DeliveryDate") + .HasColumnType("datetime(6)"); + + b.Property("MealWeekStatus") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("MealWeeks"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.PersistentConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ConfigCode") + .HasColumnType("longtext"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PersistentConfigs"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.VoteOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Weight") + .HasColumnType("double"); + + b.HasKey("Id"); + + b.ToTable("VoteOptions"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.WeekUserComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("WeekId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("WeekId"); + + b.ToTable("WeekUserComments"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.AutoVote", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.VoteOption", "VoteOption") + .WithMany() + .HasForeignKey("VoteOptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("VoteOption"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.Meal", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.MealWeek", "MealWeek") + .WithMany("Meals") + .HasForeignKey("MealWeekId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MealWeek"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.MealRating", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.Meal", "Meal") + .WithOne("MealRating") + .HasForeignKey("FoodPicker.Infrastructure.Models.MealRating", "MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Meal"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.MealVote", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.Meal", "Meal") + .WithMany("MealVotes") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FoodPicker.Infrastructure.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.HasOne("FoodPicker.Infrastructure.Models.VoteOption", "VoteOption") + .WithMany() + .HasForeignKey("VoteOptionId"); + + b.Navigation("Meal"); + + b.Navigation("User"); + + b.Navigation("VoteOption"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.WeekUserComment", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.HasOne("FoodPicker.Infrastructure.Models.MealWeek", "Week") + .WithMany() + .HasForeignKey("WeekId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Week"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FoodPicker.Infrastructure.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("FoodPicker.Infrastructure.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.Meal", b => + { + b.Navigation("MealRating"); + + b.Navigation("MealVotes"); + }); + + modelBuilder.Entity("FoodPicker.Infrastructure.Models.MealWeek", b => + { + b.Navigation("Meals"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/FoodPicker.Migrations/Migrations/20230907201038_Add user active bool.cs b/FoodPicker.Migrations/Migrations/20230907201038_Add user active bool.cs new file mode 100644 index 0000000..a93f5bf --- /dev/null +++ b/FoodPicker.Migrations/Migrations/20230907201038_Add user active bool.cs @@ -0,0 +1,67 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FoodPicker.Migrations.Migrations +{ + public partial class Adduseractivebool : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_MealVotes_VoteOptions_VoteOptionId", + table: "MealVotes"); + + migrationBuilder.AlterColumn( + name: "VoteOptionId", + table: "MealVotes", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddColumn( + name: "IsActive", + table: "AspNetUsers", + type: "tinyint(1)", + nullable: false, + defaultValue: true); + + migrationBuilder.AddForeignKey( + name: "FK_MealVotes_VoteOptions_VoteOptionId", + table: "MealVotes", + column: "VoteOptionId", + principalTable: "VoteOptions", + principalColumn: "Id"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_MealVotes_VoteOptions_VoteOptionId", + table: "MealVotes"); + + migrationBuilder.DropColumn( + name: "IsActive", + table: "AspNetUsers"); + + migrationBuilder.AlterColumn( + name: "VoteOptionId", + table: "MealVotes", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_MealVotes_VoteOptions_VoteOptionId", + table: "MealVotes", + column: "VoteOptionId", + principalTable: "VoteOptions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/FoodPicker.Migrations/Migrations/ApplicationDbContextModelSnapshot.cs b/FoodPicker.Migrations/Migrations/ApplicationDbContextModelSnapshot.cs index b861b84..f2c516c 100644 --- a/FoodPicker.Migrations/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/FoodPicker.Migrations/Migrations/ApplicationDbContextModelSnapshot.cs @@ -38,6 +38,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EmailConfirmed") .HasColumnType("tinyint(1)"); + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + b.Property("LockoutEnabled") .HasColumnType("tinyint(1)"); @@ -189,7 +192,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("UserId") .HasColumnType("varchar(255)"); - b.Property("VoteOptionId") + b.Property("VoteOptionId") .HasColumnType("int"); b.HasKey("Id"); @@ -456,9 +459,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasOne("FoodPicker.Infrastructure.Models.VoteOption", "VoteOption") .WithMany() - .HasForeignKey("VoteOptionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("VoteOptionId"); b.Navigation("Meal"); diff --git a/FoodPicker.Web/Controllers/ApiController.cs b/FoodPicker.Web/Controllers/ApiController.cs index 3807e39..64800be 100644 --- a/FoodPicker.Web/Controllers/ApiController.cs +++ b/FoodPicker.Web/Controllers/ApiController.cs @@ -58,7 +58,7 @@ group v by v.UserId into u where u.Count() >= numMeals select u.Key; - var users = _userManager.Users.ToList(); + var users = _userManager.Users.Where(u => u.IsActive).ToList(); var fullyVotedNames = users.Where(x => fullyVotedUserIds.Contains(x.Id)).Select(x => x.Name).ToList(); diff --git a/FoodPicker.Web/Controllers/AuthController.cs b/FoodPicker.Web/Controllers/AuthController.cs index 9f726a8..6261d26 100644 --- a/FoodPicker.Web/Controllers/AuthController.cs +++ b/FoodPicker.Web/Controllers/AuthController.cs @@ -17,8 +17,9 @@ public class AuthController : Controller private readonly UserManager _userManager; private readonly SignInManager _signInManager; private readonly IConfiguration _configuration; - - public AuthController(UserManager userManager, SignInManager signInManager, ILogger logger, IConfiguration configuration) + + public AuthController(UserManager userManager, SignInManager signInManager, + ILogger logger, IConfiguration configuration) { _userManager = userManager; _signInManager = signInManager; @@ -28,12 +29,9 @@ public AuthController(UserManager userManager, SignInManager @@ -46,38 +44,46 @@ public class LoginViewModel [HttpGet] public async Task Login([FromQuery] string returnUrl, [FromQuery] bool autoLogin = false) { - if (autoLogin && _configuration["ClaimsInHeaders"] == "True" && Request.Headers.ContainsKey("X-Token-Subject")) + if (autoLogin + && bool.TryParse(_configuration["ClaimsInHeaders"], out var claimsInHeaders) && claimsInHeaders + && Request.Headers.TryGetValue("X-Token-Subject", out var subject)) { - var user = await _userManager.FindByNameAsync(Request.Headers["X-Token-Subject"]); - if (user != null) + var user = await _userManager.FindByNameAsync(subject); + if (user is { IsActive: true }) { // We assume that if we're being given claims that they have been properly authenticated await _signInManager.SignInWithClaimsAsync(user, true, new[] { new Claim("PasswordLogin", "true") }); - + if (!string.IsNullOrEmpty(returnUrl)) { return LocalRedirect(returnUrl); } + return RedirectToAction("Index", "Home"); } } - + if (!_userManager.Users.Any()) return RedirectToAction("Register"); return View(); } - + [HttpPost] public async Task Login([FromForm] LoginViewModel model, [FromQuery] string returnUrl) { var user = await _userManager.FindByIdAsync(model.UserId); + if (!user.IsActive) + { + ModelState.AddModelError("UserId", "User Invalid"); + return View(); + } if (!string.IsNullOrEmpty(model.Password) && await _userManager.IsInRoleAsync(user, "Admin")) { // Password login if (await _userManager.CheckPasswordAsync(user, model.Password)) { await _signInManager.SignInWithClaimsAsync(user, false, - new[] { new Claim("PasswordLogin", "true") }); + new[] { new Claim("PasswordLogin", "true") }); } else { @@ -93,27 +99,26 @@ await _signInManager.SignInWithClaimsAsync(user, false, IsPersistent = true }); } - + if (!string.IsNullOrEmpty(returnUrl)) { return LocalRedirect(returnUrl); } + return RedirectToAction("Index", "Home"); } - + public class RegisterViewModel { - [Required] - public string Name { get; set; } - - [Required] - public string Username { get; set; } - + [Required] public string Name { get; set; } + + [Required] public string Username { get; set; } + [Required] [DataType(DataType.Password)] public string Password { get; set; } } - + [HttpGet] public IActionResult Register() { @@ -121,7 +126,7 @@ public IActionResult Register() return View(); } - + [HttpPost] public async Task Register([FromForm] RegisterViewModel model) { @@ -130,11 +135,13 @@ public async Task Register([FromForm] RegisterViewModel model) { return View(); } + var createResult = await _userManager.CreateAsync(new ApplicationUser() { Name = model.Name, UserName = model.Username, VoteIsRequired = true, + IsActive = true, }, model.Password); if (!createResult.Succeeded) { @@ -146,7 +153,7 @@ public async Task Register([FromForm] RegisterViewModel model) _logger.LogError("Error creating user: {Error}", string.Join(", ", createResult.Errors)); } - + var user = await _userManager.FindByNameAsync(model.Username); await _userManager.AddPasswordAsync(user, model.Password); await _userManager.AddToRoleAsync(user, "Admin"); diff --git a/FoodPicker.Web/Controllers/UserController.cs b/FoodPicker.Web/Controllers/UserController.cs index f37bbd1..1f51a08 100644 --- a/FoodPicker.Web/Controllers/UserController.cs +++ b/FoodPicker.Web/Controllers/UserController.cs @@ -44,6 +44,7 @@ public class UserViewModel public bool IsAdmin { get; set; } [Required] public bool VoteIsRequired { get; set; } = true; + [Required] public bool IsActive { get; set; } = true; } [HttpGet] @@ -68,7 +69,8 @@ public async Task CreateOrEdit(string id) Username = user.UserName, Password = null, IsAdmin = await _userManager.IsInRoleAsync(user, "Admin"), - VoteIsRequired = user.VoteIsRequired + VoteIsRequired = user.VoteIsRequired, + IsActive = user.IsActive, }; } return View(model); @@ -87,8 +89,10 @@ public async Task CreateOrEdit(string id, [FromForm] UserViewMode dbModel = new ApplicationUser { Id = Guid.NewGuid().ToString(), + Name = model.Name, UserName = model.Username, - VoteIsRequired = model.VoteIsRequired + VoteIsRequired = model.VoteIsRequired, + IsActive = model.IsActive, }; await _userManager.CreateAsync(dbModel); } @@ -98,6 +102,7 @@ public async Task CreateOrEdit(string id, [FromForm] UserViewMode dbModel.Name = model.Name; dbModel.UserName = model.Username; dbModel.VoteIsRequired = model.VoteIsRequired; + dbModel.IsActive = model.IsActive; await _userManager.UpdateAsync(dbModel); } diff --git a/FoodPicker.Web/Controllers/WeekController.cs b/FoodPicker.Web/Controllers/WeekController.cs index eff3c92..a61cbbe 100644 --- a/FoodPicker.Web/Controllers/WeekController.cs +++ b/FoodPicker.Web/Controllers/WeekController.cs @@ -251,7 +251,7 @@ public async Task ViewResults(int? weekId) var model = new ViewResultsViewModel { Week = week, - ParticipatingUsers = await _userManager.Users.ToListAsync(), + ParticipatingUsers = await _userManager.Users.Where(u => u.IsActive).ToListAsync(), IsEditable = week.CanVote, UserComments = await _commentRepository.GetCommentsForWeek((int) weekId) }; diff --git a/FoodPicker.Web/Views/Auth/Login.cshtml b/FoodPicker.Web/Views/Auth/Login.cshtml index 9d6f96d..956812f 100644 --- a/FoodPicker.Web/Views/Auth/Login.cshtml +++ b/FoodPicker.Web/Views/Auth/Login.cshtml @@ -1,11 +1,11 @@ @using Microsoft.AspNetCore.Identity @using Microsoft.EntityFrameworkCore @model FoodPicker.Web.Controllers.AuthController.LoginViewModel -@inject UserManager _userManager +@inject UserManager UserManager
@{ - var users = await _userManager.Users.ToListAsync(); + var users = await UserManager.Users.Where(u => u.IsActive).ToListAsync(); }
@@ -13,9 +13,10 @@ @foreach (var user in users) { - + } +
diff --git a/FoodPicker.Web/Views/User/CreateOrEdit.cshtml b/FoodPicker.Web/Views/User/CreateOrEdit.cshtml index b4c6dde..83fc34c 100644 --- a/FoodPicker.Web/Views/User/CreateOrEdit.cshtml +++ b/FoodPicker.Web/Views/User/CreateOrEdit.cshtml @@ -31,11 +31,15 @@
- +
- + +
+
+ +
diff --git a/FoodPicker.Web/Views/User/List.cshtml b/FoodPicker.Web/Views/User/List.cshtml index d5bff93..4a97917 100644 --- a/FoodPicker.Web/Views/User/List.cshtml +++ b/FoodPicker.Web/Views/User/List.cshtml @@ -1,6 +1,6 @@ @using Microsoft.AspNetCore.Identity @model List -@inject UserManager _userManager +@inject UserManager UserManager @{ ViewBag.Title = "User List"; @@ -16,6 +16,7 @@ Name Username + Is Active? Is Admin? Vote Required? Actions @@ -27,7 +28,8 @@ @user.Name @user.UserName - @((await _userManager.IsInRoleAsync(user, "Admin")) ? "Yes" : "No") + @(user.IsActive ? "Yes" : "No") + @((await UserManager.IsInRoleAsync(user, "Admin")) ? "Yes" : "No") @(user.VoteIsRequired ? "Yes" : "No") Edit