mirror of
https://github.com/bitwarden/server.git
synced 2024-11-21 12:05:42 +01:00
* resolves issue #4043 default values for itemsPerPage and startIndex * UsersController#Get now uses a queryParamModel Co-authored-by: Ahmad Mustafa Jebran <jebran.mustafa@gmail.com> Co-authored-by: Luris Solis <solisluris@gmail.com> * Test now passes, default 50 is represented --------- Co-authored-by: Jared McCannon <jmccannon@bitwarden.com>
This commit is contained in:
parent
7a509d20da
commit
da0421890f
@ -57,17 +57,15 @@ public class UsersController : Controller
|
|||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
public async Task<IActionResult> Get(
|
public async Task<IActionResult> Get(
|
||||||
Guid organizationId,
|
Guid organizationId,
|
||||||
[FromQuery] string filter,
|
[FromQuery] GetUsersQueryParamModel model)
|
||||||
[FromQuery] int? count,
|
|
||||||
[FromQuery] int? startIndex)
|
|
||||||
{
|
{
|
||||||
var usersListQueryResult = await _getUsersListQuery.GetUsersListAsync(organizationId, filter, count, startIndex);
|
var usersListQueryResult = await _getUsersListQuery.GetUsersListAsync(organizationId, model);
|
||||||
var scimListResponseModel = new ScimListResponseModel<ScimUserResponseModel>
|
var scimListResponseModel = new ScimListResponseModel<ScimUserResponseModel>
|
||||||
{
|
{
|
||||||
Resources = usersListQueryResult.userList.Select(u => new ScimUserResponseModel(u)).ToList(),
|
Resources = usersListQueryResult.userList.Select(u => new ScimUserResponseModel(u)).ToList(),
|
||||||
ItemsPerPage = count.GetValueOrDefault(usersListQueryResult.userList.Count()),
|
ItemsPerPage = model.Count,
|
||||||
TotalResults = usersListQueryResult.totalResults,
|
TotalResults = usersListQueryResult.totalResults,
|
||||||
StartIndex = startIndex.GetValueOrDefault(1),
|
StartIndex = model.StartIndex,
|
||||||
};
|
};
|
||||||
return Ok(scimListResponseModel);
|
return Ok(scimListResponseModel);
|
||||||
}
|
}
|
||||||
|
12
bitwarden_license/src/Scim/Models/GetUserQueryParamModel.cs
Normal file
12
bitwarden_license/src/Scim/Models/GetUserQueryParamModel.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
public class GetUsersQueryParamModel
|
||||||
|
{
|
||||||
|
public string Filter { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
[Range(1, int.MaxValue)]
|
||||||
|
public int Count { get; init; } = 50;
|
||||||
|
|
||||||
|
[Range(1, int.MaxValue)]
|
||||||
|
public int StartIndex { get; init; } = 1;
|
||||||
|
}
|
@ -13,11 +13,16 @@ public class GetUsersListQuery : IGetUsersListQuery
|
|||||||
_organizationUserRepository = organizationUserRepository;
|
_organizationUserRepository = organizationUserRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(IEnumerable<OrganizationUserUserDetails> userList, int totalResults)> GetUsersListAsync(Guid organizationId, string filter, int? count, int? startIndex)
|
public async Task<(IEnumerable<OrganizationUserUserDetails> userList, int totalResults)> GetUsersListAsync(Guid organizationId, GetUsersQueryParamModel userQueryParams)
|
||||||
{
|
{
|
||||||
string emailFilter = null;
|
string emailFilter = null;
|
||||||
string usernameFilter = null;
|
string usernameFilter = null;
|
||||||
string externalIdFilter = null;
|
string externalIdFilter = null;
|
||||||
|
|
||||||
|
int count = userQueryParams.Count;
|
||||||
|
int startIndex = userQueryParams.StartIndex;
|
||||||
|
string filter = userQueryParams.Filter;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(filter))
|
if (!string.IsNullOrWhiteSpace(filter))
|
||||||
{
|
{
|
||||||
var filterLower = filter.ToLowerInvariant();
|
var filterLower = filter.ToLowerInvariant();
|
||||||
@ -56,11 +61,11 @@ public class GetUsersListQuery : IGetUsersListQuery
|
|||||||
}
|
}
|
||||||
totalResults = userList.Count;
|
totalResults = userList.Count;
|
||||||
}
|
}
|
||||||
else if (string.IsNullOrWhiteSpace(filter) && startIndex.HasValue && count.HasValue)
|
else if (string.IsNullOrWhiteSpace(filter))
|
||||||
{
|
{
|
||||||
userList = orgUsers.OrderBy(ou => ou.Email)
|
userList = orgUsers.OrderBy(ou => ou.Email)
|
||||||
.Skip(startIndex.Value - 1)
|
.Skip(startIndex - 1)
|
||||||
.Take(count.Value)
|
.Take(count)
|
||||||
.ToList();
|
.ToList();
|
||||||
totalResults = orgUsers.Count;
|
totalResults = orgUsers.Count;
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,5 @@ namespace Bit.Scim.Users.Interfaces;
|
|||||||
|
|
||||||
public interface IGetUsersListQuery
|
public interface IGetUsersListQuery
|
||||||
{
|
{
|
||||||
Task<(IEnumerable<OrganizationUserUserDetails> userList, int totalResults)> GetUsersListAsync(Guid organizationId, string filter, int? count, int? startIndex);
|
Task<(IEnumerable<OrganizationUserUserDetails> userList, int totalResults)> GetUsersListAsync(Guid organizationId, GetUsersQueryParamModel userQueryParams);
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,46 @@ public class UsersControllerTests : IClassFixture<ScimApplicationFactory>, IAsyn
|
|||||||
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel);
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetList_SearchUserNameWithoutOptionalParameters_Success()
|
||||||
|
{
|
||||||
|
string filter = "userName eq user2@example.com";
|
||||||
|
int? itemsPerPage = null;
|
||||||
|
int? startIndex = null;
|
||||||
|
var expectedResponse = new ScimListResponseModel<ScimUserResponseModel>
|
||||||
|
{
|
||||||
|
ItemsPerPage = 50, //default value
|
||||||
|
TotalResults = 1,
|
||||||
|
StartIndex = 1, //default value
|
||||||
|
Resources = new List<ScimUserResponseModel>
|
||||||
|
{
|
||||||
|
new ScimUserResponseModel
|
||||||
|
{
|
||||||
|
Id = ScimApplicationFactory.TestOrganizationUserId2,
|
||||||
|
DisplayName = "Test User 2",
|
||||||
|
ExternalId = "UB",
|
||||||
|
Active = true,
|
||||||
|
Emails = new List<BaseScimUserModel.EmailModel>
|
||||||
|
{
|
||||||
|
new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user2@example.com" }
|
||||||
|
},
|
||||||
|
Groups = new List<string>(),
|
||||||
|
Name = new BaseScimUserModel.NameModel("Test User 2"),
|
||||||
|
UserName = "user2@example.com",
|
||||||
|
Schemas = new List<string> { ScimConstants.Scim2SchemaUser }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Schemas = new List<string> { ScimConstants.Scim2SchemaListResponse }
|
||||||
|
};
|
||||||
|
|
||||||
|
var context = await _factory.UsersGetListAsync(ScimApplicationFactory.TestOrganizationId1, filter, itemsPerPage, startIndex);
|
||||||
|
|
||||||
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
|
||||||
|
|
||||||
|
var responseModel = JsonSerializer.Deserialize<ScimListResponseModel<ScimUserResponseModel>>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
|
||||||
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Post_Success()
|
public async Task Post_Success()
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,7 @@ public class GetUsersListQueryTests
|
|||||||
.GetManyDetailsByOrganizationAsync(organizationId)
|
.GetManyDetailsByOrganizationAsync(organizationId)
|
||||||
.Returns(organizationUserUserDetails);
|
.Returns(organizationUserUserDetails);
|
||||||
|
|
||||||
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, null, count, startIndex);
|
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, new GetUsersQueryParamModel { Count = count, StartIndex = startIndex });
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ public class GetUsersListQueryTests
|
|||||||
.GetManyDetailsByOrganizationAsync(organizationId)
|
.GetManyDetailsByOrganizationAsync(organizationId)
|
||||||
.Returns(organizationUserUserDetails);
|
.Returns(organizationUserUserDetails);
|
||||||
|
|
||||||
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null);
|
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, new GetUsersQueryParamModel { Filter = filter });
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public class GetUsersListQueryTests
|
|||||||
.GetManyDetailsByOrganizationAsync(organizationId)
|
.GetManyDetailsByOrganizationAsync(organizationId)
|
||||||
.Returns(organizationUserUserDetails);
|
.Returns(organizationUserUserDetails);
|
||||||
|
|
||||||
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null);
|
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, new GetUsersQueryParamModel { Filter = filter });
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ public class GetUsersListQueryTests
|
|||||||
.GetManyDetailsByOrganizationAsync(organizationId)
|
.GetManyDetailsByOrganizationAsync(organizationId)
|
||||||
.Returns(organizationUserUserDetails);
|
.Returns(organizationUserUserDetails);
|
||||||
|
|
||||||
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null);
|
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, new GetUsersQueryParamModel { Filter = filter });
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ public class GetUsersListQueryTests
|
|||||||
.GetManyDetailsByOrganizationAsync(organizationId)
|
.GetManyDetailsByOrganizationAsync(organizationId)
|
||||||
.Returns(organizationUserUserDetails);
|
.Returns(organizationUserUserDetails);
|
||||||
|
|
||||||
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null);
|
var result = await sutProvider.Sut.GetUsersListAsync(organizationId, new GetUsersQueryParamModel { Filter = filter });
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyDetailsByOrganizationAsync(organizationId);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user