diff --git a/src/Admin/Controllers/ToolsController.cs b/src/Admin/Controllers/ToolsController.cs index 3e092b90af7a..ea91d01cb824 100644 --- a/src/Admin/Controllers/ToolsController.cs +++ b/src/Admin/Controllers/ToolsController.cs @@ -3,7 +3,9 @@ using Bit.Admin.Enums; using Bit.Admin.Models; using Bit.Admin.Utilities; +using Bit.Core; using Bit.Core.AdminConsole.Entities; +using Bit.Core.AdminConsole.Repositories; using Bit.Core.Entities; using Bit.Core.Models.BitStripe; using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces; @@ -28,6 +30,7 @@ public class ToolsController : Controller private readonly ITransactionRepository _transactionRepository; private readonly IInstallationRepository _installationRepository; private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IProviderUserRepository _providerUserRepository; private readonly IPaymentService _paymentService; private readonly ITaxRateRepository _taxRateRepository; private readonly IStripeAdapter _stripeAdapter; @@ -41,6 +44,7 @@ public ToolsController( ITransactionRepository transactionRepository, IInstallationRepository installationRepository, IOrganizationUserRepository organizationUserRepository, + IProviderUserRepository providerUserRepository, ITaxRateRepository taxRateRepository, IPaymentService paymentService, IStripeAdapter stripeAdapter, @@ -53,6 +57,7 @@ public ToolsController( _transactionRepository = transactionRepository; _installationRepository = installationRepository; _organizationUserRepository = organizationUserRepository; + _providerUserRepository = providerUserRepository; _taxRateRepository = taxRateRepository; _paymentService = paymentService; _stripeAdapter = stripeAdapter; @@ -220,6 +225,46 @@ public async Task PromoteAdmin(PromoteAdminModel model) return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId.Value }); } + [RequireFeature(FeatureFlagKeys.PromoteProviderServiceUserTool)] + [RequirePermission(Permission.Tools_PromoteProviderServiceUser)] + public IActionResult PromoteProviderServiceUser() + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + [RequireFeature(FeatureFlagKeys.PromoteProviderServiceUserTool)] + [RequirePermission(Permission.Tools_PromoteProviderServiceUser)] + public async Task PromoteProviderServiceUser(PromoteProviderServiceUserModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + + var providerUsers = await _providerUserRepository.GetManyByProviderAsync( + model.ProviderId.Value, null); + var serviceUser = providerUsers.FirstOrDefault(u => u.UserId == model.UserId.Value); + if (serviceUser == null) + { + ModelState.AddModelError(nameof(model.UserId), "Service User Id not found in this provider."); + } + else if (serviceUser.Type != Core.AdminConsole.Enums.Provider.ProviderUserType.ServiceUser) + { + ModelState.AddModelError(nameof(model.UserId), "User is not a service user of this provider."); + } + + if (!ModelState.IsValid) + { + return View(model); + } + + serviceUser.Type = Core.AdminConsole.Enums.Provider.ProviderUserType.ProviderAdmin; + await _providerUserRepository.ReplaceAsync(serviceUser); + return RedirectToAction("Edit", "Providers", new { id = model.ProviderId.Value }); + } + [RequirePermission(Permission.Tools_GenerateLicenseFile)] public IActionResult GenerateLicense() { diff --git a/src/Admin/Enums/Permissions.cs b/src/Admin/Enums/Permissions.cs index 274db11cb42e..c878267f8996 100644 --- a/src/Admin/Enums/Permissions.cs +++ b/src/Admin/Enums/Permissions.cs @@ -44,6 +44,7 @@ public enum Permission Tools_ChargeBrainTreeCustomer, Tools_PromoteAdmin, + Tools_PromoteProviderServiceUser, Tools_GenerateLicenseFile, Tools_ManageTaxRates, Tools_ManageStripeSubscriptions, diff --git a/src/Admin/Models/PromoteProviderServiceUserModel.cs b/src/Admin/Models/PromoteProviderServiceUserModel.cs new file mode 100644 index 000000000000..5d6ca03ce65c --- /dev/null +++ b/src/Admin/Models/PromoteProviderServiceUserModel.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace Bit.Admin.Models; + +public class PromoteProviderServiceUserModel +{ + [Required] + [Display(Name = "Provider Service User Id")] + public Guid? UserId { get; set; } + [Required] + [Display(Name = "Provider Id")] + public Guid? ProviderId { get; set; } +} diff --git a/src/Admin/Utilities/RolePermissionMapping.cs b/src/Admin/Utilities/RolePermissionMapping.cs index e260c264f46f..81da3fcf383e 100644 --- a/src/Admin/Utilities/RolePermissionMapping.cs +++ b/src/Admin/Utilities/RolePermissionMapping.cs @@ -45,6 +45,7 @@ public static class RolePermissionMapping Permission.Provider_ResendEmailInvite, Permission.Tools_ChargeBrainTreeCustomer, Permission.Tools_PromoteAdmin, + Permission.Tools_PromoteProviderServiceUser, Permission.Tools_GenerateLicenseFile, Permission.Tools_ManageTaxRates, Permission.Tools_ManageStripeSubscriptions @@ -91,6 +92,7 @@ public static class RolePermissionMapping Permission.Provider_ResendEmailInvite, Permission.Tools_ChargeBrainTreeCustomer, Permission.Tools_PromoteAdmin, + Permission.Tools_PromoteProviderServiceUser, Permission.Tools_GenerateLicenseFile, Permission.Tools_ManageTaxRates, Permission.Tools_ManageStripeSubscriptions, diff --git a/src/Admin/Views/Shared/_Layout.cshtml b/src/Admin/Views/Shared/_Layout.cshtml index 62cc5706df2c..b1f0a24420d0 100644 --- a/src/Admin/Views/Shared/_Layout.cshtml +++ b/src/Admin/Views/Shared/_Layout.cshtml @@ -1,8 +1,10 @@ @using Bit.Admin.Enums; +@using Bit.Core @inject SignInManager SignInManager @inject Bit.Core.Settings.GlobalSettings GlobalSettings @inject Bit.Admin.Services.IAccessControlService AccessControlService +@inject Bit.Core.Services.IFeatureService FeatureService @{ var canViewUsers = AccessControlService.UserHasPermission(Permission.User_List_View); @@ -11,13 +13,15 @@ var canChargeBraintree = AccessControlService.UserHasPermission(Permission.Tools_ChargeBrainTreeCustomer); var canCreateTransaction = AccessControlService.UserHasPermission(Permission.Tools_CreateEditTransaction); var canPromoteAdmin = AccessControlService.UserHasPermission(Permission.Tools_PromoteAdmin); + var canPromoteProviderServiceUser = FeatureService.IsEnabled(FeatureFlagKeys.PromoteProviderServiceUserTool) && + AccessControlService.UserHasPermission(Permission.Tools_PromoteProviderServiceUser); var canGenerateLicense = AccessControlService.UserHasPermission(Permission.Tools_GenerateLicenseFile); var canManageTaxRates = AccessControlService.UserHasPermission(Permission.Tools_ManageTaxRates); var canManageStripeSubscriptions = AccessControlService.UserHasPermission(Permission.Tools_ManageStripeSubscriptions); var canProcessStripeEvents = AccessControlService.UserHasPermission(Permission.Tools_ProcessStripeEvents); var canMigrateProviders = AccessControlService.UserHasPermission(Permission.Tools_MigrateProviders); - var canViewTools = canChargeBraintree || canCreateTransaction || canPromoteAdmin || + var canViewTools = canChargeBraintree || canCreateTransaction || canPromoteAdmin || canPromoteProviderServiceUser || canGenerateLicense || canManageTaxRates || canManageStripeSubscriptions; } @@ -91,6 +95,12 @@ Promote Admin } + @if (canPromoteProviderServiceUser) + { + + Promote Provider Service User + + } @if (canGenerateLicense) { diff --git a/src/Admin/Views/Tools/PromoteProviderServiceUser.cshtml b/src/Admin/Views/Tools/PromoteProviderServiceUser.cshtml new file mode 100644 index 000000000000..7ff45fce53ce --- /dev/null +++ b/src/Admin/Views/Tools/PromoteProviderServiceUser.cshtml @@ -0,0 +1,25 @@ +@model PromoteProviderServiceUserModel +@{ + ViewData["Title"] = "Promote Provider Service User"; +} + +

Promote Provider Service User

+ +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
\ No newline at end of file diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 9f326bdb1939..cf7feecc85df 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -159,6 +159,7 @@ public static class FeatureFlagKeys public const string InlineMenuTotp = "inline-menu-totp"; public const string PM12443RemovePagingLogic = "pm-12443-remove-paging-logic"; public const string SelfHostLicenseRefactor = "pm-11516-self-host-license-refactor"; + public const string PromoteProviderServiceUserTool = "pm-15128-promote-provider-service-user-tool"; public static List GetAllKeys() {