Skip to content

Commit

Permalink
Merge pull request #693 from immense/tech/fix-identity-scaffolding
Browse files Browse the repository at this point in the history
Fix Identity scaffolding.
  • Loading branch information
bitbound committed Jul 31, 2023
2 parents 57b8676 + a86f6ca commit 58cf570
Show file tree
Hide file tree
Showing 21 changed files with 578 additions and 303 deletions.
14 changes: 7 additions & 7 deletions Agent/Agent.csproj
Expand Up @@ -24,18 +24,18 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="7.0.7" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="7.0.9" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.9" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.7" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.4" />
<PackageReference Include="Microsoft.WSMan.Management" Version="7.3.4" />
<PackageReference Include="Microsoft.WSMan.Runtime" Version="7.3.4" />
<PackageReference Include="System.Management.Automation" Version="7.3.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.9" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.6" />
<PackageReference Include="Microsoft.WSMan.Management" Version="7.3.6" />
<PackageReference Include="Microsoft.WSMan.Runtime" Version="7.3.6" />
<PackageReference Include="System.Management.Automation" Version="7.3.6" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" />
</ItemGroup>

Expand Down
@@ -0,0 +1,33 @@
@page
@model DeletePersonalDataModel
@{
ViewData["Title"] = "Delete Personal Data";
ViewData["ActivePage"] = ManageNavPages.PersonalData;
}

<h3>@ViewData["Title"]</h3>

<div class="alert alert-warning" role="alert">
<p>
<strong>Deleting this data will permanently remove your account, and this cannot be recovered.</strong>
</p>
</div>

<div>
<form id="delete-user" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
@if (Model.RequirePassword)
{
<div class="form-floating mb-3">
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="Please enter your password." />
<label asp-for="Input.Password" class="form-label"></label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
}
<button class="w-100 btn btn-lg btn-danger" type="submit">Delete data and close my account</button>
</form>
</div>

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
@@ -0,0 +1,107 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable

using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Remotely.Server.Services;
using Remotely.Shared.Entities;

namespace Remotely.Server.Areas.Identity.Pages.Account.Manage;

public class DeletePersonalDataModel : PageModel
{
private readonly UserManager<RemotelyUser> _userManager;
private readonly SignInManager<RemotelyUser> _signInManager;
private readonly IDataService _dataService;
private readonly ILogger<DeletePersonalDataModel> _logger;

public DeletePersonalDataModel(
UserManager<RemotelyUser> userManager,
SignInManager<RemotelyUser> signInManager,
IDataService dataService,
ILogger<DeletePersonalDataModel> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_dataService = dataService;
_logger = logger;
}

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[BindProperty]
public InputModel Input { get; set; }

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class InputModel
{
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
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, "Incorrect password.");
return Page();
}
}

var userId = user.Id;
var deleteResult = await _dataService.DeleteUser(user.OrganizationID, userId);
if (!deleteResult.IsSuccess)
{
throw new InvalidOperationException($"Unexpected error occurred deleting user.");
}

await _signInManager.SignOutAsync();

_logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId);

return Redirect("~/");
}
}
160 changes: 117 additions & 43 deletions Server/Areas/Identity/Pages/Account/Manage/ManageNavPages.cs
@@ -1,49 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable

namespace Remotely.Server.Areas.Identity.Pages.Account.Manage;
using System;
using Microsoft.AspNetCore.Mvc.Rendering;

public static class ManageNavPages
namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
{
public static string Index => "Index";

public static string Email => "Email";

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 EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email);

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);

private static string PageNavClass(ViewContext viewContext, string page)
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static class ManageNavPages
{
var activePage = viewContext.ViewData["ActivePage"] as string
?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName);
return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : "";
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string Index => "Index";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string Email => "Email";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string ChangePassword => "ChangePassword";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string DownloadPersonalData => "DownloadPersonalData";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string DeletePersonalData => "DeletePersonalData";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string ExternalLogins => "ExternalLogins";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string PersonalData => "PersonalData";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string TwoFactorAuthentication => "TwoFactorAuthentication";

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication);

/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public static string PageNavClass(ViewContext viewContext, string page)
{
var activePage = viewContext.ViewData["ActivePage"] as string
?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName);
return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null;
}
}
}
18 changes: 18 additions & 0 deletions Server/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml
@@ -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://cdnjs.cloudflare.com/ajax/libs/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://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/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-R3vNCHsZ+A2Lo3d5A6XNP7fdQkeswQWTIPfiYwSpEP3YV079R+93YzTeZRah7f/F">
</script>
</environment>

0 comments on commit 58cf570

Please sign in to comment.