You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
388 lines
16 KiB
388 lines
16 KiB
using System.Text.Json; |
|
using Bit.Scim.IntegrationTest.Factories; |
|
using Bit.Scim.Models; |
|
using Bit.Scim.Utilities; |
|
using Bit.Test.Common.Helpers; |
|
using Xunit; |
|
|
|
namespace Bit.Scim.IntegrationTest.Controllers.v2; |
|
|
|
public class GroupsControllerTests : IClassFixture<ScimApplicationFactory>, IAsyncLifetime |
|
{ |
|
private readonly ScimApplicationFactory _factory; |
|
|
|
public GroupsControllerTests(ScimApplicationFactory factory) |
|
{ |
|
_factory = factory; |
|
} |
|
|
|
public Task InitializeAsync() |
|
{ |
|
var databaseContext = _factory.GetDatabaseContext(); |
|
_factory.ReinitializeDbForTests(databaseContext); |
|
return Task.CompletedTask; |
|
} |
|
|
|
Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask; |
|
|
|
[Fact] |
|
public async Task Get_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var groupId = ScimApplicationFactory.TestGroupId1; |
|
var expectedResponse = new ScimGroupResponseModel |
|
{ |
|
Id = groupId, |
|
DisplayName = "Test Group 1", |
|
ExternalId = "A", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
|
|
var context = await _factory.GroupsGetAsync(organizationId, groupId); |
|
|
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimGroupResponseModel>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
|
|
Assert.Contains("application/scim+json", context.Response.Headers.ContentType.ToString()); |
|
} |
|
|
|
[Fact] |
|
public async Task Get_NotFound() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var groupId = Guid.NewGuid(); |
|
var expectedResponse = new ScimErrorResponseModel |
|
{ |
|
Status = StatusCodes.Status404NotFound, |
|
Detail = "Group not found.", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaError } |
|
}; |
|
|
|
var context = await _factory.GroupsGetAsync(organizationId, groupId); |
|
|
|
Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimErrorResponseModel>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
|
|
[Fact] |
|
public async Task GetList_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
string filter = null; |
|
int? itemsPerPage = 2; |
|
int? startIndex = 1; |
|
var expectedResponse = new ScimListResponseModel<ScimGroupResponseModel> |
|
{ |
|
ItemsPerPage = itemsPerPage.Value, |
|
TotalResults = 3, |
|
StartIndex = startIndex.Value, |
|
Resources = new List<ScimGroupResponseModel> |
|
{ |
|
new ScimGroupResponseModel |
|
{ |
|
Id = ScimApplicationFactory.TestGroupId1, |
|
DisplayName = "Test Group 1", |
|
ExternalId = "A", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaGroup } |
|
}, |
|
new ScimGroupResponseModel |
|
{ |
|
Id = ScimApplicationFactory.TestGroupId2, |
|
DisplayName = "Test Group 2", |
|
ExternalId = "B", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaGroup } |
|
} |
|
}, |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaListResponse } |
|
}; |
|
|
|
var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); |
|
|
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimListResponseModel<ScimGroupResponseModel>>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
|
|
[Fact] |
|
public async Task GetList_SearchDisplayName_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
string filter = "displayName eq Test Group 2"; |
|
int? itemsPerPage = 10; |
|
int? startIndex = 1; |
|
var expectedResponse = new ScimListResponseModel<ScimGroupResponseModel> |
|
{ |
|
ItemsPerPage = itemsPerPage.Value, |
|
TotalResults = 1, |
|
StartIndex = startIndex.Value, |
|
Resources = new List<ScimGroupResponseModel> |
|
{ |
|
new ScimGroupResponseModel |
|
{ |
|
Id = ScimApplicationFactory.TestGroupId2, |
|
DisplayName = "Test Group 2", |
|
ExternalId = "B", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaGroup } |
|
} |
|
}, |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaListResponse } |
|
}; |
|
|
|
var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); |
|
|
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimListResponseModel<ScimGroupResponseModel>>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
|
|
[Fact] |
|
public async Task GetList_SearchExternalId_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
string filter = "externalId eq C"; |
|
int? itemsPerPage = 10; |
|
int? startIndex = 1; |
|
var expectedResponse = new ScimListResponseModel<ScimGroupResponseModel> |
|
{ |
|
ItemsPerPage = itemsPerPage.Value, |
|
TotalResults = 1, |
|
StartIndex = startIndex.Value, |
|
Resources = new List<ScimGroupResponseModel> |
|
{ |
|
new ScimGroupResponseModel |
|
{ |
|
Id = ScimApplicationFactory.TestGroupId3, |
|
DisplayName = "Test Group 3", |
|
ExternalId = "C", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaGroup } |
|
} |
|
}, |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaListResponse } |
|
}; |
|
|
|
|
|
var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); |
|
|
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimListResponseModel<ScimGroupResponseModel>>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
|
|
[Fact] |
|
public async Task GetList_EmptyResult_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
string filter = "externalId eq Z"; |
|
int? itemsPerPage = 10; |
|
int? startIndex = 1; |
|
var expectedResponse = new ScimListResponseModel<ScimGroupResponseModel> |
|
{ |
|
ItemsPerPage = itemsPerPage.Value, |
|
TotalResults = 0, |
|
StartIndex = startIndex.Value, |
|
Resources = new List<ScimGroupResponseModel>(), |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaListResponse } |
|
}; |
|
|
|
|
|
var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); |
|
|
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimListResponseModel<ScimGroupResponseModel>>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
|
|
[Fact] |
|
public async Task Post_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var displayName = "New Group"; |
|
var externalId = Guid.NewGuid().ToString(); |
|
var inputModel = new ScimGroupRequestModel |
|
{ |
|
DisplayName = displayName, |
|
ExternalId = externalId.ToString(), |
|
Members = new List<ScimGroupRequestModel.GroupMembersModel> |
|
{ |
|
new ScimGroupRequestModel.GroupMembersModel { Display = "user1@example.com", Value = ScimApplicationFactory.TestOrganizationUserId1.ToString() } |
|
}, |
|
Schemas = new List<string>() { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
var expectedResponse = new ScimGroupResponseModel |
|
{ |
|
DisplayName = displayName, |
|
ExternalId = externalId, |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
|
|
var context = await _factory.GroupsPostAsync(organizationId, inputModel); |
|
|
|
Assert.Equal(StatusCodes.Status201Created, context.Response.StatusCode); |
|
|
|
// Verifying that the response includes a header with the URL of the created Group |
|
Assert.Contains(context.Response.Headers, h => h.Key == "Location"); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimGroupResponseModel>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel, "Id"); |
|
|
|
var databaseContext = _factory.GetDatabaseContext(); |
|
Assert.Equal(ScimApplicationFactory.InitialGroupCount + 1, databaseContext.Groups.Count()); |
|
Assert.True(databaseContext.Groups.Any(g => g.Name == displayName && g.ExternalId == externalId)); |
|
|
|
Assert.Equal(ScimApplicationFactory.InitialGroupUsersCount + 1, databaseContext.GroupUsers.Count()); |
|
Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId == responseModel.Id && gu.OrganizationUserId == ScimApplicationFactory.TestOrganizationUserId1)); |
|
} |
|
|
|
[Theory] |
|
[InlineData(null)] |
|
[InlineData("")] |
|
[InlineData(" ")] |
|
public async Task Post_InvalidDisplayName_BadRequest(string? displayName) |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var model = new ScimGroupRequestModel |
|
{ |
|
DisplayName = displayName, |
|
ExternalId = null, |
|
Members = null, |
|
Schemas = new List<string>() { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
|
|
var context = await _factory.GroupsPostAsync(organizationId, model); |
|
|
|
Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode); |
|
} |
|
|
|
[Fact] |
|
public async Task Post_ExistingExternalId_Conflict() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var model = new ScimGroupRequestModel |
|
{ |
|
DisplayName = "New Group", |
|
ExternalId = "A", |
|
Members = null, |
|
Schemas = new List<string>() { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
|
|
var context = await _factory.GroupsPostAsync(organizationId, model); |
|
|
|
Assert.Equal(StatusCodes.Status409Conflict, context.Response.StatusCode); |
|
|
|
var databaseContext = _factory.GetDatabaseContext(); |
|
Assert.Equal(ScimApplicationFactory.InitialGroupCount, databaseContext.Groups.Count()); |
|
Assert.False(databaseContext.Groups.Any(g => g.Name == "New Group")); |
|
} |
|
|
|
[Fact] |
|
public async Task Put_ChangeNameAndMembers_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var groupId = ScimApplicationFactory.TestGroupId1; |
|
var newGroupName = Guid.NewGuid().ToString(); |
|
var inputModel = new ScimGroupRequestModel |
|
{ |
|
DisplayName = newGroupName, |
|
ExternalId = "A", |
|
Members = new List<ScimGroupRequestModel.GroupMembersModel> |
|
{ |
|
new ScimGroupRequestModel.GroupMembersModel { Display = "user2@example.com", Value = ScimApplicationFactory.TestOrganizationUserId2.ToString() }, |
|
new ScimGroupRequestModel.GroupMembersModel { Display = "user3@example.com", Value = ScimApplicationFactory.TestOrganizationUserId3.ToString() } |
|
}, |
|
Schemas = new List<string>() { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
var expectedResponse = new ScimGroupResponseModel |
|
{ |
|
Id = groupId, |
|
DisplayName = newGroupName, |
|
ExternalId = "A", |
|
Schemas = new List<string>() { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
|
|
var context = await _factory.GroupsPutAsync(organizationId, groupId, inputModel); |
|
|
|
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimGroupResponseModel>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
|
|
var databaseContext = _factory.GetDatabaseContext(); |
|
var firstGroup = databaseContext.Groups.FirstOrDefault(g => g.Id == groupId); |
|
Assert.Equal(newGroupName, firstGroup.Name); |
|
|
|
Assert.Equal(2, databaseContext.GroupUsers.Count(gu => gu.GroupId == groupId)); |
|
Assert.NotNull(databaseContext.GroupUsers.FirstOrDefault(gu => gu.GroupId == groupId && gu.OrganizationUserId == ScimApplicationFactory.TestOrganizationUserId2)); |
|
Assert.NotNull(databaseContext.GroupUsers.FirstOrDefault(gu => gu.GroupId == groupId && gu.OrganizationUserId == ScimApplicationFactory.TestOrganizationUserId3)); |
|
} |
|
|
|
[Fact] |
|
public async Task Put_NotFound() |
|
{ |
|
var newGroupName = "Test Group 1 New Name"; |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var groupId = Guid.NewGuid(); |
|
var inputModel = new ScimGroupRequestModel |
|
{ |
|
DisplayName = newGroupName, |
|
ExternalId = "A", |
|
Members = new List<ScimGroupRequestModel.GroupMembersModel>(), |
|
Schemas = new List<string>() { ScimConstants.Scim2SchemaGroup } |
|
}; |
|
var expectedResponse = new ScimErrorResponseModel |
|
{ |
|
Status = StatusCodes.Status404NotFound, |
|
Detail = "Group not found.", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaError } |
|
}; |
|
|
|
var context = await _factory.GroupsPutAsync(organizationId, groupId, inputModel); |
|
|
|
Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimErrorResponseModel>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
|
|
[Fact] |
|
public async Task Delete_Success() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var groupId = ScimApplicationFactory.TestGroupId3; |
|
|
|
var context = await _factory.GroupsDeleteAsync(organizationId, groupId); |
|
|
|
Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); |
|
|
|
var databaseContext = _factory.GetDatabaseContext(); |
|
Assert.Equal(ScimApplicationFactory.InitialGroupCount - 1, databaseContext.Groups.Count()); |
|
Assert.True(databaseContext.Groups.FirstOrDefault(g => g.Id == groupId) == null); |
|
} |
|
|
|
[Fact] |
|
public async Task Delete_NotFound() |
|
{ |
|
var organizationId = ScimApplicationFactory.TestOrganizationId1; |
|
var groupId = Guid.NewGuid(); |
|
var expectedResponse = new ScimErrorResponseModel |
|
{ |
|
Status = StatusCodes.Status404NotFound, |
|
Detail = "Group not found.", |
|
Schemas = new List<string> { ScimConstants.Scim2SchemaError } |
|
}; |
|
|
|
var context = await _factory.GroupsDeleteAsync(organizationId, groupId); |
|
|
|
Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); |
|
|
|
var responseModel = JsonSerializer.Deserialize<ScimErrorResponseModel>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); |
|
AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); |
|
} |
|
}
|
|
|