Skip to content

Commit

Permalink
Allow any user to manage two-factor (#16130)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
  • Loading branch information
MikeAlhayek and Piedone committed May 28, 2024
1 parent 6f422c3 commit a95a876
Show file tree
Hide file tree
Showing 67 changed files with 620 additions and 509 deletions.
6 changes: 4 additions & 2 deletions src/OrchardCore.Modules/OrchardCore.Admin/AdminFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ public override async Task OnActionExecutionAsync(ActionExecutingContext context

if (!await AuthorizeAsync(context.HttpContext))
{
context.Result = context.HttpContext.User?.Identity?.IsAuthenticated ?? false ? (IActionResult)new ForbidResult() : new ChallengeResult();
context.Result = context.HttpContext.User?.Identity?.IsAuthenticated ?? false
? new ForbidResult()
: new ChallengeResult();
return;
}

Expand Down Expand Up @@ -55,7 +57,7 @@ private Task<bool> AuthorizeAsync(Microsoft.AspNetCore.Http.HttpContext context)
{
if (AdminAttribute.IsApplied(context))
{
return _authorizationService.AuthorizeAsync(context.User, Permissions.AccessAdminPanel);
return _authorizationService.AuthorizeAsync(context.User, AdminPermissions.AccessAdminPanel);
}

return Task.FromResult(true);
Expand Down
6 changes: 4 additions & 2 deletions src/OrchardCore.Modules/OrchardCore.Admin/Permissions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OrchardCore.Security.Permissions;
Expand All @@ -6,11 +7,12 @@ namespace OrchardCore.Admin;

public class Permissions : IPermissionProvider
{
public static readonly Permission AccessAdminPanel = new("AccessAdminPanel", "Access admin panel");
[Obsolete("This property will be removed in future release. Instead use 'AdminPermissions.AccessAdminPanel'.")]
public static readonly Permission AccessAdminPanel = AdminPermissions.AccessAdminPanel;

private readonly IEnumerable<Permission> _allPermissions =
[
AccessAdminPanel,
AdminPermissions.AccessAdminPanel,
];
public Task<IEnumerable<Permission>> GetPermissionsAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace OrchardCore.ContentFields.Controllers
{
[RequireFeatures("OrchardCore.Users")]
[RequireFeatures(OrchardCore.Users.UserConstants.Features.Users)]
[Admin]
public class UserPickerAdminController : Controller
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OrchardCore.Modules.Manifest;
using OrchardCore.Users;

[assembly: Module(
Name = "Content Fields",
Expand Down Expand Up @@ -29,5 +30,9 @@
Name = "Content Fields Indexing (SQL) - User Picker",
Category = "Content Management",
Description = "User Picker Content Fields Indexing module adds database indexing for user picker fields.",
Dependencies = ["OrchardCore.ContentFields", "OrchardCore.Users"]
Dependencies =
[
"OrchardCore.ContentFields",
UserConstants.Features.Users,
]
)]
3 changes: 2 additions & 1 deletion src/OrchardCore.Modules/OrchardCore.ContentFields/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using OrchardCore.Data.Migration;
using OrchardCore.Indexing;
using OrchardCore.Modules;
using OrchardCore.Users;

namespace OrchardCore.ContentFields
{
Expand Down Expand Up @@ -176,7 +177,7 @@ public override void ConfigureServices(IServiceCollection services)
}
}

[RequireFeatures("OrchardCore.Users")]
[RequireFeatures(UserConstants.Features.Users)]
public class UserPickerStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
Expand Down
7 changes: 6 additions & 1 deletion src/OrchardCore.Modules/OrchardCore.Demo/Manifest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OrchardCore.Modules.Manifest;
using OrchardCore.Users;

[assembly: Module(
Name = "Orchard Demo",
Expand All @@ -12,7 +13,11 @@
Id = "OrchardCore.Demo",
Description = "Test",
Category = "Samples",
Dependencies = ["OrchardCore.Users", "OrchardCore.Contents"]
Dependencies =
[
UserConstants.Features.Users,
"OrchardCore.Contents",
]
)]

[assembly: Feature(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public class AdminController : Controller, IUpdateModel
public AdminController(
IAuthorizationService authorizationService,
ISession session,

IOptions<PagerOptions> pagerOptions,
IDisplayManager<Notification> notificationDisplayManager,
INotificationsAdminListQueryService notificationsAdminListQueryService,
Expand Down Expand Up @@ -143,7 +142,8 @@ public async Task<IActionResult> List(
return View(shapeViewModel);
}

[HttpPost, ActionName(nameof(List))]
[HttpPost]
[ActionName(nameof(List))]
[FormValueRequired("submit.Filter")]
public async Task<ActionResult> ListFilterPOST(ListNotificationOptions options)
{
Expand All @@ -162,7 +162,8 @@ public async Task<ActionResult> ListFilterPOST(ListNotificationOptions options)
return RedirectToAction(nameof(List), options.RouteValues);
}

[HttpPost, ActionName(nameof(List))]
[HttpPost]
[ActionName(nameof(List))]
[FormValueRequired("submit.BulkAction")]
public async Task<ActionResult> ListPOST(ListNotificationOptions options, IEnumerable<string> itemIds)
{
Expand Down
3 changes: 2 additions & 1 deletion src/OrchardCore.Modules/OrchardCore.Notifications/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using OrchardCore.Notifications.Services;
using OrchardCore.ResourceManagement;
using OrchardCore.Security.Permissions;
using OrchardCore.Users;
using OrchardCore.Users.Models;
using OrchardCore.Workflows.Helpers;
using YesSql.Filters.Query;
Expand Down Expand Up @@ -86,7 +87,7 @@ public override void ConfigureServices(IServiceCollection services)
}
}

[RequireFeatures("OrchardCore.Workflows", "OrchardCore.Users", "OrchardCore.Contents")]
[RequireFeatures("OrchardCore.Workflows", UserConstants.Features.Users, "OrchardCore.Contents")]
public class UsersWorkflowStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using OrchardCore.DisplayManagement.ModelBinding
@using Microsoft.AspNetCore.Authorization
@using OrchardCore.Admin
@using OrchardCore.Notifications.Endpoints.Management

@inject IDisplayManager<Notification> NotificationDisplayDriver
@inject IUpdateModelAccessor UpdateModelAccessor
@inject IAuthorizationService AuthorizationService

@model UserNotificationNavbarViewModel

Expand Down Expand Up @@ -53,9 +56,12 @@
<li>
<hr class="dropdown-divider">
</li>
<li>
<a class="dropdown-item fw-bold" asp-action="List" asp-controller="Admin" asp-area="@NotificationConstants.Features.Notifications">@T["Notification Center"]</a>
</li>
@if (await AuthorizationService.AuthorizeAsync(ViewContext.HttpContext.User, AdminPermissions.AccessAdminPanel))
{
<li>
<a class="dropdown-item fw-bold" asp-action="List" asp-controller="Admin" asp-area="@NotificationConstants.Features.Notifications">@T["Notification Center"]</a>
</li>
}
</ul>
</div>
</li>
Expand Down
7 changes: 6 additions & 1 deletion src/OrchardCore.Modules/OrchardCore.ReCaptcha/Manifest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OrchardCore.Modules.Manifest;
using OrchardCore.Users;

[assembly: Module(
Name = "ReCaptcha",
Expand All @@ -17,4 +18,8 @@
Name = "ReCaptcha Users",
Description = "Provides ReCaptcha functionality to harness login, register, forgot password and forms against robots.",
Category = "Security",
Dependencies = ["OrchardCore.ReCaptcha", "OrchardCore.Users"])]
Dependencies =
[
"OrchardCore.ReCaptcha",
UserConstants.Features.Users,
])]
2 changes: 1 addition & 1 deletion src/OrchardCore.Modules/OrchardCore.Users/AdminMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public Task BuildNavigationAsync(string name, NavigationBuilder builder)
.Add(S["Users"], S["Users"].PrefixPosition(), users => users
.AddClass("users")
.Id("users")
.Action("Index", "Admin", "OrchardCore.Users")
.Action("Index", "Admin", UserConstants.Features.Users)
.Permission(CommonPermissions.ListUsers)
.Resource(new User())
.LocalNav()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,11 @@ public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null,
{
if (iUser is User userToLink && registrationSettings.UsersMustValidateEmail && !userToLink.EmailConfirmed)
{
return RedirectToAction(nameof(RegistrationController.ConfirmEmailSent),
return RedirectToAction(nameof(EmailConfirmationController.ConfirmEmailSent),
new
{
Area = "OrchardCore.Users",
Controller = typeof(RegistrationController).ControllerName(),
Area = UserConstants.Features.Users,
Controller = typeof(EmailConfirmationController).ControllerName(),
ReturnUrl = returnUrl,
});
}
Expand Down Expand Up @@ -462,11 +462,11 @@ public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null,
{
if (registrationSettings.UsersMustValidateEmail && !user.EmailConfirmed)
{
return RedirectToAction(nameof(RegistrationController.ConfirmEmailSent),
return RedirectToAction(nameof(EmailConfirmationController.ConfirmEmailSent),
new
{
Area = "OrchardCore.Users",
Controller = typeof(RegistrationController).ControllerName(),
Area = UserConstants.Features.Users,
Controller = typeof(EmailConfirmationController).ControllerName(),
ReturnUrl = returnUrl,
});
}
Expand All @@ -476,7 +476,7 @@ public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null,
return RedirectToAction(nameof(RegistrationController.RegistrationPending),
new
{
Area = "OrchardCore.Users",
Area = UserConstants.Features.Users,
Controller = typeof(RegistrationController).ControllerName(),
ReturnUrl = returnUrl,
});
Expand Down Expand Up @@ -581,11 +581,11 @@ public async Task<IActionResult> RegisterExternalLogin(RegisterExternalLoginView
{
if (settings.UsersMustValidateEmail && !user.EmailConfirmed)
{
return RedirectToAction(nameof(RegistrationController.ConfirmEmailSent),
return RedirectToAction(nameof(EmailConfirmationController.ConfirmEmailSent),
new
{
Area = "OrchardCore.Users",
Controller = typeof(RegistrationController).ControllerName(),
Area = UserConstants.Features.Users,
Controller = typeof(EmailConfirmationController).ControllerName(),
ReturnUrl = returnUrl,
});
}
Expand All @@ -595,7 +595,7 @@ public async Task<IActionResult> RegisterExternalLogin(RegisterExternalLoginView
return RedirectToAction(nameof(RegistrationController.RegistrationPending),
new
{
Area = "OrchardCore.Users",
Area = UserConstants.Features.Users,
Controller = typeof(RegistrationController).ControllerName(),
ReturnUrl = returnUrl,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using OrchardCore.Admin;
using OrchardCore.DisplayManagement.Notify;
using OrchardCore.Environment.Shell;
using OrchardCore.Modules;
Expand All @@ -21,10 +20,11 @@

namespace OrchardCore.Users.Controllers;

[Authorize, Admin, Feature(UserConstants.Features.AuthenticatorApp)]
[Authorize]
[Feature(UserConstants.Features.AuthenticatorApp)]
public class AuthenticatorAppController : TwoFactorAuthenticationBaseController
{
private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&digits={3}&issuer={0}";
private const string _authenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&digits={3}&issuer={0}";

private readonly IdentityOptions _identityOptions;
private readonly UrlEncoder _urlEncoder;
Expand Down Expand Up @@ -59,7 +59,6 @@ public AuthenticatorAppController(
_shellSettings = shellSettings;
}

[Admin("Authenticator/Configure/App", "ConfigureAuthenticatorApp")]
public async Task<IActionResult> Index(string returnUrl)
{
var user = await UserManager.GetUserAsync(User);
Expand Down Expand Up @@ -109,7 +108,6 @@ public async Task<IActionResult> Index(EnableAuthenticatorViewModel model)
return await RedirectToTwoFactorAsync(user);
}

[Admin("Authenticator/Reset/App", "RemoveAuthenticatorApp")]
public async Task<IActionResult> Reset()
{
var user = await UserManager.GetUserAsync(User);
Expand All @@ -122,14 +120,15 @@ public async Task<IActionResult> Reset()

var model = new ResetAuthenticatorViewModel()
{
CanRemove = providers.Count > 1 || !await TwoFactorAuthenticationHandlerCoordinator.IsRequiredAsync(),
CanRemove = providers.Count > 1 || !await TwoFactorAuthenticationHandlerCoordinator.IsRequiredAsync(user),
WillDisableTwoFactor = providers.Count == 1,
};

return View(model);
}

[HttpPost, ActionName(nameof(Reset))]
[HttpPost]
[ActionName(nameof(Reset))]
public async Task<IActionResult> ResetPost()
{
var user = await UserManager.GetUserAsync(User);
Expand Down Expand Up @@ -195,7 +194,7 @@ private async Task<string> GenerateQrCodeUriAsync(string displayName, string unf
return string.Format(
CultureInfo.InvariantCulture,
#pragma warning disable CA1863 // Cache a 'CompositeFormat' for repeated use in this formatting operation
AuthenticatorUriFormat,
_authenticatorUriFormat,
#pragma warning restore CA1863
_urlEncoder.Encode(issuer),
_urlEncoder.Encode(displayName),
Expand Down
Loading

0 comments on commit a95a876

Please sign in to comment.