Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 211 additions & 0 deletions Controllers/AuthController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
using Microsoft.AspNetCore.Mvc;
using EduCoreSuite.Models;
using EduCoreSuite.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using EduCoreSuite.Models.ViewModels.Auth;
using Microsoft.AspNetCore.Authorization;

[Route("Auth")]
public class AuthController : Controller
{
private readonly ApplicationDbContext _db;

public AuthController(ApplicationDbContext db)
{
_db = db;
}

[HttpGet("Register")]
public IActionResult Register()
{
var viewModel = new RegisterViewModel();
ViewBag.Roles = _db.Roles.ToList();
return View(viewModel);
}

[HttpPost("Register")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel viewModel)
{
if (!ModelState.IsValid)
{
ViewBag.Roles = _db.Roles.ToList();
return View(viewModel);
}

if (await _db.Users.AnyAsync(u => u.Email == viewModel.Email || u.Username == viewModel.UserName))
{
ModelState.AddModelError("Email", "User already exists");
ViewBag.Roles = _db.Roles.ToList();
return View(viewModel);
}

var user = new User
{
Username = viewModel.UserName,
Email = viewModel.Email,
PasswordHash = HashPassword(viewModel.Password),
FirstName = viewModel.FirstName,
LastName = viewModel.LastName,
RoleID = viewModel.RoleID
};

_db.Users.Add(user);
await _db.SaveChangesAsync();
return RedirectToAction("Login");
}

[HttpGet("Login")]
[AllowAnonymous]
public IActionResult Login()
{
return View(new LoginViewModel());
}

[HttpPost("Login")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}

var user = await _db.Users.FirstOrDefaultAsync(u => u.Email == viewModel.Email);
if (user == null || !VerifyPassword(viewModel.Password, user.PasswordHash))
{
ModelState.AddModelError("", "Invalid credentials");
return View(viewModel);
}

var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.ID.ToString()),
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.Email, user.Email),
new Claim("CustomUserId", user.CustomUserId),
new Claim(ClaimTypes.Role, user.RoleID.ToString())
};

var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);

await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
principal,
new AuthenticationProperties { IsPersistent = viewModel.RememberMe });

return RedirectToAction("Approval", "User");
}

[HttpGet("Logout")]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync();
return RedirectToAction("Login");
}

[HttpGet("ForgotPassword")]
public IActionResult ForgotPassword()
{
return View(new ForgotPasswordViewModel());
}

[HttpPost("ForgotPassword")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}

var user = await _db.Users.FirstOrDefaultAsync(u => u.Email == viewModel.Email);
if (user == null)
{
ModelState.AddModelError("", "Email not found");
return View(viewModel);
}

string code = new Random().Next(100000, 999999).ToString();
HttpContext.Session.SetString("ResetCode", code);
HttpContext.Session.SetString("ResetEmail", viewModel.Email);
// TODO: Send email using SMTP or SendGrid

return RedirectToAction("VerifyCode");
}

[HttpGet("VerifyCode")]
public IActionResult VerifyCode()
{
return View(new VerifyCodeViewModel());
}

[HttpPost("VerifyCode")]
[ValidateAntiForgeryToken]
public IActionResult VerifyCode(VerifyCodeViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}

var sessionCode = HttpContext.Session.GetString("ResetCode");
if (viewModel.Code != sessionCode)
{
ModelState.AddModelError("", "Invalid code");
return View(viewModel);
}

return RedirectToAction("ResetPassword");
}

[HttpGet("ResetPassword")]
public IActionResult ResetPassword()
{
return View(new ResetPasswordViewModel());
}

[HttpPost("ResetPassword")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}

var email = HttpContext.Session.GetString("ResetEmail");
var user = await _db.Users.FirstOrDefaultAsync(u => u.Email == email);
if (user == null)
{
return RedirectToAction("Login");
}

user.PasswordHash = HashPassword(viewModel.NewPassword);
await _db.SaveChangesAsync();

// Clear the reset session
HttpContext.Session.Remove("ResetCode");
HttpContext.Session.Remove("ResetEmail");

return RedirectToAction("Login");
}

private string HashPassword(string password)
{
using var sha = SHA256.Create();
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(password));
return Convert.ToBase64String(bytes);
}

private bool VerifyPassword(string password, string hash)
{
return HashPassword(password) == hash;
}
}
81 changes: 0 additions & 81 deletions Controllers/BooksController.cs

This file was deleted.

31 changes: 31 additions & 0 deletions Controllers/UserController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using EduCoreSuite.Data;
using EduCoreSuite.Models.ViewModels.UserApproval;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;


namespace EduCoreSuite.Controllers
{
public class UserController : Controller
{
private readonly ApplicationDbContext _db;

public UserController(ApplicationDbContext db)
{
_db = db;
}
[Authorize(Roles = "3")]

[HttpGet]
public async Task<IActionResult> Approval()
{
var viewModel = new ApprovalViewModel
{
Users = await _db.Users.ToListAsync(),
//Roles = await _db.Roles.ToDictionaryAsync(r => r.ID.ToString(), r => r.Name)
};
return View(viewModel);
}
}
}
1 change: 0 additions & 1 deletion Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ namespace EduCoreSuite.Data
{
public class ApplicationDbContext : DbContext
{
public DbSet<Book> Books { get; set; }

public DbSet<User> Users { get; set; }

Expand Down
5 changes: 5 additions & 0 deletions EduCoreSuite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>fd318432-ae1c-4044-aa3e-05aef00aa902</UserSecretsId>
</PropertyGroup>

<ItemGroup>
Expand All @@ -18,6 +19,10 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.14">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
19 changes: 0 additions & 19 deletions Models/Book.cs

This file was deleted.

Loading