This commit is contained in:
2020-06-27 14:01:23 +00:00
parent 9c0f00fbb0
commit 50901186d3
27 changed files with 244 additions and 196 deletions

View File

@@ -78,15 +78,15 @@ namespace AyaNova.Api.Controllers
if (!ModelState.IsValid) if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState)); return BadRequest(new ApiErrorResponse(ModelState));
var dbObj = await ct.FileAttachment.SingleOrDefaultAsync(z => z.Id == id); var dbObject = await ct.FileAttachment.SingleOrDefaultAsync(z => z.Id == id);
if (dbObj == null) if (dbObject == null)
{ {
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
} }
long UserId = UserIdFromContext.Id(HttpContext.Items); long UserId = UserIdFromContext.Id(HttpContext.Items);
if (!Authorized.HasModifyRole(HttpContext.Items, dbObj.AttachToObjectType)) if (!Authorized.HasModifyRole(HttpContext.Items, dbObject.AttachToObjectType))
{ {
return StatusCode(403, new ApiNotAuthorizedResponse()); return StatusCode(403, new ApiNotAuthorizedResponse());
} }
@@ -95,27 +95,27 @@ namespace AyaNova.Api.Controllers
try try
{ {
string ChangeTextra = string.Empty; string ChangeTextra = string.Empty;
if (dbObj.DisplayFileName != inObj.DisplayFileName) if (dbObject.DisplayFileName != inObj.DisplayFileName)
{ {
ChangeTextra = $"\"{dbObj.DisplayFileName}\" => \"{inObj.DisplayFileName}\""; ChangeTextra = $"\"{dbObject.DisplayFileName}\" => \"{inObj.DisplayFileName}\"";
} }
if (dbObj.Notes != inObj.Notes) if (dbObject.Notes != inObj.Notes)
{ {
if (!string.IsNullOrWhiteSpace(ChangeTextra)) if (!string.IsNullOrWhiteSpace(ChangeTextra))
ChangeTextra += ", "; ChangeTextra += ", ";
ChangeTextra += "Notes"; ChangeTextra += "Notes";
} }
dbObj.DisplayFileName = inObj.DisplayFileName; dbObject.DisplayFileName = inObj.DisplayFileName;
dbObj.Notes = inObj.Notes; dbObject.Notes = inObj.Notes;
//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["Concurrency"] = inObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
//Log event and save context //Log event and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentModified, ChangeTextra), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.AttachToObjectId, dbObject.AttachToObjectType, AyaEvent.AttachmentModified, ChangeTextra), ct);
@@ -133,7 +133,7 @@ namespace AyaNova.Api.Controllers
} }
//Normallyh wouldn't return a whole list but in this case the UI demands it because of reactivity issues //Normallyh wouldn't return a whole list but in this case the UI demands it because of reactivity issues
var ret = await GetFileListForObjectAsync(dbObj.AttachToObjectType, dbObj.AttachToObjectId); var ret = await GetFileListForObjectAsync(dbObject.AttachToObjectType, dbObject.AttachToObjectId);
return Ok(ApiOkResponse.Response(ret)); return Ok(ApiOkResponse.Response(ret));
} }
@@ -367,28 +367,28 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState)); return BadRequest(new ApiErrorResponse(ModelState));
} }
var dbObj = await ct.FileAttachment.SingleOrDefaultAsync(z => z.Id == id); var dbObject = await ct.FileAttachment.SingleOrDefaultAsync(z => z.Id == id);
if (dbObj == null) if (dbObject == null)
{ {
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
} }
long UserId = UserIdFromContext.Id(HttpContext.Items); long UserId = UserIdFromContext.Id(HttpContext.Items);
if (!Authorized.HasDeleteRole(HttpContext.Items, dbObj.AttachToObjectType)) if (!Authorized.HasDeleteRole(HttpContext.Items, dbObject.AttachToObjectType))
{ {
return StatusCode(403, new ApiNotAuthorizedResponse()); return StatusCode(403, new ApiNotAuthorizedResponse());
} }
//do the delete //do the delete
//this handles removing the file if there are no refs left and also the db record for the attachment //this handles removing the file if there are no refs left and also the db record for the attachment
await FileUtil.DeleteFileAttachmentAsync(dbObj, ct); await FileUtil.DeleteFileAttachmentAsync(dbObject, ct);
//Event log process delete //Event log process delete
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.AttachToObjectId, dbObject.AttachToObjectType, AyaEvent.AttachmentDelete, dbObject.DisplayFileName), ct);
//Delete search index //Delete search index
await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, AyaType.FileAttachment); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.FileAttachment, ct);
return NoContent(); return NoContent();
} }
@@ -448,8 +448,8 @@ namespace AyaNova.Api.Controllers
} }
//Ok, user has a valid download key and it's not expired yet so get the attachment record //Ok, user has a valid download key and it's not expired yet so get the attachment record
var dbObj = await ct.FileAttachment.SingleOrDefaultAsync(z => z.Id == id); var dbObject = await ct.FileAttachment.SingleOrDefaultAsync(z => z.Id == id);
if (dbObj == null) if (dbObject == null)
{ {
await Task.Delay(nFailedAuthDelay);//fishing protection await Task.Delay(nFailedAuthDelay);//fishing protection
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
@@ -457,15 +457,15 @@ namespace AyaNova.Api.Controllers
//is this allowed? //is this allowed?
if (!Authorized.HasReadFullRole(DownloadUser.Roles, dbObj.AttachToObjectType)) if (!Authorized.HasReadFullRole(DownloadUser.Roles, dbObject.AttachToObjectType))
{ {
await Task.Delay(nFailedAuthDelay);//DOS protection await Task.Delay(nFailedAuthDelay);//DOS protection
return StatusCode(403, new ApiNotAuthorizedResponse()); return StatusCode(403, new ApiNotAuthorizedResponse());
} }
//they are allowed, let's send the file //they are allowed, let's send the file
string mimetype = dbObj.ContentType; string mimetype = dbObject.ContentType;
var filePath = FileUtil.GetPermanentAttachmentFilePath(dbObj.StoredFileName); var filePath = FileUtil.GetPermanentAttachmentFilePath(dbObject.StoredFileName);
if (!System.IO.File.Exists(filePath)) if (!System.IO.File.Exists(filePath))
{ {
//TODO: notify OPSNOTIFY //TODO: notify OPSNOTIFY
@@ -473,16 +473,16 @@ namespace AyaNova.Api.Controllers
//and a red light on the dashboard //and a red light on the dashboard
//TODO: this should reset the validity //TODO: this should reset the validity
var errText = $"Physical file {dbObj.StoredFileName} not found despite attachment record, this file is missing"; var errText = $"Physical file {dbObject.StoredFileName} not found despite attachment record, this file is missing";
log.LogError(errText); log.LogError(errText);
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND, null, errText)); return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND, null, errText));
} }
//Log //Log
await EventLogProcessor.LogEventToDatabaseAsync(new Event(DownloadUser.Id, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(DownloadUser.Id, dbObject.AttachToObjectId, dbObject.AttachToObjectType, AyaEvent.AttachmentDownload, dbObject.DisplayFileName), ct);
return PhysicalFile(filePath, mimetype, dbObj.DisplayFileName); return PhysicalFile(filePath, mimetype, dbObject.DisplayFileName);
} }
@@ -491,11 +491,11 @@ namespace AyaNova.Api.Controllers
async private Task<object> GetFileListForObjectAsync(AyaType ayaType, long ayaId) async private Task<object> GetFileListForObjectAsync(AyaType ayaType, long ayaId)
{ {
var l = await ct.FileAttachment.AsNoTracking().Where(z => z.AttachToObjectId == ayaId && z.AttachToObjectType == ayaType) return await ct.FileAttachment.AsNoTracking().Where(z => z.AttachToObjectId == ayaId && z.AttachToObjectType == ayaType).OrderBy(z => z.DisplayFileName)
.Select(z => new { z.Id, z.Concurrency, z.ContentType, z.DisplayFileName, z.LastModified, z.Notes }) .Select(z => new { z.Id, z.Concurrency, z.ContentType, z.DisplayFileName, z.LastModified, z.Notes })
.ToArrayAsync(); .ToArrayAsync();
var v = l.OrderBy(z => z.DisplayFileName); // var v = l.OrderBy(z => z.DisplayFileName);
return v; // return v;
} }

View File

@@ -226,8 +226,8 @@ namespace AyaNova.Api.Controllers
//Fetch translation and it's children //Fetch translation and it's children
//(fetch here so can return proper REST responses on failing basic validity) //(fetch here so can return proper REST responses on failing basic validity)
var dbObj = await ct.Translation.Include(z => z.TranslationItems).SingleOrDefaultAsync(z => z.Id == id); var dbObject = await ct.Translation.Include(z => z.TranslationItems).SingleOrDefaultAsync(z => z.Id == id);
if (dbObj == null) if (dbObject == null)
{ {
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
} }
@@ -240,7 +240,7 @@ namespace AyaNova.Api.Controllers
//Instantiate the business object handler //Instantiate the business object handler
TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext); TranslationBiz biz = TranslationBiz.GetBiz(ct, HttpContext);
if (!await biz.DeleteAsync(dbObj)) if (!await biz.DeleteAsync(dbObject))
{ {
return BadRequest(new ApiErrorResponse(biz.Errors)); return BadRequest(new ApiErrorResponse(biz.Errors));
} }

View File

@@ -260,8 +260,8 @@ namespace AyaNova.Api.Controllers
//Instantiate the business object handler //Instantiate the business object handler
UserBiz biz = UserBiz.GetBiz(ct, HttpContext); UserBiz biz = UserBiz.GetBiz(ct, HttpContext);
var dbObj = await ct.User.SingleOrDefaultAsync(z => z.Id == id); var dbObject = await ct.User.SingleOrDefaultAsync(z => z.Id == id);
if (dbObj == null) if (dbObject == null)
{ {
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
} }
@@ -272,7 +272,7 @@ namespace AyaNova.Api.Controllers
} }
if (!await biz.DeleteAsync(dbObj)) if (!await biz.DeleteAsync(dbObject))
{ {
return BadRequest(new ApiErrorResponse(biz.Errors)); return BadRequest(new ApiErrorResponse(biz.Errors));
} }

View File

@@ -151,10 +151,11 @@ namespace AyaNova.Biz
ct.Contract.Remove(dbObject); ct.Contract.Remove(dbObject);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType,ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType,ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -80,18 +80,18 @@ namespace AyaNova.Biz
//DUPLICATE //DUPLICATE
// //
internal async Task<DataListView> DuplicateAsync(DataListView dbObj) internal async Task<DataListView> DuplicateAsync(DataListView dbObject)
{ {
DataListView outObj = new DataListView(); DataListView outObj = new DataListView();
CopyObject.Copy(dbObj, outObj); CopyObject.Copy(dbObject, outObj);
//generate unique name //generate unique name
string newUniqueName = string.Empty; string newUniqueName = string.Empty;
bool NotUnique = true; bool NotUnique = true;
long l = 1; long l = 1;
do do
{ {
newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255); newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
NotUnique = await ct.DataListView.AnyAsync(z => z.Name == newUniqueName); NotUnique = await ct.DataListView.AnyAsync(z => z.Name == newUniqueName);
} while (NotUnique); } while (NotUnique);
outObj.Name = newUniqueName; outObj.Name = newUniqueName;
@@ -157,25 +157,25 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(DataListView dbObj, DataListView inObj) internal async Task<bool> PutAsync(DataListView dbObject, DataListView inObj)
{ {
//preserve the owner ID if none was specified //preserve the owner ID if none was specified
if (inObj.UserId == 0) if (inObj.UserId == 0)
inObj.UserId = dbObj.UserId; inObj.UserId = dbObject.UserId;
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObj, "Id"); CopyObject.Copy(inObj, dbObject, "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["Concurrency"] = inObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
await ValidateAsync(dbObj, false); await ValidateAsync(dbObject, false);
if (HasErrors) if (HasErrors)
return false; return false;
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log modification and save context //Log modification and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
@@ -186,27 +186,27 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(DataListView dbObj) internal async Task<bool> DeleteAsync(DataListView dbObject)
{ {
//Determine if the object can be deleted, do the deletion tentatively //Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc //Probably also in here deal with tags and associated search text etc
//FUTURE POSSIBLE NEED //FUTURE POSSIBLE NEED
//ValidateCanDelete(dbObj); //ValidateCanDelete(dbObject);
if (HasErrors) if (HasErrors)
return false; return false;
ct.DataListView.Remove(dbObj); ct.DataListView.Remove(dbObject);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Delete sibling objects //Delete sibling objects
//Event log process delete //Event log process delete
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
//Delete search index //Delete search index
//Search.ProcessDeletedObjectKeywords(dbObj.Id, BizType); //Search.ProcessDeletedObjectKeywords(dbObject.Id, BizType);
return true; return true;

View File

@@ -115,24 +115,24 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(FormCustom dbObj, FormCustom inObj) internal async Task<bool> PutAsync(FormCustom dbObject, FormCustom inObj)
{ {
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObj, "Id"); CopyObject.Copy(inObj, dbObject, "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["Concurrency"] = inObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
await ValidateAsync(dbObj, false); await ValidateAsync(dbObject, false);
if (HasErrors) if (HasErrors)
return false; return false;
dbObj.Template = JsonUtil.CompactJson(dbObj.Template); dbObject.Template = JsonUtil.CompactJson(dbObject.Template);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log modification and save context //Log modification and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
return true; return true;

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -106,11 +106,11 @@ namespace AyaNova.Biz
//DUPLICATE //DUPLICATE
// //
internal async Task<PM> DuplicateAsync(PM dbObj) internal async Task<PM> DuplicateAsync(PM dbObject)
{ await Task.CompletedTask; { await Task.CompletedTask;
throw new System.NotImplementedException("STUB: WORKORDER DUPLICATE"); throw new System.NotImplementedException("STUB: WORKORDER DUPLICATE");
// PM outObj = new PM(); // PM outObj = new PM();
// CopyObject.Copy(dbObj, outObj, "Wiki"); // CopyObject.Copy(dbObject, outObj, "Wiki");
// // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255); // // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
// //generate unique name // //generate unique name
// string newUniqueName = string.Empty; // string newUniqueName = string.Empty;
@@ -118,7 +118,7 @@ namespace AyaNova.Biz
// long l = 1; // long l = 1;
// do // do
// { // {
// newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255); // newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
// NotUnique = await ct.PM.AnyAsync(z => z.Name == newUniqueName); // NotUnique = await ct.PM.AnyAsync(z => z.Name == newUniqueName);
// } while (NotUnique); // } while (NotUnique);
@@ -144,38 +144,38 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(PM dbObj, PM putObj) internal async Task<bool> PutAsync(PM dbObject, PM putObj)
{ {
// make a snapshot of the original for validation but update the original to preserve workflow // make a snapshot of the original for validation but update the original to preserve workflow
PM SnapshotOfOriginalDBObj = new PM(); PM SnapshotOfOriginalDBObj = new PM();
CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj); CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(putObj, dbObj, "Id,Serial"); CopyObject.Copy(putObj, dbObject, "Id,Serial");
//if user has rights then change it, otherwise just ignore it and do the rest //if user has rights then change it, otherwise just ignore it and do the rest
if (SnapshotOfOriginalDBObj.Serial != putObj.Serial && Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial)) if (SnapshotOfOriginalDBObj.Serial != putObj.Serial && Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial))
{ {
dbObj.Serial = putObj.Serial; dbObject.Serial = putObj.Serial;
} }
dbObj.Tags = TagBiz.NormalizeTags(dbObj.Tags); dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields); dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
//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["Concurrency"] = putObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = putObj.Concurrency;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj); await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors) if (HasErrors)
return false; return false;
//Log event and save context //Log event and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObj, false); await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -206,22 +206,22 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(PM dbObj) internal async Task<bool> DeleteAsync(PM dbObject)
{ await Task.CompletedTask; { await Task.CompletedTask;
throw new System.NotImplementedException("STUB: WORKORDER DELETE"); throw new System.NotImplementedException("STUB: WORKORDER DELETE");
//Determine if the object can be deleted, do the deletion tentatively //Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc //Probably also in here deal with tags and associated search text etc
//NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObj); //NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObject);
// if (HasErrors) // if (HasErrors)
// return false; // return false;
// ct.PM.Remove(dbObj); // ct.PM.Remove(dbObject);
// await ct.SaveChangesAsync(); // await ct.SaveChangesAsync();
// //Log event // //Log event
// await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Serial.ToString(), ct); // await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Serial.ToString(), ct);
// await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType); // await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType);
// await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags); // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
// return true; // return true;
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -105,12 +105,12 @@ namespace AyaNova.Biz
//DUPLICATE //DUPLICATE
// //
internal async Task<Quote> DuplicateAsync(Quote dbObj) internal async Task<Quote> DuplicateAsync(Quote dbObject)
{ {
await Task.CompletedTask; await Task.CompletedTask;
throw new System.NotImplementedException("STUB: WORKORDER DUPLICATE"); throw new System.NotImplementedException("STUB: WORKORDER DUPLICATE");
// Quote outObj = new Quote(); // Quote outObj = new Quote();
// CopyObject.Copy(dbObj, outObj, "Wiki"); // CopyObject.Copy(dbObject, outObj, "Wiki");
// // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255); // // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
// //generate unique name // //generate unique name
// string newUniqueName = string.Empty; // string newUniqueName = string.Empty;
@@ -118,7 +118,7 @@ namespace AyaNova.Biz
// long l = 1; // long l = 1;
// do // do
// { // {
// newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255); // newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
// NotUnique = await ct.Quote.AnyAsync(z => z.Name == newUniqueName); // NotUnique = await ct.Quote.AnyAsync(z => z.Name == newUniqueName);
// } while (NotUnique); // } while (NotUnique);
@@ -144,38 +144,38 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(Quote dbObj, Quote putObj) internal async Task<bool> PutAsync(Quote dbObject, Quote putObj)
{ {
// make a snapshot of the original for validation but update the original to preserve workflow // make a snapshot of the original for validation but update the original to preserve workflow
Quote SnapshotOfOriginalDBObj = new Quote(); Quote SnapshotOfOriginalDBObj = new Quote();
CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj); CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(putObj, dbObj, "Id,Serial"); CopyObject.Copy(putObj, dbObject, "Id,Serial");
//if user has rights then change it, otherwise just ignore it and do the rest //if user has rights then change it, otherwise just ignore it and do the rest
if (SnapshotOfOriginalDBObj.Serial != putObj.Serial && Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial)) if (SnapshotOfOriginalDBObj.Serial != putObj.Serial && Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial))
{ {
dbObj.Serial = putObj.Serial; dbObject.Serial = putObj.Serial;
} }
dbObj.Tags = TagBiz.NormalizeTags(dbObj.Tags); dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields); dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
//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["Concurrency"] = putObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = putObj.Concurrency;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj); await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors) if (HasErrors)
return false; return false;
//Log event and save context //Log event and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObj, false); await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -206,23 +206,23 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(Quote dbObj) internal async Task<bool> DeleteAsync(Quote dbObject)
{ {
await Task.CompletedTask; await Task.CompletedTask;
throw new System.NotImplementedException("STUB: WORKORDER DELETE"); throw new System.NotImplementedException("STUB: WORKORDER DELETE");
//Determine if the object can be deleted, do the deletion tentatively //Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc //Probably also in here deal with tags and associated search text etc
//NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObj); //NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObject);
// if (HasErrors) // if (HasErrors)
// return false; // return false;
// ct.Quote.Remove(dbObj); // ct.Quote.Remove(dbObject);
// await ct.SaveChangesAsync(); // await ct.SaveChangesAsync();
// //Log event // //Log event
// await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Serial.ToString(), ct); // await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Serial.ToString(), ct);
// await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType); // await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType);
// await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags); // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
// return true; // return true;
} }

View File

@@ -91,11 +91,11 @@ namespace AyaNova.Biz
//DUPLICATE //DUPLICATE
// //
internal async Task<QuoteTemplate> DuplicateAsync(QuoteTemplate dbObj) internal async Task<QuoteTemplate> DuplicateAsync(QuoteTemplate dbObject)
{ {
QuoteTemplate outObj = new QuoteTemplate(); QuoteTemplate outObj = new QuoteTemplate();
CopyObject.Copy(dbObj, outObj, "Wiki"); CopyObject.Copy(dbObject, outObj, "Wiki");
// outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255); // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
//generate unique name //generate unique name
string newUniqueName = string.Empty; string newUniqueName = string.Empty;
@@ -103,7 +103,7 @@ namespace AyaNova.Biz
long l = 1; long l = 1;
do do
{ {
newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255); newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
NotUnique = await ct.QuoteTemplate.AnyAsync(z => z.Name == newUniqueName); NotUnique = await ct.QuoteTemplate.AnyAsync(z => z.Name == newUniqueName);
} while (NotUnique); } while (NotUnique);
@@ -129,32 +129,32 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(QuoteTemplate dbObj, QuoteTemplate inObj) internal async Task<bool> PutAsync(QuoteTemplate dbObject, QuoteTemplate inObj)
{ {
//make a snapshot of the original for validation but update the original to preserve workflow //make a snapshot of the original for validation but update the original to preserve workflow
QuoteTemplate SnapshotOfOriginalDBObj = new QuoteTemplate(); QuoteTemplate SnapshotOfOriginalDBObj = new QuoteTemplate();
CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj); CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObj, "Id"); CopyObject.Copy(inObj, dbObject, "Id");
dbObj.Tags = TagBiz.NormalizeTags(dbObj.Tags); dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields); dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
//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["Concurrency"] = inObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj); await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors) if (HasErrors)
return false; return false;
//Log event and save context //Log event and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObj, false); await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -183,21 +183,22 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(QuoteTemplate dbObj) internal async Task<bool> DeleteAsync(QuoteTemplate dbObject)
{ {
//Determine if the object can be deleted, do the deletion tentatively //Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc //Probably also in here deal with tags and associated search text etc
//NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObj); //NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObject);
if (HasErrors) if (HasErrors)
return false; return false;
ct.QuoteTemplate.Remove(dbObj); ct.QuoteTemplate.Remove(dbObject);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }

View File

@@ -650,12 +650,11 @@ namespace AyaNova.Biz
await ProcessKeywordsAsync(searchIndexObjectParameters, false); await ProcessKeywordsAsync(searchIndexObjectParameters, false);
} }
public static async Task ProcessDeletedObjectKeywordsAsync(long objectID, AyaType objectType) public static async Task ProcessDeletedObjectKeywordsAsync(long objectID, AyaType objectType, AyContext ct)
{ {
//Be careful in future, if you put ToString at the end of each object in the string interpolation //Be careful in future, if you put ToString at the end of each object in the string interpolation
//npgsql driver will assume it's a string and put quotes around it triggering an error that a string can't be compared to an int //npgsql driver will assume it's a string and put quotes around it triggering an error that a string can't be compared to an int
using (AyContext ct = ServiceProviderProvider.DBContext) await ct.Database.ExecuteSqlInterpolatedAsync($"delete from asearchkey where objectid={objectID} and objecttype={(int)objectType}");
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from asearchkey where objectid={objectID} and objecttype={(int)objectType}");
//nothing to save here, it's a direct command already executed //nothing to save here, it's a direct command already executed
} }

View File

@@ -315,16 +315,16 @@ namespace AyaNova.Biz
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(Translation dbObj) internal async Task<bool> DeleteAsync(Translation dbObject)
{ {
//Determine if the object can be deleted, do the deletion tentatively //Determine if the object can be deleted, do the deletion tentatively
await ValidateCanDeleteAsync(dbObj); await ValidateCanDeleteAsync(dbObject);
if (HasErrors) if (HasErrors)
return false; return false;
ct.Translation.Remove(dbObj); ct.Translation.Remove(dbObject);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log //Log
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.Translation, dbObj.Id, dbObj.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.Translation, dbObject.Id, dbObject.Name, ct);
return true; return true;
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -86,8 +86,8 @@ namespace AyaNova.Biz
{ {
using (AyContext ct = ServiceProviderProvider.DBContext) using (AyContext ct = ServiceProviderProvider.DBContext)
{ {
User dbObj = ct.User.FirstOrDefault(z => z.Id == 1); User dbObject = ct.User.FirstOrDefault(z => z.Id == 1);
dbObj.Password = Hasher.hash(dbObj.Salt, ServerBootConfig.AYANOVA_SET_SUPERUSER_PW); dbObject.Password = Hasher.hash(dbObject.Salt, ServerBootConfig.AYANOVA_SET_SUPERUSER_PW);
ct.SaveChanges(); ct.SaveChanges();
//TODO: notify OPSNOTIFY //TODO: notify OPSNOTIFY
} }
@@ -304,12 +304,12 @@ namespace AyaNova.Biz
// //
internal async Task<bool> ChangePasswordAsync(long userId, string newPassword) internal async Task<bool> ChangePasswordAsync(long userId, string newPassword)
{ {
User dbObj = await ct.User.FirstOrDefaultAsync(z => z.Id == userId); User dbObject = await ct.User.FirstOrDefaultAsync(z => z.Id == userId);
dbObj.Password = Hasher.hash(dbObj.Salt, newPassword); dbObject.Password = Hasher.hash(dbObject.Salt, newPassword);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log modification and save context //Log modification and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
return true; return true;
} }
@@ -340,28 +340,39 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(User dbObj) internal async Task<bool> DeleteAsync(User dbObject)
{ {
await ValidateCanDelete(dbObj); await ValidateCanDelete(dbObject);
if (HasErrors) if (HasErrors)
return false; return false;
//Remove the object using (var transaction = await ct.Database.BeginTransactionAsync())
ct.User.Remove(dbObj); {
await ct.SaveChangesAsync(); try
{
//Remove the object
ct.User.Remove(dbObject);
await ct.SaveChangesAsync();
//Delete sibling objects //Delete sibling objects
//USEROPTIONS //USEROPTIONS
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from auseroptions where userid = {dbObj.Id}"); await ct.Database.ExecuteSqlInterpolatedAsync($"delete from auseroptions where userid = {dbObject.Id}");
//personal datalistview //personal datalistview
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from adatalistview where public = {false} and userid = {dbObj.Id}"); await ct.Database.ExecuteSqlInterpolatedAsync($"delete from adatalistview where public = {false} and userid = {dbObject.Id}");
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags); await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
await transaction.CommitAsync();
return true; }
catch
{
//Just re-throw for now, let exception handler deal, but in future may want to deal with this more here
throw;
}
return true;
}
} }

View File

@@ -43,23 +43,23 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(UserOptions dbObj, UserOptions inObj) internal async Task<bool> PutAsync(UserOptions dbObject, UserOptions inObj)
{ {
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObj, "Id, UserId"); CopyObject.Copy(inObj, dbObject, "Id, UserId");
//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["Concurrency"] = inObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
Validate(dbObj); Validate(dbObject);
if (HasErrors) if (HasErrors)
return false; return false;
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log //Log
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, AyaType.User, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, AyaType.User, AyaEvent.Modified), ct);
return true; return true;
} }

View File

@@ -153,8 +153,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -158,8 +158,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit //all good do the commit
await transaction.CommitAsync(); await transaction.CommitAsync();
} }

View File

@@ -212,8 +212,9 @@ namespace AyaNova.Biz
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Serial.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Serial.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
#if (DEBUG) #if (DEBUG)
@@ -553,8 +554,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItem, dbObject.Id, "wo:" + dbObject.WorkOrderId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItem, dbObject.Id, "wo:" + dbObject.WorkOrderId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItem); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItem, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//all good do the commit if it's ours //all good do the commit if it's ours
if (parentTransaction == null) if (parentTransaction == null)
@@ -756,8 +758,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemExpense, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemExpense, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemExpense); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemExpense, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -945,8 +948,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemLabor, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemLabor, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemLabor); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemLabor, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -1133,8 +1137,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemLoan, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemLoan, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemLoan); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemLoan, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -1322,8 +1327,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemPart, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemPart, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemPart); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemPart, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -1508,8 +1514,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemPartRequest, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemPartRequest, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemPartRequest); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemPartRequest, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -1697,8 +1704,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemScheduledUser, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemScheduledUser, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemScheduledUser); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemScheduledUser, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -1886,8 +1894,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemTask, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemTask, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemTask); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemTask, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -2075,8 +2084,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemTravel, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemTravel, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemTravel); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemTravel, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }
@@ -2264,8 +2274,9 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemUnit, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemUnit, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemUnit); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemUnit, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }

View File

@@ -91,11 +91,11 @@ namespace AyaNova.Biz
//DUPLICATE //DUPLICATE
// //
internal async Task<WorkOrderTemplate> DuplicateAsync(WorkOrderTemplate dbObj) internal async Task<WorkOrderTemplate> DuplicateAsync(WorkOrderTemplate dbObject)
{ {
WorkOrderTemplate outObj = new WorkOrderTemplate(); WorkOrderTemplate outObj = new WorkOrderTemplate();
CopyObject.Copy(dbObj, outObj, "Wiki"); CopyObject.Copy(dbObject, outObj, "Wiki");
// outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255); // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
//generate unique name //generate unique name
string newUniqueName = string.Empty; string newUniqueName = string.Empty;
@@ -103,7 +103,7 @@ namespace AyaNova.Biz
long l = 1; long l = 1;
do do
{ {
newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255); newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
NotUnique = await ct.WorkOrderTemplate.AnyAsync(z => z.Name == newUniqueName); NotUnique = await ct.WorkOrderTemplate.AnyAsync(z => z.Name == newUniqueName);
} while (NotUnique); } while (NotUnique);
@@ -129,32 +129,32 @@ namespace AyaNova.Biz
// //
//put //put
internal async Task<bool> PutAsync(WorkOrderTemplate dbObj, WorkOrderTemplate inObj) internal async Task<bool> PutAsync(WorkOrderTemplate dbObject, WorkOrderTemplate inObj)
{ {
//make a snapshot of the original for validation but update the original to preserve workflow //make a snapshot of the original for validation but update the original to preserve workflow
WorkOrderTemplate SnapshotOfOriginalDBObj = new WorkOrderTemplate(); WorkOrderTemplate SnapshotOfOriginalDBObj = new WorkOrderTemplate();
CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj); CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object //Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObj, "Id"); CopyObject.Copy(inObj, dbObject, "Id");
dbObj.Tags = TagBiz.NormalizeTags(dbObj.Tags); dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields); dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
//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["Concurrency"] = inObj.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj); await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors) if (HasErrors)
return false; return false;
//Log event and save context //Log event and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObj, false); await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
return true; return true;
} }
@@ -184,21 +184,22 @@ namespace AyaNova.Biz
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE //DELETE
// //
internal async Task<bool> DeleteAsync(WorkOrderTemplate dbObj) internal async Task<bool> DeleteAsync(WorkOrderTemplate dbObject)
{ {
//Determine if the object can be deleted, do the deletion tentatively //Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc //Probably also in here deal with tags and associated search text etc
//NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObj); //NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObject);
if (HasErrors) if (HasErrors)
return false; return false;
ct.WorkOrderTemplate.Remove(dbObj); ct.WorkOrderTemplate.Remove(dbObject);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true; return true;
} }

View File

@@ -416,6 +416,19 @@ namespace AyaNova.Util
} }
//////////////////////////////////////////////////////////
//
// Delete all attachments for object
//
internal static async Task DeleteAttachmentsForObjectAsync(AyaType ayaType, long ayaId, AyContext ct)
{
var deleteList = await ct.FileAttachment.Where(z => z.AttachToObjectId == ayaId && z.AttachToObjectType == ayaType).ToListAsync();
foreach (var d in deleteList)
{
await DeleteFileAttachmentAsync(d, ct);
}
}
/// <summary> /// <summary>
/// Delete a file attachment /// Delete a file attachment
/// checks ref count and if would be zero deletes file physically /// checks ref count and if would be zero deletes file physically
@@ -542,9 +555,9 @@ namespace AyaNova.Util
//probably all 64 chars but let's not count on that and go with folder is correct //probably all 64 chars but let's not count on that and go with folder is correct
//what *should* the path be for a file of this name? //what *should* the path be for a file of this name?
var ExpectedFullPath=GetPermanentAttachmentFilePath(FileName); var ExpectedFullPath = GetPermanentAttachmentFilePath(FileName);
//if expected equals real then it's very likely an orphaned file //if expected equals real then it's very likely an orphaned file
return fullPathName==ExpectedFullPath; return fullPathName == ExpectedFullPath;
} }