This commit is contained in:
@@ -40,7 +40,7 @@ namespace AyaNova.Biz
|
|||||||
inObj.Salt = Hasher.GenerateSalt();
|
inObj.Salt = Hasher.GenerateSalt();
|
||||||
inObj.Password = Hasher.hash(inObj.Salt, inObj.Password);
|
inObj.Password = Hasher.hash(inObj.Salt, inObj.Password);
|
||||||
|
|
||||||
Validate(inObj, true);
|
Validate(inObj, null);
|
||||||
if (HasErrors)
|
if (HasErrors)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
@@ -153,14 +153,27 @@ namespace AyaNova.Biz
|
|||||||
//put
|
//put
|
||||||
internal bool Put(User dbObj, User inObj)
|
internal bool Put(User dbObj, User inObj)
|
||||||
{
|
{
|
||||||
|
//Replace the db object with the PUT object skipping the password and salt and Id fields
|
||||||
|
CopyObject.Copy(inObj, dbObj, "Id, Salt, Password");
|
||||||
|
|
||||||
|
//Is the user updating the password?
|
||||||
|
if (!string.IsNullOrWhiteSpace(inObj.Password) && dbObj.Password != inObj.Password)
|
||||||
|
{
|
||||||
|
//YES password is being updated:
|
||||||
|
inObj.Password = Hasher.hash(inObj.Salt, inObj.Password);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//No, use the db password value
|
||||||
|
//Should not require any code to run as it will retain it's db value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Replace the db object with the PUT object
|
|
||||||
CopyObject.Copy(inObj, dbObj, "Id");
|
|
||||||
//Set "original" value of concurrency token to input token
|
//Set "original" value of concurrency token to input token
|
||||||
//this will allow EF to check it out
|
//this will allow EF to check it out
|
||||||
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
|
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
|
||||||
|
|
||||||
Validate(dbObj, false);
|
Validate(dbObj, inObj);
|
||||||
if (HasErrors)
|
if (HasErrors)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -170,10 +183,17 @@ namespace AyaNova.Biz
|
|||||||
//patch
|
//patch
|
||||||
internal bool Patch(User dbObj, JsonPatchDocument<User> objectPatch, uint concurrencyToken)
|
internal bool Patch(User dbObj, JsonPatchDocument<User> objectPatch, uint concurrencyToken)
|
||||||
{
|
{
|
||||||
|
//TODO: objectPatch handle patching password
|
||||||
|
|
||||||
|
//make a snapshot of the original for validation but update the original to preserve workflow
|
||||||
|
|
||||||
|
User snapshotObj=null;
|
||||||
|
CopyObject.Copy(dbObj, snapshotObj);
|
||||||
|
|
||||||
//Do the patching
|
//Do the patching
|
||||||
objectPatch.ApplyTo(dbObj);
|
objectPatch.ApplyTo(dbObj);
|
||||||
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
|
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
|
||||||
Validate(dbObj, false);
|
Validate(dbObj, snapshotObj);
|
||||||
if (HasErrors)
|
if (HasErrors)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -212,14 +232,17 @@ namespace AyaNova.Biz
|
|||||||
//
|
//
|
||||||
|
|
||||||
//Can save or update?
|
//Can save or update?
|
||||||
private void Validate(User inObj, bool isNew)
|
private void Validate(User proposedObj, User currentObj)
|
||||||
{
|
{
|
||||||
//run validation and biz rules
|
//run validation and biz rules
|
||||||
if (isNew)
|
bool isNew = currentObj == null;
|
||||||
|
|
||||||
|
|
||||||
|
if (isNew) //Yes, no currentObj
|
||||||
{
|
{
|
||||||
//Not sure why we would care about this particular rule or why I added it? Maybe it's from widget?
|
//Not sure why we would care about this particular rule or why I added it? Maybe it's from widget?
|
||||||
// //NEW Users must be active
|
// //NEW Users must be active
|
||||||
// if (((bool)inObj.Active) == false)
|
// if (((bool)proposedObj.Active) == false)
|
||||||
// {
|
// {
|
||||||
// AddError(ValidationErrorType.InvalidValue, "Active", "New User must be active");
|
// AddError(ValidationErrorType.InvalidValue, "Active", "New User must be active");
|
||||||
// }
|
// }
|
||||||
@@ -228,23 +251,23 @@ namespace AyaNova.Biz
|
|||||||
//OwnerId required
|
//OwnerId required
|
||||||
if (!isNew)
|
if (!isNew)
|
||||||
{
|
{
|
||||||
if (inObj.OwnerId == 0)
|
if (proposedObj.OwnerId == 0)
|
||||||
AddError(ValidationErrorType.RequiredPropertyEmpty, "OwnerId");
|
AddError(ValidationErrorType.RequiredPropertyEmpty, "OwnerId");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Name required
|
//Name required
|
||||||
if (string.IsNullOrWhiteSpace(inObj.Name))
|
if (string.IsNullOrWhiteSpace(proposedObj.Name))
|
||||||
AddError(ValidationErrorType.RequiredPropertyEmpty, "Name");
|
AddError(ValidationErrorType.RequiredPropertyEmpty, "Name");
|
||||||
|
|
||||||
//Name must be less than 255 characters
|
//Name must be less than 255 characters
|
||||||
if (inObj.Name.Length > 255)
|
if (proposedObj.Name.Length > 255)
|
||||||
AddError(ValidationErrorType.LengthExceeded, "Name", "255 max");
|
AddError(ValidationErrorType.LengthExceeded, "Name", "255 max");
|
||||||
|
|
||||||
//If name is otherwise OK, check that name is unique
|
//If name is otherwise OK, check that name is unique
|
||||||
if (!PropertyHasErrors("Name"))
|
if (!PropertyHasErrors("Name"))
|
||||||
{
|
{
|
||||||
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
|
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
|
||||||
if (ct.User.Any(m => m.Name == inObj.Name && m.Id != inObj.Id))
|
if (ct.User.Any(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id))
|
||||||
{
|
{
|
||||||
AddError(ValidationErrorType.NotUnique, "Name");
|
AddError(ValidationErrorType.NotUnique, "Name");
|
||||||
}
|
}
|
||||||
@@ -278,15 +301,15 @@ namespace AyaNova.Biz
|
|||||||
need to check open workorders and any other critical items when de-activating a user
|
need to check open workorders and any other critical items when de-activating a user
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!inObj.UserType.IsValid())
|
if (!proposedObj.UserType.IsValid())
|
||||||
{
|
{
|
||||||
AddError(ValidationErrorType.InvalidValue, "UserType");
|
AddError(ValidationErrorType.InvalidValue, "UserType");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Validate client type user
|
//Validate client type user
|
||||||
if (!V7ValidationImportMode && inObj.UserType == UserType.Client)
|
if (!V7ValidationImportMode && proposedObj.UserType == UserType.Client)
|
||||||
{
|
{
|
||||||
if (inObj.ClientId == null || inObj.ClientId == 0)
|
if (proposedObj.ClientId == null || proposedObj.ClientId == 0)
|
||||||
{
|
{
|
||||||
AddError(ValidationErrorType.RequiredPropertyEmpty, "ClientId");
|
AddError(ValidationErrorType.RequiredPropertyEmpty, "ClientId");
|
||||||
}
|
}
|
||||||
@@ -298,9 +321,9 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Validate headoffice type user
|
//Validate headoffice type user
|
||||||
if (!V7ValidationImportMode && inObj.UserType == UserType.HeadOffice)
|
if (!V7ValidationImportMode && proposedObj.UserType == UserType.HeadOffice)
|
||||||
{
|
{
|
||||||
if (inObj.HeadOfficeId == null || inObj.HeadOfficeId == 0)
|
if (proposedObj.HeadOfficeId == null || proposedObj.HeadOfficeId == 0)
|
||||||
{
|
{
|
||||||
AddError(ValidationErrorType.RequiredPropertyEmpty, "HeadOfficeId");
|
AddError(ValidationErrorType.RequiredPropertyEmpty, "HeadOfficeId");
|
||||||
}
|
}
|
||||||
@@ -312,9 +335,9 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Validate headoffice type user
|
//Validate headoffice type user
|
||||||
if (!V7ValidationImportMode && inObj.UserType == UserType.Subcontractor)
|
if (!V7ValidationImportMode && proposedObj.UserType == UserType.Subcontractor)
|
||||||
{
|
{
|
||||||
if (inObj.SubVendorId == null || inObj.SubVendorId == 0)
|
if (proposedObj.SubVendorId == null || proposedObj.SubVendorId == 0)
|
||||||
{
|
{
|
||||||
AddError(ValidationErrorType.RequiredPropertyEmpty, "SubVendorId");
|
AddError(ValidationErrorType.RequiredPropertyEmpty, "SubVendorId");
|
||||||
}
|
}
|
||||||
@@ -325,13 +348,13 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inObj.Roles.IsValid())
|
if (!proposedObj.Roles.IsValid())
|
||||||
{
|
{
|
||||||
AddError(ValidationErrorType.InvalidValue, "Roles");
|
AddError(ValidationErrorType.InvalidValue, "Roles");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Optional employee number field must be less than 255 characters
|
//Optional employee number field must be less than 255 characters
|
||||||
if (!string.IsNullOrWhiteSpace(inObj.EmployeeNumber) && inObj.EmployeeNumber.Length > 255)
|
if (!string.IsNullOrWhiteSpace(proposedObj.EmployeeNumber) && proposedObj.EmployeeNumber.Length > 255)
|
||||||
AddError(ValidationErrorType.LengthExceeded, "EmployeeNumber", "255 max");
|
AddError(ValidationErrorType.LengthExceeded, "EmployeeNumber", "255 max");
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,16 @@ namespace raven_integration
|
|||||||
Util.ValidateDataReturnResponseOk(r1);
|
Util.ValidateDataReturnResponseOk(r1);
|
||||||
long d1Id = r1.ObjectResponse["result"]["id"].Value<long>();
|
long d1Id = r1.ObjectResponse["result"]["id"].Value<long>();
|
||||||
|
|
||||||
HERE
|
|
||||||
dynamic d2 = new JObject();
|
dynamic d2 = new JObject();
|
||||||
d2.name = Util.Uniquify("Second Test User");
|
d2.name = Util.Uniquify("Second Test User");
|
||||||
d2.dollarAmount = 2.22m;
|
d2.ownerId = 1L;
|
||||||
d2.active = true;
|
d2.active=true;
|
||||||
d2.roles = 0;
|
d2.login=Util.Uniquify("LOGIN");
|
||||||
|
d2.password=Util.Uniquify("PASSWORD");
|
||||||
|
d2.roles=0;//norole
|
||||||
|
d2.localeId=1;//random locale
|
||||||
|
d2.userType=3;//non scheduleable
|
||||||
|
|
||||||
ApiResponse r2 = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), d2.ToString());
|
ApiResponse r2 = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), d2.ToString());
|
||||||
Util.ValidateDataReturnResponseOk(r2);
|
Util.ValidateDataReturnResponseOk(r2);
|
||||||
|
|||||||
Reference in New Issue
Block a user