This commit is contained in:
@@ -126,7 +126,7 @@ https://en.wikipedia.org/wiki/Non-functional_requirement
|
||||
|
||||
- REST best practices
|
||||
- Excellent reference guide here: https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md
|
||||
- URLS: A good api url: https://api.ayanova.com/v1.0/client/22
|
||||
- URLS: A good api url: https://api.ayanova.com/v1.0/customer/22
|
||||
- Keep length under 2000 characters for maximum client compatibility
|
||||
- concurrency (The ETag response-header field provides the current value of the entity tag for the requested variant. Used with If-Match, If-None-Match and If-Range to implement optimistic concurrency control.)
|
||||
- JSON property names SHOULD be camelCased.
|
||||
@@ -135,11 +135,11 @@ https://en.wikipedia.org/wiki/Non-functional_requirement
|
||||
This object MUST contain name/value pairs with the names "code" and "message," and it MAY contain name/value pairs with the names "target," "details" and "innererror."
|
||||
eg: error:{code=1200,message="blah"} error:{code=1200,message="blah",target="eg property name", details="details for programmer", innererror:}
|
||||
- Versioning: this is an area I need to treat carefully, there are tools to make it easier:
|
||||
- I will use URL Path segment versioning, i.e. api/v1.0/client/22
|
||||
- I will use URL Path segment versioning, i.e. api/v1.0/customer/22
|
||||
- https://www.hanselman.com/blog/ASPNETCoreRESTfulWebAPIVersioningMadeEasy.aspx
|
||||
- https://github.com/Microsoft/aspnet-api-versioning/wiki
|
||||
- https://github.com/Microsoft/aspnet-api-versioning/tree/master/samples/aspnetcore/SwaggerSample
|
||||
- Push notifications (I.e. on a client record being created or a workorder updated or...?)
|
||||
- Push notifications (I.e. on a customer record being created or a workorder updated or...?)
|
||||
- If so there is a segment in the rest doc from microsoft that goes over it in detail
|
||||
- API THROTTLING / RATE LIMITING
|
||||
- https://github.com/stefanprodan/AspNetCoreRateLimit
|
||||
|
||||
@@ -10,6 +10,10 @@ ROLES set general accessibility to change or delete or read objects, however Bus
|
||||
**DELETE RIGHTS***
|
||||
If you can modify an object you can delete an object unless business rules say otherwise
|
||||
|
||||
**SEE NAME / PICKLISTS ***
|
||||
- Not sure if correct but for now assuming anyone can read the name of any object and that the UI will exclude them by biz rule if they aren't supposed to see something
|
||||
- this does mean a subcontractor could use the api to fetch a list of customers outside of the client though...hmmm..
|
||||
|
||||
|
||||
**LIMITED ROLES / BUSINESS RULES LIMITATIONS **
|
||||
(formerly self owned)
|
||||
@@ -17,7 +21,7 @@ In some cases business rules may further restrict what a user can do.
|
||||
For example a SubContractorLimited has the change right to a workorder, but in fact the workorder itself has business rules that limit that drastically down to almost nothing but a single area entry in labor
|
||||
|
||||
=-=-=-=- HOW TO HANDLE EDIT OWN PLANNING =-=-=-=-=-
|
||||
- EditOwn is really not about editown it's about supporting a user who is not supposed to see any data other than the bare minimum in order to fill out workorders
|
||||
- EditOwn IS DEPRECATED FROM ORIGINAL PLAN is really not about editown it's about supporting a user who is not supposed to see any data other than the bare minimum in order to fill out workorders
|
||||
- Make it a business rule(s) instead in the areas of workorders and anything specific
|
||||
- Get rid of edit own rights code entirely
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ UPDATE SPEC DOCS with new format and names etc or at least remove nonsense as ne
|
||||
UPDATE MANUAL API REGARDING LISTS
|
||||
|
||||
|
||||
|
||||
CLIENT / TEST ROLE NAME CHANGE
|
||||
- "client" now "customer"
|
||||
|
||||
|
||||
CLIENT PROJECT CUSTOM FIELDS CHANGE
|
||||
@@ -43,6 +44,12 @@ DO CLIENT STUFF NOW COME BACK TO THIS STUFF LATER
|
||||
TODO: the license being logged breaks the format of the log file because it has line breaks etc, so instead, maybe log out as a single line (remove breaks)
|
||||
- Or maybe don't log it at all, what's the point? People can just edit it, maybe the DBID is the only really useful thing so we can match it for support to the customer
|
||||
- or just log the ID number or a more succint version
|
||||
\
|
||||
|
||||
TODO: Need route to gather all object role rights in a format useful to display in UI so that a biz manager can see at a glance the rights for different roles to objects
|
||||
- This way it's dynamic and picked up from the code itself which is always the source of truth so no need to put in the manual
|
||||
- Would likely want to display multiple ways: for a specific object or role or selected user maybe too in the user info form ("effective roles")
|
||||
- Move this over to client once the backend supports it
|
||||
|
||||
*** BEFORE NEXT UPDATE TO DEVOPS SERVER:::::::
|
||||
TODO: 2019-06-07 10:47:57.8894|WARN|Microsoft.AspNetCore.Cors.Infrastructure.CorsService|The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time.
|
||||
@@ -58,6 +65,7 @@ TODO: DO I NOT HAVE AN ERASE DB ROUTE?
|
||||
TODO: API RATE LIMITING / THROTTLING
|
||||
- Return code 429
|
||||
- Going to need rate limiting to save people from themselves
|
||||
- Have this link from solutions.txt about this: https://github.com/stefanprodan/AspNetCoreRateLimit
|
||||
- All the big api's have hourly limits on requests and also limits on total data throughput per hour
|
||||
- (minute as well which actually makes more sense since it means they would only be down for a minute if they exceed it) too
|
||||
- Find out what others do
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace AyaNova.Api.Controllers
|
||||
LocaleKeysToFetch.Add("UserTypesAdministrator");
|
||||
LocaleKeysToFetch.Add("UserTypesSchedulable");
|
||||
LocaleKeysToFetch.Add("UserTypesNonSchedulable");
|
||||
LocaleKeysToFetch.Add("UserTypesClient");
|
||||
LocaleKeysToFetch.Add("UserTypesCustomer");
|
||||
LocaleKeysToFetch.Add("UserTypesHeadOffice");
|
||||
LocaleKeysToFetch.Add("UserTypesSubContractor");
|
||||
var LT = LocaleBiz.GetSubsetStatic(LocaleKeysToFetch, LocaleId).Result;
|
||||
@@ -89,7 +89,7 @@ namespace AyaNova.Api.Controllers
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesAdministrator"], Id = (long)UserType.Administrator });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesSchedulable"], Id = (long)UserType.Schedulable });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesNonSchedulable"], Id = (long)UserType.NonSchedulable });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesClient"], Id = (long)UserType.Client });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesCustomer"], Id = (long)UserType.Customer });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesHeadOffice"], Id = (long)UserType.HeadOffice });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["UserTypesSubContractor"], Id = (long)UserType.Subcontractor });
|
||||
}
|
||||
@@ -110,8 +110,8 @@ namespace AyaNova.Api.Controllers
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleTechFull");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleSubContractorLimited");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleSubContractorFull");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleClientLimited");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleClientFull");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleCustomerLimited");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleCustomerFull");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleOpsAdminLimited");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleOpsAdminFull");
|
||||
LocaleKeysToFetch.Add("AuthorizationRoleSalesLimited");
|
||||
@@ -131,8 +131,8 @@ namespace AyaNova.Api.Controllers
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleTechFull"], Id = (long)AuthorizationRoles.TechFull });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSubContractorLimited"], Id = (long)AuthorizationRoles.SubContractorLimited });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSubContractorFull"], Id = (long)AuthorizationRoles.SubContractorFull });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleClientLimited"], Id = (long)AuthorizationRoles.ClientLimited });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleClientFull"], Id = (long)AuthorizationRoles.ClientFull });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleCustomerLimited"], Id = (long)AuthorizationRoles.CustomerLimited });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleCustomerFull"], Id = (long)AuthorizationRoles.CustomerFull });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleOpsAdminLimited"], Id = (long)AuthorizationRoles.OpsAdminLimited });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleOpsAdminFull"], Id = (long)AuthorizationRoles.OpsAdminFull });
|
||||
ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSalesLimited"], Id = (long)AuthorizationRoles.SalesLimited });
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace AyaNova.Api.Controllers
|
||||
//Instantiate the business object handler
|
||||
DataListFilterBiz biz = DataListFilterBiz.GetBiz(ct, HttpContext);
|
||||
|
||||
//If a user has change roles, or editOwnRoles then they can create, true is passed for isOwner since they are creating so by definition the owner
|
||||
//check roles
|
||||
if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
|
||||
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace AyaNova.DataList
|
||||
AuthorizationRoles FullListAllowedRoles { get; set; }
|
||||
|
||||
//allowed roles to access mini list templated fields
|
||||
//generally this will be *any* because most forms will need to allow this for picklists such as usernames etc
|
||||
// but this is a safety valve for sensitive lists like financial reports where there is just no need for untrusted roles to see it
|
||||
AuthorizationRoles MiniListAllowedRoles { get; set; }
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace AyaNova.DataList
|
||||
{
|
||||
LtKey = "WidgetName",
|
||||
FieldKey = "widgetname",
|
||||
AyaObjectType = (int)AyaType.Widget,
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
SqlIdColumnName = "awidget.id",
|
||||
SqlValueColumnName = "awidget.name"
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace AyaNova.DataList
|
||||
ListKey = nameof(TestWidgetUserEmailDataList);
|
||||
SQLFrom = "from awidget left outer join auser on (awidget.userid=auser.id) left outer join auseroptions on (auser.id=auseroptions.userid)";
|
||||
FullListAllowedRoles = AuthorizationRoles.AllInternalStaff;//anyone but clients and subcontractors (just for test)
|
||||
MiniListAllowedRoles = AuthorizationRoles.All;//anyone (so can select on forms)
|
||||
MiniListAllowedRoles = AuthorizationRoles.AllExceptCustomers;//anyone but clients who shouldn't see users email addresses (so can select on forms)
|
||||
DefaultListObjectType = AyaType.Widget;
|
||||
DefaultDataListDisplayTemplate = @"
|
||||
{
|
||||
|
||||
@@ -11,117 +11,91 @@ namespace AyaNova.DataList
|
||||
SQLFrom = "from auser";
|
||||
FullListAllowedRoles = AuthorizationRoles.AllInternalStaff;//anyone but clients and subcontractors (just for test)
|
||||
MiniListAllowedRoles = AuthorizationRoles.All;//anyone (so can select on forms)
|
||||
DefaultListObjectType = AyaType.Widget;
|
||||
DefaultListObjectType = AyaType.User;
|
||||
DefaultDataListDisplayTemplate = @"
|
||||
{
|
||||
""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetroles"",""widgetstartdate"",""widgetactive"",""username""],
|
||||
""mini"":[""widgetname"",""widgetserial""]
|
||||
""full"":[""username"",""useremployeenumber"",""useractive"",""usernotes"",""userroles""],
|
||||
""mini"":[""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<AyaDataListFieldDefinition>();
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { FieldKey = "df", AyaObjectType = (int)AyaType.Widget, SqlIdColumnName = "awidget.id" });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { FieldKey = "df", AyaObjectType = (int)AyaType.User, SqlIdColumnName = "auser.id" });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetName",
|
||||
FieldKey = "widgetname",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
SqlIdColumnName = "awidget.id",
|
||||
SqlValueColumnName = "awidget.name"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetSerial",
|
||||
FieldKey = "widgetserial",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Integer,
|
||||
SqlValueColumnName = "awidget.serial"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetDollarAmount",
|
||||
FieldKey = "widgetdollaramount",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Currency,
|
||||
SqlValueColumnName = "awidget.dollaramount"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetCount",
|
||||
FieldKey = "widgetcount",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Integer,
|
||||
SqlValueColumnName = "awidget.count"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetRoles",
|
||||
FieldKey = "widgetroles",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Enum,
|
||||
EnumType = typeof(AuthorizationRoles).ToString(),
|
||||
SqlValueColumnName = "awidget.roles"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetStartDate",
|
||||
FieldKey = "widgetstartdate",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.DateTime,
|
||||
SqlValueColumnName = "awidget.startdate"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetEndDate",
|
||||
FieldKey = "widgetenddate",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.DateTime,
|
||||
SqlValueColumnName = "awidget.enddate"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "WidgetNotes",
|
||||
FieldKey = "widgetnotes",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
SqlValueColumnName = "awidget.notes"
|
||||
});
|
||||
|
||||
//FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "User", FieldKey = "userid", UiFieldDataType = (int)AyaUiFieldDataType.Text, AyaObjectType = (int)AyaType.User });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
FieldKey = "username",
|
||||
LtKey = "User",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
FieldKey = "username",
|
||||
AyaObjectType = (int)AyaType.User,
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
SqlIdColumnName = "auser.id",
|
||||
SqlValueColumnName = "auser.name"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "Active",
|
||||
FieldKey = "widgetactive",
|
||||
FieldKey = "useractive",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Bool,
|
||||
SqlValueColumnName = "awidget.active"
|
||||
});
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "Tags",
|
||||
FieldKey = "widgettags",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Tags,
|
||||
SqlValueColumnName = "awidget.tags"
|
||||
SqlValueColumnName = "auser.active"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom1", FieldKey = "widgetcustom1", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom2", FieldKey = "widgetcustom2", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom3", FieldKey = "widgetcustom3", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom4", FieldKey = "widgetcustom4", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom5", FieldKey = "widgetcustom5", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom6", FieldKey = "widgetcustom6", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom7", FieldKey = "widgetcustom7", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom8", FieldKey = "widgetcustom8", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom9", FieldKey = "widgetcustom9", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom10", FieldKey = "widgetcustom10", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom11", FieldKey = "widgetcustom11", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom12", FieldKey = "widgetcustom12", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom13", FieldKey = "widgetcustom13", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom14", FieldKey = "widgetcustom14", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom15", FieldKey = "widgetcustom15", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom16", FieldKey = "widgetcustom16", IsCustomField = true });
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "AuthorizationRoles",
|
||||
FieldKey = "userroles",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Enum,
|
||||
EnumType = typeof(AuthorizationRoles).ToString(),
|
||||
SqlValueColumnName = "auser.roles"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "UserUserType",
|
||||
FieldKey = "usertype",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Enum,
|
||||
EnumType = typeof(UserType).ToString(),
|
||||
SqlValueColumnName = "auser.usertype"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "UserEmployeeNumber",
|
||||
FieldKey = "useremployeenumber",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
SqlValueColumnName = "auser.employeenumber"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new AyaDataListFieldDefinition
|
||||
{
|
||||
LtKey = "UserNotes",
|
||||
FieldKey = "usernotes",
|
||||
UiFieldDataType = (int)AyaUiFieldDataType.Text,
|
||||
SqlValueColumnName = "auser.notes"
|
||||
});
|
||||
|
||||
|
||||
// //-------------------------
|
||||
//NOT SURE ABOUT CUSTOM FIELDS
|
||||
//NEED TO COME BACK TO THIS ONCE CLIENT IS CONSUMING THESE LISTS
|
||||
//WIDGETLIST has custom fields so good test before doing here
|
||||
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom1", FieldKey = "widgetcustom1", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom2", FieldKey = "widgetcustom2", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom3", FieldKey = "widgetcustom3", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom4", FieldKey = "widgetcustom4", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom5", FieldKey = "widgetcustom5", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom6", FieldKey = "widgetcustom6", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom7", FieldKey = "widgetcustom7", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom8", FieldKey = "widgetcustom8", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom9", FieldKey = "widgetcustom9", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom10", FieldKey = "widgetcustom10", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom11", FieldKey = "widgetcustom11", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom12", FieldKey = "widgetcustom12", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom13", FieldKey = "widgetcustom13", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom14", FieldKey = "widgetcustom14", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom15", FieldKey = "widgetcustom15", IsCustomField = true });
|
||||
// FieldDefinitions.Add(new AyaDataListFieldDefinition { LtKey = "WidgetCustom16", FieldKey = "widgetcustom16", IsCustomField = true });
|
||||
}
|
||||
}//eoc
|
||||
}//eons
|
||||
@@ -37,9 +37,9 @@ namespace AyaNova.Biz
|
||||
///<summary>SubContractorFull</summary>
|
||||
SubContractorFull = 1024,
|
||||
///<summary>ClientLimited</summary>
|
||||
ClientLimited = 2048,
|
||||
CustomerLimited = 2048,
|
||||
///<summary>ClientFull</summary>
|
||||
ClientFull = 4096,
|
||||
CustomerFull = 4096,
|
||||
///<summary>OpsAdminLimited</summary>
|
||||
OpsAdminLimited = 8192,
|
||||
///<summary>OpsAdminFull</summary>
|
||||
@@ -53,11 +53,16 @@ namespace AyaNova.Biz
|
||||
///<summary>Anyone of any role</summary>
|
||||
All = BizAdminLimited | BizAdminFull | DispatchLimited | DispatchFull | InventoryLimited |
|
||||
InventoryFull | AccountingFull | TechLimited | TechFull | SubContractorLimited |
|
||||
SubContractorFull | ClientLimited | ClientFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited,
|
||||
SubContractorFull | CustomerLimited | CustomerFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited,
|
||||
|
||||
///<summary>Anyone inside company</summary>
|
||||
AllInternalStaff = BizAdminLimited | BizAdminFull | DispatchLimited | DispatchFull | InventoryLimited |
|
||||
InventoryFull | AccountingFull | TechLimited | TechFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited
|
||||
InventoryFull | AccountingFull | TechLimited | TechFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited,
|
||||
|
||||
///<summary>Anyone except customers</summary>
|
||||
AllExceptCustomers = BizAdminLimited | BizAdminFull | DispatchLimited | DispatchFull | InventoryLimited |
|
||||
InventoryFull | AccountingFull | TechLimited | TechFull | SubContractorLimited |
|
||||
SubContractorFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited
|
||||
|
||||
}//end AuthorizationRoles
|
||||
//, 65536, 131072, 262144, 524288, 1,048,576
|
||||
|
||||
@@ -16,17 +16,15 @@ namespace AyaNova.Biz
|
||||
|
||||
static BizRoles()
|
||||
{
|
||||
//TODO: change this entire block to work off a fragment of JSON that can be shared with the Client side project as well
|
||||
|
||||
//Add all object roles here
|
||||
//NOTE: do not need to add change roles to read roles, Authorized.cs takes care of that automatically
|
||||
//by assuming if you can change you can read
|
||||
|
||||
//HOW THIS WORKS / WHATS EXPECTED
|
||||
//Change = CREATE, RETRIEVE, UPDATE, DELETE - Full rights
|
||||
//EditOwn = special subset of CHANGE: You can create and if it's one you created then you have rights to edit it or delete, but you can't edit ones others have created
|
||||
//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
|
||||
//PICKLIST NOTE: this does not control getting a list of names for selection which is role independent because it's required for so much indirectly
|
||||
//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
|
||||
//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
|
||||
@@ -178,8 +176,7 @@ namespace AyaNova.Biz
|
||||
System.Diagnostics.Debugger.Log(1, "JSONFRAGMENTFORCLIENT", "BizRoles.cs -> biz-role-rights.js Client roles JSON fragment:");
|
||||
System.Diagnostics.Debugger.Log(1, "JSONFRAGMENTFORCLIENT", json);
|
||||
|
||||
//ONGOING VALIDATION TO CATCH MISMATCH WHEN NEW ROLES ADDED (wont' catch changes to existing unfortunately)
|
||||
// var lastRoles = "{\r\n \"User\": {\r\n \"Change\": 2,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 1\r\n },\r\n \"UserOptions\": {\r\n \"Change\": 2,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 1\r\n },\r\n \"Widget\": {\r\n \"Change\": 34,\r\n \"EditOwn\": 256,\r\n \"ReadFullRecord\": 17\r\n },\r\n \"ServerState\": {\r\n \"Change\": 16384,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 32767\r\n },\r\n \"License\": {\r\n \"Change\": 16386,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 8193\r\n },\r\n \"LogFile\": {\r\n \"Change\": 0,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 24576\r\n },\r\n \"JobOperations\": {\r\n \"Change\": 16384,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 8195\r\n },\r\n \"AyaNova7Import\": {\r\n \"Change\": 16384,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 0\r\n },\r\n \"Metrics\": {\r\n \"Change\": 0,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 24576\r\n },\r\n \"Locale\": {\r\n \"Change\": 16386,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 32767\r\n },\r\n \"DataFilter\": {\r\n \"Change\": 2,\r\n \"EditOwn\": 32767,\r\n \"ReadFullRecord\": 32767\r\n },\r\n \"FormCustom\": {\r\n \"Change\": 2,\r\n \"EditOwn\": 0,\r\n \"ReadFullRecord\": 32767\r\n }\r\n}";
|
||||
//ONGOING VALIDATION TO CATCH MISMATCH WHEN NEW ROLES ADDED (wont' catch changes to existing unfortunately)
|
||||
var lastRoles = "{\"User\":{\"Change\":2,\"ReadFullRecord\":1},\"UserOptions\":{\"Change\":2,\"ReadFullRecord\":1},\"Widget\":{\"Change\":34,\"ReadFullRecord\":17},\"ServerState\":{\"Change\":16384,\"ReadFullRecord\":32767},\"License\":{\"Change\":16386,\"ReadFullRecord\":8193},\"LogFile\":{\"Change\":0,\"ReadFullRecord\":24576},\"JobOperations\":{\"Change\":16384,\"ReadFullRecord\":8195},\"AyaNova7Import\":{\"Change\":16384,\"ReadFullRecord\":0},\"Metrics\":{\"Change\":0,\"ReadFullRecord\":24576},\"Locale\":{\"Change\":16386,\"ReadFullRecord\":32767},\"DataFilter\":{\"Change\":2,\"ReadFullRecord\":32767},\"FormCustom\":{\"Change\":2,\"ReadFullRecord\":32767}}";
|
||||
|
||||
Dictionary<AyaType, BizRoleSet> lastRolesDeserialized = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<AyaType, BizRoleSet>>(lastRoles);
|
||||
|
||||
@@ -479,12 +479,12 @@ namespace AyaNova.Biz
|
||||
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "UserType");
|
||||
}
|
||||
|
||||
//Validate client type user
|
||||
if (!SeedOrImportRelaxedRulesMode && proposedObj.UserType == UserType.Client)
|
||||
//Validate customer type user
|
||||
if (!SeedOrImportRelaxedRulesMode && proposedObj.UserType == UserType.Customer)
|
||||
{
|
||||
if (proposedObj.ClientId == null || proposedObj.ClientId == 0)
|
||||
if (proposedObj.CustomerId == null || proposedObj.CustomerId == 0)
|
||||
{
|
||||
AddError(ApiErrorCode.VALIDATION_REQUIRED, "ClientId");
|
||||
AddError(ApiErrorCode.VALIDATION_REQUIRED, "CustomerId");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -594,7 +594,7 @@ namespace AyaNova.Biz
|
||||
UserType = o.UserType,
|
||||
EmployeeNumber = o.EmployeeNumber,
|
||||
Notes = o.Notes,
|
||||
ClientId = o.ClientId,
|
||||
CustomerId = o.CustomerId,
|
||||
HeadOfficeId = o.HeadOfficeId,
|
||||
SubVendorId = o.SubVendorId
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace AyaNova.Biz
|
||||
Administrator = 1,
|
||||
Schedulable = 2,
|
||||
NonSchedulable = 3,
|
||||
Client = 4,
|
||||
Customer = 4,
|
||||
HeadOffice = 5,
|
||||
Utility = 6,
|
||||
Subcontractor = 7
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace AyaNova.Models
|
||||
[MaxLength(255)]
|
||||
public string EmployeeNumber { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public long? ClientId { get; set; }
|
||||
public long? CustomerId { get; set; }
|
||||
public long? HeadOfficeId { get; set; }
|
||||
public long? SubVendorId { get; set; }
|
||||
public string CustomFields { get; set; }
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace AyaNova.Util
|
||||
//Add user table
|
||||
exec("CREATE TABLE auser (id BIGSERIAL PRIMARY KEY, active bool not null, name varchar(255) not null, " +
|
||||
"login text not null, password text not null, salt text not null, roles integer not null, localeid bigint not null REFERENCES alocale (id), " +
|
||||
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, clientid bigint, " +
|
||||
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " +
|
||||
"headofficeid bigint, subvendorid bigint, customfields text, tags varchar(255) ARRAY)");
|
||||
|
||||
//Index for name fetching
|
||||
|
||||
@@ -205,11 +205,11 @@ namespace AyaNova.Util
|
||||
//1 accountant / bookkeeper
|
||||
GenSeedUser(log, 1, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable, timeZoneOffset);
|
||||
|
||||
//10 full on client users
|
||||
GenSeedUser(log, 10, AuthorizationRoles.ClientLimited, UserType.Client, timeZoneOffset);
|
||||
//10 full on customer users
|
||||
GenSeedUser(log, 10, AuthorizationRoles.CustomerLimited, UserType.Customer, timeZoneOffset);
|
||||
|
||||
//10 limited client users
|
||||
GenSeedUser(log, 10, AuthorizationRoles.ClientLimited, UserType.Client, timeZoneOffset);
|
||||
//10 limited customer users
|
||||
GenSeedUser(log, 10, AuthorizationRoles.CustomerLimited, UserType.Customer, timeZoneOffset);
|
||||
//PERF
|
||||
watch.Stop();
|
||||
LogStatus(JobId, LogJob, log, $"{SeededUserCount} Users seeded in {watch.ElapsedMilliseconds} ms");
|
||||
@@ -280,11 +280,11 @@ namespace AyaNova.Util
|
||||
//5 accountant / bookkeeper
|
||||
GenSeedUser(log, 5, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable, timeZoneOffset);
|
||||
|
||||
//100 full on client users
|
||||
GenSeedUser(log, 20, AuthorizationRoles.ClientFull, UserType.Client, timeZoneOffset);
|
||||
//100 full on customer users
|
||||
GenSeedUser(log, 20, AuthorizationRoles.CustomerFull, UserType.Customer, timeZoneOffset);
|
||||
|
||||
//100 limited client users
|
||||
GenSeedUser(log, 20, AuthorizationRoles.ClientLimited, UserType.Client, timeZoneOffset);
|
||||
//100 limited customer users
|
||||
GenSeedUser(log, 20, AuthorizationRoles.CustomerLimited, UserType.Customer, timeZoneOffset);
|
||||
|
||||
//PERF
|
||||
watch.Stop();
|
||||
@@ -356,11 +356,11 @@ namespace AyaNova.Util
|
||||
//accountant / bookkeeper
|
||||
GenSeedUser(log, 20, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable, timeZoneOffset);
|
||||
|
||||
//full on client users
|
||||
GenSeedUser(log, 200, AuthorizationRoles.ClientFull, UserType.Client, timeZoneOffset);
|
||||
//full on customer users
|
||||
GenSeedUser(log, 200, AuthorizationRoles.CustomerFull, UserType.Customer, timeZoneOffset);
|
||||
|
||||
//limited client users
|
||||
GenSeedUser(log, 50, AuthorizationRoles.ClientLimited, UserType.Client, timeZoneOffset);
|
||||
//limited customer users
|
||||
GenSeedUser(log, 50, AuthorizationRoles.CustomerLimited, UserType.Customer, timeZoneOffset);
|
||||
|
||||
//PERF
|
||||
watch.Stop();
|
||||
@@ -444,8 +444,8 @@ namespace AyaNova.Util
|
||||
|
||||
GenSeedUser(log, 1, AuthorizationRoles.SubContractorLimited, UserType.Subcontractor, timeZoneOffset, "SubContractorLimited", "SubContractorLimited");
|
||||
GenSeedUser(log, 1, AuthorizationRoles.SubContractorFull, UserType.Subcontractor, timeZoneOffset, "SubContractorFull", "SubContractorFull");
|
||||
GenSeedUser(log, 1, AuthorizationRoles.ClientLimited, UserType.Client, timeZoneOffset, "ClientLimited", "ClientLimited");
|
||||
GenSeedUser(log, 1, AuthorizationRoles.ClientFull, UserType.Client, timeZoneOffset, "ClientFull", "ClientFull");
|
||||
GenSeedUser(log, 1, AuthorizationRoles.CustomerLimited, UserType.Customer, timeZoneOffset, "CustomerLimited", "CustomerLimited");
|
||||
GenSeedUser(log, 1, AuthorizationRoles.CustomerFull, UserType.Customer, timeZoneOffset, "CustomerFull", "CustomerFull");
|
||||
|
||||
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable, timeZoneOffset, "OpsAdminLimited", "OpsAdminLimited");
|
||||
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminFull, UserType.NonSchedulable, timeZoneOffset, "OpsAdminFull", "OpsAdminFull");
|
||||
|
||||
Reference in New Issue
Block a user