mirror of
https://github.com/bitwarden/server.git
synced 2025-12-10 00:42:07 -06:00
[PM-23756] Report summary endpoints- mocked (#6092)
This commit is contained in:
parent
765c02b7d2
commit
4963911d7e
@ -281,4 +281,127 @@ public class ReportsController : Controller
|
||||
}
|
||||
return await _getOrganizationReportQuery.GetLatestOrganizationReportAsync(orgId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Organization Report Summary for an organization.
|
||||
/// This includes the latest report's encrypted data, encryption key, and date.
|
||||
/// This is a mock implementation and should be replaced with actual data retrieval logic.
|
||||
/// </summary>
|
||||
/// <param name="orgId"></param>
|
||||
/// <param name="from">Min date (example: 2023-01-01)</param>
|
||||
/// <param name="to">Max date (example: 2023-12-31)</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
[HttpGet("organization-report-summary/{orgId}")]
|
||||
public IEnumerable<OrganizationReportSummaryModel> GetOrganizationReportSummary(
|
||||
[FromRoute] Guid orgId,
|
||||
[FromQuery] DateOnly from,
|
||||
[FromQuery] DateOnly to)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
throw new BadRequestException(ModelState);
|
||||
}
|
||||
|
||||
GuardOrganizationAccess(orgId);
|
||||
|
||||
// FIXME: remove this mock class when actual data retrieval is implemented
|
||||
return MockOrganizationReportSummary.GetMockData()
|
||||
.Where(_ => _.OrganizationId == orgId
|
||||
&& _.Date >= from.ToDateTime(TimeOnly.MinValue)
|
||||
&& _.Date <= to.ToDateTime(TimeOnly.MaxValue));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Organization Report Summary for an organization.
|
||||
/// This is a mock implementation and should be replaced with actual creation logic.
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns>Returns 204 Created with the created OrganizationReportSummaryModel</returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
[HttpPost("organization-report-summary")]
|
||||
public IActionResult CreateOrganizationReportSummary([FromBody] OrganizationReportSummaryModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
throw new BadRequestException(ModelState);
|
||||
}
|
||||
|
||||
GuardOrganizationAccess(model.OrganizationId);
|
||||
|
||||
// TODO: Implement actual creation logic
|
||||
|
||||
// Returns 204 No Content as a placeholder
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPut("organization-report-summary")]
|
||||
public IActionResult UpdateOrganizationReportSummary([FromBody] OrganizationReportSummaryModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
throw new BadRequestException(ModelState);
|
||||
}
|
||||
|
||||
GuardOrganizationAccess(model.OrganizationId);
|
||||
|
||||
// TODO: Implement actual update logic
|
||||
|
||||
// Returns 204 No Content as a placeholder
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
private void GuardOrganizationAccess(Guid organizationId)
|
||||
{
|
||||
if (!_currentContext.AccessReports(organizationId).Result)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: remove this mock class when actual data retrieval is implemented
|
||||
private class MockOrganizationReportSummary
|
||||
{
|
||||
public static List<OrganizationReportSummaryModel> GetMockData()
|
||||
{
|
||||
return new List<OrganizationReportSummaryModel>
|
||||
{
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.EtCcxDEBoF1MYChYHC4Q1w==|RyZ07R7qEFBbc/ICLFpEMockL9K+PD6rOod6DGHHrkaRLHUDqDwmxbu3jnD0cg8s7GIYmp0jApHXC+82QdApk87pA0Kr8fN2Rj0+8bDQCjhKfoRTipAB25S/n2E+ttjvlFfag92S66XqUH9S/eZw/Q==|0bPfykHk3SqS/biLNcNoYtH6YTstBEKu3AhvdZZLxhU=",
|
||||
EncryptionKey = "2.Dd/TtdNwxWdYg9+fRkxh6w==|8KAiK9SoadgFRmyVOchd4tNh2vErD1Rv9x1gqtsE5tzxKE/V/5kkr1WuVG+QpEj//YaQt221UEMESRSXicZ7a9cB6xXLBkbbFwmecQRJVBs=|902em44n9cwciZzYrYuX6MRzRa+4hh1HHfNAxyJx/IM=",
|
||||
Date = DateTime.UtcNow
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.HvY4fAvbzYV1hqa3255m5Q==|WcKga2Wka5i8fVso8MgjzfBAwxaqdhZDL3bnvhDsisZ0r9lNKQcG3YUQSFpJxr74cgg5QRQaFieCUe2YppciHDT6bsaE2VzFce3cNNB821uTFqnlJClkGJpG1nGvPupdErrg4Ik57WenEzYesmR4pw==|F0aJfF+1MlPm+eAlQnDgFnwfv198N9VtPqFJa4+UFqk=",
|
||||
EncryptionKey = "2.ctMgLN4ycPusbQArG/uiag==|NtqiQsAoUxMSTBQsxAMyVLWdt5lVEUGZQNxZSBU4l76ywH2f6dx5FWFrcF3t3GBqy5yDoc5eBg0VlJDW9coqzp8j9n8h1iMrtmXPyBMAhbc=|pbH+w68BUdUKYCfNRpjd8NENw2lZ0vfxgMuTrsrRCTQ=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.NH4qLZYUkz/+qpB/mRsLTA==|LEFt05jJz0ngh+Hl5lqk6kebj7lZMefA3eFdL1kLJSGdD3uTOngRwH7GXLQNFeQOxutnLX9YUILbUEPwaM8gCwNQ1KWYdB1Z+Ky4nzKRb60N7L5aTA2za6zXTIdjv7Zwhg0jPZ6sPevTuvSyqjMCuA==|Uuu6gZaF0wvB2mHFwtvHegMxfe8DgsYWTRfGiVn4lkM=",
|
||||
EncryptionKey = "2.3YwG78ykSxAn44NcymdG4w==|4jfn0nLoFielicAFbmq27DNUUjV4SwGePnjYRmOa7hk4pEPnQRS3MsTJFbutVyXOgKFY9Yn2yGFZownY9EmXOMM+gHPD0t6TfzUKqQcRyuI=|wasP9zZEL9mFH5HzJYrMxnKUr/XlFKXCxG9uW66uaPU=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.YmKWj/707wDPONh+JXPBOw==|Fx4jcUHmnUnSMCU8vdThMSYpDyKPnC09TxpSbNxia0M6MFbd5WHElcVribrYgTENyU0HlqPW43hThJ6xXCM0EjEWP7/jb/0l07vMNkA7sDYq+czf0XnYZgZSGKh06wFVz8xkhaPTdsiO4CXuMsoH+w==|DDVwVFHzdfbPQe3ycCx82eYVHDW97V/eWTPsNpHX/+U=",
|
||||
EncryptionKey = "2.f/U45I7KF+JKfnvOArUyaw==|zNhhS2q2WwBl6SqLWMkxrXC8EX91Ra9LJExywkJhsRbxubRLt7fK+YWc8T1LUaDmMwJ3G8buSPGzyacKX0lnUR33dW6DIaLNgRZ/ekb/zkg=|qFoIZWwS0foiiIOyikFRwQKmmmI2HeyHcOVklJnIILI=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.WYauwooJUEY3kZsDPphmrA==|oguYW6h10A4GxK4KkRS0X32qSTekU2CkGqNDNGfisUgvJzsyoVTafO9sVcdPdg4BUM7YNkPMjYiKEc5jMHkIgLzbnM27jcGvMJrrccSrLHiWL6/mEiqQkV3TlfiZF9i3wqj1ITsYRzM454uNle6Wrg==|uR67aFYb1i5LSidWib0iTf8091l8GY5olHkVXse3CAw=",
|
||||
EncryptionKey = "2.ZyV9+9A2cxNaf8dfzfbnlA==|hhorBpVkcrrhTtNmd6SNHYI8gPNokGLOC22Vx8Qa/AotDAcyuYWw56zsawMnzpAdJGEJFtszKM2+VUVOcroCTMWHpy8yNf/kZA6uPk3Lz3s=|ASzVeJf+K1ZB8NXuypamRBGRuRq0GUHZBEy5r/O7ORY=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Bit.Api.Dirt.Models.Response;
|
||||
|
||||
public class OrganizationReportSummaryModel
|
||||
{
|
||||
public Guid OrganizationId { get; set; }
|
||||
public required string EncryptedData { get; set; }
|
||||
public required string EncryptionKey { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
}
|
||||
@ -1,12 +1,14 @@
|
||||
using AutoFixture;
|
||||
using Bit.Api.Dirt.Controllers;
|
||||
using Bit.Api.Dirt.Models;
|
||||
using Bit.Api.Dirt.Models.Response;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
@ -280,4 +282,185 @@ public class ReportsControllerTests
|
||||
_ = sutProvider.GetDependency<IGetOrganizationReportQuery>()
|
||||
.Received(0);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void CreateOrganizationReportSummary_ReturnsNoContent_WhenAccessGranted(SutProvider<ReportsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key",
|
||||
Date = DateTime.UtcNow
|
||||
};
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(true);
|
||||
|
||||
// Act
|
||||
var result = sutProvider.Sut.CreateOrganizationReportSummary(model);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<NoContentResult>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void CreateOrganizationReportSummary_ThrowsNotFoundException_WhenAccessDenied(SutProvider<ReportsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key",
|
||||
Date = DateTime.UtcNow
|
||||
};
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<Bit.Core.Exceptions.NotFoundException>(
|
||||
() => sutProvider.Sut.CreateOrganizationReportSummary(model));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void GetOrganizationReportSummary_ThrowsNotFoundException_WhenAccessDenied(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<Bit.Core.Exceptions.NotFoundException>(
|
||||
() => sutProvider.Sut.GetOrganizationReportSummary(orgId, DateOnly.FromDateTime(DateTime.UtcNow), DateOnly.FromDateTime(DateTime.UtcNow)));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void GetOrganizationReportSummary_returnsExpectedResult(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var dates = new[]
|
||||
{
|
||||
DateOnly.FromDateTime(DateTime.UtcNow),
|
||||
DateOnly.FromDateTime(DateTime.UtcNow.AddMonths(-1))
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(true);
|
||||
|
||||
// Act
|
||||
var result = sutProvider.Sut.GetOrganizationReportSummary(orgId, dates[0], dates[1]);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void CreateOrganizationReportSummary_ReturnsNoContent_WhenModelIsValidAndAccessGranted(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key"
|
||||
};
|
||||
sutProvider.Sut.ModelState.Clear();
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(true);
|
||||
|
||||
// Act
|
||||
var result = sutProvider.Sut.CreateOrganizationReportSummary(model);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<NoContentResult>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void CreateOrganizationReportSummary_ThrowsBadRequestException_WhenModelStateIsInvalid(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key"
|
||||
};
|
||||
sutProvider.Sut.ModelState.AddModelError("key", "error");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<BadRequestException>(() => sutProvider.Sut.CreateOrganizationReportSummary(model));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void UpdateOrganizationReportSummary_ReturnsNoContent_WhenModelIsValidAndAccessGranted(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key"
|
||||
};
|
||||
sutProvider.Sut.ModelState.Clear();
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(true);
|
||||
|
||||
// Act
|
||||
var result = sutProvider.Sut.UpdateOrganizationReportSummary(model);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<NoContentResult>(result);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void UpdateOrganizationReportSummary_ThrowsBadRequestException_WhenModelStateIsInvalid(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key"
|
||||
};
|
||||
sutProvider.Sut.ModelState.AddModelError("key", "error");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<BadRequestException>(() => sutProvider.Sut.UpdateOrganizationReportSummary(model));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void UpdateOrganizationReportSummary_ThrowsNotFoundException_WhenAccessDenied(
|
||||
SutProvider<ReportsController> sutProvider
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var orgId = Guid.NewGuid();
|
||||
var model = new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = orgId,
|
||||
EncryptedData = "mock-data",
|
||||
EncryptionKey = "mock-key"
|
||||
};
|
||||
sutProvider.Sut.ModelState.Clear();
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessReports(orgId).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<NotFoundException>(() => sutProvider.Sut.UpdateOrganizationReportSummary(model));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user