diff --git a/RentACar/Data/Data.csproj b/RentACar/Data/Data.csproj index 52c6c53..c0a087d 100644 --- a/RentACar/Data/Data.csproj +++ b/RentACar/Data/Data.csproj @@ -4,6 +4,12 @@ net5.0 + + + + + + @@ -17,8 +23,4 @@ - - - - diff --git a/RentACar/Data/Data/RentACarDbContext.cs b/RentACar/Data/Data/RentACarDbContext.cs index 8539c6a..54829fe 100644 --- a/RentACar/Data/Data/RentACarDbContext.cs +++ b/RentACar/Data/Data/RentACarDbContext.cs @@ -8,7 +8,6 @@ namespace Data { public class RentACarDbContext : IdentityDbContext { - public virtual DbSet Cars { get; set; } public virtual DbSet Rents { get; set; } @@ -26,7 +25,7 @@ namespace Data { if (!optionsBuilder.IsConfigured) { - optionsBuilder.UseSqlServer("Server=.;Database=RentACar;Integrated Security=true;"); + optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=RentACar;Integrated Security=true;"); } } diff --git a/RentACar/WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs b/RentACar/Data/Migrations/20220329101121_initial.Designer.cs similarity index 60% rename from RentACar/WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs rename to RentACar/Data/Migrations/20220329101121_initial.Designer.cs index 2563c99..96cd065 100644 --- a/RentACar/WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs +++ b/RentACar/Data/Migrations/20220329101121_initial.Designer.cs @@ -1,26 +1,149 @@ -// +// using System; -using API.Data; +using Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -namespace API.Data.Migrations +namespace Data.Migrations { - [DbContext(typeof(ApplicationDbContext))] - [Migration("00000000000000_CreateIdentitySchema")] - partial class CreateIdentitySchema + [DbContext(typeof(RentACarDbContext))] + [Migration("20220329101121_initial")] + partial class initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.13") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("Data.Entities.Car", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Brand") + .HasColumnType("nvarchar(max)"); + + b.Property("CountPassengerSeats") + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Model") + .HasColumnType("nvarchar(max)"); + + b.Property("PriceForDay") + .HasColumnType("decimal(18,2)"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Cars"); + }); + + modelBuilder.Entity("Data.Entities.Rents", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CarId") + .HasColumnType("int"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CarId"); + + b.HasIndex("UserId"); + + b.ToTable("Rents"); + }); + + modelBuilder.Entity("Data.Entities.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedUserName") + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PersonalNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserName") + .IsUnique() + .HasFilter("[UserName] IS NOT NULL"); + + b.ToTable("User"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") @@ -31,18 +154,18 @@ namespace API.Data.Migrations .HasColumnType("nvarchar(max)"); b.Property("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() - .HasName("RoleNameIndex") + .HasDatabaseName("RoleNameIndex") .HasFilter("[NormalizedName] IS NOT NULL"); b.ToTable("AspNetRoles"); @@ -85,8 +208,8 @@ namespace API.Data.Migrations .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("EmailConfirmed") .HasColumnType("bit"); @@ -98,12 +221,12 @@ namespace API.Data.Migrations .HasColumnType("datetimeoffset"); b.Property("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); @@ -121,17 +244,17 @@ namespace API.Data.Migrations .HasColumnType("bit"); b.Property("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); + .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() - .HasName("UserNameIndex") + .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); b.ToTable("AspNetUsers"); @@ -164,12 +287,10 @@ namespace API.Data.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnType("nvarchar(450)"); b.Property("ProviderKey") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnType("nvarchar(450)"); b.Property("ProviderDisplayName") .HasColumnType("nvarchar(max)"); @@ -206,12 +327,10 @@ namespace API.Data.Migrations .HasColumnType("nvarchar(450)"); b.Property("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnType("nvarchar(450)"); b.Property("Name") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); + .HasColumnType("nvarchar(450)"); b.Property("Value") .HasColumnType("nvarchar(max)"); @@ -221,6 +340,21 @@ namespace API.Data.Migrations b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("Data.Entities.Rents", b => + { + b.HasOne("Data.Entities.Car", "Car") + .WithMany() + .HasForeignKey("CarId"); + + b.HasOne("Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Car"); + + b.Navigation("User"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) diff --git a/RentACar/Data/Migrations/20220329101121_initial.cs b/RentACar/Data/Migrations/20220329101121_initial.cs new file mode 100644 index 0000000..9fb816c --- /dev/null +++ b/RentACar/Data/Migrations/20220329101121_initial.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Data.Migrations +{ + public partial class initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/RentACar/WebApp/Areas/Identity/IdentityHostingStartup.cs b/RentACar/WebApp/Areas/Identity/IdentityHostingStartup.cs new file mode 100644 index 0000000..bb403e8 --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/IdentityHostingStartup.cs @@ -0,0 +1,21 @@ +using System; +using Data; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +[assembly: HostingStartup(typeof(WebApp.Areas.Identity.IdentityHostingStartup))] +namespace WebApp.Areas.Identity +{ + public class IdentityHostingStartup : IHostingStartup + { + public void Configure(IWebHostBuilder builder) + { + builder.ConfigureServices((context, services) => { + }); + } + } +} \ No newline at end of file diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/Login.cshtml b/RentACar/WebApp/Areas/Identity/Pages/Account/Login.cshtml new file mode 100644 index 0000000..8e4d327 --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/Login.cshtml @@ -0,0 +1,85 @@ +@page +@model LoginModel + +@{ + ViewData["Title"] = "Log in"; +} + +

@ViewData["Title"]

+
+
+
+
+

Use a local account to log in.

+
+
+
+ + + +
+
+ + + +
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+

Use another service to log in.

+
+ @{ + if ((Model.ExternalLogins?.Count ?? 0) == 0) + { +
+

+ There are no external authentication services configured. See this article + for details on setting up this ASP.NET application to support logging in via external services. +

+
+ } + else + { +
+
+

+ @foreach (var provider in Model.ExternalLogins) + { + + } +

+
+
+ } + } +
+
+
+ +@section Scripts { + +} diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/Login.cshtml.cs b/RentACar/WebApp/Areas/Identity/Pages/Account/Login.cshtml.cs new file mode 100644 index 0000000..011e062 --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Logging; +using Data.Entities; + +namespace WebApp.Areas.Identity.Pages.Account +{ + [AllowAnonymous] + public class LoginModel : PageModel + { + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public LoginModel(SignInManager signInManager, + ILogger logger, + UserManager userManager) + { + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + } + + [BindProperty] + public InputModel Input { get; set; } + + public IList ExternalLogins { get; set; } + + public string ReturnUrl { get; set; } + + [TempData] + public string ErrorMessage { get; set; } + + public class InputModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } + + [Display(Name = "Remember me?")] + public bool RememberMe { get; set; } + } + + public async Task OnGetAsync(string returnUrl = null) + { + if (!string.IsNullOrEmpty(ErrorMessage)) + { + ModelState.AddModelError(string.Empty, ErrorMessage); + } + + returnUrl ??= Url.Content("~/"); + + // Clear the existing external cookie to ensure a clean login process + await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); + + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + + ReturnUrl = returnUrl; + } + + public async Task OnPostAsync(string returnUrl = null) + { + returnUrl ??= Url.Content("~/"); + + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + + if (ModelState.IsValid) + { + // This doesn't count login failures towards account lockout + // To enable password failures to trigger account lockout, set lockoutOnFailure: true + var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false); + if (result.Succeeded) + { + _logger.LogInformation("User logged in."); + return LocalRedirect(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe }); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User account locked out."); + return RedirectToPage("./Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return Page(); + } + } + + // If we got this far, something failed, redisplay form + return Page(); + } + } +} diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/Logout.cshtml b/RentACar/WebApp/Areas/Identity/Pages/Account/Logout.cshtml new file mode 100644 index 0000000..eca33c6 --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/Logout.cshtml @@ -0,0 +1,21 @@ +@page +@model LogoutModel +@{ + ViewData["Title"] = "Log out"; +} + +
+

@ViewData["Title"]

+ @{ + if (User.Identity.IsAuthenticated) + { +
+ +
+ } + else + { +

You have successfully logged out of the application.

+ } + } +
\ No newline at end of file diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/Logout.cshtml.cs b/RentACar/WebApp/Areas/Identity/Pages/Account/Logout.cshtml.cs new file mode 100644 index 0000000..5755a27 --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/Logout.cshtml.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Data.Entities; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Logging; + +namespace WebApp.Areas.Identity.Pages.Account +{ + [AllowAnonymous] + public class LogoutModel : PageModel + { + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public LogoutModel(SignInManager signInManager, ILogger logger) + { + _signInManager = signInManager; + _logger = logger; + } + + public void OnGet() + { + } + + public async Task OnPost(string returnUrl = null) + { + await _signInManager.SignOutAsync(); + _logger.LogInformation("User logged out."); + if (returnUrl != null) + { + return LocalRedirect(returnUrl); + } + else + { + return RedirectToPage(); + } + } + } +} diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/Register.cshtml b/RentACar/WebApp/Areas/Identity/Pages/Account/Register.cshtml new file mode 100644 index 0000000..d9b50ab --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/Register.cshtml @@ -0,0 +1,67 @@ +@page +@model RegisterModel +@{ + ViewData["Title"] = "Register"; +} + +

@ViewData["Title"]

+ +
+
+
+

Create a new account.

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+ +
+
+
+
+

Use another service to register.

+
+ @{ + if ((Model.ExternalLogins?.Count ?? 0) == 0) + { +
+

+ There are no external authentication services configured. See this article + for details on setting up this ASP.NET application to support logging in via external services. +

+
+ } + else + { +
+
+

+ @foreach (var provider in Model.ExternalLogins) + { + + } +

+
+
+ } + } +
+
+
+ +@section Scripts { + +} diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/Register.cshtml.cs b/RentACar/WebApp/Areas/Identity/Pages/Account/Register.cshtml.cs new file mode 100644 index 0000000..4ba281f --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/Register.cshtml.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Data; +using Data.Entities; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Logging; + +namespace WebApp.Areas.Identity.Pages.Account +{ + [AllowAnonymous] + public class RegisterModel : PageModel + { + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly ILogger _logger; + private readonly RentACarDbContext _rentACartDbContext; + + public RegisterModel( + UserManager userManager, + SignInManager signInManager, + ILogger logger, + RentACarDbContext rentACarDbContext) + { + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + _rentACartDbContext = rentACarDbContext; + } + + [BindProperty] + public InputModel Input { get; set; } + + public string ReturnUrl { get; set; } + + public IList ExternalLogins { get; set; } + + public class InputModel + { + [Required] + [EmailAddress] + [Display(Name = "Email")] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } + + public async Task OnGetAsync(string returnUrl = null) + { + ReturnUrl = returnUrl; + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + } + + public async Task OnPostAsync(string returnUrl = null) + { + returnUrl ??= Url.Content("~/"); + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + if (ModelState.IsValid) + { + var user = new User { UserName = Input.Email, Email = Input.Email }; + var result = await _userManager.CreateAsync(user, Input.Password); + if (result.Succeeded) + { + _logger.LogInformation("User created a new account with password."); + + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var callbackUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl }, + protocol: Request.Scheme); + + + await _signInManager.SignInAsync(user, isPersistent: false); + return LocalRedirect(returnUrl); + + } + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } + } + + // If we got this far, something failed, redisplay form + return Page(); + } + } +} diff --git a/RentACar/WebApp/Areas/Identity/Pages/Account/_ViewImports.cshtml b/RentACar/WebApp/Areas/Identity/Pages/Account/_ViewImports.cshtml new file mode 100644 index 0000000..bb94c6b --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/Account/_ViewImports.cshtml @@ -0,0 +1 @@ +@using WebApp.Areas.Identity.Pages.Account \ No newline at end of file diff --git a/RentACar/WebApp/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml b/RentACar/WebApp/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml new file mode 100644 index 0000000..bacc0ae --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/RentACar/WebApp/Areas/Identity/Pages/_ViewImports.cshtml b/RentACar/WebApp/Areas/Identity/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..af3a34a --- /dev/null +++ b/RentACar/WebApp/Areas/Identity/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@using Microsoft.AspNetCore.Identity +@using WebApp.Areas.Identity +@using WebApp.Areas.Identity.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/RentACar/WebApp/Controllers/CarsController.cs b/RentACar/WebApp/Controllers/CarsController.cs new file mode 100644 index 0000000..823c87e --- /dev/null +++ b/RentACar/WebApp/Controllers/CarsController.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.EntityFrameworkCore; +using Data; +using Data.Entities; + +namespace WebApp.Controllers +{ + public class CarsController : Controller + { + private readonly RentACarDbContext _context; + + public CarsController(RentACarDbContext context) + { + _context = context; + } + + // GET: Cars + public async Task Index() + { + return View(await _context.Cars.ToListAsync()); + } + + // GET: Cars/Details/5 + public async Task Details(int? id) + { + if (id == null) + { + return NotFound(); + } + + var car = await _context.Cars + .FirstOrDefaultAsync(m => m.Id == id); + if (car == null) + { + return NotFound(); + } + + return View(car); + } + + // GET: Cars/Create + public IActionResult Create() + { + return View(); + } + + // POST: Cars/Create + // To protect from overposting attacks, enable the specific properties you want to bind to. + // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598. + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Create([Bind("Id,Brand,Model,Year,CountPassengerSeats,Description,PriceForDay")] Car car) + { + if (ModelState.IsValid) + { + _context.Add(car); + await _context.SaveChangesAsync(); + return RedirectToAction(nameof(Index)); + } + return View(car); + } + + // GET: Cars/Edit/5 + public async Task Edit(int? id) + { + if (id == null) + { + return NotFound(); + } + + var car = await _context.Cars.FindAsync(id); + if (car == null) + { + return NotFound(); + } + return View(car); + } + + // POST: Cars/Edit/5 + // To protect from overposting attacks, enable the specific properties you want to bind to. + // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598. + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Edit(int id, [Bind("Id,Brand,Model,Year,CountPassengerSeats,Description,PriceForDay")] Car car) + { + if (id != car.Id) + { + return NotFound(); + } + + if (ModelState.IsValid) + { + try + { + _context.Update(car); + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!CarExists(car.Id)) + { + return NotFound(); + } + else + { + throw; + } + } + return RedirectToAction(nameof(Index)); + } + return View(car); + } + + // GET: Cars/Delete/5 + public async Task Delete(int? id) + { + if (id == null) + { + return NotFound(); + } + + var car = await _context.Cars + .FirstOrDefaultAsync(m => m.Id == id); + if (car == null) + { + return NotFound(); + } + + return View(car); + } + + // POST: Cars/Delete/5 + [HttpPost, ActionName("Delete")] + [ValidateAntiForgeryToken] + public async Task DeleteConfirmed(int id) + { + var car = await _context.Cars.FindAsync(id); + _context.Cars.Remove(car); + await _context.SaveChangesAsync(); + return RedirectToAction(nameof(Index)); + } + + private bool CarExists(int id) + { + return _context.Cars.Any(e => e.Id == id); + } + } +} diff --git a/RentACar/WebApp/Controllers/RentsController.cs b/RentACar/WebApp/Controllers/RentsController.cs new file mode 100644 index 0000000..03fb828 --- /dev/null +++ b/RentACar/WebApp/Controllers/RentsController.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.EntityFrameworkCore; +using Data; +using Data.Entities; + +namespace WebApp.Controllers +{ + public class RentsController : Controller + { + private readonly RentACarDbContext _context; + + public RentsController(RentACarDbContext context) + { + _context = context; + } + + // GET: Rents + public async Task Index() + { + return View(await _context.Rents.ToListAsync()); + } + + // GET: Rents/Details/5 + public async Task Details(int? id) + { + if (id == null) + { + return NotFound(); + } + + var rents = await _context.Rents + .FirstOrDefaultAsync(m => m.Id == id); + if (rents == null) + { + return NotFound(); + } + + return View(rents); + } + + // GET: Rents/Create + public IActionResult Create() + { + return View(); + } + + // POST: Rents/Create + // To protect from overposting attacks, enable the specific properties you want to bind to. + // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598. + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Create([Bind("Id,StartDate,EndDate")] Rents rents) + { + if (ModelState.IsValid) + { + _context.Add(rents); + await _context.SaveChangesAsync(); + return RedirectToAction(nameof(Index)); + } + return View(rents); + } + + // GET: Rents/Edit/5 + public async Task Edit(int? id) + { + if (id == null) + { + return NotFound(); + } + + var rents = await _context.Rents.FindAsync(id); + if (rents == null) + { + return NotFound(); + } + return View(rents); + } + + // POST: Rents/Edit/5 + // To protect from overposting attacks, enable the specific properties you want to bind to. + // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598. + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Edit(int id, [Bind("Id,StartDate,EndDate")] Rents rents) + { + if (id != rents.Id) + { + return NotFound(); + } + + if (ModelState.IsValid) + { + try + { + _context.Update(rents); + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!RentsExists(rents.Id)) + { + return NotFound(); + } + else + { + throw; + } + } + return RedirectToAction(nameof(Index)); + } + return View(rents); + } + + // GET: Rents/Delete/5 + public async Task Delete(int? id) + { + if (id == null) + { + return NotFound(); + } + + var rents = await _context.Rents + .FirstOrDefaultAsync(m => m.Id == id); + if (rents == null) + { + return NotFound(); + } + + return View(rents); + } + + // POST: Rents/Delete/5 + [HttpPost, ActionName("Delete")] + [ValidateAntiForgeryToken] + public async Task DeleteConfirmed(int id) + { + var rents = await _context.Rents.FindAsync(id); + _context.Rents.Remove(rents); + await _context.SaveChangesAsync(); + return RedirectToAction(nameof(Index)); + } + + private bool RentsExists(int id) + { + return _context.Rents.Any(e => e.Id == id); + } + } +} diff --git a/RentACar/WebApp/Data/ApplicationDbContext.cs b/RentACar/WebApp/Data/ApplicationDbContext.cs deleted file mode 100644 index bfbc4b7..0000000 --- a/RentACar/WebApp/Data/ApplicationDbContext.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; - -namespace API.Data -{ - public class ApplicationDbContext : IdentityDbContext - { - public ApplicationDbContext(DbContextOptions options) - : base(options) - { - } - } -} diff --git a/RentACar/WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs b/RentACar/WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs deleted file mode 100644 index 76f8dc7..0000000 --- a/RentACar/WebApp/Data/Migrations/00000000000000_CreateIdentitySchema.cs +++ /dev/null @@ -1,220 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace API.Data.Migrations -{ - public partial class CreateIdentitySchema : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 256, nullable: true), - NormalizedName = table.Column(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(nullable: false), - UserName = table.Column(maxLength: 256, nullable: true), - NormalizedUserName = table.Column(maxLength: 256, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false), - PasswordHash = table.Column(nullable: true), - SecurityStamp = table.Column(nullable: true), - ConcurrencyStamp = table.Column(nullable: true), - PhoneNumber = table.Column(nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false), - TwoFactorEnabled = table.Column(nullable: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false), - AccessFailedCount = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - RoleId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - UserId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(maxLength: 128, nullable: false), - ProviderKey = table.Column(maxLength: 128, nullable: false), - ProviderDisplayName = table.Column(nullable: true), - UserId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 128, nullable: false), - Name = table.Column(maxLength: 128, nullable: false), - Value = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - } - } -} diff --git a/RentACar/WebApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/RentACar/WebApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 32e7034..0000000 --- a/RentACar/WebApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,275 +0,0 @@ -// -using System; -using API.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace API.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property("Name") - .HasColumnType("nvarchar(128)") - .HasMaxLength(128); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - 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("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", 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("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/RentACar/WebApp/ScaffoldingReadMe.txt b/RentACar/WebApp/ScaffoldingReadMe.txt new file mode 100644 index 0000000..6e6208d --- /dev/null +++ b/RentACar/WebApp/ScaffoldingReadMe.txt @@ -0,0 +1,3 @@ +Support for ASP.NET Core Identity was added to your project. + +For setup and configuration information, see https://go.microsoft.com/fwlink/?linkid=2116645. diff --git a/RentACar/WebApp/Startup.cs b/RentACar/WebApp/Startup.cs index 1b6f8c4..7e67b4c 100644 --- a/RentACar/WebApp/Startup.cs +++ b/RentACar/WebApp/Startup.cs @@ -2,7 +2,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using API.Data; +using Data; +using Data.Entities; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; @@ -22,19 +23,28 @@ namespace API Configuration = configuration; } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; set; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddDbContext(options => - options.UseSqlServer( - Configuration.GetConnectionString("DefaultConnection"))); + services.AddDbContext(options => + options.UseSqlServer( + Configuration.GetConnectionString("DefaultConnection"))); services.AddDatabaseDeveloperPageExceptionFilter(); + services.AddIdentity(options => + { + options.Password.RequireDigit = true; + options.Password.RequiredLength = 3; + options.Password.RequireLowercase = true; + options.Password.RequireNonAlphanumeric = false; + options.Password.RequireUppercase = true; - services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) - .AddEntityFrameworkStores(); + options.User.RequireUniqueEmail = false; + }) + .AddEntityFrameworkStores(); services.AddControllersWithViews(); + services.AddRazorPages(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/RentACar/WebApp/Views/Cars/Create.cshtml b/RentACar/WebApp/Views/Cars/Create.cshtml new file mode 100644 index 0000000..3555bec --- /dev/null +++ b/RentACar/WebApp/Views/Cars/Create.cshtml @@ -0,0 +1,62 @@ +@model Data.Entities.Car + +@{ + ViewData["Title"] = "Create"; +} + +

Create

+ +

Car

+
+
+
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+
+
+ + + +@section Scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} +} diff --git a/RentACar/WebApp/Views/Cars/Delete.cshtml b/RentACar/WebApp/Views/Cars/Delete.cshtml new file mode 100644 index 0000000..c917cf8 --- /dev/null +++ b/RentACar/WebApp/Views/Cars/Delete.cshtml @@ -0,0 +1,57 @@ +@model Data.Entities.Car + +@{ + ViewData["Title"] = "Delete"; +} + +

Delete

+ +

Are you sure you want to delete this?

+
+

Car

+
+
+
+ @Html.DisplayNameFor(model => model.Brand) +
+
+ @Html.DisplayFor(model => model.Brand) +
+
+ @Html.DisplayNameFor(model => model.Model) +
+
+ @Html.DisplayFor(model => model.Model) +
+
+ @Html.DisplayNameFor(model => model.Year) +
+
+ @Html.DisplayFor(model => model.Year) +
+
+ @Html.DisplayNameFor(model => model.CountPassengerSeats) +
+
+ @Html.DisplayFor(model => model.CountPassengerSeats) +
+
+ @Html.DisplayNameFor(model => model.Description) +
+
+ @Html.DisplayFor(model => model.Description) +
+
+ @Html.DisplayNameFor(model => model.PriceForDay) +
+
+ @Html.DisplayFor(model => model.PriceForDay) +
+
+ +
+ + | + Back to List +
+
diff --git a/RentACar/WebApp/Views/Cars/Details.cshtml b/RentACar/WebApp/Views/Cars/Details.cshtml new file mode 100644 index 0000000..f0ad8cc --- /dev/null +++ b/RentACar/WebApp/Views/Cars/Details.cshtml @@ -0,0 +1,54 @@ +@model Data.Entities.Car + +@{ + ViewData["Title"] = "Details"; +} + +

Details

+ +
+

Car

+
+
+
+ @Html.DisplayNameFor(model => model.Brand) +
+
+ @Html.DisplayFor(model => model.Brand) +
+
+ @Html.DisplayNameFor(model => model.Model) +
+
+ @Html.DisplayFor(model => model.Model) +
+
+ @Html.DisplayNameFor(model => model.Year) +
+
+ @Html.DisplayFor(model => model.Year) +
+
+ @Html.DisplayNameFor(model => model.CountPassengerSeats) +
+
+ @Html.DisplayFor(model => model.CountPassengerSeats) +
+
+ @Html.DisplayNameFor(model => model.Description) +
+
+ @Html.DisplayFor(model => model.Description) +
+
+ @Html.DisplayNameFor(model => model.PriceForDay) +
+
+ @Html.DisplayFor(model => model.PriceForDay) +
+
+
+ diff --git a/RentACar/WebApp/Views/Cars/Edit.cshtml b/RentACar/WebApp/Views/Cars/Edit.cshtml new file mode 100644 index 0000000..5300704 --- /dev/null +++ b/RentACar/WebApp/Views/Cars/Edit.cshtml @@ -0,0 +1,59 @@ +@model Data.Entities.Car + +@{ + ViewData["Title"] = "Edit"; +} + +

Edit

+ +

Car

+
+
+
+
+
+ +
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+
+
+ + + +@section Scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} +} diff --git a/RentACar/WebApp/Views/Cars/Index.cshtml b/RentACar/WebApp/Views/Cars/Index.cshtml new file mode 100644 index 0000000..bab159c --- /dev/null +++ b/RentACar/WebApp/Views/Cars/Index.cshtml @@ -0,0 +1,65 @@ +@model IEnumerable + +@{ + ViewData["Title"] = "Index"; +} + +

Index

+ +

+ New Car +

+ + + + + + + + + + + + + +@foreach (var item in Model) { + + + + + + + + + +} + +
+ @Html.DisplayNameFor(model => model.Brand) + + @Html.DisplayNameFor(model => model.Model) + + @Html.DisplayNameFor(model => model.Year) + + @Html.DisplayNameFor(model => model.CountPassengerSeats) + + @Html.DisplayNameFor(model => model.Description) + + @Html.DisplayNameFor(model => model.PriceForDay) +
+ @Html.DisplayFor(modelItem => item.Brand) + + @Html.DisplayFor(modelItem => item.Model) + + @Html.DisplayFor(modelItem => item.Year) + + @Html.DisplayFor(modelItem => item.CountPassengerSeats) + + @Html.DisplayFor(modelItem => item.Description) + + @Html.DisplayFor(modelItem => item.PriceForDay) + + Edit | + Details | + Delete +
diff --git a/RentACar/WebApp/Views/Rents/Create.cshtml b/RentACar/WebApp/Views/Rents/Create.cshtml new file mode 100644 index 0000000..c6e8065 --- /dev/null +++ b/RentACar/WebApp/Views/Rents/Create.cshtml @@ -0,0 +1,38 @@ +@model Data.Entities.Rents + +@{ + ViewData["Title"] = "Create"; +} + +

Create

+ +

Rents

+
+
+
+
+
+
+ + + +
+
+ + + +
+
+ +
+
+
+
+ + + +@section Scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} +} diff --git a/RentACar/WebApp/Views/Rents/Delete.cshtml b/RentACar/WebApp/Views/Rents/Delete.cshtml new file mode 100644 index 0000000..aacf430 --- /dev/null +++ b/RentACar/WebApp/Views/Rents/Delete.cshtml @@ -0,0 +1,33 @@ +@model Data.Entities.Rents + +@{ + ViewData["Title"] = "Delete"; +} + +

Delete

+ +

Are you sure you want to delete this?

+
+

Rents

+
+
+
+ @Html.DisplayNameFor(model => model.StartDate) +
+
+ @Html.DisplayFor(model => model.StartDate) +
+
+ @Html.DisplayNameFor(model => model.EndDate) +
+
+ @Html.DisplayFor(model => model.EndDate) +
+
+ +
+ + | + Back to List +
+
diff --git a/RentACar/WebApp/Views/Rents/Details.cshtml b/RentACar/WebApp/Views/Rents/Details.cshtml new file mode 100644 index 0000000..e6b5f63 --- /dev/null +++ b/RentACar/WebApp/Views/Rents/Details.cshtml @@ -0,0 +1,30 @@ +@model Data.Entities.Rents + +@{ + ViewData["Title"] = "Details"; +} + +

Details

+ +
+

Rents

+
+
+
+ @Html.DisplayNameFor(model => model.StartDate) +
+
+ @Html.DisplayFor(model => model.StartDate) +
+
+ @Html.DisplayNameFor(model => model.EndDate) +
+
+ @Html.DisplayFor(model => model.EndDate) +
+
+
+ diff --git a/RentACar/WebApp/Views/Rents/Edit.cshtml b/RentACar/WebApp/Views/Rents/Edit.cshtml new file mode 100644 index 0000000..63aea9d --- /dev/null +++ b/RentACar/WebApp/Views/Rents/Edit.cshtml @@ -0,0 +1,39 @@ +@model Data.Entities.Rents + +@{ + ViewData["Title"] = "Edit"; +} + +

Edit

+ +

Rents

+
+
+
+
+
+ +
+ + + +
+
+ + + +
+
+ +
+
+
+
+ + + +@section Scripts { + @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} +} diff --git a/RentACar/WebApp/Views/Rents/Index.cshtml b/RentACar/WebApp/Views/Rents/Index.cshtml new file mode 100644 index 0000000..80c82a5 --- /dev/null +++ b/RentACar/WebApp/Views/Rents/Index.cshtml @@ -0,0 +1,41 @@ +@model IEnumerable + +@{ + ViewData["Title"] = "Index"; +} + +

Index

+ +

+ Create New +

+ + + + + + + + + +@foreach (var item in Model) { + + + + + +} + +
+ @Html.DisplayNameFor(model => model.StartDate) + + @Html.DisplayNameFor(model => model.EndDate) +
+ @Html.DisplayFor(modelItem => item.StartDate) + + @Html.DisplayFor(modelItem => item.EndDate) + + Edit | + Details | + Delete +
diff --git a/RentACar/WebApp/Views/Shared/_Layout.cshtml b/RentACar/WebApp/Views/Shared/_Layout.cshtml index 3ff6897..40f538c 100644 --- a/RentACar/WebApp/Views/Shared/_Layout.cshtml +++ b/RentACar/WebApp/Views/Shared/_Layout.cshtml @@ -24,6 +24,9 @@ + diff --git a/RentACar/WebApp/Views/Shared/_LoginPartial.cshtml b/RentACar/WebApp/Views/Shared/_LoginPartial.cshtml index cd256aa..099c53d 100644 --- a/RentACar/WebApp/Views/Shared/_LoginPartial.cshtml +++ b/RentACar/WebApp/Views/Shared/_LoginPartial.cshtml @@ -1,26 +1,27 @@ @using Microsoft.AspNetCore.Identity -@inject SignInManager SignInManager -@inject UserManager UserManager +@using Data.Entities +@inject SignInManager SignInManager +@inject UserManager UserManager diff --git a/RentACar/WebApp/WebApp.csproj b/RentACar/WebApp/WebApp.csproj index c9c8900..8dd026f 100644 --- a/RentACar/WebApp/WebApp.csproj +++ b/RentACar/WebApp/WebApp.csproj @@ -7,10 +7,14 @@ - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/RentACar/WebApp/appsettings.json b/RentACar/WebApp/appsettings.json index adcb56a..b524ae9 100644 --- a/RentACar/WebApp/appsettings.json +++ b/RentACar/WebApp/appsettings.json @@ -1,13 +1,13 @@ { - "ConnectionStrings": { - "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-API-8C2D17B8-38FF-4A01-BC6F-33667A9BA115;Trusted_Connection=True;MultipleActiveResultSets=true" - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*" + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=RentACar;Integrated Security=true;" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" } diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.Internal.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.Internal.dll index 4bb5021..9882aa4 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.Internal.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.Internal.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll index 6a8799c..073a44e 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll index a6e4b28..62437b8 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll index 23f1f1b..5c312ea 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.dll index b3b4a66..df04632 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.AspNetCore.Identity.UI.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.Design.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.Design.dll index e3bb47c..80ce204 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.Design.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.Design.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.SqlServer.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.SqlServer.dll index 5c16a73..ead5ec3 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.SqlServer.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.EntityFrameworkCore.SqlServer.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.FileProviders.Embedded.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.FileProviders.Embedded.dll index eee6789..ffa5133 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.FileProviders.Embedded.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.FileProviders.Embedded.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Core.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Core.dll index 1d99b39..029060f 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Core.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Core.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Stores.dll b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Stores.dll index e10dd04..55b944c 100644 Binary files a/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Stores.dll and b/RentACar/WebApp/bin/Debug/net5.0/Microsoft.Extensions.Identity.Stores.dll differ diff --git a/RentACar/WebApp/bin/Debug/net5.0/appsettings.json b/RentACar/WebApp/bin/Debug/net5.0/appsettings.json index adcb56a..b524ae9 100644 --- a/RentACar/WebApp/bin/Debug/net5.0/appsettings.json +++ b/RentACar/WebApp/bin/Debug/net5.0/appsettings.json @@ -1,13 +1,13 @@ { - "ConnectionStrings": { - "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-API-8C2D17B8-38FF-4A01-BC6F-33667A9BA115;Trusted_Connection=True;MultipleActiveResultSets=true" - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*" + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=RentACar;Integrated Security=true;" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" }