mirror of
https://github.com/bitwarden/server.git
synced 2025-02-22 02:51:33 +01:00
refactor policy apis
This commit is contained in:
parent
c5ae1b8283
commit
f3f1ac57d2
@ -8,6 +8,7 @@ using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
@ -29,11 +30,16 @@ namespace Bit.Api.Controllers
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public async Task<PolicyResponseModel> Get(string orgId, string id)
|
||||
[HttpGet("{type}")]
|
||||
public async Task<PolicyResponseModel> Get(string orgId, int type)
|
||||
{
|
||||
var policy = await _policyRepository.GetByIdAsync(new Guid(id));
|
||||
if(policy == null || !_currentContext.OrganizationAdmin(policy.OrganizationId))
|
||||
var orgIdGuid = new Guid(orgId);
|
||||
if(!_currentContext.OrganizationAdmin(orgIdGuid))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(orgIdGuid, (PolicyType)type);
|
||||
if(policy == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
@ -55,45 +61,26 @@ namespace Bit.Api.Controllers
|
||||
return new ListResponseModel<PolicyResponseModel>(responses);
|
||||
}
|
||||
|
||||
[HttpPost("")]
|
||||
public async Task<PolicyResponseModel> Post(string orgId, [FromBody]PolicyRequestModel model)
|
||||
[HttpPut("{type}")]
|
||||
public async Task<PolicyResponseModel> Put(string orgId, int type, [FromBody]PolicyRequestModel model)
|
||||
{
|
||||
var orgIdGuid = new Guid(orgId);
|
||||
if(!_currentContext.OrganizationAdmin(orgIdGuid))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(new Guid(orgId), (PolicyType)type);
|
||||
if(policy == null)
|
||||
{
|
||||
policy = model.ToPolicy(orgIdGuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
policy = model.ToPolicy(policy);
|
||||
}
|
||||
|
||||
var policy = model.ToPolicy(orgIdGuid);
|
||||
await _policyService.SaveAsync(policy);
|
||||
return new PolicyResponseModel(policy);
|
||||
}
|
||||
|
||||
[HttpPut("{id}")]
|
||||
[HttpPost("{id}")]
|
||||
public async Task<PolicyResponseModel> Put(string orgId, string id, [FromBody]PolicyRequestModel model)
|
||||
{
|
||||
var policy = await _policyRepository.GetByIdAsync(new Guid(id));
|
||||
if(policy == null || !_currentContext.OrganizationAdmin(policy.OrganizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _policyService.SaveAsync(model.ToPolicy(policy));
|
||||
return new PolicyResponseModel(policy);
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[HttpPost("{id}/delete")]
|
||||
public async Task Delete(string orgId, string id)
|
||||
{
|
||||
var policy = await _policyRepository.GetByIdAsync(new Guid(id));
|
||||
if(policy == null || !_currentContext.OrganizationAdmin(policy.OrganizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _policyService.DeleteAsync(policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Api.Public;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
@ -33,17 +34,17 @@ namespace Bit.Api.Public.Controllers
|
||||
/// Retrieve a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing policy. You need only supply the unique group identifier
|
||||
/// that was returned upon policy creation.
|
||||
/// Retrieves the details of a policy.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the policy to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
/// <param name="type">The type of policy to be retrieved.</param>
|
||||
[HttpGet("{type}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
public async Task<IActionResult> Get(PolicyType type)
|
||||
{
|
||||
var policy = await _policyRepository.GetByIdAsync(id);
|
||||
if(policy == null || policy.OrganizationId != _currentContext.OrganizationId)
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(
|
||||
_currentContext.OrganizationId.Value, type);
|
||||
if(policy == null)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
@ -67,69 +68,34 @@ namespace Bit.Api.Public.Controllers
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a new policy object.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(PolicyResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Post([FromBody]PolicyCreateRequestModel model)
|
||||
{
|
||||
var policy = model.ToPolicy(_currentContext.OrganizationId.Value);
|
||||
await _policyService.SaveAsync(policy);
|
||||
var response = new PolicyResponseModel(policy);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified policy object. If a property is not provided,
|
||||
/// Updates the specified policy. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the policy to be updated.</param>
|
||||
/// <param name="type">The type of policy to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(PolicyResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody]PolicyUpdateRequestModel model)
|
||||
public async Task<IActionResult> Put(PolicyType type, [FromBody]PolicyUpdateRequestModel model)
|
||||
{
|
||||
var existingPolicy = await _policyRepository.GetByIdAsync(id);
|
||||
if(existingPolicy == null || existingPolicy.OrganizationId != _currentContext.OrganizationId)
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(
|
||||
_currentContext.OrganizationId.Value, type);
|
||||
if(policy == null)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
policy = model.ToPolicy(_currentContext.OrganizationId.Value);
|
||||
}
|
||||
var updatedPolicy = model.ToPolicy(existingPolicy);
|
||||
await _policyService.SaveAsync(updatedPolicy);
|
||||
var response = new PolicyResponseModel(updatedPolicy);
|
||||
else
|
||||
{
|
||||
policy = model.ToPolicy(policy);
|
||||
}
|
||||
await _policyService.SaveAsync(policy);
|
||||
var response = new PolicyResponseModel(policy);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a policy. This cannot be undone.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the policy to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var policy = await _policyRepository.GetByIdAsync(id);
|
||||
if(policy == null || policy.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _policyRepository.DeleteAsync(policy);
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ namespace Bit.Core.Models.Api.Public
|
||||
/// <summary>
|
||||
/// Data for the policy.
|
||||
/// </summary>
|
||||
[StringLength(300)]
|
||||
public Dictionary<string, object> Data { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public class PolicyCreateRequestModel : PolicyUpdateRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of policy.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Enums.PolicyType? Type { get; set; }
|
||||
|
||||
public Policy ToPolicy(Guid orgId)
|
||||
{
|
||||
return ToPolicy(new Policy
|
||||
{
|
||||
OrganizationId = orgId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,19 @@
|
||||
using Bit.Core.Models.Table;
|
||||
using System;
|
||||
using Bit.Core.Models.Table;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public class PolicyUpdateRequestModel : PolicyBaseModel
|
||||
{
|
||||
public Policy ToPolicy(Guid orgId)
|
||||
{
|
||||
return ToPolicy(new Policy
|
||||
{
|
||||
OrganizationId = orgId
|
||||
});
|
||||
}
|
||||
|
||||
public virtual Policy ToPolicy(Policy existingPolicy)
|
||||
{
|
||||
existingPolicy.Enabled = Enabled.GetValueOrDefault();
|
||||
|
@ -2,11 +2,13 @@
|
||||
using Bit.Core.Models.Table;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.Repositories
|
||||
{
|
||||
public interface IPolicyRepository : IRepository<Policy, Guid>
|
||||
{
|
||||
Task<Policy> GetByOrganizationIdTypeAsync(Guid organizationId, PolicyType type);
|
||||
Task<ICollection<Policy>> GetManyByOrganizationIdAsync(Guid organizationId);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Data.SqlClient;
|
||||
using System.Data;
|
||||
using Dapper;
|
||||
using System.Linq;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.Repositories.SqlServer
|
||||
{
|
||||
@ -18,6 +19,18 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
public PolicyRepository(string connectionString, string readOnlyConnectionString)
|
||||
: base(connectionString, readOnlyConnectionString)
|
||||
{ }
|
||||
public async Task<Policy> GetByOrganizationIdTypeAsync(Guid organizationId, PolicyType type)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.QueryAsync<Policy>(
|
||||
$"[{Schema}].[{Table}_ReadByOrganizationIdType]",
|
||||
new { OrganizationId = organizationId, Type = (byte)type },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return results.SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ICollection<Policy>> GetManyByOrganizationIdAsync(Guid organizationId)
|
||||
{
|
||||
|
@ -259,5 +259,6 @@
|
||||
<Build Include="dbo\Stored Procedures\Policy_ReadByOrganizationId.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Policy_Update.sql" />
|
||||
<Build Include="dbo\Views\PolicyView.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Policy_ReadByOrganizationIdType.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,15 @@
|
||||
CREATE PROCEDURE [dbo].[Policy_ReadByOrganizationIdType]
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT TOP 1
|
||||
*
|
||||
FROM
|
||||
[dbo].[PolicyView]
|
||||
WHERE
|
||||
[OrganizationId] = @OrganizationId
|
||||
AND [Type] = @Type
|
||||
END
|
@ -2,7 +2,7 @@
|
||||
[Id] UNIQUEIDENTIFIER NOT NULL,
|
||||
[OrganizationId] UNIQUEIDENTIFIER NOT NULL,
|
||||
[Type] TINYINT NOT NULL,
|
||||
[Data] NVARCHAR (MAX) NOT NULL,
|
||||
[Data] NVARCHAR (MAX) NULL,
|
||||
[Enabled] BIT NOT NULL,
|
||||
[CreationDate] DATETIME2 (7) NOT NULL,
|
||||
[RevisionDate] DATETIME2 (7) NOT NULL,
|
||||
@ -12,6 +12,6 @@
|
||||
|
||||
|
||||
GO
|
||||
CREATE NONCLUSTERED INDEX [IX_Policy_OrganizationId_Enabled]
|
||||
ON [dbo].[Policy]([OrganizationId] ASC, [Enabled] ASC);
|
||||
CREATE UNIQUE NONCLUSTERED INDEX [IX_Policy_OrganizationId_Type]
|
||||
ON [dbo].[Policy]([OrganizationId] ASC, [Type] ASC);
|
||||
|
||||
|
@ -4,7 +4,7 @@ BEGIN
|
||||
[Id] UNIQUEIDENTIFIER NOT NULL,
|
||||
[OrganizationId] UNIQUEIDENTIFIER NOT NULL,
|
||||
[Type] TINYINT NOT NULL,
|
||||
[Data] NVARCHAR (MAX) NOT NULL,
|
||||
[Data] NVARCHAR (MAX) NULL,
|
||||
[Enabled] BIT NOT NULL,
|
||||
[CreationDate] DATETIME2 (7) NOT NULL,
|
||||
[RevisionDate] DATETIME2 (7) NOT NULL,
|
||||
@ -12,8 +12,8 @@ BEGIN
|
||||
CONSTRAINT [FK_Policy_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_Policy_OrganizationId_Enabled]
|
||||
ON [dbo].[Policy]([OrganizationId] ASC, [Enabled] ASC);
|
||||
CREATE UNIQUE NONCLUSTERED INDEX [IX_Policy_OrganizationId_Type]
|
||||
ON [dbo].[Policy]([OrganizationId] ASC, [Type] ASC);
|
||||
END
|
||||
GO
|
||||
|
||||
@ -128,6 +128,29 @@ BEGIN
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[Policy_ReadByOrganizationIdType]') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE [dbo].[Policy_ReadByOrganizationIdType]
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [dbo].[Policy_ReadByOrganizationIdType]
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT TOP 1
|
||||
*
|
||||
FROM
|
||||
[dbo].[PolicyView]
|
||||
WHERE
|
||||
[OrganizationId] = @OrganizationId
|
||||
AND [Type] = @Type
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[Policy_Update]') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE [dbo].[Policy_Update]
|
||||
|
Loading…
Reference in New Issue
Block a user