Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,5 @@ public async Task ReturnUsersOnValidLastNameParameters()
Assert.Equal(results.First().LastName, expectedLastName);
}


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using AutoMapper;
using Hng.Application.Features.SuperAdmin.Dto;
using Hng.Application.Features.SuperAdmin.Handlers;
using Hng.Application.Features.SuperAdmin.Queries;
using Hng.Application.Shared.Dtos;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Moq;
using System.Linq.Expressions;
using Xunit;

public class GetUsersMemberOrganizationsByUserIdQueryHandlerShould
{
private readonly Mock<IRepository<User>> _mockRepository;
private readonly IMapper _mapper;
private readonly GetUsersMemberOrganizationsByUserIdQueryHandler handler;

public GetUsersMemberOrganizationsByUserIdQueryHandlerShould()
{
_mockRepository = new Mock<IRepository<User>>();

// Set up AutoMapper with your profiles
var config = new MapperConfiguration(cfg =>
{
// Add your AutoMapper profiles here
cfg.CreateMap<User, UserSuperDto>();
cfg.CreateMap<Organization, OrganizationDto>();
});

_mapper = config.CreateMapper();
handler = new GetUsersMemberOrganizationsByUserIdQueryHandler(_mockRepository.Object, _mapper);
}

[Fact]
public async Task ReturnNullWhenUserIsNotFound()
{
_mockRepository.Setup(repo => repo.GetBySpec(
It.IsAny<Expression<Func<User, bool>>>(),
It.IsAny<Expression<Func<User, object>>[]>()
)).ReturnsAsync((User)null);

var result = await handler.Handle(
new GetUsersMemberOrganizationsByUserIdQuery(Guid.NewGuid(), new BaseQueryParameters()),
CancellationToken.None
);

Assert.Null(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using AutoMapper;
using Hng.Application.Features.SuperAdmin.Dto;
using Hng.Application.Features.SuperAdmin.Handlers;
using Hng.Application.Features.SuperAdmin.Queries;
using Hng.Application.Shared.Dtos;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Moq;
using System.Linq.Expressions;
using Xunit;

namespace Hng.Application.Test.Features.SuperAdmin
{
public class GetUsersMemberOrganizationsByUserIdQueryHandlerShould
{
private readonly Mock<IRepository<User>> _mockRepository;
private readonly IMapper _mapper;
private readonly GetUsersMemberOrganizationsByUserIdQueryHandler handler;

public GetUsersMemberOrganizationsByUserIdQueryHandlerShould()
{
_mockRepository = new Mock<IRepository<User>>();

var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<User, UserSuperDto>();
cfg.CreateMap<Domain.Entities.Organization, OrganizationDto>();
});
_mapper = config.CreateMapper();

handler = new GetUsersMemberOrganizationsByUserIdQueryHandler(_mockRepository.Object, _mapper);
}

[Fact]
public async Task ReturnNullWhenUserIsNotFound()
{
_mockRepository.Setup(repo => repo.GetBySpec(
It.IsAny<Expression<Func<User, bool>>>(),
It.IsAny<Expression<Func<User, object>>[]>()
)).ReturnsAsync((User)null);

var result = await handler.Handle(new GetUsersMemberOrganizationsByUserIdQuery(Guid.NewGuid(), new BaseQueryParameters()), CancellationToken.None);

Assert.Null(result);
}
}
}
2 changes: 2 additions & 0 deletions src/Hng.Application.Test/Hng.Application.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Paystack.Net" Version="1.1.1" />
<PackageReference Include="xunit" Version="2.9.0" />

<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Hng.Application.Shared.Dtos;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Hng.Infrastructure.Services.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;

namespace Hng.Application.Features.SuperAdmin.Authorization;

public class IsSuperAdminHandler : AuthorizationHandler<IsSuperAdminRequirement>
{
private readonly IRepository<User> _userRepository;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IAuthenticationService _authenticationService;

public IsSuperAdminHandler(IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IAuthenticationService authenticationService)
{
_userRepository = userRepository;
_httpContextAccessor = httpContextAccessor;
_authenticationService = authenticationService;
}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IsSuperAdminRequirement requirement)
{

var userId = await _authenticationService.GetCurrentUserAsync();

if (!Guid.TryParse(userId.ToString(), out _))
{
context.Fail();
return;
}

var user = await _userRepository.GetBySpec(u => u.Id == userId);

Console.WriteLine($"This is the User : {user}");

if (user != null && user.IsSuperAdmin)
{
context.Succeed(requirement);
}
else
{
var response = new StatusCodeResponse()
{
StatusCode = StatusCodes.Status403Forbidden,
Message = "You are not Authorized to access this resource"
};
_httpContextAccessor.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
await _httpContextAccessor.HttpContext.Response.WriteAsJsonAsync(response);
context.Fail();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Authorization;

namespace Hng.Application.Features.SuperAdmin.Authorization;

public class IsSuperAdminRequirement : IAuthorizationRequirement
{

}
31 changes: 31 additions & 0 deletions src/Hng.Application/Features/SuperAdmin/Dto/OrganizationDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Text.Json.Serialization;

namespace Hng.Application.Features.SuperAdmin.Dto;

public class OrganizationDto
{

[JsonPropertyName("name")] public string Name { get; set; }

[JsonPropertyName("description")] public string Description { get; set; }

[JsonPropertyName("slug")] public string Slug { get; set; }

[JsonPropertyName("email")] public string Email { get; set; }

[JsonPropertyName("industry")] public string Industry { get; set; }

[JsonPropertyName("type")] public string Type { get; set; }

[JsonPropertyName("country")] public string Country { get; set; }

[JsonPropertyName("address")] public string Address { get; set; }

[JsonPropertyName("state")] public string State { get; set; }

[JsonPropertyName("is_active")] public bool IsActive { get; set; }

[JsonPropertyName("created_at")] public DateTime CreatedAt { get; set; }

}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field 'GetUsersMemberOrganizationsByUserIdQueryHandler._authenticationService' is never used

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using AutoMapper;
using Hng.Application.Features.SuperAdmin.Dto;
using Hng.Application.Features.SuperAdmin.Queries;
using Hng.Application.Shared.Dtos;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Hng.Infrastructure.Services.Interfaces;
using MediatR;

namespace Hng.Application.Features.SuperAdmin.Handlers;

public class GetUsersMemberOrganizationsByUserIdQueryHandler : IRequestHandler<GetUsersMemberOrganizationsByUserIdQuery, PagedListDto<OrganizationDto>>
{
private readonly IRepository<User> _userRepository;
private readonly IMapper _mapper;

public GetUsersMemberOrganizationsByUserIdQueryHandler(IRepository<User> userRepository, IMapper mapper)
{
_userRepository = userRepository;
_mapper = mapper;
}

public async Task<PagedListDto<OrganizationDto>> Handle(GetUsersMemberOrganizationsByUserIdQuery request, CancellationToken cancellationToken)
{
var user = await _userRepository.GetBySpec(user => user.Id == request.UserId, user => user.Organizations);

if (user == null)
{
return null;
}
var userMemberOrganizations = user.Organizations.Where(org => org.OwnerId != user.Id).ToList();

var mappedOrganizations = _mapper.Map<List<OrganizationDto>>(userMemberOrganizations);

// var mappedProducts = _mapper.Map<IEnumerable<ProductDto>>(products);

var organizationResult = PagedListDto<OrganizationDto>.ToPagedList(mappedOrganizations, request.UserMemberOrganizationsQueryParameter.Offset, request.UserMemberOrganizationsQueryParameter.Limit);

return organizationResult;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user is not found, you can return an empty list instead of the null.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using AutoMapper;
using Hng.Application.Features.SuperAdmin.Dto;
using Hng.Application.Features.SuperAdmin.Queries;
using Hng.Application.Shared.Dtos;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Hng.Infrastructure.Services.Interfaces;
using MediatR;

namespace Hng.Application.Features.SuperAdmin.Handlers;

public class GetUsersOwnedOrganizationsByUserIdQueryHandler : IRequestHandler<GetUsersOwnedOrganizationsByUserIdQuery, PagedListDto<OrganizationDto>>
{
private readonly IRepository<User> _userRepository;
private readonly IMapper _mapper;

public GetUsersOwnedOrganizationsByUserIdQueryHandler(IRepository<User> userRepository, IMapper mapper)
{
_userRepository = userRepository;
_mapper = mapper;
}

public async Task<PagedListDto<OrganizationDto>> Handle(GetUsersOwnedOrganizationsByUserIdQuery request, CancellationToken cancellationToken)
{
var user = await _userRepository.GetBySpec(user => user.Id == request.UserId, user => user.Organizations);

if (user == null)
{
return null;
}
var userOwnedOrganizations = user.Organizations.Where(org => org.OwnerId == user.Id).ToList();

var mappedOrganizations = _mapper.Map<List<OrganizationDto>>(userOwnedOrganizations);

var organizationResult = PagedListDto<OrganizationDto>.ToPagedList(mappedOrganizations, request.UserOwnedOrganizationsQueryParameter.Offset, request.UserOwnedOrganizationsQueryParameter.Limit);

return organizationResult;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class AdminUsersMappingProfile : AutoMapper.Profile
public AdminUsersMappingProfile()
{
CreateMap<User, UserSuperDto>().ReverseMap();
CreateMap<Organization, OrganizationDto>().ReverseMap();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Hng.Application.Features.SuperAdmin.Dto;
using Hng.Application.Shared.Dtos;
using MediatR;

namespace Hng.Application.Features.SuperAdmin.Queries;

public class GetUsersMemberOrganizationsByUserIdQuery : IRequest<PagedListDto<OrganizationDto>>
{
public GetUsersMemberOrganizationsByUserIdQuery(Guid userId, BaseQueryParameters userMemberOrganizationsQueryParameter)
{
UserId = userId;
UserMemberOrganizationsQueryParameter = userMemberOrganizationsQueryParameter;
}
public Guid UserId { get; set; }
public BaseQueryParameters UserMemberOrganizationsQueryParameter { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Hng.Application.Features.SuperAdmin.Dto;
using Hng.Application.Shared.Dtos;
using MediatR;

namespace Hng.Application.Features.SuperAdmin.Queries;

public class GetUsersOwnedOrganizationsByUserIdQuery : IRequest<PagedListDto<OrganizationDto>>
{
public GetUsersOwnedOrganizationsByUserIdQuery(Guid userId, BaseQueryParameters userOwnedOrganizationsQueryParameter)
{
UserId = userId;
UserOwnedOrganizationsQueryParameter = userOwnedOrganizationsQueryParameter;
}
public Guid UserId { get; set; }
public BaseQueryParameters UserOwnedOrganizationsQueryParameter { get; set; }
}
1 change: 0 additions & 1 deletion src/Hng.Infrastructure/Repository/Interface/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ public interface IRepository<T> where T : EntityBase
Task<T> GetBySpec(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties);
Task<IEnumerable<T>> GetAllAsync(params Expression<Func<T, object>>[] includeProperties);
Task<IEnumerable<T>> GetAllBySpec(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties);

IQueryable<T> GetQueryableBySpec(Expression<Func<T, bool>> predicate);
Task<T> AddAsync(T entity);
Task AddRangeAsync(IEnumerable<T> entities);
Expand Down
13 changes: 6 additions & 7 deletions src/Hng.Infrastructure/Repository/Repository.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Linq.Expressions;
using Hng.Domain.Entities;
using Hng.Infrastructure.Context;
using Hng.Infrastructure.Repository.Interface;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace Hng.Infrastructure.Repository
{
Expand Down Expand Up @@ -85,11 +85,11 @@ public async Task<IEnumerable<T>> GetAllBySpec(Expression<Func<T, bool>> predica
return await entities.ToListAsync();
}


public IQueryable<T> GetQueryableBySpec(Expression<Func<T, bool>> predicate)
{
return _context.Set<T>().AsNoTracking().Where(predicate);
}

public async Task<T> GetBySpec(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties)
{
var entities = _context.Set<T>().Where(predicate).AsNoTracking();
Expand All @@ -109,12 +109,11 @@ public Task UpdateAsync(T entity)

public async Task SaveChanges()
{

//Add newly registered user to the organisation if they were invited
// Add newly registered user to the organisation if they were invited
var newUsers = _context.ChangeTracker.Entries<User>()
.Where(e => e.State == EntityState.Added)
.Select(e => e.Entity)
.ToList();
.Where(e => e.State == EntityState.Added)
.Select(e => e.Entity)
.ToList();

if (newUsers.Count != 0)
{
Expand Down
Loading
Loading