This commit is contained in:
2018-09-05 18:57:55 +00:00
parent 620a27d35c
commit da9814868b
3 changed files with 94 additions and 79 deletions

View File

@@ -153,19 +153,24 @@ 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 //Get a snapshot of the original db value object before changes
CopyObject.Copy(inObj, dbObj, "Id, Salt, Password"); User SnapshotObj = new User();
CopyObject.Copy(dbObj, SnapshotObj);
//Update the db object with the PUT object values
CopyObject.Copy(inObj, dbObj, "Id, Salt");
//Is the user updating the password? //Is the user updating the password?
if (!string.IsNullOrWhiteSpace(inObj.Password) && dbObj.Password != inObj.Password) if (!string.IsNullOrWhiteSpace(inObj.Password) && SnapshotObj.Password != inObj.Password)
{ {
//YES password is being updated: //YES password is being updated:
inObj.Password = Hasher.hash(inObj.Salt, inObj.Password); dbObj.Password = Hasher.hash(SnapshotObj.Salt, inObj.Password);
} }
else else
{ {
//No, use the db password value //No, use the snapshot password value
//Should not require any code to run as it will retain it's db value dbObj.Password = SnapshotObj.Password;
dbObj.Salt = SnapshotObj.Salt;
} }
@@ -173,7 +178,7 @@ namespace AyaNova.Biz
//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, inObj); Validate(dbObj, SnapshotObj);
if (HasErrors) if (HasErrors)
return false; return false;
@@ -183,15 +188,20 @@ 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 = new User();
//make a snapshot of the original for validation but update the original to preserve workflow
User snapshotObj=null;
CopyObject.Copy(dbObj, snapshotObj); CopyObject.Copy(dbObj, snapshotObj);
//Do the patching //Do the patching
objectPatch.ApplyTo(dbObj); objectPatch.ApplyTo(dbObj);
//Is the user patching the password?
if (!string.IsNullOrWhiteSpace(dbObj.Password) && dbObj.Password != snapshotObj.Password)
{
//YES password is being updated:
dbObj.Password = Hasher.hash(dbObj.Salt, dbObj.Password);
}
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken; ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
Validate(dbObj, snapshotObj); Validate(dbObj, snapshotObj);
if (HasErrors) if (HasErrors)
@@ -237,7 +247,7 @@ namespace AyaNova.Biz
//run validation and biz rules //run validation and biz rules
bool isNew = currentObj == null; bool isNew = currentObj == null;
if (isNew) //Yes, no currentObj 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?

View File

@@ -22,7 +22,10 @@ namespace AyaNova.Util
{ {
string[] excluded = null; string[] excluded = null;
if (!string.IsNullOrEmpty(excludedProperties)) if (!string.IsNullOrEmpty(excludedProperties))
{
excludedProperties=excludedProperties.Replace(", ", ",").Replace(" ,",",").Trim();
excluded = excludedProperties.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); excluded = excludedProperties.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
MemberInfo[] miT = target.GetType().GetMembers(memberAccess); MemberInfo[] miT = target.GetType().GetMembers(memberAccess);
foreach (MemberInfo Field in miT) foreach (MemberInfo Field in miT)

View File

@@ -15,44 +15,44 @@ namespace raven_integration
[Fact] [Fact]
public async void CRUD() public async void CRUD()
{ {
//CREATE //CREATE
dynamic d1 = new JObject(); dynamic D1 = new JObject();
d1.name = Util.Uniquify("First Test User"); D1.name = Util.Uniquify("First Test User");
d1.ownerId = 1L; D1.ownerId = 1L;
d1.active=true; D1.active = true;
d1.login=Util.Uniquify("LOGIN"); D1.login = Util.Uniquify("LOGIN");
d1.password=Util.Uniquify("PASSWORD"); D1.password = Util.Uniquify("PASSWORD");
d1.roles=0;//norole D1.roles = 0;//norole
d1.localeId=1;//random locale D1.localeId = 1;//random locale
d1.userType=3;//non scheduleable D1.userType = 3;//non scheduleable
ApiResponse r1 = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), d1.ToString()); ApiResponse R1 = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), D1.ToString());
Util.ValidateDataReturnResponseOk(r1); Util.ValidateDataReturnResponseOk(R1);
long d1Id = r1.ObjectResponse["result"]["id"].Value<long>(); long d1Id = R1.ObjectResponse["result"]["id"].Value<long>();
dynamic d2 = new JObject(); dynamic D2 = new JObject();
d2.name = Util.Uniquify("Second Test User"); D2.name = Util.Uniquify("Second Test User");
d2.ownerId = 1L; D2.ownerId = 1L;
d2.active=true; D2.active = true;
d2.login=Util.Uniquify("LOGIN"); D2.login = Util.Uniquify("LOGIN");
d2.password=Util.Uniquify("PASSWORD"); D2.password = Util.Uniquify("PASSWORD");
d2.roles=0;//norole D2.roles = 0;//norole
d2.localeId=1;//random locale D2.localeId = 1;//random locale
d2.userType=3;//non scheduleable 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);
long d2Id = r2.ObjectResponse["result"]["id"].Value<long>(); long d2Id = R2.ObjectResponse["result"]["id"].Value<long>();
//RETRIEVE //RETRIEVE
//Get one //Get one
ApiResponse r3 = await Util.GetAsync("User/" + d2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in")); ApiResponse R3 = await Util.GetAsync("User/" + d2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
Util.ValidateDataReturnResponseOk(r3); Util.ValidateDataReturnResponseOk(R3);
r3.ObjectResponse["result"]["name"].Value<string>().Should().Be(d2.name.ToString()); R3.ObjectResponse["result"]["name"].Value<string>().Should().Be(D2.name.ToString());
@@ -60,16 +60,16 @@ namespace raven_integration
//PUT //PUT
//update w2id //update w2id
d2.name = Util.Uniquify("UPDATED VIA PUT SECOND TEST User"); D2.name = Util.Uniquify("UPDATED VIA PUT SECOND TEST User");
d2.OwnerId = 1; D2.OwnerId = 1;
d2.concurrencyToken = r2.ObjectResponse["result"]["concurrencyToken"].Value<uint>(); D2.concurrencyToken = R2.ObjectResponse["result"]["concurrencyToken"].Value<uint>();
ApiResponse PUTTestResponse = await Util.PutAsync("User/" + d2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"), d2.ToString()); ApiResponse PUTTestResponse = await Util.PutAsync("User/" + d2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"), D2.ToString());
Util.ValidateHTTPStatusCode(PUTTestResponse, 200); Util.ValidateHTTPStatusCode(PUTTestResponse, 200);
//check PUT worked //check PUT worked
ApiResponse checkPUTWorked = await Util.GetAsync("User/" + d2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in")); ApiResponse checkPUTWorked = await Util.GetAsync("User/" + d2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
Util.ValidateNoErrorInResponse(checkPUTWorked); Util.ValidateNoErrorInResponse(checkPUTWorked);
checkPUTWorked.ObjectResponse["result"]["name"].Value<string>().Should().Be(d2.name.ToString()); checkPUTWorked.ObjectResponse["result"]["name"].Value<string>().Should().Be(D2.name.ToString());
uint concurrencyToken = PUTTestResponse.ObjectResponse["result"]["concurrencyToken"].Value<uint>(); uint concurrencyToken = PUTTestResponse.ObjectResponse["result"]["concurrencyToken"].Value<uint>();
//PATCH //PATCH
@@ -89,7 +89,7 @@ namespace raven_integration
} }
//TODO: Test password updating code
@@ -101,8 +101,8 @@ namespace raven_integration
{ {
//Get non existant //Get non existant
//Should return status code 404, api error code 2010 //Should return status code 404, api error code 2010
ApiResponse a = await Util.GetAsync("User/999999", await Util.GetTokenAsync("manager", "l3tm3in")); ApiResponse R = await Util.GetAsync("User/999999", await Util.GetTokenAsync("manager", "l3tm3in"));
Util.ValidateResponseNotFound(a); Util.ValidateResponseNotFound(R);
} }
/// <summary> /// <summary>
@@ -113,8 +113,8 @@ namespace raven_integration
{ {
//Get non existant //Get non existant
//Should return status code 400, api error code 2200 and a first target in details of "id" //Should return status code 400, api error code 2200 and a first target in details of "id"
ApiResponse a = await Util.GetAsync("User/2q2", await Util.GetTokenAsync("manager", "l3tm3in")); ApiResponse R = await Util.GetAsync("User/2q2", await Util.GetTokenAsync("manager", "l3tm3in"));
Util.ValidateBadModelStateResponse(a, "id"); Util.ValidateBadModelStateResponse(R, "id");
} }
@@ -128,29 +128,29 @@ namespace raven_integration
[Fact] [Fact]
public async void PutConcurrencyViolationShouldFail() public async void PutConcurrencyViolationShouldFail()
{ {
//CREATE
dynamic D = new JObject();
D.name = Util.Uniquify("PutConcurrencyViolationShouldFail");
D.ownerId = 1L;
D.active = true;
D.login = Util.Uniquify("LOGIN");
D.password = Util.Uniquify("PASSWORD");
D.roles = 0;//norole
D.localeId = 1;//random locale
D.userType = 3;//non scheduleable
//CREATE ApiResponse R = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), D.ToString());
Util.ValidateDataReturnResponseOk(R);
dynamic w2 = new JObject(); long D1Id = R.ObjectResponse["result"]["id"].Value<long>();
w2.name = Util.Uniquify("PutConcurrencyViolationShouldFail"); uint OriginalConcurrencyToken = R.ObjectResponse["result"]["concurrencyToken"].Value<uint>();
w2.dollarAmount = 2.22m;
w2.active = true;
w2.roles = 0;
ApiResponse r2 = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), w2.ToString());
Util.ValidateDataReturnResponseOk(r2);
long w2Id = r2.ObjectResponse["result"]["id"].Value<long>();
uint OriginalConcurrencyToken = r2.ObjectResponse["result"]["concurrencyToken"].Value<uint>();
//UPDATE //UPDATE
//PUT //PUT
w2.name = Util.Uniquify("PutConcurrencyViolationShouldFail UPDATE VIA PUT "); D.name = Util.Uniquify("PutConcurrencyViolationShouldFail UPDATE VIA PUT ");
w2.OwnerId = 1; D.concurrencyToken = OriginalConcurrencyToken - 1;//bad token
w2.concurrencyToken = OriginalConcurrencyToken - 1;//bad token ApiResponse PUTTestResponse = await Util.PutAsync("User/" + D1Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"), D.ToString());
ApiResponse PUTTestResponse = await Util.PutAsync("User/" + w2Id.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"), w2.ToString());
Util.ValidateConcurrencyError(PUTTestResponse); Util.ValidateConcurrencyError(PUTTestResponse);
@@ -165,19 +165,21 @@ namespace raven_integration
[Fact] [Fact]
public async void PatchConcurrencyViolationShouldFail() public async void PatchConcurrencyViolationShouldFail()
{ {
//CREATE //CREATE
dynamic D = new JObject();
D.name = Util.Uniquify("PatchConcurrencyViolationShouldFail");
D.ownerId = 1L;
D.active = true;
D.login = Util.Uniquify("LOGIN");
D.password = Util.Uniquify("PASSWORD");
D.roles = 0;//norole
D.localeId = 1;//random locale
D.userType = 3;//non scheduleable
dynamic w2 = new JObject(); ApiResponse R = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), D.ToString());
w2.name = Util.Uniquify("PatchConcurrencyViolationShouldFail"); Util.ValidateDataReturnResponseOk(R);
w2.dollarAmount = 2.22m; long w2Id = R.ObjectResponse["result"]["id"].Value<long>();
w2.active = true; uint OriginalConcurrencyToken = R.ObjectResponse["result"]["concurrencyToken"].Value<uint>();
w2.roles = 0;
ApiResponse r2 = await Util.PostAsync("User", await Util.GetTokenAsync("manager", "l3tm3in"), w2.ToString());
Util.ValidateDataReturnResponseOk(r2);
long w2Id = r2.ObjectResponse["result"]["id"].Value<long>();
uint OriginalConcurrencyToken = r2.ObjectResponse["result"]["concurrencyToken"].Value<uint>();
//PATCH //PATCH