Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add group users limit verification #114

Merged
merged 1 commit into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Src/DeUrgenta.Api/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddDatabase<DeUrgentaContext>(Configuration.GetConnectionString("DbConnectionString"));
services.AddExceptionHandling(WebHostEnvironment);

services.AddUserApiServices();
services.AddUserApiServices(Configuration);
services.AddBackpackApiServices();
services.AddGroupApiServices(Configuration);
services.AddCertificationsApiServices();
Expand Down
3 changes: 2 additions & 1 deletion Src/DeUrgenta.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
},
"Group": {
"MaxJoinedGroupsPerUser": 5,
"MaxCreatedGroupsPerUser": 5
"MaxCreatedGroupsPerUser": 5,
"UsersLimit": 30
},
"Passwords": {
"RequiredLength": 6,
Expand Down
4 changes: 3 additions & 1 deletion Src/DeUrgenta.User.Api/BootstrappingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ public static void SetupEmailService(this IServiceCollection services, IConfigur
}
}

public static IServiceCollection AddUserApiServices(this IServiceCollection services)
public static IServiceCollection AddUserApiServices(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<GroupsConfig>(configuration.GetSection(GroupsConfig.SectionName));

services.AddTransient<IValidateRequest<GetUser>, GetUserValidator>();
services.AddTransient<IValidateRequest<UpdateUser>, UpdateUserValidator>();
services.AddTransient<IValidateRequest<GetBackpackInvites>, GetBackpackInvitesValidator>();
Expand Down
8 changes: 8 additions & 0 deletions Src/DeUrgenta.User.Api/Options/GroupsConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DeUrgenta.User.Api.Options
{
public class GroupsConfig
{
public const string SectionName = "Group";
public int UsersLimit { get; set; }
}
}
33 changes: 28 additions & 5 deletions Src/DeUrgenta.User.Api/Validators/AcceptGroupInviteValidator.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
using System.Threading.Tasks;
using System.Linq;
using System.Threading.Tasks;
using DeUrgenta.Common.Validation;
using DeUrgenta.Domain;
using DeUrgenta.User.Api.Commands;
using DeUrgenta.User.Api.Options;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace DeUrgenta.User.Api.Validators
{
public class AcceptGroupInviteValidator : IValidateRequest<AcceptGroupInvite>
{
private readonly DeUrgentaContext _context;
private readonly IOptions<GroupsConfig> _options;

public AcceptGroupInviteValidator(DeUrgentaContext context)
public AcceptGroupInviteValidator(DeUrgentaContext context, IOptions<GroupsConfig> options)
{
_context = context;
_options = options;
}

public async Task<bool> IsValidAsync(AcceptGroupInvite request)
Expand All @@ -24,11 +29,29 @@ public async Task<bool> IsValidAsync(AcceptGroupInvite request)
return false;
}

var inviteExists = await _context
var invite = await _context
.GroupInvites
.AnyAsync(bi => bi.InvitationReceiver.Sub == request.UserSub && bi.Id == request.GroupInviteId);
.FirstOrDefaultAsync(bi => bi.InvitationReceiver.Sub == request.UserSub && bi.Id == request.GroupInviteId);

return inviteExists;
if (invite is null)
{
return false;
}

var config = _options.Value;

var exceedsLimit = await _context.UsersToGroups
.Where(x => x.GroupId == invite.GroupId)
.GroupBy(x => x.GroupId)
.Where(g => g.Count() >= config.UsersLimit)
decembrya marked this conversation as resolved.
Show resolved Hide resolved
.AnyAsync();

if (exceedsLimit)
{
return false;
}

return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
using DeUrgenta.Tests.Helpers;
using DeUrgenta.Tests.Helpers.Builders;
using DeUrgenta.User.Api.Commands;
using DeUrgenta.User.Api.Options;
using DeUrgenta.User.Api.Validators;
using FluentAssertions;
using Microsoft.Extensions.Options;
using NSubstitute;
using Xunit;

namespace DeUrgenta.User.Api.Tests.Validators
Expand All @@ -15,10 +18,11 @@ namespace DeUrgenta.User.Api.Tests.Validators
public class AcceptGroupInviteValidatorShould
{
private readonly DeUrgentaContext _dbContext;

private readonly IOptions<GroupsConfig> _defaultOptions = Substitute.For<IOptions<GroupsConfig>>();
public AcceptGroupInviteValidatorShould(DatabaseFixture fixture)
{
_dbContext = fixture.Context;
_defaultOptions.Value.Returns(new GroupsConfig { UsersLimit = 30 });
}

[Theory]
Expand All @@ -28,7 +32,7 @@ public AcceptGroupInviteValidatorShould(DatabaseFixture fixture)
public async Task Invalidate_request_when_no_user_found_by_sub(string sub)
{
// Arrange
var sut = new AcceptGroupInviteValidator(_dbContext);
var sut = new AcceptGroupInviteValidator(_dbContext, _defaultOptions);

// Act
var isValid = await sut.IsValidAsync(new AcceptGroupInvite(sub, Guid.NewGuid()));
Expand All @@ -40,7 +44,7 @@ public async Task Invalidate_request_when_no_user_found_by_sub(string sub)
[Fact]
public async Task Invalidate_when_invite_is_for_other_user()
{
var sut = new AcceptGroupInviteValidator(_dbContext);
var sut = new AcceptGroupInviteValidator(_dbContext, _defaultOptions);

// Arrange
var userSub = Guid.NewGuid().ToString();
Expand Down Expand Up @@ -84,7 +88,7 @@ public async Task Invalidate_when_invite_is_for_other_user()
[Fact]
public async Task Invalidate_when_invite_does_not_exist()
{
var sut = new AcceptGroupInviteValidator(_dbContext);
var sut = new AcceptGroupInviteValidator(_dbContext, _defaultOptions);

// Arrange
var userSub = Guid.NewGuid().ToString();
Expand Down Expand Up @@ -113,10 +117,57 @@ public async Task Invalidate_when_invite_does_not_exist()
isValid.Should().BeFalse();
}

[Fact]
public async Task Invalidate_when_exceeds_group_users_limit()
{
var options = Substitute.For<IOptions<GroupsConfig>>();
options.Value.Returns(new GroupsConfig { UsersLimit = 2 });
var sut = new AcceptGroupInviteValidator(_dbContext, options);

// Arrange
var userSub = Guid.NewGuid().ToString();
var user = new UserBuilder().WithSub(userSub).Build();

var secondUserSub = Guid.NewGuid().ToString();
var secondUser = new UserBuilder().WithSub(secondUserSub).Build();

var adminSub = Guid.NewGuid().ToString();
var admin = new UserBuilder().WithSub(adminSub).Build();

await _dbContext.Users.AddAsync(user);
await _dbContext.Users.AddAsync(admin);

var group = new Group
{
Admin = admin,
Name = "group"
};

await _dbContext.UsersToGroups.AddAsync(new UserToGroup { Group = group, User = admin });
await _dbContext.UsersToGroups.AddAsync(new UserToGroup { Group = group, User = user });

var groupInvite = new GroupInvite
{
InvitationReceiver = secondUser,
InvitationSender = admin,
Group = group
};
await _dbContext.GroupInvites.AddAsync(groupInvite);
await _dbContext.Groups.AddAsync(group);

await _dbContext.SaveChangesAsync();

// Act
var isValid = await sut.IsValidAsync(new AcceptGroupInvite(secondUserSub, groupInvite.Id));

// Assert
isValid.Should().BeFalse();
}

[Fact]
public async Task Validate_when_an_invite_exists()
{
var sut = new AcceptGroupInviteValidator(_dbContext);
var sut = new AcceptGroupInviteValidator(_dbContext, _defaultOptions);

// Arrange
var userSub = Guid.NewGuid().ToString();
Expand Down