diff --git a/server/AyaNova/ControllerHelpers/Authorized.cs b/server/AyaNova/ControllerHelpers/Authorized.cs index 73224a59..a0b7a801 100644 --- a/server/AyaNova/ControllerHelpers/Authorized.cs +++ b/server/AyaNova/ControllerHelpers/Authorized.cs @@ -39,6 +39,40 @@ namespace AyaNova.Api.ControllerHelpers + /// + /// READ FULL RECORD (not just name and id) + /// + /// + /// + /// + internal static bool HasSelectRole(IDictionary HttpContextItems, AyaType objectType) + { + AuthorizationRoles currentUserRoles = UserRolesFromContext.Roles(HttpContextItems); + return HasSelectRole(currentUserRoles, objectType); + } + + /// + /// SELECT BY NAME + /// + /// + /// + /// + internal static bool HasSelectRole(AuthorizationRoles currentUserRoles, AyaType objectType) + { + //NOTE: this assumes that if you can change you can read + if (currentUserRoles.HasAnyFlags(BizRoles.GetRoleSet(objectType).Change)) + return true; + + if (currentUserRoles.HasAnyFlags(BizRoles.GetRoleSet(objectType).ReadFullRecord)) + return true; + + if (currentUserRoles.HasAnyFlags(BizRoles.GetRoleSet(objectType).Select)) + return true; + + return false; + } + + /// /// READ FULL RECORD (not just name and id) /// diff --git a/server/AyaNova/PickList/AyaPickList.cs b/server/AyaNova/PickList/AyaPickList.cs new file mode 100644 index 00000000..ca2cabc1 --- /dev/null +++ b/server/AyaNova/PickList/AyaPickList.cs @@ -0,0 +1,218 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using AyaNova.Biz; +using Newtonsoft.Json.Linq; +using Microsoft.EntityFrameworkCore; + +namespace AyaNova.PickList +{ + + /// + /// PickList object base class + /// + internal abstract class AyaPickList : IAyaPickList + { + + public AyaPickList() + { + + } + + public string SQLFrom { get; set; } + public List FieldDefinitions { get; set; } + public AuthorizationRoles AllowedRoles { get; set; } + public AyaType DefaultListObjectType { get; set; } + + public string DefaultListView { get; set; } + + + //return array of field keys in list view + public List GetFieldListFromListView(JArray listViewArray) + { + // [{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}] + List ret = new List(); + for (int i = 0; i < listViewArray.Count; i++) + { + var cm = listViewArray[i]; + ret.Add(cm["fld"].Value()); + } + return ret; + } + + + + public Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(JArray listViewArray) + { + + var ListViewFieldKeys = GetFieldListFromListView(listViewArray); + var CustomFieldDefinitions = GetCustomFieldDefinitionsForList(); + + //Generate JSON fragment to return with column definitions + StringBuilder sb = new StringBuilder(); + + sb.Append("["); + + bool FirstColumnAdded = false; + + foreach (string s in ListViewFieldKeys) + { + AyaPickListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s); +#if (DEBUG) + //Developers little helper + if (o == null) + { + throw new System.ArgumentNullException($"DEV ERROR in AyaPickList::GenerateListColumnsJSONFromListView - field {s} specified in ListView was NOT found in ObjectFields list"); + } +#endif + + if (o != null) + {//Here is where we can vet the field name, if it doesn't exist. For production we'll just ignore those ones + + if (FirstColumnAdded) + sb.Append(","); + sb.Append("{"); + //Build required part of column definition + if (!o.IsCustomField) + sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)o.UiFieldDataType}"); + else + { + //insert specific type for this custom field + if (CustomFieldDefinitions.ContainsKey(o.LtKey)) + { + var customFieldType = CustomFieldDefinitions[o.LtKey]; + sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{customFieldType}"); + } + else + { + //this is normal as there may not be a definition for a Custom field but it's been requested so just treat it like text + sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)UiFieldDataType.Text}"); + } + } + + //Has a AyObjectType? (linkable / openable) + if (o.AyaObjectType != 0) + sb.Append($",\"ay\":{(int)o.AyaObjectType}"); + + //Row ID column? + if (o.IsRowId) + { + sb.Append($",\"rid\":1"); + } + + //Has a Enumtype? + if (!string.IsNullOrEmpty(o.EnumType)) + sb.Append($",\"et\":\"{AyaNova.Util.StringUtil.TrimTypeName(o.EnumType)}\""); + + sb.Append("}"); + FirstColumnAdded = true; + + } + } + sb.Append("]"); + + return JArray.Parse(sb.ToString()); + } + + + //Find and return a dictionary of all custom fields definitions for all types in list + //used to build the column array and define specific type defined for custom fields so client datatable + //knows how to format it + private Dictionary GetCustomFieldDefinitionsForList() + { + //all keys and types can go in the same list since they are unique to each type of list + //i.e. both users and widget custom fields can be in the same list + Dictionary ret = new Dictionary(); + List typesProcessed = new List(); + //custom fields handling + foreach (AyaPickListFieldDefinition d in this.FieldDefinitions) + { + if (d.IsCustomField) + { + //this relies on the convention I'm using of AyaType name as the first part of all custom fields lT keys, e.g. + //WidgetCustom1 -> Widget + var ayatypename = d.LtKey.Split("Custom")[0]; + if (!typesProcessed.Contains(ayatypename)) + { + //make sure we do each type only once + typesProcessed.Add(ayatypename); + //fetch it and set it + using (var ct = AyaNova.Util.ServiceProviderProvider.DBContext) + { + var fc = ct.FormCustom.AsNoTracking().SingleOrDefault(x => x.FormKey == ayatypename); +#if (DEBUG) + if (fc == null) + { + throw new System.ArgumentNullException($"AyaPickList:GetCustomFieldDefinitionsForList, Custom field object type {ayatypename} has no FormCustom defined"); + } +#endif + //production handling of missing formcustom + if (fc == null) + continue; + + //iterate the fields and add each custom one with a type to the return dictionary + var flds = JArray.Parse(fc.Template); + foreach (JToken t in flds) + { + if (t["type"] != null) + { + ret.Add(t["fld"].Value(), t["type"].Value()); + } + } + + + } + + } + } + } + /*{[ + { + "fld": "Notes", + "required": true + }, + { + "fld": "WidgetCustom1", + "required": false, + "type": 1 + }, + { + "fld": "WidgetCustom2", + "required": true, + "type": 4 + }, + { + "fld": "WidgetCustom3", + "required": false, + "type": 5 + }, + { + "fld": "WidgetCustom4", + "required": false, + "type": 6 + }, + { + "fld": "WidgetCustom5", + "required": false, + "type": 8 + }, + { + "fld": "WidgetCustom6", + "required": false, + "type": 2 + }, + { + "fld": "WidgetCustom7", + "required": false, + "type": 3 + } + ]}*/ + return ret; + + } + + + + }//eoc + +}//eons \ No newline at end of file diff --git a/server/AyaNova/PickList/AyaPickListFieldDefinition.cs b/server/AyaNova/PickList/AyaPickListFieldDefinition.cs new file mode 100644 index 00000000..7e5093c4 --- /dev/null +++ b/server/AyaNova/PickList/AyaPickListFieldDefinition.cs @@ -0,0 +1,83 @@ +using AyaNova.Biz; +using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json; + +namespace AyaNova.PickList +{ + + //This class defines a field used for returning data in list format for UI pick lists + public class AyaPickListFieldDefinition + { + //CLIENT / SERVER Unique identifier used at BOTH client and server + //also the sql displaycolumnname if identical + public string FieldKey { get; set; } + + //CLIENT Use only for display + public string LtKey { get; set; } + + //CLIENT / SERVER - client display server validation purposes + public bool IsCustomField { get; set; } + + //CLIENT / SERVER - client display server validation purposes + public bool IsFilterable { get; set; } + + //CLIENT / SERVER - client display server validation purposes + public bool IsSortable { get; set; } + + //CLIENT Use only for display + public int UiFieldDataType { get; set; } + + //CLIENT Use only for display + public string EnumType { get; set; } + + //SERVER / CLIENT - used to identify the column that represents the entire row ID and object + //MUST be present in all datalists and displayed at the client + public bool IsRowId { get; set; } + + //CLIENT / SERVER - client display and to indicate what object to open , Server for formatting return object + public int AyaObjectType { get; set; } + + //SERVER - for building sql queries + //don't return these properties when api user fetches field list definitions in DataListController + [JsonIgnore] + public string SqlIdColumnName { get; set; } + [JsonIgnore] + public string SqlValueColumnName { get; set; } + + + + + + public AyaPickListFieldDefinition() + { + //most common defaults + + IsCustomField = false; + IsFilterable = true; + IsSortable = true; + IsRowId = false; + //Set openable object type to no type which is the default and means it's not a link to another object + AyaObjectType = (int)AyaType.NoType; + + } + + //Get column to query for display name or use FieldName if there is no difference + public string GetSqlValueColumnName() + { + if (string.IsNullOrEmpty(SqlValueColumnName)) + { + return FieldKey.ToLowerInvariant(); + } + else + { + return SqlValueColumnName; + } + } + + public bool HasIdColumn() + { + return !string.IsNullOrWhiteSpace(SqlIdColumnName); + } + + } +} \ No newline at end of file diff --git a/server/AyaNova/PickList/IAyaPickList.cs b/server/AyaNova/PickList/IAyaPickList.cs new file mode 100644 index 00000000..3e722582 --- /dev/null +++ b/server/AyaNova/PickList/IAyaPickList.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using AyaNova.Biz; +namespace AyaNova.PickList +{ + internal interface IAyaPickList + { + + //sql query from fragment with table joins et + string SQLFrom { get; set; } + + //List of fields for this object + List FieldDefinitions { get; set; } + + //allowed roles to access this list + AuthorizationRoles AllowedRoles { get; set; } + + //Default object type to open for rows of this list (use no object if no) + AyaType DefaultListObjectType { get; set; } + + //Default / STOCK DataListView when none is specified + string DefaultListView { get; set; } + + Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(JArray listViewArray); + List GetFieldListFromListView(JArray listViewArray); + + + } + +} \ No newline at end of file diff --git a/server/AyaNova/PickList/PickListFactory.cs b/server/AyaNova/PickList/PickListFactory.cs new file mode 100644 index 00000000..7592bfc2 --- /dev/null +++ b/server/AyaNova/PickList/PickListFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Linq; +using AyaNova.Biz; + + +namespace AyaNova.PickList +{ + internal static class PickListFactory + { + + //Instantiate list object specified from type + internal static IAyaPickList GetAyaPickList(AyaType ayaType) + { + switch(ayaType){ + case AyaType.Widget: + return new WidgetPickList() as IAyaDataList; + } + } + + //List all the datalist types available + internal static List GetListOfAllPickListKeyNames() + { + //https://stackoverflow.com/a/42574373/8939 + + List ret = new List(); + System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly(); + + foreach (System.Reflection.TypeInfo ti in ass.DefinedTypes) + { + if (!ti.IsAbstract && ti.ImplementedInterfaces.Contains(typeof(IAyaPickList))) + { + ret.Add(ti.Name); + } + } + return ret; + } + + + }//eoc +}//eons \ No newline at end of file diff --git a/server/AyaNova/PickList/PickListFetcher.cs b/server/AyaNova/PickList/PickListFetcher.cs new file mode 100644 index 00000000..7db1dff2 --- /dev/null +++ b/server/AyaNova/PickList/PickListFetcher.cs @@ -0,0 +1,183 @@ +using System.Collections.Generic; +using System.Linq; +using AyaNova.Biz; +using Newtonsoft.Json.Linq; +using AyaNova.Api.ControllerHelpers; +using Microsoft.AspNetCore.Mvc; +using AyaNova.Models; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using EnumsNET; + +namespace AyaNova.PickList +{ + internal static class PickListFetcher + { + internal static async Task GetResponseAsync(AyaType ayaType, string query, AuthorizationRoles userRoles) + //string PickListKey, AyContext ct, ListOptions listOptions, long UserId, AuthorizationRoles UserRoles) + { + + var PickList = PickListFactory.GetAyaPickList(ayaType); + + //was the name not found as a list? + if (PickList == null) + { + throw new System.ArgumentOutOfRangeException($"PickList \"{PickListKey}\" specified does not exist"); + } + + //check rights + + if (!UserRoles.HasAnyFlags(PickList.AllowedRoles)) + throw new System.UnauthorizedAccessException("User roles insufficient for this datalist"); + + //do we need to default the listView? + if (string.IsNullOrWhiteSpace(listOptions.ListView)) + { + listOptions.ListView = PickList.DefaultListView; + } + + //parse the list view + var ListViewArray = JArray.Parse(listOptions.ListView); + + + //Get the field key names in a list from the listview + List ListViewFieldList = PickList.GetFieldListFromListView(ListViewArray); + + //BUILD THE QUERY + //SELECT FRAGMENT COLUMNS FROM TEMPLATE + var SelectBuild = PickListSqlSelectBuilder.Build(PickList.FieldDefinitions, ListViewFieldList); + + //FROM CLAUSE + var qFrom = PickList.SQLFrom; + + var qWhere = string.Empty; + var qOrderBy = string.Empty; + + //WHERE CLAUSE - FILTER + qWhere = PickListSqlFilterCriteriaBuilder.DataFilterToSQLCriteria(PickList.FieldDefinitions, ListViewArray, UserId); + + //ORDER BY CLAUSE - SORT + //BUILD ORDER BY + qOrderBy = PickListSqlFilterOrderByBuilder.DataFilterToSQLOrderBy(PickList.FieldDefinitions, ListViewArray); + + //LIMIT AND OFFSET CLAUSE - PAGING + listOptions.Offset = listOptions.Offset ?? ListOptions.DefaultOffset; + listOptions.Limit = listOptions.Limit ?? ListOptions.DefaultLimit; + var qLimitOffset = $"LIMIT {listOptions.Limit} OFFSET {listOptions.Offset}"; + + //PUT IT ALL TOGETHER + string qDataQuery = string.Empty; + string qTotalRecordsQuery = string.Empty; + + qDataQuery = $"{SelectBuild.Select} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}".Replace(" ", " "); + qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}".Replace(" ", " "); + + //RETURN OBJECTS + int returnRowColumnCount = ListViewFieldList.Count(); + List> rows = new List>(); + long totalRecordCount = 0; + + //QUERY THE DB + using (var command = ct.Database.GetDbConnection().CreateCommand()) + { + await ct.Database.OpenConnectionAsync(); + + //GET DATA RETURN ROWS + command.CommandText = qDataQuery; + using (var dr = await command.ExecuteReaderAsync()) + { + while (dr.Read()) + { + List row = new List(returnRowColumnCount); + + + //INSERT REMAINING FIELDS FROM TEMPLATE INTO THE RETURN ROWS LIST + foreach (string TemplateField in ListViewFieldList) + { + + //get the AyaObjectFieldDefinition + AyaPickListFieldDefinition f = PickList.FieldDefinitions.FirstOrDefault(x => x.FieldKey == TemplateField); + if (f.IsCustomField) + { + + AyaFieldData AyaField = new AyaFieldData(); + var cust = dr.GetString(SelectBuild.map[f.GetSqlValueColumnName()]); + if (!string.IsNullOrWhiteSpace(cust)) + { + JObject j = JObject.Parse(cust); + //convert field name to cust name then get value + var InternalCustomFieldName = AyaFormFieldDefinitions.TranslateLTCustomFieldToInternalCustomFieldName(TemplateField); + //Sometimes a custom field is specified but doesn't exist in the collection so don't assume it's there + // AyaField.v = j[InternalCustomFieldName].Value(); + JToken o = j[InternalCustomFieldName]; + if (o != null) + AyaField.v = o.Value(); + else + AyaField.v = null; + + row.Add(AyaField); + } + + /* + TODO: Custom field handling + GetName works just not with multipart identifiers + I could force naming by making all fields and AS, or + I could map the ordinal when generating the Select fields so that I have a map to refer to here + mapping in advance actually makes a lot of sense, then no more of this fragility of going by pointer index and hoping for the best + it would just be premapped out. + + dr.GetOrdinal(f.SqlValueColumnName) +'dr.GetOrdinal(f.SqlValueColumnName)' threw an exception of type 'System.IndexOutOfRangeException' +f.SqlValueColumnName +"awidget.customfields" +dr.GetName(nCurrentColumnPointer) +"customfields" +dr.GetOrdinal("customfields"); +5 + + */ + } + else + { + AyaFieldData AyaField = new AyaFieldData(); + AyaField.v = dr.GetValue(SelectBuild.map[f.GetSqlValueColumnName()]); + + + if (f.SqlIdColumnName != null) + { + var ordinal = SelectBuild.map[f.SqlIdColumnName]; + if (!await dr.IsDBNullAsync(ordinal)) + AyaField.i = dr.GetInt64(ordinal); + + } + row.Add(AyaField); + } + } + rows.Add(row); + } + } + + //GET TOTAL RECORD COUNT + command.CommandText = qTotalRecordsQuery; + using (var dr = await command.ExecuteReaderAsync()) + { + if (dr.Read()) + { + totalRecordCount = dr.GetInt64(0); + } + } + } + + + //BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT + Newtonsoft.Json.Linq.JArray ColumnsJSON = null; + + ColumnsJSON = PickList.GenerateListColumnsJSONFromListView(ListViewArray); + + return new ApiPickListResponse(rows, totalRecordCount, ColumnsJSON); + + } + + + }//eoc +}//eons \ No newline at end of file diff --git a/server/AyaNova/PickList/WidgetPickList.cs b/server/AyaNova/PickList/WidgetPickList.cs new file mode 100644 index 00000000..b6a25393 --- /dev/null +++ b/server/AyaNova/PickList/WidgetPickList.cs @@ -0,0 +1,167 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using AyaNova.Biz; +namespace AyaNova.PickList +{ + internal class WidgetPickList : AyaPickList + { + public WidgetPickList() + { + + DefaultListObjectType = AyaType.Widget; + SQLFrom = "from awidget left outer join auser on (awidget.userid=auser.id)"; + AllowedRoles = BizRoles.GetRoleSet(DefaultListObjectType).Select; + + //Default ListView + dynamic dlistView = new JArray(); + + dynamic cm = new JObject(); + cm.fld = "widgetname"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "widgetserial"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "widgetdollaramount"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "widgetusertype"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "widgetstartdate"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "widgetactive"; + dlistView.Add(cm); + + cm = new JObject(); + cm.fld = "username"; + dlistView.Add(cm); + + DefaultListView = dlistView.ToString(Newtonsoft.Json.Formatting.None); + + + + // DefaultPickListView = @" + // { + // [{key:""COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}] + + // ""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetusertype"",""widgetstartdate"",""widgetactive"",""username""], + + // } + // "; + + //NOTE: Due to the join, all the sql id and name fields that can conflict with the joined (in this case User) table need to be specified completely + FieldDefinitions = new List(); + //DEPRECATED: FieldDefinitions.Add(new AyaPickListFieldDefinition { FieldKey = "df", AyaObjectType = (int)AyaType.Widget, SqlIdColumnName = "awidget.id", IsFilterable = false, IsSortable = false, }); + + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetName", + FieldKey = "widgetname", + AyaObjectType = (int)AyaType.Widget, + UiFieldDataType = (int)UiFieldDataType.Text, + SqlIdColumnName = "awidget.id", + SqlValueColumnName = "awidget.name", + IsRowId = true + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetSerial", + FieldKey = "widgetserial", + UiFieldDataType = (int)UiFieldDataType.Integer, + SqlValueColumnName = "awidget.serial" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetDollarAmount", + FieldKey = "widgetdollaramount", + UiFieldDataType = (int)UiFieldDataType.Currency, + SqlValueColumnName = "awidget.dollaramount" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetCount", + FieldKey = "widgetcount", + UiFieldDataType = (int)UiFieldDataType.Integer, + SqlValueColumnName = "awidget.count" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetUserType", + FieldKey = "widgetusertype", + UiFieldDataType = (int)UiFieldDataType.Enum, + EnumType = AyaNova.Util.StringUtil.TrimTypeName(typeof(UserType).ToString()), + SqlValueColumnName = "awidget.usertype" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetStartDate", + FieldKey = "widgetstartdate", + UiFieldDataType = (int)UiFieldDataType.DateTime, + SqlValueColumnName = "awidget.startdate" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetEndDate", + FieldKey = "widgetenddate", + UiFieldDataType = (int)UiFieldDataType.DateTime, + SqlValueColumnName = "awidget.enddate" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "WidgetNotes", + FieldKey = "widgetnotes", + UiFieldDataType = (int)UiFieldDataType.Text, + SqlValueColumnName = "awidget.notes" + }); + + //FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "User", FieldKey = "userid", UiFieldDataType = (int)AyaUiFieldDataType.Text, AyaObjectType = (int)AyaType.User }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + FieldKey = "username", + LtKey = "User", + UiFieldDataType = (int)UiFieldDataType.Text, + AyaObjectType = (int)AyaType.User, + SqlIdColumnName = "auser.id", + SqlValueColumnName = "auser.name" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "Active", + FieldKey = "widgetactive", + UiFieldDataType = (int)UiFieldDataType.Bool, + SqlValueColumnName = "awidget.active" + }); + FieldDefinitions.Add(new AyaPickListFieldDefinition + { + LtKey = "Tags", + FieldKey = "widgettags", + UiFieldDataType = (int)UiFieldDataType.Tags, + SqlValueColumnName = "awidget.tags" + }); + + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom1", FieldKey = "widgetcustom1", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom2", FieldKey = "widgetcustom2", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom3", FieldKey = "widgetcustom3", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom4", FieldKey = "widgetcustom4", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom5", FieldKey = "widgetcustom5", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom6", FieldKey = "widgetcustom6", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom7", FieldKey = "widgetcustom7", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom8", FieldKey = "widgetcustom8", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom9", FieldKey = "widgetcustom9", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom10", FieldKey = "widgetcustom10", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom11", FieldKey = "widgetcustom11", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom12", FieldKey = "widgetcustom12", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom13", FieldKey = "widgetcustom13", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom14", FieldKey = "widgetcustom14", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom15", FieldKey = "widgetcustom15", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + FieldDefinitions.Add(new AyaPickListFieldDefinition { LtKey = "WidgetCustom16", FieldKey = "widgetcustom16", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" }); + } + }//eoc +}//eons \ No newline at end of file diff --git a/server/AyaNova/biz/BizRoleSet.cs b/server/AyaNova/biz/BizRoleSet.cs index 189e6c44..97c59ec3 100644 --- a/server/AyaNova/biz/BizRoleSet.cs +++ b/server/AyaNova/biz/BizRoleSet.cs @@ -1,14 +1,15 @@ namespace AyaNova.Biz { -/// -/// This is a set of roles to be stored in the central BizRoles with a key for each object type -/// + /// + /// This is a set of roles to be stored in the central BizRoles with a key for each object type + /// public class BizRoleSet { - public AuthorizationRoles Change { get; set; } + public AuthorizationRoles Change { get; set; } public AuthorizationRoles ReadFullRecord { get; set; } - + public AuthorizationRoles Select { get; set; } + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/biz/BizRoles.cs b/server/AyaNova/biz/BizRoles.cs index 1950c426..9255cf99 100644 --- a/server/AyaNova/biz/BizRoles.cs +++ b/server/AyaNova/biz/BizRoles.cs @@ -24,7 +24,8 @@ namespace AyaNova.Biz //HOW THIS WORKS / WHATS EXPECTED //Change = CREATE, RETRIEVE, UPDATE, DELETE - Full rights //ReadFullRecord = You can read *all* the fields of the record, but can't modify it. Change is automatically checked for so only add different roles from change - //MINI / PICKLIST NOTE: roles do not control getting a list of names for selection which is role independent because it's required for so much indirectly + //SELECT - this role allows user to select (fetch picklist) this type of object on other forms, we have this security level because otherwise a Customer role user for example, could see other customers via api if not prohibited + // Setting SELECT - Select only needs to be set on objects for which there is a defined PickList object because that's where it's used solely (as of now anyway) //DELETE = There is no specific delete right for now though it's checked for by routes in Authorized.cs in case we want to add it in future as a separate right from create. #region All roles initialization @@ -35,7 +36,8 @@ namespace AyaNova.Biz roles.Add(AyaType.User, new BizRoleSet() { Change = AuthorizationRoles.BizAdminFull, - ReadFullRecord = AuthorizationRoles.BizAdminLimited + ReadFullRecord = AuthorizationRoles.BizAdminLimited, + Select = AuthorizationRoles.All }); //////////////////////////////////////////////////////////// @@ -56,7 +58,8 @@ namespace AyaNova.Biz roles.Add(AyaType.Widget, new BizRoleSet() { Change = AuthorizationRoles.BizAdminFull | AuthorizationRoles.InventoryFull, - ReadFullRecord = AuthorizationRoles.BizAdminLimited | AuthorizationRoles.InventoryLimited + ReadFullRecord = AuthorizationRoles.BizAdminLimited | AuthorizationRoles.InventoryLimited, + Select = AuthorizationRoles.All }); //////////////////////////////////////////////////////////// @@ -155,13 +158,14 @@ namespace AyaNova.Biz ReadFullRecord = AuthorizationRoles.All }); - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// //PICKLISTTEMPLATE // roles.Add(AyaType.PickListTemplate, new BizRoleSet() { Change = AuthorizationRoles.BizAdminFull, - ReadFullRecord = AuthorizationRoles.All + ReadFullRecord = AuthorizationRoles.All, + Select = AuthorizationRoles.All }); //////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/biz/PickListBiz.cs b/server/AyaNova/biz/PickListBiz.cs index 69caa2b4..3c7c9ebc 100644 --- a/server/AyaNova/biz/PickListBiz.cs +++ b/server/AyaNova/biz/PickListBiz.cs @@ -6,7 +6,7 @@ using Newtonsoft.Json.Linq; using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using AyaNova.Models; -//using AyaNova.PickList; +using AyaNova.PickList; namespace AyaNova.Biz @@ -39,18 +39,18 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// /// GET - //Get one - internal async Task GetAsync(long fetchId, bool logTheGetEvent = true) - { - //This is simple so nothing more here, but often will be copying to a different output object or some other ops - var ret = await ct.DataListView.SingleOrDefaultAsync(m => m.Id == fetchId && (m.Public == true || m.UserId == UserId)); - if (logTheGetEvent && ret != null) - { - //Log - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct); - } - return ret; - } + // //Get one + // internal async Task GetAsync(long fetchId, bool logTheGetEvent = true) + // { + // //This is simple so nothing more here, but often will be copying to a different output object or some other ops + // var ret = await ct.DataListView.SingleOrDefaultAsync(m => m.Id == fetchId && (m.Public == true || m.UserId == UserId)); + // if (logTheGetEvent && ret != null) + // { + // //Log + // await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct); + // } + // return ret; + // } @@ -67,7 +67,7 @@ namespace AyaNova.Biz //get picklist templates, basically all the object types that support picklists internal async Task> GetListOfAllPickListKeyNames() { - throw new System.NotImplementedException(); + return PickListFactory.GetListOfAllPickListKeyNames(); // List items = await PickListFetcher.GetResponseAsync(ayaType, query, ct, UserId, userRoles); // return items; }