Add PersonalData tab/functionality

This commit is contained in:
Hao Kung 2018-01-17 11:58:38 -08:00
parent 330823bed8
commit f1ed482c26
23 changed files with 276 additions and 20 deletions

View File

@ -29,5 +29,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -22,5 +22,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -78,5 +78,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -32,10 +32,10 @@
</div>
</div>
<p>
Don't have access to your authenticator device? You can
Don't have access to your authenticator device? You can
<a asp-page="./LoginWithRecoveryCode" asp-route-returnUrl="@Model.ReturnUrl">log in with a recovery code</a>.
</p>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -23,7 +23,7 @@
</form>
</div>
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

View File

@ -31,5 +31,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -0,0 +1,34 @@
@page
@model DeletePersonalDataModel
@{
ViewData["Title"] = "Delete Personal Data";
ViewData["ActivePage"] = ManageNavPages.DeletePersonalData;
}
<h4>@ViewData["Title"]</h4>
<div class="alert alert-warning" role="alert">
<p>
<span class="glyphicon glyphicon-warning-sign"></span>
<strong>Deleting this data will permanently remove your account, and this cannot be recovered.</strong>
</p>
</div>
<div>
<form method="post" class="form-group">
<div asp-validation-summary="All" class="text-danger"></div>
@if (Model.RequirePassword)
{
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
}
<button class="btn btn-danger" type="submit">Delete data and close my account</button>
</form>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

View File

@ -0,0 +1,84 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage
{
public class DeletePersonalDataModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<DeletePersonalDataModel> _logger;
public DeletePersonalDataModel(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
ILogger<DeletePersonalDataModel> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
public bool RequirePassword { get; set; }
public async Task<IActionResult> OnGet()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
RequirePassword = await _userManager.HasPasswordAsync(user);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
RequirePassword = await _userManager.HasPasswordAsync(user);
if (RequirePassword)
{
if (!await _userManager.CheckPasswordAsync(user, Input.Password))
{
ModelState.AddModelError(string.Empty, "Password not correct.");
return Page();
}
}
var result = await _userManager.DeleteAsync(user);
if (!result.Succeeded)
{
throw new InvalidOperationException($"Unexpected error occurred deleteing user with ID '{user.Id}'.");
}
await _signInManager.SignOutAsync();
_logger.LogInformation("User with ID '{UserId}' deleted themselves.", _userManager.GetUserId(User));
return Redirect("~/");
}
}
}

View File

@ -2,7 +2,7 @@
@model Disable2faModel
@{
ViewData["Title"] = "Disable two-factor authentication (2FA)";
ViewData["ActivePage"] = "TwoFactorAuthentication";
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
}
<h2>@ViewData["Title"]</h2>

View File

@ -0,0 +1,12 @@
@page
@model DownloadPersonalDataModel
@{
ViewData["Title"] = "Download Your Data";
ViewData["ActivePage"] = ManageNavPages.DownloadPersonalData;
}
<h4>@ViewData["Title"]</h4>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

View File

@ -0,0 +1,51 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage
{
public class DownloadPersonalDataModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly ILogger<DownloadPersonalDataModel> _logger;
public DownloadPersonalDataModel(
UserManager<IdentityUser> userManager,
ILogger<DownloadPersonalDataModel> logger)
{
_userManager = userManager;
_logger = logger;
}
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
_logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User));
// Only include personal data for download
var personalData = new Dictionary<string, string>();
personalData.Add("UserId", await _userManager.GetUserIdAsync(user));
personalData.Add("UserName", await _userManager.GetUserNameAsync(user));
personalData.Add("Email", await _userManager.GetEmailAsync(user));
personalData.Add("EmailConfirmed", (await _userManager.IsEmailConfirmedAsync(user)).ToString());
personalData.Add("PhoneNumber", await _userManager.GetPhoneNumberAsync(user));
personalData.Add("PhoneNumberConfirmed", (await _userManager.IsEmailConfirmedAsync(user)).ToString());
Response.Headers.Add("Content-Disposition", "attachment; filename=PersonalData.json");
return new FileContentResult(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(personalData)), "text/json");
}
}
}

View File

@ -2,7 +2,7 @@
@model EnableAuthenticatorModel
@{
ViewData["Title"] = "Configure authenticator app";
ViewData["ActivePage"] = "TwoFactorAuthentication";
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
}
<h4>@ViewData["Title"]</h4>
@ -49,5 +49,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -2,7 +2,7 @@
@model GenerateRecoveryCodesModel
@{
ViewData["Title"] = "Generate two-factor authentication (2FA) recovery codes";
ViewData["ActivePage"] = "TwoFactorAuthentication";
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
}
<h4>@ViewData["Title"]</h4>

View File

@ -41,5 +41,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -12,16 +12,28 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage
public static string ChangePassword => "ChangePassword";
public static string DownloadPersonalData => "DownloadPersonalData";
public static string DeletePersonalData => "DeletePersonalData";
public static string ExternalLogins => "ExternalLogins";
public static string PersonalData => "PersonalData";
public static string TwoFactorAuthentication => "TwoFactorAuthentication";
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);
public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData);
public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData);
public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins);
public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData);
public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication);
public static string PageNavClass(ViewContext viewContext, string page)

View File

@ -0,0 +1,27 @@
@page
@model PersonalDataModel
@{
ViewData["Title"] = "Personal Data";
ViewData["ActivePage"] = ManageNavPages.PersonalData;
}
<h4>@ViewData["Title"]</h4>
<div class="row">
<div class="col-md-6">
<p>Your account contains personal data that you have given us. This page allows you to download or delete that data.</p>
<p>
<strong>Deleting this data will permanently remove your account, and this cannot be recovered.</strong>
</p>
<form asp-page="DownloadPersonalData" method="post" class="form-group">
<button class="btn btn-default" type="submit">Download</button>
</form>
<p>
<a asp-page="DeletePersonalData" class="btn btn-default">Delete</a>
</p>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

View File

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage
{
public class PersonalDataModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly ILogger<PersonalDataModel> _logger;
public PersonalDataModel(
UserManager<IdentityUser> userManager,
ILogger<PersonalDataModel> logger)
{
_userManager = userManager;
_logger = logger;
}
public async Task<IActionResult> OnGet()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
return Page();
}
}
}

View File

@ -2,7 +2,7 @@
@model ResetAuthenticatorModel
@{
ViewData["Title"] = "Reset authenticator key";
ViewData["ActivePage"] = "TwoFactorAuthentication";
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
}
<h4>@ViewData["Title"]</h4>

View File

@ -2,7 +2,7 @@
@model SetPasswordModel
@{
ViewData["Title"] = "Set password";
ViewData["ActivePage"] = "ChangePassword";
ViewData["ActivePage"] = ManageNavPages.ChangePassword;
}
<h4>Set your password</h4>
@ -31,5 +31,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -45,5 +45,5 @@ else
}
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -11,5 +11,6 @@
<li class="@ManageNavPages.ExternalLoginsNavClass(ViewContext)"><a asp-page="./ExternalLogins">External logins</a></li>
}
<li class="@ManageNavPages.TwoFactorAuthenticationNavClass(ViewContext)"><a asp-page="./TwoFactorAuthentication">Two-factor authentication</a></li>
<li class="@ManageNavPages.PersonalDataNavClass(ViewContext)"><a asp-page="./PersonalData">Personal data</a></li>
</ul>

View File

@ -33,5 +33,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}

View File

@ -33,5 +33,5 @@
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<partial name="_ValidationScriptsPartial" />
}