1
0
mirror of https://github.com/bitwarden/server.git synced 2025-02-16 01:51:21 +01:00

Remove policies from the portal (#1534)

This commit is contained in:
Oscar Hinton 2021-08-26 19:31:56 +02:00 committed by GitHub
parent 4bc683c38d
commit 69e7c651cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1 additions and 782 deletions

View File

@ -1,175 +0,0 @@
using System;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Portal.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Bit.Portal.Controllers
{
[Authorize]
public class PoliciesController : Controller
{
private readonly IUserService _userService;
private readonly IOrganizationService _organizationService;
private readonly IPolicyService _policyService;
private readonly IPolicyRepository _policyRepository;
private readonly EnterprisePortalCurrentContext _enterprisePortalCurrentContext;
private readonly II18nService _i18nService;
public PoliciesController(
IUserService userService,
IOrganizationService organizationService,
IPolicyService policyService,
IPolicyRepository policyRepository,
EnterprisePortalCurrentContext enterprisePortalCurrentContext,
II18nService i18nService)
{
_userService = userService;
_organizationService = organizationService;
_policyService = policyService;
_policyRepository = policyRepository;
_enterprisePortalCurrentContext = enterprisePortalCurrentContext;
_i18nService = i18nService;
}
public async Task<IActionResult> Index()
{
var orgId = _enterprisePortalCurrentContext.SelectedOrganizationId;
if (orgId == null)
{
return Redirect("~/");
}
if (!_enterprisePortalCurrentContext.SelectedOrganizationDetails.UsePolicies ||
!_enterprisePortalCurrentContext.CanManagePoliciesForSelectedOrganization)
{
return Redirect("~/");
}
var policies = await _policyRepository.GetManyByOrganizationIdAsync(orgId.Value);
return View(new PoliciesModel(policies, _enterprisePortalCurrentContext.SelectedOrganizationDetails));
}
[HttpGet("/edit/{type}")]
public async Task<IActionResult> Edit(PolicyType type)
{
var orgId = _enterprisePortalCurrentContext.SelectedOrganizationId;
if (orgId == null)
{
return Redirect("~");
}
if (!_enterprisePortalCurrentContext.SelectedOrganizationDetails.UsePolicies ||
!_enterprisePortalCurrentContext.CanManagePoliciesForSelectedOrganization)
{
return Redirect("~/");
}
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(orgId.Value, type);
return BuildPolicyView(policy, type);
}
[HttpPost("/edit/{type}")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(PolicyType type, PolicyEditModel model)
{
var orgId = _enterprisePortalCurrentContext.SelectedOrganizationId;
if (orgId == null)
{
return Redirect("~");
}
if (!_enterprisePortalCurrentContext.SelectedOrganizationDetails.UsePolicies ||
!_enterprisePortalCurrentContext.CanManagePoliciesForSelectedOrganization)
{
return Redirect("~/");
}
await ValidateDependentPolicies(type, orgId, model.Enabled);
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(orgId.Value, type);
if (!ModelState.IsValid)
{
return BuildPolicyView(policy, type);
}
if (policy == null)
{
policy = model.ToPolicy(type, orgId.Value);
}
else
{
policy = model.ToPolicy(policy);
}
var userId = _userService.GetProperUserId(User);
await _policyService.SaveAsync(policy, _userService, _organizationService, userId);
return RedirectToAction("Edit", new { type });
}
private IActionResult BuildPolicyView(Policy policy, PolicyType type)
{
if (policy == null)
{
return View(new PolicyEditModel(type, _i18nService));
}
else
{
return View(new PolicyEditModel(policy, _i18nService));
}
}
private async Task ValidateDependentPolicies(PolicyType type, Guid? orgId, bool enabled)
{
if (orgId == null)
{
throw new ArgumentNullException(nameof(orgId), "OrgId cannot be null");
}
switch(type)
{
case PolicyType.MasterPassword:
case PolicyType.PasswordGenerator:
case PolicyType.TwoFactorAuthentication:
case PolicyType.PersonalOwnership:
case PolicyType.DisableSend:
case PolicyType.SendOptions:
case PolicyType.ResetPassword:
break;
case PolicyType.SingleOrg:
if (enabled)
{
break;
}
var requireSso =
await _policyRepository.GetByOrganizationIdTypeAsync(orgId.Value, PolicyType.RequireSso);
if (requireSso?.Enabled == true)
{
ModelState.AddModelError(string.Empty, _i18nService.T("DisableRequireSsoError"));
}
break;
case PolicyType.RequireSso:
if (!enabled)
{
break;
}
var singleOrg = await _policyRepository.GetByOrganizationIdTypeAsync(orgId.Value, PolicyType.SingleOrg);
if (singleOrg?.Enabled != true)
{
ModelState.AddModelError(string.Empty, _i18nService.T("RequireSsoPolicyReqError"));
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

View File

@ -39,9 +39,6 @@ namespace Bit.Portal
public bool OwnerForSelectedOrganization =>
SelectedOrganizationDetails?.Type == Core.Enums.OrganizationUserType.Owner;
public bool CanManagePoliciesForSelectedOrganization =>
AdminForSelectedOrganization || SelectedOrganizationDetailsPermissions.ManagePolicies == true;
public bool CanManageSsoForSelectedOrganization =>
AdminForSelectedOrganization || SelectedOrganizationDetailsPermissions.ManageSso == true;

View File

@ -1,21 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Portal.Models
{
public class MasterPasswordDataModel
{
[Display(Name = "MinimumLength")]
[Range(8, int.MaxValue, ErrorMessage = "MasterPasswordMinLengthError")]
public int? MinLength { get; set; }
[Display(Name = "MinimumComplexityScore")]
public int? MinComplexity { get; set; }
[Display(Name = "UppercaseAZ")]
public bool RequireUpper { get; set; }
[Display(Name = "LowercaseAZ")]
public bool RequireLower { get; set; }
[Display(Name = "Numbers09")]
public bool RequireNumbers { get; set; }
[Display(Name = "SpecialCharacters")]
public bool RequireSpecial { get; set; }
}
}

View File

@ -1,37 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Portal.Models
{
public class PasswordGeneratorDataModel
{
// Shared
[Display(Name = "MinimumLength")]
[Range(5, 128)]
public int? MinLength { get; set; }
[Display(Name = "DefaultType")]
public string DefaultType { get; set; }
// PG - Password
[Display(Name = "UppercaseAZ")]
public bool UseUpper { get; set; }
[Display(Name = "LowercaseAZ")]
public bool UseLower { get; set; }
[Display(Name = "Numbers09")]
public bool UseNumbers { get; set; }
[Display(Name = "SpecialCharacters")]
public bool UseSpecial { get; set; }
[Display(Name = "MinimumNumbers")]
[Range(0, 9)]
public int? MinNumbers { get; set; }
[Display(Name = "MinimumSpecial")]
[Range(0, 9)]
public int? MinSpecial { get; set; }
// PG - Passphrase
[Display(Name = "MinimumNumberOfWords")]
[Range(3, 20)]
public int? MinNumberWords { get; set; }
[Display(Name = "Capitalize")]
public bool Capitalize { get; set; }
[Display(Name = "IncludeNumber")]
public bool IncludeNumber { get; set; }
}
}

View File

@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Table;
namespace Bit.Portal.Models
{
public class PoliciesModel
{
public PoliciesModel(ICollection<Policy> policies, OrganizationUserOrganizationDetails selectedOrgDetails)
{
if (policies == null)
{
return;
}
var policyDict = policies?.ToDictionary(p => p.Type);
Policies = new List<PolicyModel>();
foreach (var type in Enum.GetValues(typeof(PolicyType)).Cast<PolicyType>())
{
if (type == PolicyType.RequireSso && !selectedOrgDetails.UseSso)
{
continue;
}
if (type == PolicyType.ResetPassword && !selectedOrgDetails.UseResetPassword)
{
continue;
}
var enabled = policyDict.ContainsKey(type) ? policyDict[type].Enabled : false;
Policies.Add(new PolicyModel(type, enabled));
}
}
public List<PolicyModel> Policies { get; set; }
}
}

View File

@ -1,135 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Models.Data;
using Bit.Core.Services;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Bit.Portal.Models
{
public class PolicyEditModel : PolicyModel
{
public PolicyEditModel() { }
public PolicyEditModel(PolicyType type, II18nService i18nService)
: base(type, false)
{
// Inject service and create static lists
TranslateStrings(i18nService);
}
public PolicyEditModel(Policy model, II18nService i18nService)
: base(model)
{
if (model == null)
{
return;
}
// Inject service and create static lists
TranslateStrings(i18nService);
if (model.Data != null)
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
switch (model.Type)
{
case PolicyType.MasterPassword:
MasterPasswordDataModel = JsonSerializer.Deserialize<MasterPasswordDataModel>(model.Data, options);
break;
case PolicyType.PasswordGenerator:
PasswordGeneratorDataModel = JsonSerializer.Deserialize<PasswordGeneratorDataModel>(model.Data, options);
break;
case PolicyType.SendOptions:
SendOptionsDataModel = JsonSerializer.Deserialize<SendOptionsPolicyData>(model.Data, options);
break;
case PolicyType.ResetPassword:
ResetPasswordDataModel =
JsonSerializer.Deserialize<ResetPasswordDataModel>(model.Data, options);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public MasterPasswordDataModel MasterPasswordDataModel { get; set; }
public PasswordGeneratorDataModel PasswordGeneratorDataModel { get; set; }
public SendOptionsPolicyData SendOptionsDataModel { get; set; }
public ResetPasswordDataModel ResetPasswordDataModel { get; set; }
public List<SelectListItem> Complexities { get; set; }
public List<SelectListItem> DefaultTypes { get; set; }
public string EnableCheckboxText { get; set; }
public Policy ToPolicy(PolicyType type, Guid organizationId)
{
return ToPolicy(new Policy
{
Type = type,
OrganizationId = organizationId
});
}
public Policy ToPolicy(Policy existingPolicy)
{
existingPolicy.Enabled = Enabled;
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
switch (existingPolicy.Type)
{
case PolicyType.MasterPassword:
existingPolicy.Data = JsonSerializer.Serialize(MasterPasswordDataModel, options);
break;
case PolicyType.PasswordGenerator:
existingPolicy.Data = JsonSerializer.Serialize(PasswordGeneratorDataModel, options);
break;
case PolicyType.SendOptions:
existingPolicy.Data = JsonSerializer.Serialize(SendOptionsDataModel, options);
break;
case PolicyType.ResetPassword:
existingPolicy.Data = JsonSerializer.Serialize(ResetPasswordDataModel, options);
break;
case PolicyType.SingleOrg:
case PolicyType.TwoFactorAuthentication:
case PolicyType.RequireSso:
case PolicyType.PersonalOwnership:
case PolicyType.DisableSend:
break;
default:
throw new ArgumentOutOfRangeException();
}
return existingPolicy;
}
public void TranslateStrings(II18nService i18nService)
{
Complexities = new List<SelectListItem>
{
new SelectListItem { Value = null, Text = "--" + i18nService.T("Select") + "--"},
new SelectListItem { Value = "0", Text = i18nService.T("Weak") + " (0)" },
new SelectListItem { Value = "1", Text = i18nService.T("Weak") + " (1)" },
new SelectListItem { Value = "2", Text = i18nService.T("Weak") + " (2)" },
new SelectListItem { Value = "3", Text = i18nService.T("Good") + " (3)" },
new SelectListItem { Value = "4", Text = i18nService.T("Strong") + " (4)" },
};
DefaultTypes = new List<SelectListItem>
{
new SelectListItem { Value = null, Text = i18nService.T("UserPreference") },
new SelectListItem { Value = "password", Text = i18nService.T("Password") },
new SelectListItem { Value = "passphrase", Text = i18nService.T("Passphrase") },
};
EnableCheckboxText = PolicyType == PolicyType.PersonalOwnership
? i18nService.T("PersonalOwnershipCheckboxDesc") : i18nService.T("Enabled");
}
}
}

View File

@ -1,69 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
namespace Bit.Portal.Models
{
public class PolicyModel
{
public PolicyModel() { }
public PolicyModel(Policy policy)
: this(policy.Type, policy.Enabled)
{ }
public PolicyModel(PolicyType policyType, bool enabled)
{
switch (policyType)
{
case PolicyType.TwoFactorAuthentication:
NameKey = "TwoStepLogin";
DescriptionKey = "TwoStepLoginDescription";
break;
case PolicyType.MasterPassword:
NameKey = "MasterPassword";
DescriptionKey = "MasterPasswordDescription";
break;
case PolicyType.PasswordGenerator:
NameKey = "PasswordGenerator";
DescriptionKey = "PasswordGeneratorDescription";
break;
case PolicyType.SingleOrg:
NameKey = "SingleOrganization";
DescriptionKey = "SingleOrganizationDescription";
break;
case PolicyType.RequireSso:
NameKey = "RequireSso";
DescriptionKey = "RequireSsoDescription";
break;
case PolicyType.PersonalOwnership:
NameKey = "PersonalOwnership";
DescriptionKey = "PersonalOwnershipDescription";
break;
case PolicyType.DisableSend:
NameKey = "DisableSend";
DescriptionKey = "DisableSendDescription";
break;
case PolicyType.SendOptions:
NameKey = "SendOptions";
DescriptionKey = "SendOptionsDescription";
break;
case PolicyType.ResetPassword:
NameKey = "ResetPassword";
DescriptionKey = "ResetPasswordDescription";
break;
default:
throw new ArgumentOutOfRangeException();
}
PolicyType = policyType;
Enabled = enabled;
}
public string NameKey { get; set; }
public string DescriptionKey { get; set; }
public PolicyType PolicyType { get; set; }
public bool Enabled { get; set; }
}
}

View File

@ -18,14 +18,4 @@
</a>
</div>
}
@if (EnterprisePortalCurrentContext.SelectedOrganizationDetails.UsePolicies &&
EnterprisePortalCurrentContext.CanManagePoliciesForSelectedOrganization)
{
<div class="col">
<a class="card p-5 border border-primary" asp-area="" asp-controller="Policies" asp-action="Index">
<h2 class="card-title text-center">@i18nService.T("Policies")</h2>
</a>
</div>
}
</div>

View File

@ -1,250 +0,0 @@
@using Bit.Core.Enums
@model PolicyEditModel
@inject Bit.Core.Services.II18nService i18nService
@{
ViewData["Title"] = i18nService.T("EditPolicy", i18nService.T(Model.NameKey));
}
<div class="page-header">
<h1>@i18nService.T("EditPolicy", i18nService.T(Model.NameKey))</h1>
</div>
<p>@i18nService.T(Model.DescriptionKey)</p>
<form method="post" id="edit-form">
@if (Model.PolicyType == PolicyType.TwoFactorAuthentication)
{
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("EditPolicyTwoStepLoginWarning")
</div>
}
@if (Model.PolicyType == PolicyType.SingleOrg)
{
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("SingleOrganizationPolicyWarning")
</div>
}
@if (Model.PolicyType == PolicyType.RequireSso)
{
<div class="callout callout-success" role="alert">
<h3 class="callout-heading">
<i class="fa fa-lightbulb-o" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Prerequisite")
</h3>
@i18nService.T("RequireSsoPolicyReq")
</div>
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("RequireSsoExemption")
</div>
}
@if (Model.PolicyType == PolicyType.PersonalOwnership)
{
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("PersonalOwnershipExemption")
</div>
}
@if (Model.PolicyType == PolicyType.DisableSend)
{
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("DisableSendExemption")
</div>
}
@if (Model.PolicyType == PolicyType.SendOptions)
{
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("SendOptionsExemption")
</div>
}
@if (Model.PolicyType == PolicyType.ResetPassword)
{
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("ResetPasswordWarning")
</div>
}
<div asp-validation-summary="ModelOnly" class="alert alert-danger"></div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="Enabled">
<label class="form-check-label" asp-for="Enabled">@Model.EnableCheckboxText</label>
</div>
</div>
@if (Model.PolicyType == PolicyType.MasterPassword)
{
<div class="row">
<div class="col-6 form-group">
<label asp-for="MasterPasswordDataModel.MinComplexity"></label>
<select asp-for="MasterPasswordDataModel.MinComplexity" asp-items="Model.Complexities"
class="form-control"></select>
</div>
<div class="col-6 form-group">
<label asp-for="MasterPasswordDataModel.MinLength"></label>
<input class="form-control" type="number" asp-for="MasterPasswordDataModel.MinLength">
<span asp-validation-for="MasterPasswordDataModel.MinLength" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="MasterPasswordDataModel.RequireUpper">
<label class="form-check-label" asp-for="MasterPasswordDataModel.RequireUpper"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="MasterPasswordDataModel.RequireLower">
<label class="form-check-label" asp-for="MasterPasswordDataModel.RequireLower"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="MasterPasswordDataModel.RequireNumbers">
<label class="form-check-label" asp-for="MasterPasswordDataModel.RequireNumbers"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="MasterPasswordDataModel.RequireSpecial">
<label class="form-check-label" asp-for="MasterPasswordDataModel.RequireSpecial"></label>
</div>
</div>
}
@if (Model.PolicyType == PolicyType.PasswordGenerator)
{
<div class="row">
<div class="col-6 form-group mb-0">
<label asp-for="PasswordGeneratorDataModel.DefaultType"></label>
<select asp-for="PasswordGeneratorDataModel.DefaultType" asp-items="Model.DefaultTypes"
class="form-control"></select>
</div>
</div>
<div class="config-section">
<h2>@i18nService.T("Password")</h2>
<div class="row">
<div class="col-6 form-group">
<label asp-for="PasswordGeneratorDataModel.MinLength"></label>
<input class="form-control" type="number" asp-for="PasswordGeneratorDataModel.MinLength">
<span asp-validation-for="PasswordGeneratorDataModel.MinLength" class="text-danger"></span>
</div>
</div>
<div class="row">
<div class="col-6 form-group">
<label asp-for="PasswordGeneratorDataModel.MinNumbers"></label>
<input class="form-control" type="number" asp-for="PasswordGeneratorDataModel.MinNumbers">
<span asp-validation-for="PasswordGeneratorDataModel.MinNumbers" class="text-danger"></span>
</div>
<div class="col-6 form-group">
<label asp-for="PasswordGeneratorDataModel.MinSpecial"></label>
<input class="form-control" type="number" asp-for="PasswordGeneratorDataModel.MinSpecial">
<span asp-validation-for="PasswordGeneratorDataModel.MinSpecial" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="PasswordGeneratorDataModel.UseUpper">
<label class="form-check-label" asp-for="PasswordGeneratorDataModel.UseUpper"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="PasswordGeneratorDataModel.UseLower">
<label class="form-check-label" asp-for="PasswordGeneratorDataModel.UseLower"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="PasswordGeneratorDataModel.UseNumbers">
<label class="form-check-label" asp-for="PasswordGeneratorDataModel.UseNumbers"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="PasswordGeneratorDataModel.UseSpecial">
<label class="form-check-label" asp-for="PasswordGeneratorDataModel.UseSpecial"></label>
</div>
</div>
</div>
<div class="config-section">
<h2>@i18nService.T("Passphrase")</h2>
<div class="row">
<div class="col-6 form-group">
<label asp-for="PasswordGeneratorDataModel.MinNumberWords"></label>
<input class="form-control" type="number" asp-for="PasswordGeneratorDataModel.MinNumberWords">
<span asp-validation-for="PasswordGeneratorDataModel.MinNumberWords" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="PasswordGeneratorDataModel.Capitalize">
<label class="form-check-label" asp-for="PasswordGeneratorDataModel.Capitalize"></label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="PasswordGeneratorDataModel.IncludeNumber">
<label class="form-check-label" asp-for="PasswordGeneratorDataModel.IncludeNumber"></label>
</div>
</div>
</div>
}
@if (Model.PolicyType == PolicyType.SendOptions)
{
<div class="config-section">
<h2>@i18nService.T("Options")</h2>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="SendOptionsDataModel.DisableHideEmail">
<label class="form-check-label" asp-for="SendOptionsDataModel.DisableHideEmail"></label>
</div>
</div>
</div>
}
@if (Model.PolicyType == PolicyType.ResetPassword)
{
<div class="config-section">
<h2>@i18nService.T("ResetPasswordAutoEnroll")</h2>
<p>@i18nService.T("ResetPasswordAutoEnrollDescription")</p>
<div class="callout callout-warning" role="alert">
<h3 class="callout-heading">
<i class="fa fa-warning" *ngIf="icon" aria-hidden="true"></i>
@i18nService.T("Warning")
</h3>
@i18nService.T("ResetPasswordAutoEnrollWarning")
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" asp-for="ResetPasswordDataModel.AutoEnrollEnabled">
<label class="form-check-label" asp-for="ResetPasswordDataModel.AutoEnrollEnabled"></label>
</div>
</div>
</div>
}
<div class="d-flex">
<button type="submit" class="btn btn-primary">@i18nService.T("Save")</button>
<a class="btn btn-outline-secondary ml-1" asp-controller="Policies" asp-action="Index">@i18nService.T("Cancel")</a>
</div>
</form>

View File

@ -1,29 +0,0 @@
@model PoliciesModel
@inject Bit.Core.Services.II18nService i18nService
@{
ViewData["Title"] = i18nService.T("Policies");
}
<div class="page-header">
<h1>@i18nService.T("Policies")</h1>
</div>
<div class="table-responsive">
<table class="table table-striped table-hover">
<tbody>
@foreach (var policyModel in Model.Policies)
{
<tr>
<td>
<a asp-action="Edit" asp-route-type="@policyModel.PolicyType">@i18nService.T(policyModel.NameKey)</a>
@if (policyModel.Enabled)
{
<span class="badge badge-success">@i18nService.T("Enabled")</span>
}
<small class="text-muted d-block">@i18nService.T(policyModel.DescriptionKey)</small>
</td>
</tr>
}
</tbody>
</table>
</div>

View File

@ -31,8 +31,7 @@
{
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
@if (EnterprisePortalCurrentContext.SelectedOrganizationDetails.UseSso &&
EnterprisePortalCurrentContext.CanManagePoliciesForSelectedOrganization)
@if (EnterprisePortalCurrentContext.SelectedOrganizationDetails.UseSso)
{
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Sso" asp-action="Index">
@ -40,16 +39,6 @@
</a>
</li>
}
@if (EnterprisePortalCurrentContext.SelectedOrganizationDetails.UsePolicies &&
EnterprisePortalCurrentContext.CanManagePoliciesForSelectedOrganization)
{
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Policies" asp-action="Index">
@i18nService.T("Policies")
</a>
</li>
}
</ul>
</div>
}