Skip to content

Commit

Permalink
Merge pull request #405 from bcgov/yj
Browse files Browse the repository at this point in the history
Yj
  • Loading branch information
ychung-mot authored Jun 19, 2024
2 parents 9fac73e + 6fb83b7 commit 51da0e0
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 3 deletions.
44 changes: 44 additions & 0 deletions server/StrDss.Api/Controllers/RolesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,50 @@ public async Task<ActionResult<List<RoleDto>>> GetRoles()
return Ok(await _roleService.GetRolesAync());
}

[ApiAuthorize]
[HttpPost("", Name = "CreateRole")]
public async Task<ActionResult> CreateRole(RoleUpdateDto dto)
{
var errors = await _roleService.CreateRoleAsync(dto);

if (errors.Count > 0)
{
return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
}

return NoContent();
}

[ApiAuthorize]
[HttpPut("{roleCd}", Name = "UpdateRole")]
public async Task<ActionResult> UpdateRole(string roleCd, RoleUpdateDto dto)
{
dto.UserRoleCd = roleCd;

var errors = await _roleService.UpdateRoleAsync(dto);

if (errors.Count > 0)
{
return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
}

return NoContent();
}

[ApiAuthorize]
[HttpDelete("{roleCd}", Name = "DeleteRole")]
public async Task<ActionResult> DeleteRole(string roleCd)
{
var errors = await _roleService.DeleteRoleAsync(roleCd);

if (errors.Count > 0)
{
return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
}

return NoContent();
}

[ApiAuthorize]
[HttpGet("{roleCd}", Name = "GetRole")]
public async Task<ActionResult<RoleDto>> GetRole(string roleCd)
Expand Down
10 changes: 7 additions & 3 deletions server/StrDss.Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ public class Constants
}
public static class Entities
{
public const string SystemUser = "SystemUser";
public const string StrApplication = "StrApplication";
public const string Audit = "Audit";
public const string RentalListingRowUntyped = "RentalListingRowUntyped";
public const string Role = "Role";

}
public static class Fields
{
Expand Down Expand Up @@ -84,6 +83,11 @@ public static class RentalListingReportFields
public const string SupplierHost5Id = "SupplierHost5Id";
}

public static class RoleFields
{
public const string UserRoleCd = "UserRoleCd";
public const string UserRoleNm = "UserRoleNm";
}

public static class AccessRequestStatuses
{
Expand Down
2 changes: 2 additions & 0 deletions server/StrDss.Data/Mappings/ModelToEntityProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public ModelToEntityProfile()
.ForMember(dest => dest.AvailableBedroomsQty, opt => opt.MapFrom(src => CommonUtils.StringToShort(src.BedroomsQty)))
.ForMember(dest => dest.NightsBookedQty, opt => opt.MapFrom(src => CommonUtils.StringToShort(src.NightsBookedQty)))
.ForMember(dest => dest.SeparateReservationsQty, opt => opt.MapFrom(src => CommonUtils.StringToShort(src.ReservationsQty)));

CreateMap<RoleUpdateDto, DssUserRole>();
}
}
}
62 changes: 62 additions & 0 deletions server/StrDss.Data/Repositories/RoleRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using StrDss.Data.Entities;
using StrDss.Model;
using StrDss.Model.UserDtos;
using System.Collections.Generic;
using System.Security;

namespace StrDss.Data.Repositories
{
Expand All @@ -13,6 +15,11 @@ public interface IRoleRepository
Task<List<RoleDto>> GetRolesAync();
Task<List<PermissionDto>> GetPermissionsAync();
Task<RoleDto?> GetRoleAync(string roleCd);
Task CreateRoleAsync(RoleUpdateDto role);
Task<int> CountActivePermissionIdsAsnyc(IEnumerable<string> permissions);
Task<bool> DoesRoleCdExist(string roleCd);
Task UpdateRoleAsync(RoleUpdateDto role);
Task DeleteRoleAsync(string roleCd);
}
public class RoleRepository : RepositoryBase<DssUserRole>, IRoleRepository
{
Expand Down Expand Up @@ -48,5 +55,60 @@ public async Task<List<PermissionDto>> GetPermissionsAync()
{
return _mapper.Map<List<PermissionDto>>(await _dbContext.DssUserPrivileges.AsNoTracking().ToListAsync());
}

public async Task<int> CountActivePermissionIdsAsnyc(IEnumerable<string> permissions)
{
return await _dbContext.DssUserPrivileges.CountAsync(x => permissions.Contains(x.UserPrivilegeCd));
}

public async Task CreateRoleAsync(RoleUpdateDto role)
{
var roleEntity = _mapper.Map<DssUserRole>(role);

await _dbSet.AddAsync(roleEntity);

foreach (var permission in role.Permissions)
{
var privilege = await _dbContext.DssUserPrivileges
.FirstAsync(x => x.UserPrivilegeCd == permission);

roleEntity.UserPrivilegeCds.Add(privilege);
}
}

public async Task<bool> DoesRoleCdExist(string roleCd)
{
return await _dbSet.AnyAsync(x => x.UserRoleCd == roleCd);
}

public async Task UpdateRoleAsync(RoleUpdateDto role)
{
var roleEntity = await _dbSet.Include(x => x.UserPrivilegeCds).FirstAsync(x => x.UserRoleCd == role.UserRoleCd);

_mapper.Map(role, roleEntity);

roleEntity.UserPrivilegeCds.Clear();

var permissions = role.Permissions.Distinct();

foreach (var permission in role.Permissions)
{
var privilege = await _dbContext.DssUserPrivileges
.FirstAsync(x => x.UserPrivilegeCd == permission);

roleEntity.UserPrivilegeCds.Add(privilege);
}
}

public async Task DeleteRoleAsync(string roleCd)
{
var roleEntity = await _dbSet
.Include(x => x.UserPrivilegeCds)
.FirstAsync(x => x.UserRoleCd == roleCd);

roleEntity.UserPrivilegeCds.Clear();

_dbSet.Remove(roleEntity);
}
}
}
9 changes: 9 additions & 0 deletions server/StrDss.Model/UserDtos/RoleUpdateDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace StrDss.Model.UserDtos
{
public class RoleUpdateDto
{
public string UserRoleCd { get; set; } = null!;
public string UserRoleNm { get; set; } = null!;
public virtual ICollection<string> Permissions { get; set; } = new List<string>();
}
}
1 change: 1 addition & 0 deletions server/StrDss.Service/FieldValidatorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public FieldValidatorService()
_rules = new List<FieldValidationRule>();

RentalListingReportValidationRule.LoadReportValidationRules(_rules);
RoleValidationRule.LoadReportValidationRules(_rules);
}

public IEnumerable<FieldValidationRule> GetFieldValidationRules(string entityName)
Expand Down
89 changes: 89 additions & 0 deletions server/StrDss.Service/RoleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Extensions.Logging;
using StrDss.Common;
using StrDss.Data;
using StrDss.Data.Entities;
using StrDss.Data.Repositories;
using StrDss.Model;
using StrDss.Model.UserDtos;
Expand All @@ -14,6 +15,9 @@ public interface IRoleService
Task<List<RoleDto>> GetRolesAync();
Task<RoleDto?> GetRoleAync(string roleCd);
Task<List<PermissionDto>> GetPermissionsAync();
Task<Dictionary<string, List<string>>> CreateRoleAsync(RoleUpdateDto role);
Task<Dictionary<string, List<string>>> UpdateRoleAsync(RoleUpdateDto role);
Task<Dictionary<string, List<string>>> DeleteRoleAsync(string roleCd);
}
public class RoleService : ServiceBase, IRoleService
{
Expand All @@ -38,5 +42,90 @@ public async Task<List<PermissionDto>> GetPermissionsAync()
{
return await _roleRepo.GetPermissionsAync();
}
public async Task<Dictionary<string, List<string>>> CreateRoleAsync(RoleUpdateDto role)
{
var errors = await ValidateRoleDtoAsync(role);

if (await _roleRepo.DoesRoleCdExist(role.UserRoleCd))
{
errors.AddItem("userRoleCd", $"Role Code [{role.UserRoleCd}] already exists.");
}

if (errors.Count > 0)
{
return errors;
}

await _roleRepo.CreateRoleAsync(role);

_unitOfWork.Commit();

return errors;
}

private async Task<Dictionary<string, List<string>>> ValidateRoleDtoAsync(RoleUpdateDto role)
{
var errors = new Dictionary<string, List<string>>();

errors = _validator.Validate(Entities.Role, role, errors);

var permissionCount = await _roleRepo.CountActivePermissionIdsAsnyc(role.Permissions);
if (permissionCount != role.Permissions.Count)
{
errors.AddItem("permission", $"Some of the permissions are invalid.");
}

return errors;
}

public async Task<Dictionary<string, List<string>>> UpdateRoleAsync(RoleUpdateDto role)
{
var errors = await ValidateRoleDtoAsync(role);

if (!await _roleRepo.DoesRoleCdExist(role.UserRoleCd))
{
errors.AddItem("userRoleCd", $"Role Code [{role.UserRoleCd}] not found.");
}

if (errors.Count > 0)
{
return errors;
}

await _roleRepo.UpdateRoleAsync(role);

_unitOfWork.Commit();

return errors;
}

public async Task<Dictionary<string, List<string>>> DeleteRoleAsync(string roleCd)
{
var errors = new Dictionary<string, List<string>>();

var role = await _roleRepo.GetRoleAync(roleCd);

if (role == null)
{
errors.AddItem("userRoleCd", $"Role Code [{roleCd}] not found.");
return errors;
}

if (role.IsReferenced)
{
errors.AddItem("userRoleCd", $"Role Code [{roleCd}] is assigned to users and cannot be deleted.");
}

if (errors.Count > 0)
{
return errors;
}

await _roleRepo.DeleteRoleAsync(roleCd);

_unitOfWork.Commit();

return errors;
}
}
}
30 changes: 30 additions & 0 deletions server/StrDss.Service/RoleValidationRule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using StrDss.Common;

namespace StrDss.Service
{
public class RoleValidationRule
{
public static void LoadReportValidationRules(List<FieldValidationRule> rules)
{
rules.Add(new FieldValidationRule
{
EntityName = Entities.Role,
FieldName = RoleFields.UserRoleCd,
FieldType = FieldTypes.String,
Required = true,
MaxLength = 25,
MinLength = 1,
});

rules.Add(new FieldValidationRule
{
EntityName = Entities.Role,
FieldName = RoleFields.UserRoleNm,
FieldType = FieldTypes.String,
Required = true,
MaxLength = 250,
MinLength = 1,
});
}
}
}

0 comments on commit 51da0e0

Please sign in to comment.