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
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@page
@model IndexModel
@{
ViewData["Title"] = "Profile";
}

<h4>@ViewData["Title"]</h4>
@await Html.PartialAsync("_StatusMessage", Model.StatusMessage)
<div class="row">
<div class="col-md-6">
<form id="profile-form" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username"></label>
<input asp-for="Username" class="form-control" disabled />
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
@if (Model.IsEmailConfirmed)
{
<div class="input-group">
<input asp-for="Input.Email" class="form-control" />
<span class="input-group-addon" aria-hidden="true"><span class="glyphicon glyphicon-ok text-success"></span></span>
</div>
}
else
{
<input asp-for="Input.Email" class="form-control" />
<button id="email-verification" type="submit" asp-page-handler="SendVerificationEmail" class="btn btn-link">Send verification email</button>
}
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.PhoneNumber"></label>
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.DateOfBirth"></label>
<input asp-for="Input.DateOfBirth" class="form-control" />
<span asp-validation-for="Input.DateOfBirth" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Save</button>
</form>
</div>
</div>

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
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.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using ToDoApp.Models;

namespace ToDoApp.Areas.Identity.Pages.Account.Manage
{
public partial class IndexModel : PageModel
{
private readonly UserManager<ToDoUser> _userManager;
private readonly SignInManager<ToDoUser> _signInManager;
private readonly IEmailSender _emailSender;

public IndexModel(
UserManager<ToDoUser> userManager,
SignInManager<ToDoUser> signInManager,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
}

public string Username { get; set; }

public bool IsEmailConfirmed { get; set; }

[TempData]
public string StatusMessage { get; set; }

[BindProperty]
public InputModel Input { get; set; }

public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }

[Phone]
[Display(Name = "Phone number")]
public string PhoneNumber { get; set; }

[DisplayFormat(DataFormatString = "MM/dd/yyyy", ConvertEmptyStringToNull = true)]
[Display(Name = "Date of Birth")]
[DataType(DataType.Date)]
public DateTime? DateOfBirth { get; set; }
}

public async Task<IActionResult> OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}

var userName = await _userManager.GetUserNameAsync(user);
var email = await _userManager.GetEmailAsync(user);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
var dateOfBirth = user.DateOfBirth;

Username = userName;

Input = new InputModel
{
Email = email,
PhoneNumber = phoneNumber,
DateOfBirth = dateOfBirth
};

IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);

return Page();
}

public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}

var email = await _userManager.GetEmailAsync(user);
if (Input.Email != email)
{
var setEmailResult = await _userManager.SetEmailAsync(user, Input.Email);
if (!setEmailResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred setting email for user with ID '{userId}'.");
}
}

var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred setting phone number for user with ID '{userId}'.");
}
}

var dateOfBirth = user.DateOfBirth;
if (Input.DateOfBirth != dateOfBirth)
{
var latestUser = await _userManager.GetUserAsync(User);
latestUser.DateOfBirth = Input.DateOfBirth;
var setDateOfBirthResult = await _userManager.UpdateAsync(latestUser);
if (!setDateOfBirthResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred setting date of birth for user with ID '{userId}'.");
}
}

await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}

public async Task<IActionResult> OnPostSendVerificationEmailAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}


var userId = await _userManager.GetUserIdAsync(user);
var email = await _userManager.GetEmailAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = userId, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(
email,
"Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

StatusMessage = "Verification email sent. Please check your email.";
return RedirectToPage();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@using ToDoApp.Areas.Identity.Pages.Account.Manage
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@using ToDoApp.Areas.Identity.Pages.Account
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<environment include="Development">
<script src="~/Identity/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/Identity/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
</script>
</environment>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@using Microsoft.AspNetCore.Identity
@using ToDoApp.Areas.Identity
@using Microsoft.AspNetCore.Identity
@namespace ToDoApp.Areas.Identity.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

@{
Layout = "/Views/Shared/_Layout.cshtml";
}
3 changes: 3 additions & 0 deletions Lesson06/StartOfLesson/ToDo/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ToDoApp.Models;

namespace ToDoApp.Controllers
{
[Authorize(Roles = "Admin")]
public class HomeController : Controller
{
[AllowAnonymous]
public IActionResult Index()
{
return View();
Expand Down
8 changes: 8 additions & 0 deletions Lesson06/StartOfLesson/ToDo/Controllers/StatusController.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using ToDoApp.Models;
using ToDoApp.Services;

namespace ToDoApp.Controllers
{
[Authorize]
public class StatusController : Controller
{
private readonly IRepository _repository;
Expand All @@ -30,6 +32,7 @@ public ActionResult Details(int id)
}

// GET: Status/Create
[Authorize(Roles = "Admin")]
public ActionResult Create()
{
return View();
Expand All @@ -38,6 +41,7 @@ public ActionResult Create()
// POST: Status/Create
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult Create(Status status)
{
try
Expand All @@ -52,6 +56,7 @@ public ActionResult Create(Status status)
}

// GET: Status/Edit/5
[Authorize(Roles = "Admin")]
public ActionResult Edit(int id)
{
return View(_repository.GetStatus(id));
Expand All @@ -60,6 +65,7 @@ public ActionResult Edit(int id)
// POST: Status/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult Edit(int id, Status status)
{
try
Expand All @@ -74,6 +80,7 @@ public ActionResult Edit(int id, Status status)
}

// GET: Status/Delete/5
[Authorize(Roles = "Admin")]
public ActionResult Delete(int id)
{
return View(_repository.GetStatus(id));
Expand All @@ -82,6 +89,7 @@ public ActionResult Delete(int id)
// POST: Status/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult Delete(int id, Status status)
{
try
Expand Down
9 changes: 8 additions & 1 deletion Lesson06/StartOfLesson/ToDo/Controllers/ToDoController.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ToDoApp.Areas.Tags.Data;
using ToDoApp.Models;
using ToDoApp.Services;

namespace ToDoApp.Controllers
{
[Authorize]
public class ToDoController : Controller
{
private readonly IRepository _repository;
private readonly TagContext tagContext;
private readonly ILogger<ToDoController> _logger;

public ToDoController(IRepository repository, ILogger<ToDoController> logger)
public ToDoController(IRepository repository, TagContext tagContext, ILogger<ToDoController> logger)
{
_repository = repository;
this.tagContext = tagContext;
_logger = logger;
}

Expand Down Expand Up @@ -43,6 +49,7 @@ public ActionResult Create(ToDo toDo)
{
try
{
toDo.Tags = tagContext.Tags.ToList();
_repository.Add(toDo);
return RedirectToAction(nameof(Index));
}
Expand Down
6 changes: 5 additions & 1 deletion Lesson06/StartOfLesson/ToDo/Data/ToDoContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using ToDoApp.Models;

namespace ToDoApp.Data
{
public class ToDoContext : DbContext, IReadOnlyToDoContext
public class ToDoContext : IdentityDbContext<ToDoUser, IdentityRole<int>, int>, IReadOnlyToDoContext
{
public ToDoContext(DbContextOptions<ToDoContext> options) : base(options)
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.HasDefaultSchema("ToDos");

modelBuilder.Entity<ToDo>().HasKey(x => x.Id).ForSqlServerIsClustered();
Expand Down
Loading