From f65a24e2720a6cd1d2740781374faad972abb8e6 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Sat, 12 Dec 2020 01:16:34 +0000 Subject: [PATCH] --- .../AyaNova/Controllers/DataListController.cs | 3 +- .../AyaNova/Controllers/ExportController.cs | 2 +- .../Controllers/JobOperationsController.cs | 2 +- server/AyaNova/Controllers/TagController.cs | 6 +- server/AyaNova/DataList/AyaDataList.cs | 4 +- server/AyaNova/DataList/DataListFetcher.cs | 30 ++++++- server/AyaNova/DataList/IAyaDataList.cs | 6 ++ .../DataList/IAyaDataListExtraCriteria.cs | 9 ++ server/AyaNova/DataList/MemoDataList.cs | 89 +++++++++++++++++++ server/AyaNova/biz/BizRoles.cs | 2 +- server/AyaNova/biz/ReportBiz.cs | 2 +- .../AyaNova/models/dto/DataListSelection.cs | 4 +- server/AyaNova/util/AySchema.cs | 4 +- 13 files changed, 148 insertions(+), 15 deletions(-) create mode 100644 server/AyaNova/DataList/IAyaDataListExtraCriteria.cs create mode 100644 server/AyaNova/DataList/MemoDataList.cs diff --git a/server/AyaNova/Controllers/DataListController.cs b/server/AyaNova/Controllers/DataListController.cs index 073e9d8c..fc3636af 100644 --- a/server/AyaNova/Controllers/DataListController.cs +++ b/server/AyaNova/Controllers/DataListController.cs @@ -70,10 +70,11 @@ namespace AyaNova.Api.Controllers return BadRequest(new ApiErrorResponse(ModelState)); var UserRoles = UserRolesFromContext.Roles(HttpContext.Items); + var UserId = UserIdFromContext.Id(HttpContext.Items); try { - ApiDataListResponse r = await DataListFetcher.GetResponseAsync(listOptions.DataListKey, ct, listOptions, UserRoles, log); + ApiDataListResponse r = await DataListFetcher.GetResponseAsync(listOptions.DataListKey, ct, listOptions, UserRoles, log, UserId); return Ok(r); } catch (System.UnauthorizedAccessException) diff --git a/server/AyaNova/Controllers/ExportController.cs b/server/AyaNova/Controllers/ExportController.cs index 77b022cf..1d38d68e 100644 --- a/server/AyaNova/Controllers/ExportController.cs +++ b/server/AyaNova/Controllers/ExportController.cs @@ -70,7 +70,7 @@ 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); + await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); if (dataListSelection.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); diff --git a/server/AyaNova/Controllers/JobOperationsController.cs b/server/AyaNova/Controllers/JobOperationsController.cs index 552f81d3..026337f3 100644 --- a/server/AyaNova/Controllers/JobOperationsController.cs +++ b/server/AyaNova/Controllers/JobOperationsController.cs @@ -211,7 +211,7 @@ namespace AyaNova.Api.Controllers return StatusCode(403, new ApiNotAuthorizedResponse()); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log); + await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); if (dataListSelection.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); diff --git a/server/AyaNova/Controllers/TagController.cs b/server/AyaNova/Controllers/TagController.cs index 1e910da1..8581adb6 100644 --- a/server/AyaNova/Controllers/TagController.cs +++ b/server/AyaNova/Controllers/TagController.cs @@ -103,7 +103,7 @@ namespace AyaNova.Api.Controllers if (string.IsNullOrWhiteSpace(tag)) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "tag required")); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log); + await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); if (dataListSelection.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); @@ -192,7 +192,7 @@ namespace AyaNova.Api.Controllers if (string.IsNullOrWhiteSpace(tag)) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "tag")); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log); + await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); if (dataListSelection.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); @@ -284,7 +284,7 @@ namespace AyaNova.Api.Controllers toTag = TagBiz.NormalizeTag(toTag); if (string.IsNullOrWhiteSpace(toTag)) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "toTag")); - await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log); + await dataListSelection.RehydrateIdList(ct, UserRolesFromContext.Roles(HttpContext.Items), log, UserIdFromContext.Id(HttpContext.Items)); if (dataListSelection.SelectedRowIds.Length == 0) return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_REQUIRED, null, "List of ids")); diff --git a/server/AyaNova/DataList/AyaDataList.cs b/server/AyaNova/DataList/AyaDataList.cs index a41682ed..cb946351 100644 --- a/server/AyaNova/DataList/AyaDataList.cs +++ b/server/AyaNova/DataList/AyaDataList.cs @@ -16,7 +16,7 @@ namespace AyaNova.DataList //CoreBizObject add here //well, not here exactly but add a new DATALIST class if it will be displayed as a list anywhere in the UI or reported on public AyaDataList() - { + { } @@ -26,6 +26,8 @@ namespace AyaNova.DataList public AyaType DefaultListObjectType { get; set; } public string DefaultListView { get; set; } + public string AdditionalCriteriaInternalListView { get; set; } + public long CurrentUserId { get; set; } //return array of field keys in list view diff --git a/server/AyaNova/DataList/DataListFetcher.cs b/server/AyaNova/DataList/DataListFetcher.cs index ab90853c..936e5467 100644 --- a/server/AyaNova/DataList/DataListFetcher.cs +++ b/server/AyaNova/DataList/DataListFetcher.cs @@ -18,7 +18,7 @@ namespace AyaNova.DataList // Get the data list data requested // // - internal static async Task GetResponseAsync(string DataListKey, AyContext ct, ListOptions listOptions, AuthorizationRoles UserRoles, ILogger log) + internal static async Task GetResponseAsync(string DataListKey, AyContext ct, ListOptions listOptions, AuthorizationRoles UserRoles, ILogger log, long userId) { var DataList = DataListFactory.GetAyaDataList(DataListKey); @@ -27,6 +27,7 @@ namespace AyaNova.DataList if (DataList == null) throw new System.ArgumentOutOfRangeException($"DataList \"{DataListKey}\" specified does not exist"); + //check rights if (!UserRoles.HasAnyFlags(DataList.AllowedRoles)) throw new System.UnauthorizedAccessException("User roles insufficient for this datalist"); @@ -39,8 +40,20 @@ namespace AyaNova.DataList //This one is for the return list to the Client for grid column display var PublicListViewArray = JArray.Parse(listOptions.ListView); + + //this one is for internal use here to build the filter and sort etc var InternalListViewArray = JArray.Parse(listOptions.ListView); + + //Hard coded extra criteria from server end + if (DataList is IAyaDataListViewServerCriteria) + { + var ServerCriteriaListView = ((IAyaDataListViewServerCriteria)DataList).ListViewServerCriteria(userId); + foreach (JToken jt in ServerCriteriaListView) + InternalListViewArray.Add(jt); + } + + //Hard coded extra criteria from Client end var MetaListViewArray = JArray.Parse(listOptions.MetaView ?? "[]"); foreach (JToken jt in MetaListViewArray) InternalListViewArray.Add(jt); @@ -216,13 +229,15 @@ 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) + internal static async Task GetIdListResponseAsync(string dataListKey, string listView, string metaListView, AyContext ct, AuthorizationRoles userRoles, ILogger log, long userId) { var DataList = DataListFactory.GetAyaDataList(dataListKey); //was the name not found as a list? if (DataList == null) throw new System.ArgumentOutOfRangeException($"DataList \"{dataListKey}\" specified does not exist"); + + //check rights if (!userRoles.HasAnyFlags(DataList.AllowedRoles)) throw new System.UnauthorizedAccessException("User roles insufficient for this datalist"); @@ -234,6 +249,17 @@ namespace AyaNova.DataList //parse the list view var ListViewArray = JArray.Parse(listView); + + //Hard coded extra criteria from server end + if (DataList is IAyaDataListViewServerCriteria) + { + var ServerCriteriaListView = ((IAyaDataListViewServerCriteria)DataList).ListViewServerCriteria(userId); + foreach (JToken jt in ServerCriteriaListView) + ListViewArray.Add(jt); + } + + //Hard coded extra criteria from Client end + //parse and combine any additional listview hard coded from Client UI var MetaListViewArray = JArray.Parse(metaListView ?? "[]"); foreach (JToken jt in MetaListViewArray) ListViewArray.Add(jt); diff --git a/server/AyaNova/DataList/IAyaDataList.cs b/server/AyaNova/DataList/IAyaDataList.cs index ba8d49d8..f37c9094 100644 --- a/server/AyaNova/DataList/IAyaDataList.cs +++ b/server/AyaNova/DataList/IAyaDataList.cs @@ -21,6 +21,12 @@ namespace AyaNova.DataList //Default / STOCK DataListView when none is specified string DefaultListView { get; set; } + //Additional criteria for security or other reasons + //hard coded into some lists (e.g. MemoDataList so users can't get other people's memos) + // string AdditionalCriteriaInternalListView (long userId); + + + Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(JArray listViewArray); List GetFieldListFromListView(JArray listViewArray); diff --git a/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs b/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs new file mode 100644 index 00000000..9dff8d6a --- /dev/null +++ b/server/AyaNova/DataList/IAyaDataListExtraCriteria.cs @@ -0,0 +1,9 @@ +namespace AyaNova.DataList +{ + internal interface IAyaDataListViewServerCriteria + { + //Additional criteria for security or other reasons + //hard coded into some lists (e.g. MemoDataList so users can't get other people's memos) + string ListViewServerCriteria (long userId); + } +} \ No newline at end of file diff --git a/server/AyaNova/DataList/MemoDataList.cs b/server/AyaNova/DataList/MemoDataList.cs new file mode 100644 index 00000000..40c29773 --- /dev/null +++ b/server/AyaNova/DataList/MemoDataList.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using AyaNova.Biz; +namespace AyaNova.DataList +{ + internal class MemoDataList : AyaDataList,IAyaDataListViewServerCriteria + { + public MemoDataList() + { + + DefaultListObjectType = AyaType.Memo; + SQLFrom = "from amemo left outer join auser on (amemo.fromid=auser.id)"; + var RoleSet = BizRoles.GetRoleSet(DefaultListObjectType); + AllowedRoles = RoleSet.ReadFullRecord | RoleSet.Change; + + + + + //######## DEFAULT VIEW WHEN NO VIEW CHOSEN ############ + //Default ListView + dynamic dlistView = new JArray(); + + + dynamic cm = new JObject(); + cm.fld = "MemoSubject"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "MemoFromID"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "MemoSent"; + dlistView.Add(cm); + DefaultListView = dlistView.ToString(Newtonsoft.Json.Formatting.None); + + + //NOTE: Due to the join, all the sql id and name fields that can conflict with the joined table need to be specified completely + FieldDefinitions = new List(); + + FieldDefinitions.Add(new AyaDataListFieldDefinition + { + TKey = "User", + FieldKey = "username", + AyaObjectType = (int)AyaType.User, + UiFieldDataType = (int)UiFieldDataType.Text, + SqlIdColumnName = "auser.id", + SqlValueColumnName = "auser.name", + IsRowId = false + }); + + + FieldDefinitions.Add(new AyaDataListFieldDefinition + { + TKey = "MemoNotes", + FieldKey = "notes", + AyaObjectType = (int)AyaType.Memo, + UiFieldDataType = (int)UiFieldDataType.Text, + SqlIdColumnName = "amemo.id", + SqlValueColumnName = "amemo.notes", + IsRowId = true + }); + + FieldDefinitions.Add(new AyaDataListFieldDefinition + { + TKey = "MemoNoteDate", + FieldKey = "notedate", + UiFieldDataType = (int)UiFieldDataType.DateTime, + SqlValueColumnName = "amemo.notedate" + }); + + //META column + FieldDefinitions.Add(new AyaDataListFieldDefinition + { + FieldKey = "metacustomer", + SqlIdColumnName = "amemo.customerid", + SqlValueColumnName = "amemo.customerid", + IsMeta = true + }); + } + + string IAyaDataListViewServerCriteria.ListViewServerCriteria(long userId) + { + //todo: take user id here and return additional criteria listview + throw new System.NotImplementedException(); + } + + }//eoc +}//eons \ No newline at end of file diff --git a/server/AyaNova/biz/BizRoles.cs b/server/AyaNova/biz/BizRoles.cs index 56e008c3..d771d1d6 100644 --- a/server/AyaNova/biz/BizRoles.cs +++ b/server/AyaNova/biz/BizRoles.cs @@ -598,7 +598,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////// //MEMO // (everyone but outside users Customer and HO can send and receive memos) - roles.Add(AyaType.Widget, new BizRoleSet() + roles.Add(AyaType.Memo, new BizRoleSet() { Change = AuthorizationRoles.AllInsideUserRoles, ReadFullRecord = AuthorizationRoles.AllInsideUserRoles, diff --git a/server/AyaNova/biz/ReportBiz.cs b/server/AyaNova/biz/ReportBiz.cs index 1bd9477b..79acd3cc 100644 --- a/server/AyaNova/biz/ReportBiz.cs +++ b/server/AyaNova/biz/ReportBiz.cs @@ -331,7 +331,7 @@ namespace AyaNova.Biz //Do we need to rehydrate the ID List from a DataList? if (reportDataParam.SelectedRowIds.Length == 0) - reportDataParam.SelectedRowIds = await AyaNova.DataList.DataListFetcher.GetIdListResponseAsync(reportDataParam.DataListKey, reportDataParam.ListView, reportDataParam.MetaView, ct, effectiveRoles, log); + reportDataParam.SelectedRowIds = await AyaNova.DataList.DataListFetcher.GetIdListResponseAsync(reportDataParam.DataListKey, reportDataParam.ListView, reportDataParam.MetaView, ct, effectiveRoles, log, UserId); log.LogDebug($"Instantiating biz object handler for {reportDataParam.ObjectType}"); var biz = BizObjectFactory.GetBizObject(reportDataParam.ObjectType, ct); diff --git a/server/AyaNova/models/dto/DataListSelection.cs b/server/AyaNova/models/dto/DataListSelection.cs index 0156a4b6..9f8ba03c 100644 --- a/server/AyaNova/models/dto/DataListSelection.cs +++ b/server/AyaNova/models/dto/DataListSelection.cs @@ -22,10 +22,10 @@ namespace AyaNova.Models } } - public async Task RehydrateIdList(AyContext ct, AuthorizationRoles userRoles, Microsoft.Extensions.Logging.ILogger log) + public async Task RehydrateIdList(AyContext ct, AuthorizationRoles userRoles, Microsoft.Extensions.Logging.ILogger log, long userId) { if (SelectedRowIds.Length == 0) - SelectedRowIds = await AyaNova.DataList.DataListFetcher.GetIdListResponseAsync(DataListKey, ListView, MetaView, ct, userRoles, log); + SelectedRowIds = await AyaNova.DataList.DataListFetcher.GetIdListResponseAsync(DataListKey, ListView, MetaView, ct, userRoles, log, userId); } } } diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 6f47d2fc..ea31abaf 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -22,8 +22,8 @@ namespace AyaNova.Util //!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!! private const int DESIRED_SCHEMA_LEVEL = 15; - internal const long EXPECTED_COLUMN_COUNT = 500; - internal const long EXPECTED_INDEX_COUNT = 145; + internal const long EXPECTED_COLUMN_COUNT = 511; + internal const long EXPECTED_INDEX_COUNT = 148; //!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!