1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00
Rui Tomé 9d59e4dc9e
[AC-1637] Sanitize Business and Organization Names from html script injection prior to storing in db (#3302)
* [AC-1637] Added HtmlEncodingStringConverter to encode/decode special chars on JSON serialization/deserialization

* [AC-1637] Added unit tests for HtmlEncodingStringConverter

* [AC-1637] Moved expected values on unit tests to the arrange phase

* [AC-1637] Added HtmlEncodingStringConverter to properties that are for input/output of Org Name and Business name

* [AC-1637] Modified views in Admin project to decode values to display

* [AC-1637] Replaced Html.Raw with HttpUtility.HtmlDecode

* [AC-1637] Added JsonConverter to Provider DTOs

* [AC-1637] Modified HandlebarsMailService to decode organization name before sending emails

* Revert "[AC-1637] Added JsonConverter to Provider DTOs"

This reverts commit 94d507cf93e4c9f7f02890b9286dba90bad3f516.

* [AC-1637] Fixed Admin panel organization search

* [AC-1637] Sanitizing Organization name and business name on creation in Admin panel

* [AC-1637] Sanitizing organization name and business name on creation by a provider

* [AC-1637] Sanitizing provider name on creation and on viewing in admin panel

* [AC-1637] Added sanitization to more places where Org name is used

* [AC-1637] Swapped using HttpUtility for WebUtility since the later is part of the dotnet framework

* [AC-1637] Updated error messages

* [AC-1637] Decoding on Admin panel add existing organization

* [AC-1637] Fix HTML decoding issues

* [AC-1637] Refactor HTML decoding in View and Model classes on Admin panel

* [AC-1637] Refactor provider name and business name usages to use methods that output decoded values

* [AC-1637] Fixed typo

* [AC-1637] Renamed Provider methods to retrieve Decoded Name and BusinessName

* [AC-1637] Renamed Organization methods to retrieve Decoded Name and BusinessName

* [AC-1637] Update the display name method in the `ProviderOrganizationOrganizationDetails` class to `DisplayName()`
2024-03-05 10:56:48 +00:00

115 lines
5.0 KiB
Plaintext

@using Bit.Admin.Enums;
@using Bit.Admin.Models
@using Bit.Core.Enums
@inject Bit.Admin.Services.IAccessControlService AccessControlService
@model OrganizationEditModel
@{
ViewData["Title"] = (Model.Provider != null ? "Client " : string.Empty) + "Organization: " + Model.Name;
var canViewOrganizationInformation = AccessControlService.UserHasPermission(Permission.Org_OrgInformation_View);
var canViewBillingInformation = AccessControlService.UserHasPermission(Permission.Org_BillingInformation_View);
var canInitiateTrial = AccessControlService.UserHasPermission(Permission.Org_InitiateTrial);
var canDelete = AccessControlService.UserHasPermission(Permission.Org_Delete);
var canUnlinkFromProvider = AccessControlService.UserHasPermission(Permission.Provider_Edit);
}
@section Scripts {
@await Html.PartialAsync("~/AdminConsole/Views/Shared/_OrganizationFormScripts.cshtml")
<script>
(() => {
document.getElementById('teams-trial').addEventListener('click', () => {
if (document.getElementById('@(nameof(Model.PlanType))').value !== '@((byte)PlanType.Free)') {
alert('Organization is not on a free plan.');
return;
}
setTrialDefaults('@((byte)PlanType.TeamsAnnually)');
togglePlanFeatures('@((byte)PlanType.TeamsAnnually)');
document.getElementById('@(nameof(Model.Plan))').value = 'Teams (Trial)';
});
document.getElementById('enterprise-trial').addEventListener('click', () => {
if (document.getElementById('@(nameof(Model.PlanType))').value !== '@((byte)PlanType.Free)') {
alert('Organization is not on a free plan.');
return;
}
setTrialDefaults('@((byte)PlanType.EnterpriseAnnually)');
togglePlanFeatures('@((byte)PlanType.EnterpriseAnnually)');
document.getElementById('@(nameof(Model.Plan))').value = 'Enterprise (Trial)';
});
function setTrialDefaults(planType) {
// Plan
document.getElementById('@(nameof(Model.PlanType))').value = planType;
// Password Manager
document.getElementById('@(nameof(Model.Seats))').value = '10';
document.getElementById('@(nameof(Model.MaxCollections))').value = '';
document.getElementById('@(nameof(Model.MaxStorageGb))').value = '1';
// Secret Manager
if (document.getElementById('@(nameof(Model.UseSecretsManager))').checked) {
document.getElementById('@(nameof(Model.SmSeats))').value = '10';
document.getElementById('@(nameof(Model.SmServiceAccounts))').value = getPlan(planType)?.baseServiceAccount;
}
// Licensing
document.getElementById('@(nameof(Model.LicenseKey))').value = '@Model.RandomLicenseKey';
document.getElementById('@(nameof(Model.ExpirationDate))').value = '@Model.FourteenDayExpirationDate';
document.getElementById('@(nameof(Model.SalesAssistedTrialStarted))').value = true;
}
})();
</script>
}
<h1>@(Model.Provider != null ? "Client " : string.Empty)Organization <small>@Model.Name</small></h1>
@if (Model.Provider != null)
{
<h2>Provider Relationship</h2>
@await Html.PartialAsync("_ProviderInformation", Model.Provider)
}
@if (canViewOrganizationInformation)
{
<h2>Organization Information</h2>
@await Html.PartialAsync("_ViewInformation", Model)
}
@if (canViewBillingInformation)
{
<h2>Billing Information</h2>
@await Html.PartialAsync("_BillingInformation",
new BillingInformationModel { BillingInfo = Model.BillingInfo, OrganizationId = Model.Organization.Id, Entity = "Organization" })
}
@await Html.PartialAsync("~/AdminConsole/Views/Shared/_OrganizationForm.cshtml", Model)
<div class="d-flex mt-4">
<button type="submit" class="btn btn-primary" form="edit-form">Save</button>
<div class="ml-auto d-flex">
@if (canInitiateTrial && Model.Provider is null)
{
<button class="btn btn-secondary mr-2" type="button" id="teams-trial">
Teams Trial
</button>
<button class="btn btn-secondary mr-2" type="button" id="enterprise-trial">
Enterprise Trial
</button>
}
@if (canUnlinkFromProvider && Model.Provider is not null)
{
<button
class="btn btn-outline-danger mr-2"
onclick="return unlinkProvider('@Model.Organization.Id');"
>
Unlink provider
</button>
}
@if (canDelete)
{
<form asp-action="Delete" asp-route-id="@Model.Organization.Id"
onsubmit="return confirm('Are you sure you want to delete this organization?')">
<button class="btn btn-danger" type="submit">Delete</button>
</form>
}
</div>
</div>