diff --git a/server/AyaNova/Controllers/DataListController.cs b/server/AyaNova/Controllers/DataListController.cs index a6ce3f1f..c34448ed 100644 --- a/server/AyaNova/Controllers/DataListController.cs +++ b/server/AyaNova/Controllers/DataListController.cs @@ -8,8 +8,6 @@ using AyaNova.Biz; using AyaNova.DataList; using System.Threading.Tasks; using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using EnumsNET; namespace AyaNova.Api.Controllers diff --git a/server/AyaNova/Controllers/ExportController.cs b/server/AyaNova/Controllers/ExportController.cs index a8a8b3a0..d3543717 100644 --- a/server/AyaNova/Controllers/ExportController.cs +++ b/server/AyaNova/Controllers/ExportController.cs @@ -47,10 +47,10 @@ namespace AyaNova.Api.Controllers /// Export to file /// /// Valid values are: "csv","json" - /// + /// /// downloadable export file name [HttpPost("render/{format}")] - public async Task RenderExport([FromRoute] string format, [FromBody] DataListSelectedProcessingOptions dataListSelection) + public async Task RenderExport([FromRoute] string format, [FromBody] DataListSelectedRequest selectedRequest) { if (!serverState.IsOpen) @@ -58,10 +58,10 @@ namespace AyaNova.Api.Controllers if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - if (dataListSelection.IsEmpty) + if (selectedRequest.IsEmpty) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "DataListSelection is required")); - if (!Authorized.HasReadFullRole(HttpContext.Items, dataListSelection.ObjectType)) + if (!Authorized.HasReadFullRole(HttpContext.Items, selectedRequest.ObjectType)) return StatusCode(403, new ApiNotAuthorizedResponse()); if (string.IsNullOrWhiteSpace(format)) @@ -70,17 +70,17 @@ namespace AyaNova.Api.Controllers if (format != "csv" && format != "json") return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, "format not valid, must be 'csv' or 'json'")); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); - if (dataListSelection.SelectedRowIds.Length == 0) + await selectedRequest.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); + if (selectedRequest.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); - log.LogDebug($"Instantiating biz object handler for {dataListSelection.ObjectType}"); - var biz = BizObjectFactory.GetBizObject(dataListSelection.ObjectType, ct); - log.LogDebug($"Fetching data for {dataListSelection.SelectedRowIds.Length} {dataListSelection.ObjectType} items"); + log.LogDebug($"Instantiating biz object handler for {selectedRequest.ObjectType}"); + var biz = BizObjectFactory.GetBizObject(selectedRequest.ObjectType, ct); + log.LogDebug($"Fetching data for {selectedRequest.SelectedRowIds.Length} {selectedRequest.ObjectType} items"); // var TheData = await ((IExportAbleObject)biz).GetJSONExportData(dataListSelection.SelectedRowIds); - string baseFileName = FileUtil.StringToSafeFileName($"{dataListSelection.ObjectType.ToString().ToLowerInvariant()}-{format}-{FileUtil.GetSafeDateFileName()}"); + string baseFileName = FileUtil.StringToSafeFileName($"{selectedRequest.ObjectType.ToString().ToLowerInvariant()}-{format}-{FileUtil.GetSafeDateFileName()}"); // string outputRandomFileNameNoExtension = StringUtil.ReplaceLastOccurrence(FileUtil.NewRandomFileName, ".", ""); string outputSourceFileName = baseFileName + "." + format; @@ -93,7 +93,7 @@ namespace AyaNova.Api.Controllers case "csv": using (var w = new ChoCSVWriter(outputSourceFullPath).WithFirstLineHeader()) { - var dat = await ((IExportAbleObject)biz).GetExportData(dataListSelection.SelectedRowIds); + var dat = await ((IExportAbleObject)biz).GetExportData(selectedRequest.SelectedRowIds); w.Write(ToDynamicList(dat)); } break; @@ -101,7 +101,7 @@ namespace AyaNova.Api.Controllers using (StreamWriter file = System.IO.File.CreateText(outputSourceFullPath)) using (JsonTextWriter writer = new JsonTextWriter(file)) { - var dat = await ((IExportAbleObject)biz).GetExportData(dataListSelection.SelectedRowIds); + var dat = await ((IExportAbleObject)biz).GetExportData(selectedRequest.SelectedRowIds); dat.WriteTo(writer); } break; diff --git a/server/AyaNova/Controllers/JobOperationsController.cs b/server/AyaNova/Controllers/JobOperationsController.cs index d508848a..73671683 100644 --- a/server/AyaNova/Controllers/JobOperationsController.cs +++ b/server/AyaNova/Controllers/JobOperationsController.cs @@ -193,37 +193,37 @@ namespace AyaNova.Api.Controllers /// /// Batch DELETE list of object id's specified /// - /// + /// /// Job Id [HttpPost("batch-delete")] - public async Task BatchDeleteObjects([FromBody] DataListSelectedProcessingOptions dataListSelection) + public async Task BatchDeleteObjects([FromBody] DataListSelectedRequest selectedRequest) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - if (dataListSelection.IsEmpty) + if (selectedRequest.IsEmpty) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "DataListSelection is required")); - if (!Authorized.HasDeleteRole(HttpContext.Items, dataListSelection.ObjectType)) + if (!Authorized.HasDeleteRole(HttpContext.Items, selectedRequest.ObjectType)) return StatusCode(403, new ApiNotAuthorizedResponse()); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); - if (dataListSelection.SelectedRowIds.Length == 0) + await selectedRequest.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); + if (selectedRequest.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); - var JobName = $"LT:BatchDeleteJob - LT:{dataListSelection.ObjectType} ({dataListSelection.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}"; + var JobName = $"LT:BatchDeleteJob - LT:{selectedRequest.ObjectType} ({selectedRequest.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}"; JObject o = JObject.FromObject(new { - idList = dataListSelection.SelectedRowIds + idList = selectedRequest.SelectedRowIds }); OpsJob j = new OpsJob(); j.Name = JobName; - j.ObjectType = dataListSelection.ObjectType; + j.ObjectType = selectedRequest.ObjectType; j.JobType = JobType.BatchCoreObjectOperation; j.SubType = JobSubType.Delete; j.Exclusive = false; diff --git a/server/AyaNova/Controllers/ReportController.cs b/server/AyaNova/Controllers/ReportController.cs index c475194c..6729a0c6 100644 --- a/server/AyaNova/Controllers/ReportController.cs +++ b/server/AyaNova/Controllers/ReportController.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -14,6 +13,8 @@ using AyaNova.Biz; using AyaNova.Util; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using EnumsNET; +using AyaNova.DataList; namespace AyaNova.Api.Controllers { @@ -184,18 +185,45 @@ namespace AyaNova.Api.Controllers /// /// Get data from id list in format used by report designer /// - /// Data required for report + /// Data required for report /// From route path /// [HttpPost("data")] - public async Task GetReportData([FromBody] DataListSelectedProcessingOptions reportDataParam, ApiVersion apiVersion) + public async Task GetReportData([FromBody] DataListSelectedRequest selectedRequest, ApiVersion apiVersion) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); ReportBiz biz = ReportBiz.GetBiz(ct, HttpContext); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - var reportData = await biz.GetReportData(reportDataParam); + + + //------------------------------- + var UserRoles = UserRolesFromContext.Roles(HttpContext.Items); + var UserId = UserIdFromContext.Id(HttpContext.Items); + DataListSavedColumnViewBiz viewbiz = DataListSavedColumnViewBiz.GetBiz(ct, HttpContext); + var SavedView = await viewbiz.GetAsync(UserId, selectedRequest.DataListKey, true); + + DataListSavedFilter SavedFilter = null; + if (selectedRequest.FilterId != 0) + { + DataListSavedFilterBiz filterbiz = DataListSavedFilterBiz.GetBiz(ct, HttpContext); + SavedFilter = await filterbiz.GetAsync(selectedRequest.FilterId, false); + } + var DataList = DataListFactory.GetAyaDataList(selectedRequest.DataListKey); + if (DataList == null) + return BadRequest(new ApiErrorResponse(ApiErrorCode.NOT_FOUND, "DataListKey", $"DataList \"{selectedRequest.DataListKey}\" specified does not exist")); + + //check rights + if (!UserRoles.HasAnyFlags(DataList.AllowedRoles)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + + //hydrate the saved view and filter + DataListSelectedProcessingOptions dataListSelectedOptions = new DataListSelectedProcessingOptions(selectedRequest, DataList, SavedView, SavedFilter, UserId, UserRoles); + //------------------------ + + + var reportData = await biz.GetReportData(dataListSelectedOptions); if (reportData == null) return BadRequest(new ApiErrorResponse(biz.Errors)); else @@ -206,11 +234,11 @@ namespace AyaNova.Api.Controllers /// /// Render Report /// - /// report id and object id values for object type specified in report template + /// report id and object id values for object type specified in report template /// From route path /// downloadable pdf name [HttpPost("render")] - public async Task RenderReport([FromBody] DataListReportProcessingOptions reportParam, ApiVersion apiVersion) + public async Task RenderReport([FromBody] DataListReportRequest reportRequest, ApiVersion apiVersion) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); @@ -224,7 +252,7 @@ namespace AyaNova.Api.Controllers var API_URL = $"http://127.0.0.1:{httpConnectionFeature.LocalPort}/api/v8/"; try { - var result = await biz.RenderReport(reportParam, API_URL); + var result = await biz.RenderReport(reportRequest, API_URL); if (string.IsNullOrWhiteSpace(result)) return BadRequest(new ApiErrorResponse(biz.Errors)); diff --git a/server/AyaNova/Controllers/TagController.cs b/server/AyaNova/Controllers/TagController.cs index d357f4ac..67abfe33 100644 --- a/server/AyaNova/Controllers/TagController.cs +++ b/server/AyaNova/Controllers/TagController.cs @@ -80,43 +80,43 @@ namespace AyaNova.Api.Controllers /// Batch add tags to list of object id's specified /// /// - /// + /// /// Job Id [HttpPost("batch-add/{tag}")] - public async Task BatchAdd([FromRoute] string tag, [FromBody] DataListSelectedProcessingOptions dataListSelection) + public async Task BatchAdd([FromRoute] string tag, [FromBody] DataListSelectedRequest selectedRequest) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - if (dataListSelection.IsEmpty) + if (selectedRequest.IsEmpty) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "DataListSelection is required")); - if (!dataListSelection.ObjectType.HasAttribute(typeof(CoreBizObjectAttribute))) + if (!selectedRequest.ObjectType.HasAttribute(typeof(CoreBizObjectAttribute))) return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Not a taggable object type")); - if (!Authorized.HasModifyRole(HttpContext.Items, dataListSelection.ObjectType)) + if (!Authorized.HasModifyRole(HttpContext.Items, selectedRequest.ObjectType)) return StatusCode(403, new ApiNotAuthorizedResponse()); tag = TagBiz.NormalizeTag(tag); if (string.IsNullOrWhiteSpace(tag)) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "tag required")); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); - if (dataListSelection.SelectedRowIds.Length == 0) + await selectedRequest.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); + if (selectedRequest.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); - var JobName = $"LT:BatchJob LT:Add LT:Tag \"{tag}\" LT:{dataListSelection.ObjectType} ({dataListSelection.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}"; + var JobName = $"LT:BatchJob LT:Add LT:Tag \"{tag}\" LT:{selectedRequest.ObjectType} ({selectedRequest.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}"; JObject o = JObject.FromObject(new { - idList = dataListSelection.SelectedRowIds, + idList = selectedRequest.SelectedRowIds, tag = tag }); OpsJob j = new OpsJob(); j.Name = JobName; - j.ObjectType = dataListSelection.ObjectType; + j.ObjectType = selectedRequest.ObjectType; j.JobType = JobType.BatchCoreObjectOperation; j.SubType = JobSubType.TagAdd; j.Exclusive = false; @@ -170,43 +170,43 @@ namespace AyaNova.Api.Controllers /// Batch remove tags to list of object id's specified /// /// - /// + /// /// Job Id [HttpPost("batch-remove/{tag}")] - public async Task BatchRemove([FromRoute] string tag, [FromBody] DataListSelectedProcessingOptions dataListSelection) + public async Task BatchRemove([FromRoute] string tag, [FromBody] DataListSelectedRequest selectedRequest) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - if (dataListSelection.IsEmpty) + if (selectedRequest.IsEmpty) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "DataListSelection is required")); - if (!dataListSelection.ObjectType.HasAttribute(typeof(CoreBizObjectAttribute))) + if (!selectedRequest.ObjectType.HasAttribute(typeof(CoreBizObjectAttribute))) return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Not a taggable object type")); - if (!Authorized.HasModifyRole(HttpContext.Items, dataListSelection.ObjectType)) + if (!Authorized.HasModifyRole(HttpContext.Items, selectedRequest.ObjectType)) return StatusCode(403, new ApiNotAuthorizedResponse()); tag = TagBiz.NormalizeTag(tag); if (string.IsNullOrWhiteSpace(tag)) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "tag")); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); - if (dataListSelection.SelectedRowIds.Length == 0) + await selectedRequest.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); + if (selectedRequest.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); - var JobName = $"LT:BatchJob LT:Remove LT:Tag \"{tag}\" LT:{dataListSelection.ObjectType} ({dataListSelection.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}"; + var JobName = $"LT:BatchJob LT:Remove LT:Tag \"{tag}\" LT:{selectedRequest.ObjectType} ({selectedRequest.SelectedRowIds.LongLength}) LT:User {UserNameFromContext.Name(HttpContext.Items)}"; JObject o = JObject.FromObject(new { - idList = dataListSelection.SelectedRowIds, + idList = selectedRequest.SelectedRowIds, tag = tag }); OpsJob j = new OpsJob(); j.Name = JobName; - j.ObjectType = dataListSelection.ObjectType; + j.ObjectType = selectedRequest.ObjectType; j.JobType = JobType.BatchCoreObjectOperation; j.SubType = JobSubType.TagRemove; j.Exclusive = false; @@ -266,7 +266,7 @@ namespace AyaNova.Api.Controllers /// /// Job Id [HttpPost("batch-replace/{fromTag}")] - public async Task BatchReplace([FromRoute] string fromTag, [FromQuery] string toTag, [FromBody] DataListSelectedProcessingOptions dataListSelection) + public async Task BatchReplace([FromRoute] string fromTag, [FromQuery] string toTag, [FromBody] DataListSelectedRequest dataListSelection) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); diff --git a/server/AyaNova/DataList/DataListFetcher.cs b/server/AyaNova/DataList/DataListFetcher.cs index 5eadd287..f78cfe41 100644 --- a/server/AyaNova/DataList/DataListFetcher.cs +++ b/server/AyaNova/DataList/DataListFetcher.cs @@ -236,13 +236,12 @@ namespace AyaNova.DataList // Get a list of id's of the datalist results for reporting // // - //internal static async Task GetIdListResponseAsync(string dataListKey, string listView, string metaListView, AyContext ct, AuthorizationRoles userRoles, ILogger log, long userId) - internal static async Task GetIdListResponseAsync(AyContext ct, DataListSelectedProcessingOptions dataListSelectionOptions, AuthorizationRoles userRoles, ILogger log, long userId) + internal static async Task GetIdListResponseAsync(AyContext ct, DataListSelectedProcessingOptions dataListSelectionOptions,IDataListProcessing DataList, AuthorizationRoles userRoles, ILogger log, long userId) { - var DataList = DataListFactory.GetAyaDataList(dataListSelectionOptions.DataListKey); - //was the name not found as a list? - if (DataList == null) - throw new System.ArgumentOutOfRangeException($"DataList \"{dataListSelectionOptions.DataListKey}\" specified does not exist"); + // var DataList = DataListFactory.GetAyaDataList(dataListSelectionOptions.DataListKey); + // //was the name not found as a list? + // if (DataList == null) + // throw new System.ArgumentOutOfRangeException($"DataList \"{dataListSelectionOptions.DataListKey}\" specified does not exist"); diff --git a/server/AyaNova/models/DataListSelectedProcessingOptions.cs b/server/AyaNova/models/DataListSelectedProcessingOptions.cs index 95f4e495..3cea481e 100644 --- a/server/AyaNova/models/DataListSelectedProcessingOptions.cs +++ b/server/AyaNova/models/DataListSelectedProcessingOptions.cs @@ -22,7 +22,7 @@ namespace AyaNova.Models } } -TODO: recode this to fulfil requirements of datalistfetcher in the same way as +///TODO: recode this to fulfil requirements of datalistfetcher in the same way as //DataListTableProcessingOptions constructor //clean out datalistfetcher comments and similar afterwards public async Task RehydrateIdList(AyContext ct, AuthorizationRoles userRoles, Microsoft.Extensions.Logging.ILogger log, long userId) @@ -32,3 +32,41 @@ TODO: recode this to fulfil requirements of datalistfetcher in the same way as } } } + +/* + internal DataListTableProcessingOptions( + DataListTableRequest request, + IDataListProcessing dataList, + DataListSavedColumnView savedView, + DataListSavedFilter savedFilter, + long userId, + AuthorizationRoles userRoles) + { + //set some values from request + Limit = request.Limit; + Offset = request.Offset; + base.ClientCriteria = request.ClientCriteria; + base.DataListKey = request.DataListKey; + + //SET COLUMNS + Columns = JsonConvert.DeserializeObject>(savedView.Columns); + + //SET SORTBY + base.SortBy = JsonConvert.DeserializeObject>(savedView.Sort); + + //SET FILTER + if (request.FilterId != 0 && savedFilter != null) + base.Filter = JsonConvert.DeserializeObject>(savedFilter.Filter); + + //ADD STATIC SERVER FILTERS + List StaticServerFilterOptions = new List(); + if (dataList is IDataListInternalCriteria) + StaticServerFilterOptions = ((IDataListInternalCriteria)dataList).DataListInternalCriteria(userId, userRoles, request.ClientCriteria); + + //Add the internal filters into the listoptions existing filters + //NOTE: There is currently no overlap between internal filtered columns and filters coming from the client + foreach (DataListFilterOption dfo in StaticServerFilterOptions) + base.Filter.Add(dfo); + + } +*/ \ No newline at end of file diff --git a/server/AyaNova/models/DataListSelectedRequest.cs b/server/AyaNova/models/DataListSelectedRequest.cs index df1636f3..a17f3a03 100644 --- a/server/AyaNova/models/DataListSelectedRequest.cs +++ b/server/AyaNova/models/DataListSelectedRequest.cs @@ -3,7 +3,7 @@ namespace AyaNova.Models { //Request version of selection request used by report and bulk ops //handles posts from client - public class DataListSelectedRequest : DataListProcessingBase + public class DataListSelectedRequest : DataListRequestBase { public AyaType ObjectType { get; set; } public long[] SelectedRowIds { get; set; }