diff --git a/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs b/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs index 2bb32493..ea08a45b 100644 --- a/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs +++ b/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs @@ -55,7 +55,6 @@ public OperatingSystemItemController( #endregion #region Endpoints - // TODO: Limit based on role and tenant. /// /// /// @@ -64,6 +63,7 @@ public OperatingSystemItemController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Operating System Item" })] + [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -87,7 +87,6 @@ public IActionResult Find() } } - // TODO: Limit based on role and tenant. /// /// /// diff --git a/src/api/Areas/Dashboard/Controllers/OrganizationController.cs b/src/api/Areas/Dashboard/Controllers/OrganizationController.cs index a699df48..8cdaa7dd 100644 --- a/src/api/Areas/Dashboard/Controllers/OrganizationController.cs +++ b/src/api/Areas/Dashboard/Controllers/OrganizationController.cs @@ -51,15 +51,16 @@ public OrganizationController( #endregion #region Endpoints - // TODO: Limit based on role and tenant. /// - /// + /// Find all organizations that match the specified query filter. + /// Only returns organizations the current user has access to. /// /// [HttpGet(Name = "GetOrganizations-Dashboard")] [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Organization" })] + [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -69,7 +70,7 @@ public IActionResult Find() var isHSB = this.User.HasClientRole(ClientRole.HSB); if (isHSB) { - var result = _service.Find(filter.GeneratePredicate(), filter.Sort); + var result = _service.Find(filter); return new JsonResult(result.Select(o => new OrganizationModel(o))); } else @@ -78,14 +79,13 @@ public IActionResult Find() var user = _authorization.GetUser(); if (user == null) return Forbid(); - var result = _service.FindForUser(user.Id, filter.GeneratePredicate(), filter.Sort); + var result = _service.FindForUser(user.Id, filter); return new JsonResult(result.Select(o => new OrganizationModel(o))); } } - // TODO: Limit based on role and tenant. /// - /// + /// Get the organization for the specified 'id'. /// /// /// @@ -109,7 +109,7 @@ public IActionResult GetForId(int id) var user = _authorization.GetUser(); if (user == null) return Forbid(); - var entity = _service.FindForUser(user.Id, (o) => o.Id == id, o => o.Id).FirstOrDefault(); + var entity = _service.FindForUser(user.Id, new HSB.Models.Filters.OrganizationFilter() { Id = id }).FirstOrDefault(); if (entity == null) return Forbid(); return new JsonResult(new OrganizationModel(entity)); } diff --git a/src/api/Areas/Dashboard/Controllers/ServerItemController.cs b/src/api/Areas/Dashboard/Controllers/ServerItemController.cs index f605bf79..7d4cf905 100644 --- a/src/api/Areas/Dashboard/Controllers/ServerItemController.cs +++ b/src/api/Areas/Dashboard/Controllers/ServerItemController.cs @@ -67,6 +67,7 @@ public ServerItemController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Server Item" })] + [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); diff --git a/src/api/Areas/Dashboard/Controllers/TenantController.cs b/src/api/Areas/Dashboard/Controllers/TenantController.cs index 6698a1c0..a857de41 100644 --- a/src/api/Areas/Dashboard/Controllers/TenantController.cs +++ b/src/api/Areas/Dashboard/Controllers/TenantController.cs @@ -51,7 +51,6 @@ public TenantController( #endregion #region Endpoints - // TODO: Limit based on role and tenant. /// /// /// @@ -60,6 +59,7 @@ public TenantController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Tenant" })] + [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -83,7 +83,6 @@ public IActionResult Find() } } - // TODO: Limit based on role and tenant. /// /// /// diff --git a/src/api/Program.cs b/src/api/Program.cs index 6d2734a9..d9993941 100644 --- a/src/api/Program.cs +++ b/src/api/Program.cs @@ -72,7 +72,8 @@ public static void Main(string[] args) .AllowAnyMethod(); ; }); } - }); + }) + .AddResponseCaching(); var app = builder.Build(); @@ -93,6 +94,7 @@ public static void Main(string[] args) app.UseCors("CorsPolicy"); app.UseMiddleware(typeof(LogRequestMiddleware)); + app.UseResponseCaching(); app.UseAuthentication(); app.UseAuthorization(); diff --git a/src/libs/dal/Services/IOrganizationService.cs b/src/libs/dal/Services/IOrganizationService.cs index bb7358f6..6222e667 100644 --- a/src/libs/dal/Services/IOrganizationService.cs +++ b/src/libs/dal/Services/IOrganizationService.cs @@ -4,17 +4,10 @@ namespace HSB.DAL.Services; public interface IOrganizationService : IBaseService { - IEnumerable FindForUser( - long userId, - System.Linq.Expressions.Expression> predicate, - System.Linq.Expressions.Expression>? sort = null, - int? take = null, - int? skip = null); + IEnumerable Find( + Models.Filters.OrganizationFilter filter); - public IEnumerable FindForUser( + IEnumerable FindForUser( long userId, - System.Linq.Expressions.Expression> predicate, - string[] sort, - int? take = null, - int? skip = null); + Models.Filters.OrganizationFilter filter); } diff --git a/src/libs/dal/Services/OrganizationService.cs b/src/libs/dal/Services/OrganizationService.cs index c34d63d1..b9e946d4 100644 --- a/src/libs/dal/Services/OrganizationService.cs +++ b/src/libs/dal/Services/OrganizationService.cs @@ -18,26 +18,21 @@ public OrganizationService(HSBContext dbContext, ClaimsPrincipal principal, ISer #endregion #region Methods - public IEnumerable FindForUser( - long userId, - System.Linq.Expressions.Expression> predicate, - System.Linq.Expressions.Expression>? sort = null, - int? take = null, - int? skip = null) + public IEnumerable Find( + Models.Filters.OrganizationFilter filter) { var query = (from org in this.Context.Organizations - join uo in this.Context.UserOrganizations on org.Id equals uo.OrganizationId - where uo.UserId == userId select org) - .Where(predicate) + .Where(filter.GeneratePredicate()) .Distinct(); - if (sort != null) - query = query.OrderBy(sort); - if (take.HasValue) - query = query.Take(take.Value); - if (skip.HasValue) - query = query.Skip(skip.Value); + if (filter.Sort?.Any() == true) + query = query.OrderByProperty(filter.Sort); + else query = query.OrderBy(si => si.Name); + if (filter.Quantity.HasValue) + query = query.Take(filter.Quantity.Value); + if (filter.Page.HasValue && filter.Quantity.HasValue && filter.Page > 1) + query = query.Skip(filter.Page.Value * filter.Quantity.Value); return query .AsNoTracking() @@ -46,25 +41,29 @@ join uo in this.Context.UserOrganizations on org.Id equals uo.OrganizationId public IEnumerable FindForUser( long userId, - System.Linq.Expressions.Expression> predicate, - string[] sort, - int? take = null, - int? skip = null) + Models.Filters.OrganizationFilter filter) { + var userOrganizationQuery = from uo in this.Context.UserOrganizations + where uo.UserId == userId + select uo.OrganizationId; + var tenantOrganizationQuery = from tOrg in this.Context.TenantOrganizations + join ut in this.Context.UserTenants on tOrg.TenantId equals ut.TenantId + where ut.UserId == userId + select tOrg.OrganizationId; var query = (from org in this.Context.Organizations - join uo in this.Context.UserOrganizations on org.Id equals uo.OrganizationId - where uo.UserId == userId + where userOrganizationQuery.Contains(org.Id) || tenantOrganizationQuery.Contains(org.Id) select org) - .Where(predicate) + .Where(filter.GeneratePredicate()) .Distinct(); - if (sort?.Any() == true) - query = query.OrderByProperty(sort); - if (take.HasValue) - query = query.Take(take.Value); - if (skip.HasValue) - query = query.Skip(skip.Value); + if (filter.Sort?.Any() == true) + query = query.OrderByProperty(filter.Sort); + else query = query.OrderBy(si => si.Name); + if (filter.Quantity.HasValue) + query = query.Take(filter.Quantity.Value); + if (filter.Page.HasValue && filter.Quantity.HasValue && filter.Page > 1) + query = query.Skip(filter.Page.Value * filter.Quantity.Value); return query .AsNoTracking() diff --git a/src/libs/dal/Services/TenantService.cs b/src/libs/dal/Services/TenantService.cs index 5c2ba1a7..05955944 100644 --- a/src/libs/dal/Services/TenantService.cs +++ b/src/libs/dal/Services/TenantService.cs @@ -5,7 +5,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using HSB.DAL.Extensions; -using System.Linq.Expressions; namespace HSB.DAL.Services; @@ -27,8 +26,8 @@ public IEnumerable FindForUser( int? skip = null) { var query = (from t in this.Context.Tenants - join usert in this.Context.UserTenants on t.Id equals usert.TenantId - where usert.UserId == userId + join ut in this.Context.UserTenants on t.Id equals ut.TenantId + where ut.UserId == userId select t) .Where(predicate); @@ -52,8 +51,8 @@ public IEnumerable FindForUser( int? skip = null) { var query = (from t in this.Context.Tenants - join usert in this.Context.UserTenants on t.Id equals usert.TenantId - where usert.UserId == userId + join ut in this.Context.UserTenants on t.Id equals ut.TenantId + where ut.UserId == userId select t) .Where(predicate); diff --git a/src/libs/models/Filters/OrganizationFilter.cs b/src/libs/models/Filters/OrganizationFilter.cs index a3e47fe0..905d9884 100644 --- a/src/libs/models/Filters/OrganizationFilter.cs +++ b/src/libs/models/Filters/OrganizationFilter.cs @@ -7,6 +7,7 @@ namespace HSB.Models.Filters; public class OrganizationFilter : PageFilter { #region Properties + public int? Id { get; set; } public string? Name { get; set; } public bool? IsEnabled { get; set; } @@ -29,6 +30,7 @@ public OrganizationFilter(Dictionary(queryParams, StringComparer.OrdinalIgnoreCase); + this.Id = filter.GetIntNullValue(nameof(this.Id)); this.Name = filter.GetStringValue(nameof(this.Name)); this.IsEnabled = filter.GetBoolNullValue(nameof(this.IsEnabled)); this.ServiceNowKey = filter.GetStringValue(nameof(this.ServiceNowKey)); @@ -45,6 +47,8 @@ public OrganizationFilter(Dictionary GeneratePredicate() { var predicate = PredicateBuilder.New(); + if (this.Id != null) + predicate = predicate.And((u) => u.Id == this.Id); if (this.Name != null) predicate = predicate.And((u) => EF.Functions.Like(u.Name, $"%{this.Name}%")); if (this.IsEnabled != null)