1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-09 20:03:47 -05:00

Add RBAC to Bitwarden Portal (#2853)

* Auth/pm-48 (#2680)

* PM-48 - add user's role as a claim and establish access control service

* PM-48 - remove function unrelated to the role claim

* PM-48 - fix whitespace issues

* PM-48 - move registration of CustomClaimsPrincipalFactory, replace role claim type string with constant, streamline code that retrieves the user's role

* Auth/pm-47 (#2699)

* PM-48 - add user's role as a claim and establish access control service

* PM-48 - remove function unrelated to the role claim

* PM-48 - fix whitespace issues

* PM-47 - add list of permission enums, role:permissions mapping, and function that determines if the logged in user has the given permission

* PM-47 - remove unneeded service registration, set role to lowercase

* PM-47 - fix code style issues

* PM-46 - create permission filter attribute (#2753)

* Auth/pm-54 add rbac for users (#2758)

* PM-54 - add permission gates to User elements

* PM-54 - fix formatting

* PM-54 - remove unused function

* PM-54 - fix variable reference, add permission to billing role

* PM-54 - handle Upgrade Premium button functionality and fix spelling

* PM-54 - change permission name to be more accurate

* PM-49 - update role retrieval (#2779)

* Auth/[PM-50] add rbac for logs (#2782)

* PM-50 - add rbac for logs

* PM-50 - remove unnecessary action filter

* PM-51 - add RBAC for tools (#2799)

* Auth/[pm-52] add rbac providers (#2818)

* PM-52 add rbac for providers

* PM-52 - update redirect action

* PM-52 - add back edit functionality and permission

* PM-52 - reverse changes around removing edit functionality

* PM-52 - moved permission check to variable assignement

* PM-53 - add rbac for organizations (#2798)

* PM-52 - add missed permission to billing role (#2836)

* Fixed merge conflicts.

* [PM-1846] Updates to add RBAC back after merge conflicts (#2870)

* Updates to add RBAC to changes from reseller.

* Added back checks for delete and initiating a trial.

* Removed extraneous Razor tag.

---------

Co-authored-by: dgoodman-bw <109169446+dgoodman-bw@users.noreply.github.com>
Co-authored-by: Danielle Goodman <dgoodman@bitwarden.com>
Co-authored-by: Jacob Fink <jfink@bitwarden.com>
This commit is contained in:
Todd Martin
2023-05-04 15:18:49 -04:00
committed by GitHub
parent 2ac513e15a
commit 0bd0910c39
24 changed files with 1101 additions and 410 deletions

View File

@ -1,247 +1,286 @@
@using Bit.SharedWeb.Utilities
@using Bit.Admin.Enums;
@inject Bit.Admin.Services.IAccessControlService AccessControlService;
@model OrganizationEditModel
@{
var canViewGeneralDetails = AccessControlService.UserHasPermission(Permission.Org_GeneralDetails_View);
var canViewBilling = AccessControlService.UserHasPermission(Permission.Org_Billing_View);
var canViewBusinessInformation = AccessControlService.UserHasPermission(Permission.Org_BusinessInformation_View);
var canViewPlan = AccessControlService.UserHasPermission(Permission.Org_Plan_View);
var canViewLicensing = AccessControlService.UserHasPermission(Permission.Org_Licensing_View);
var canCheckEnabled = AccessControlService.UserHasPermission(Permission.Org_CheckEnabledBox);
var canEditPlan = AccessControlService.UserHasPermission(Permission.Org_Plan_Edit);
var canEditLicensing = AccessControlService.UserHasPermission(Permission.Org_Licensing_Edit);
var canEditBilling = AccessControlService.UserHasPermission(Permission.Org_Billing_Edit);
var canLaunchGateway = AccessControlService.UserHasPermission(Permission.Org_Billing_LaunchGateway);
}
<form method="post" id="edit-form" asp-route-providerId="@Model.Provider?.Id">
<input asp-for="SalesAssistedTrialStarted" type="hidden">
<h2>General</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="Name"></label>
<input type="text" class="form-control" asp-for="Name" required>
</div>
</div>
</div>
@if (Model.Provider?.Type == ProviderType.Reseller)
@if (canViewGeneralDetails)
{
<h2>General</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label>Client Owner Email</label>
@if (!string.IsNullOrWhiteSpace(Model.Owners))
<label asp-for="Name"></label>
<input type="text" class="form-control" asp-for="Name" required>
</div>
</div>
</div>
@if (Model.Provider?.Type == ProviderType.Reseller)
{
<div class="row">
<div class="col-sm">
<div class="form-group">
<label>Client Owner Email</label>
@if (!string.IsNullOrWhiteSpace(Model.Owners))
{
<input type="text" class="form-control" asp-for="Owners" readonly="readonly">
}
else
{
<input type="text" class="form-control" asp-for="Owners" required>
}
<label class="form-check-label small text-muted align-top">This user should be independent of the Provider. If the Provider is disassociated with the organization, this user will maintain ownership of the organization.</label>
</div>
</div>
</div>
}
@if (Model.Organization != null)
{
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" asp-for="Enabled" disabled='@(canCheckEnabled ? null : "disabled")'>
<label class="form-check-label" asp-for="Enabled"></label>
</div>
}
}
@if (canViewBusinessInformation)
{
<h2>Business Information</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="BusinessName"></label>
<input type="text" class="form-control" asp-for="BusinessName">
</div>
</div>
</div>
}
@if (canViewPlan)
{
<h2>Plan</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="PlanType"></label>
@{
var planTypes = Enum.GetValues<PlanType>()
.Where(p => Model.Provider == null || p is >= PlanType.TeamsMonthly and <= PlanType.EnterpriseAnnually)
.Select(e => new SelectListItem
{
Value = ((int)e).ToString(),
Text = e.GetDisplayAttribute()?.GetName() ?? e.ToString()
})
.ToList();
}
<select class="form-control" asp-for="PlanType" asp-items="planTypes" disabled='@(canEditPlan ? null : "disabled")'></select>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="Plan"></label>
<input type="text" class="form-control" asp-for="Plan" required readonly='@(!canEditPlan)'>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="Seats"></label>
<input type="number" class="form-control" asp-for="Seats" min="1" readonly='@(!canEditPlan)'>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="MaxCollections"></label>
<input type="number" class="form-control" asp-for="MaxCollections" min="1" readonly='@(!canEditPlan)'>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="MaxStorageGb"></label>
<input type="number" class="form-control" asp-for="MaxStorageGb" min="1" readonly='@(!canEditPlan)'>
</div>
</div>
</div>
<div class="row">
<div class="col-4">
<div class="form-group">
<label asp-for="MaxAutoscaleSeats"></label>
<input type="number" class="form-control" asp-for="MaxAutoscaleSeats" min="1" readonly='@(!canEditPlan)'>
</div>
</div>
</div>
<h2>Features</h2>
<div class="row mb-3">
<div class="col-4">
<h3>General</h3>
<div class="form-check mb-2">
<input type="checkbox" class="form-check-input" asp-for="SelfHost" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="SelfHost"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Use2fa" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="Use2fa"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseApi" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseApi"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseGroups" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseGroups"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UsePolicies" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UsePolicies"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseSso" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseSso"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseKeyConnector" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseKeyConnector"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseScim" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseScim"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseDirectory" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseDirectory"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseEvents" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseEvents"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseResetPassword" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseResetPassword"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseCustomPermissions" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseCustomPermissions"></label>
</div>
</div>
<div class="col-4">
<h3>Password Manager</h3>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseTotp" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseTotp"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UsersGetPremium" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UsersGetPremium"></label>
</div>
</div>
<div class="col-4">
<h3>Secrets Manager</h3>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseSecretsManager" disabled='@(canEditPlan ? null : "disabled")'>
<label class="form-check-label" asp-for="UseSecretsManager"></label>
</div>
</div>
</div>
}
@if(canViewLicensing)
{
<h2>Licensing</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="LicenseKey"></label>
<input type="text" class="form-control" asp-for="LicenseKey" readonly='@(!canEditLicensing)'>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="ExpirationDate"></label>
<input type="datetime-local" class="form-control" asp-for="ExpirationDate" readonly='@(!canEditLicensing)'>
</div>
</div>
</div>
}
@if (canViewBilling)
{
<h2>Billing</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="BillingEmail"></label>
@if (Model.Provider?.Type == ProviderType.Reseller)
{
<input type="text" class="form-control" asp-for="Owners" readonly="readonly">
<input type="email" class="form-control" asp-for="BillingEmail" readonly="readonly">
}
else
{
<input type="text" class="form-control" asp-for="Owners" required>
<input type="email" class="form-control" asp-for="BillingEmail" readonly='@(!canEditBilling)'>
}
<label class="form-check-label small text-muted align-top">This user should be independent of the Provider. If the Provider is disassociated with the organization, this user will maintain ownership of the organization.</label>
</div>
</div>
</div>
}
@if (Model.Organization != null)
{
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" asp-for="Enabled">
<label class="form-check-label" asp-for="Enabled"></label>
</div>
}
<h2>Business Information</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="BusinessName"></label>
<input type="text" class="form-control" asp-for="BusinessName">
</div>
</div>
</div>
<h2>Plan</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="PlanType"></label>
@{
var planTypes = Enum.GetValues<PlanType>()
.Where(p => Model.Provider == null || p is >= PlanType.TeamsMonthly and <= PlanType.EnterpriseAnnually)
.Select(e => new SelectListItem
{
Value = ((int)e).ToString(),
Text = e.GetDisplayAttribute()?.GetName() ?? e.ToString()
})
.ToList();
}
<select class="form-control" asp-for="PlanType" asp-items="planTypes"></select>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="Plan"></label>
<input type="text" class="form-control" asp-for="Plan" required>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="Seats"></label>
<input type="number" class="form-control" asp-for="Seats" min="1">
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="MaxCollections"></label>
<input type="number" class="form-control" asp-for="MaxCollections" min="1">
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="MaxStorageGb"></label>
<input type="number" class="form-control" asp-for="MaxStorageGb" min="1">
</div>
</div>
</div>
<div class="row">
<div class="col-4">
<div class="form-group">
<label asp-for="MaxAutoscaleSeats"></label>
<input type="number" class="form-control" asp-for="MaxAutoscaleSeats" min="1">
</div>
</div>
</div>
<h2>Features</h2>
<div class="row mb-3">
<div class="col-4">
<h3>General</h3>
<div class="form-check mb-2">
<input type="checkbox" class="form-check-input" asp-for="SelfHost">
<label class="form-check-label" asp-for="SelfHost"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Use2fa">
<label class="form-check-label" asp-for="Use2fa"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseApi">
<label class="form-check-label" asp-for="UseApi"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseGroups">
<label class="form-check-label" asp-for="UseGroups"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UsePolicies">
<label class="form-check-label" asp-for="UsePolicies"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseSso">
<label class="form-check-label" asp-for="UseSso"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseKeyConnector">
<label class="form-check-label" asp-for="UseKeyConnector"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseScim">
<label class="form-check-label" asp-for="UseScim"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseDirectory">
<label class="form-check-label" asp-for="UseDirectory"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseEvents">
<label class="form-check-label" asp-for="UseEvents"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseResetPassword">
<label class="form-check-label" asp-for="UseResetPassword"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseCustomPermissions">
<label class="form-check-label" asp-for="UseCustomPermissions"></label>
</div>
</div>
<div class="col-4">
<h3>Password Manager</h3>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseTotp">
<label class="form-check-label" asp-for="UseTotp"></label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UsersGetPremium">
<label class="form-check-label" asp-for="UsersGetPremium"></label>
</div>
</div>
<div class="col-4">
<h3>Secrets Manager</h3>
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="UseSecretsManager">
<label class="form-check-label" asp-for="UseSecretsManager"></label>
</div>
</div>
</div>
<h2>Licensing</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="LicenseKey"></label>
<input type="text" class="form-control" asp-for="LicenseKey">
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="ExpirationDate"></label>
<input type="datetime-local" class="form-control" asp-for="ExpirationDate">
</div>
</div>
</div>
<h2>Billing</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="BillingEmail"></label>
@if (Model.Provider?.Type == ProviderType.Reseller)
{
<input type="email" class="form-control" asp-for="BillingEmail" readonly="readonly">
}
else
{
<input type="email" class="form-control" asp-for="BillingEmail">
}
</div>
</div>
<div class="col-sm">
<div class="form-group">
<div class="col-sm">
<div class="form-group">
<label asp-for="Gateway"></label>
<select class="form-control" asp-for="Gateway"
asp-items="Html.GetEnumSelectList<Bit.Core.Enums.GatewayType>()">
<option value="">--</option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="GatewayCustomerId"></label>
<div class="input-group">
<input type="text" class="form-control" asp-for="GatewayCustomerId">
<div class="input-group-append">
<button class="btn btn-secondary" type="button" id="gateway-customer-link">
<i class="fa fa-external-link"></i>
</button>
<div class="form-group">
<label asp-for="Gateway"></label>
<select class="form-control" asp-for="Gateway" disabled='@(canEditBilling ? null : "disabled")'
asp-items="Html.GetEnumSelectList<Bit.Core.Enums.GatewayType>()">
<option value="">--</option>
</select>
</div>
</div>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="GatewaySubscriptionId"></label>
<div class="input-group">
<input type="text" class="form-control" asp-for="GatewaySubscriptionId">
<div class="input-group-append">
<button class="btn btn-secondary" type="button" id="gateway-subscription-link">
<i class="fa fa-external-link"></i>
</button>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="GatewayCustomerId"></label>
<div class="input-group">
<input type="text" class="form-control" asp-for="GatewayCustomerId" readonly='@(!canEditBilling)'>
@if(canLaunchGateway)
{
<div class="input-group-append">
<button class="btn btn-secondary" type="button" id="gateway-customer-link">
<i class="fa fa-external-link"></i>
</button>
</div>
}
</div>
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="GatewaySubscriptionId"></label>
<div class="input-group">
<input type="text" class="form-control" asp-for="GatewaySubscriptionId" readonly='@(!canEditBilling)'>
@if (canLaunchGateway)
{
<div class="input-group-append">
<button class="btn btn-secondary" type="button" id="gateway-subscription-link">
<i class="fa fa-external-link"></i>
</button>
</div>
}
</div>
</div>
</div>
</div>
</div>
}
</form>