1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-07 04:32:20 -05:00
This commit is contained in:
Jonas Hendrickx 2024-11-01 09:35:37 +01:00
parent 65bc9bb01f
commit eaa40e8239
8 changed files with 0 additions and 435 deletions

View File

@ -18,11 +18,6 @@
<Folder Include="Billing\Controllers\" />
<Folder Include="Billing\Models\" />
</ItemGroup>
<ItemGroup>
<Compile Update="AdminConsole\Components\Admins.cs">
<DependentUpon>Admins.razor</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.10" />
</ItemGroup>

View File

@ -1,40 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Bit.Admin.AdminConsole.Models;
using Bit.Admin.Enums;
using Bit.Admin.Services;
using Microsoft.AspNetCore.Components;
namespace Bit.Admin.AdminConsole.Components;
public partial class Admins(
IAccessControlService accessControlService) : ComponentBase
{
private readonly bool _canResendEmailInvite = accessControlService.UserHasPermission(Permission.Provider_ResendEmailInvite);
[Parameter] public ProviderViewModel Model { get; set; }
[SupplyParameterFromForm(FormName = "ManageAdminsForm")]
public ManageAdminsFormModel FormModel { get; set; } = new();
[Parameter]
public Guid ProviderId { get; set; }
[Parameter]
public Guid OwnerId { get; set; }
[SupplyParameterFromQuery]
public Guid? InviteResentTo { get; set; }
private async Task OnValidSubmitAsync()
{
await ProviderService.ResendProviderSetupInviteEmailAsync(ProviderId, OwnerId);
var uri = NavigationManager.GetUriWithQueryParameters($"/admin/providers/{ProviderId}/admins", new Dictionary<string, object?> { { "inviteResentTo", OwnerId.ToString() } });
NavigationManager.NavigateTo(uri);
}
public class ManageAdminsFormModel
{
[Required]
public Guid UserId { get; set; }
}
}

View File

@ -1,69 +0,0 @@
@using Bit.Admin.Services
@using Bit.Core.AdminConsole.Enums.Provider
@using Bit.Core.AdminConsole.Services
@inject IAccessControlService AccessControlService
@inject IProviderService ProviderService
@inject NavigationManager NavigationManager
<h2>Provider Admins</h2>
<div class="row">
<div class="col-8">
<div class="table-responsive">
<EditForm FormName="ManageAdminsForm" Model="FormModel" OnValidSubmit="OnValidSubmitAsync">
<DataAnnotationsValidator />
<table class="table table-striped table-hover">
<thead>
<tr>
<th style="width: 190px;">Email</th>
<th style="width: 40px;">Status</th>
<th style="width: 30px;"></th>
</tr>
</thead>
<tbody>
@if (!Model.ProviderAdmins.Any())
{
<tr>
<td colspan="6">No results to list.</td>
</tr>
}
else
{
@foreach (var admin in Model.ProviderAdmins)
{
<tr>
<td class="align-middle">
@admin.Email
</td>
<td class="align-middle">
@admin.Status
</td>
<td>
@if (admin.Status.Equals(ProviderUserStatusType.Confirmed)
&& Model.Provider.Status.Equals(ProviderStatusType.Pending)
&& _canResendEmailInvite)
{
@if (InviteResentTo == admin.UserId!.Value)
{
<button class="btn btn-outline-success btn-sm disabled" disabled>Invite Resent!</button>
}
else
{
<button class="btn btn-outline-secondary btn-sm"
type="submit"
name="FormModel.UserId"
value="@admin.Id">
Resend Setup Invite
</button>
}
}
</td>
</tr>
}
}
</tbody>
</table>
</EditForm>
</div>
</div>
</div>

View File

@ -1,187 +0,0 @@
@page "/providers2/edit/{id:guid}"
@using Bit.Admin.Enums
@using Bit.Core
@using Bit.Core.Billing.Extensions
@{
//ViewData["Title"] = "Provider: " + Model.Provider.DisplayName();
var canEdit = accessControlService.UserHasPermission(Permission.Provider_Edit);
}
<h1>Provider <small>@Model.Provider.DisplayName()</small></h1>
<h2>Provider Information</h2>
<ViewInformation Model="@ViewModel" />
<Admins Model="@ViewModel" ProviderId="@Id" />
<form method="post" id="edit-form">
<div asp-validation-summary="All" class="alert alert-danger"></div>
<input type="hidden" asp-for="Type" readonly>
<h2>General</h2>
<dl class="row">
<dt class="col-sm-4 col-lg-3">Name</dt>
<dd class="col-sm-8 col-lg-9">@Model.Provider.DisplayName()</dd>
</dl>
<h2>Business Information</h2>
<dl class="row">
<dt class="col-sm-4 col-lg-3">Business Name</dt>
<dd class="col-sm-8 col-lg-9">@Model.Provider.DisplayBusinessName()</dd>
</dl>
<h2>Billing</h2>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="BillingEmail"></label>
<input type="email" class="form-control" asp-for="BillingEmail" readonly='@(!canEdit)'>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="BillingPhone"></label>
<input type="tel" class="form-control" asp-for="BillingPhone">
</div>
</div>
</div>
@if (featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling) && Model.Provider.IsBillable())
{
<div class="row">
<div class="col-sm">
<div class="form-group">
<label asp-for="TeamsMonthlySeatMinimum"></label>
<input type="number" class="form-control" asp-for="TeamsMonthlySeatMinimum">
</div>
</div>
<div class="col-sm">
<div class="form-group">
<label asp-for="EnterpriseMonthlySeatMinimum"></label>
<input type="number" class="form-control" asp-for="EnterpriseMonthlySeatMinimum">
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<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">
<a href="@Model.GatewayCustomerUrl" class="btn btn-secondary" target="_blank">
<i class="fa fa-external-link"></i>
</a>
</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">
<a href="@Model.GatewaySubscriptionUrl" class="btn btn-secondary" target="_blank">
<i class="fa fa-external-link"></i>
</a>
</div>
</div>
</div>
</div>
</div>
}
</form>
<!--@await Html.PartialAsync("Organizations", Model)-->
@if (canEdit)
{
<!-- Modals -->
<div class="modal fade rounded" id="requestDeletionModal" tabindex="-1" aria-labelledby="requestDeletionModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content rounded">
<div class="p-3">
<h4 class="font-weight-bolder" id="exampleModalLabel">Request provider deletion</h4>
</div>
<div class="modal-body">
<span class="font-weight-light">
Enter the email of the provider admin that will receive the request to delete the provider portal.
</span>
<form>
<div class="form-group">
<label for="provider-email" class="col-form-label">Provider email</label>
<input type="email" class="form-control" id="provider-email">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-primary btn-pill" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger btn-pill" onclick="initiateDeleteProvider('@Model.Provider.Id')">Send email request</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="DeleteModal" tabindex="-1" aria-labelledby="DeleteModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content rounded">
<div class="p-3">
<h4 class="font-weight-bolder" id="exampleModalLabel">Delete provider</h4>
</div>
<div class="modal-body">
<span class="font-weight-light">
This action is permanent and irreversible. Enter the provider name to complete deletion of the provider and associated data.
</span>
<form>
<div class="form-group">
<label for="provider-name" class="col-form-label">Provider name</label>
<input type="text" class="form-control" id="provider-name">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-primary btn-pill" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger btn-pill" onclick="deleteProvider('@Model.Provider.Id');">Delete provider</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="linkedWarningModal" tabindex="-1" role="dialog" aria-labelledby="linkedWarningModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content rounded">
<div class="modal-body">
<h4 class="font-weight-bolder">Cannot Delete @Model.Name</h4>
<p class="font-weight-lighter">You must unlink all clients before you can delete @Model.Name.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-primary btn-pill" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary btn-pill" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
<!-- End of Modal Section -->
<div class="d-flex mt-4">
<button type="submit" class="btn btn-primary" form="edit-form">Save</button>
<div class="ml-auto d-flex">
<button class="btn btn-danger" onclick="openRequestDeleteModal(@Model.ProviderOrganizations.Count())">Request Delete</button>
<button id="requestDeletionBtn" hidden="hidden" data-toggle="modal" data-target="#requestDeletionModal"></button>
<button class="btn btn-outline-danger ml-2" onclick="openDeleteModal(@Model.ProviderOrganizations.Count())">Delete</button>
<button id="deleteBtn" hidden="hidden" data-toggle="modal" data-target="#DeleteModal"></button>
<button id="linkAccWarningBtn" hidden="hidden" data-toggle="modal" data-target="#linkedWarningModal"></button>
</div>
</div>
}

View File

@ -1,98 +0,0 @@
using Bit.Admin.AdminConsole.Models;
using Bit.Admin.Services;
using Bit.Admin.Utilities;
using Bit.Core;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Billing.Entities;
using Bit.Core.Billing.Extensions;
using Bit.Core.Billing.Repositories;
using Bit.Core.Enums;
using Bit.Core.Services;
using Bit.Core.Settings;
using Microsoft.AspNetCore.Components;
namespace Bit.Admin.AdminConsole.Components;
public partial class EditProviderPage(
GlobalSettings globalSettings,
IAccessControlService accessControlService,
IFeatureService featureService,
IProviderRepository providerRepository,
IProviderOrganizationRepository providerOrganizationRepository,
IProviderPlanRepository providerPlanRepository,
IProviderUserRepository providerUserRepository,
IWebHostEnvironment webHostEnvironment)
: ComponentBase
{
private readonly string _stripeUrl = webHostEnvironment.GetStripeUrl();
private readonly string _braintreeMerchantUrl = webHostEnvironment.GetBraintreeMerchantUrl();
private readonly string _braintreeMerchantId = globalSettings.Braintree.MerchantId;
[Parameter] public Guid Id { get; set; }
public ProviderEditModel? Model { get; set; }
public ProviderViewModel? ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
var provider = await providerRepository.GetByIdAsync(Id);
if (provider == null)
{
return;
}
var users = await providerUserRepository.GetManyDetailsByProviderAsync(Id);
var providerOrganizations = await providerOrganizationRepository.GetManyDetailsByProviderAsync(Id);
var isConsolidatedBillingEnabled = featureService.IsEnabled(FeatureFlagKeys.EnableConsolidatedBilling);
if (!isConsolidatedBillingEnabled || !provider.IsBillable())
{
Model = new ProviderEditModel(provider, users, providerOrganizations, new List<ProviderPlan>());
ViewModel = new ProviderViewModel(provider, users, providerOrganizations);
return;
}
var providerPlans = await providerPlanRepository.GetByProviderId(Id);
Model = new ProviderEditModel(
provider, users, providerOrganizations,
providerPlans.ToList(), GetGatewayCustomerUrl(provider), GetGatewaySubscriptionUrl(provider));
ViewModel = new ProviderViewModel(provider, users, providerOrganizations);
}
private string GetGatewayCustomerUrl(Provider provider)
{
if (!provider.Gateway.HasValue || string.IsNullOrEmpty(provider.GatewayCustomerId))
{
return null;
}
return provider.Gateway switch
{
GatewayType.Stripe => $"{_stripeUrl}/customers/{provider.GatewayCustomerId}",
GatewayType.PayPal => $"{_braintreeMerchantUrl}/{_braintreeMerchantId}/${provider.GatewayCustomerId}",
_ => null
};
}
private string GetGatewaySubscriptionUrl(Provider provider)
{
if (!provider.Gateway.HasValue || string.IsNullOrEmpty(provider.GatewaySubscriptionId))
{
return null;
}
return provider.Gateway switch
{
GatewayType.Stripe => $"{_stripeUrl}/subscriptions/{provider.GatewaySubscriptionId}",
GatewayType.PayPal => $"{_braintreeMerchantUrl}/{_braintreeMerchantId}/subscriptions/${provider.GatewaySubscriptionId}",
_ => null
};
}
}

View File

@ -1,22 +0,0 @@
@using Bit.SharedWeb.Utilities
@using Bit.Core.AdminConsole.Enums.Provider
<dl class="row">
<dt class="col-sm-4 col-lg-3">Id</dt>
<dd class="col-sm-8 col-lg-9"><code>@Model.Provider.Id</code></dd>
<dt class="col-sm-4 col-lg-3">Status</dt>
<dd class="col-sm-8 col-lg-9">@Model.Provider.Status</dd>
<dt class="col-sm-4 col-lg-3">Users</dt>
<dd class="col-sm-8 col-lg-9">@(Model.Provider.Type == ProviderType.Reseller ? "N/A" : Model.UserCount)</dd>
<dt class="col-sm-4 col-lg-3">Provider Type</dt>
<dd class="col-sm-8 col-lg-9">@(Model.Provider.Type.GetDisplayAttribute()?.GetName())</dd>
<dt class="col-sm-4 col-lg-3">Created</dt>
<dd class="col-sm-8 col-lg-9">@Model.Provider.CreationDate</dd>
<dt class="col-sm-4 col-lg-3">Modified</dt>
<dd class="col-sm-8 col-lg-9">@Model.Provider.RevisionDate</dd>
</dl>

View File

@ -1,9 +0,0 @@
using Bit.Admin.AdminConsole.Models;
using Microsoft.AspNetCore.Components;
namespace Bit.Admin.AdminConsole.Components;
public partial class ViewInformation : ComponentBase
{
[Parameter] public ProviderViewModel Model { get; set; }
}

View File

@ -1,5 +0,0 @@
@using Bit.Core.Utilities
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@attribute [SelfHosted(NotSelfHostedOnly = true)]