Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow any user to manage two-factor #16130

Merged
merged 33 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0cdf97d
Allow any user to manage two-factor
MikeAlhayek May 21, 2024
b2666ce
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 22, 2024
f82fe05
Use email confirmation for 2FA
MikeAlhayek May 22, 2024
9a860a2
Merge branch 'ma/fix-2fa-admin-attribute' of https://github.com/Orcha…
MikeAlhayek May 22, 2024
84be641
cleanup
MikeAlhayek May 22, 2024
aa62415
document the breaking change
MikeAlhayek May 22, 2024
a0ea4fd
Fix tests
MikeAlhayek May 22, 2024
c15e1d5
address feedback
MikeAlhayek May 24, 2024
3dddeb0
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 24, 2024
5b91f72
Fix build
MikeAlhayek May 24, 2024
ac57bc4
Merge branch 'ma/fix-2fa-admin-attribute' of https://github.com/Orcha…
MikeAlhayek May 24, 2024
4415a69
docs
MikeAlhayek May 24, 2024
a8810a6
Use Layout-TwoFactor instead of changing the AdminAttribute
MikeAlhayek May 24, 2024
f04b3f4
fix settings driver
MikeAlhayek May 24, 2024
bdc5b42
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 24, 2024
5bc5bbe
Prevent a breaking change
MikeAlhayek May 25, 2024
9189352
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 25, 2024
3b35ba9
address feedback
MikeAlhayek May 26, 2024
d9a83f9
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 26, 2024
9fb580c
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 27, 2024
7c6a0c5
remove email authenticator controller
MikeAlhayek May 27, 2024
56256c4
Merge branch 'ma/fix-2fa-admin-attribute' of https://github.com/Orcha…
MikeAlhayek May 27, 2024
ed5fd2e
Merge remote-tracking branch 'origin/main' into ma/fix-2fa-admin-attr…
MikeAlhayek May 27, 2024
846537a
cleanup
MikeAlhayek May 27, 2024
ea8204f
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 27, 2024
28635b6
Fix filter
MikeAlhayek May 27, 2024
b6a6925
Merge branch 'main' into ma/fix-2fa-admin-attribute
MikeAlhayek May 27, 2024
7542d66
cleanup
MikeAlhayek May 27, 2024
97bba26
Merge branch 'ma/fix-2fa-admin-attribute' of https://github.com/Orcha…
MikeAlhayek May 27, 2024
7b42e70
Update src/OrchardCore/OrchardCore.Admin.Abstractions/AdminPermission…
MikeAlhayek May 27, 2024
e98a6d3
change fontawesome placement
MikeAlhayek May 27, 2024
3f9c1d2
Merge branch 'ma/fix-2fa-admin-attribute' of https://github.com/Orcha…
MikeAlhayek May 27, 2024
06e6cec
fix layout
MikeAlhayek May 28, 2024
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
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")]
Piedone marked this conversation as resolved.
Show resolved Hide resolved
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