This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
Business history log
|
||||
|
||||
FROM CASE 79
|
||||
A central event log used to track major changes to business objects and major events of significance in AyaNova.
|
||||
??Has some sort of checksum or verification so we can tell it wasn't fucked with (too hard to implement, would be something like a blockchain?)
|
||||
A central event log used to track major changes to business objects and major events of significance in AyaNova
|
||||
Consumed by various widgets for record history purposes
|
||||
Default feature, no need to turn on or off keeps logs for 45 days, users who want more can
|
||||
Default feature, no need to turn on or off
|
||||
Items are only removed from log when source object is deleted (and replaced with a deleted entry and textual description of deleted item)
|
||||
Needs a cleaner job that periodically looks for non-existant objects that are logged
|
||||
Has to handle a scenario where there is no data for an object because in future we will likely have a purge feature or maybe a feature to turn it off and needs to accept that scenario
|
||||
?FUTURE: Has some sort of checksum or verification so we can tell it wasn't fucked with (too hard to implement, would be something like a blockchain?)
|
||||
?FUTURE: Needs a cleaner job that periodically looks for non-existant objects that are logged
|
||||
?FUTURE: keeps logs for 45 days initially keeps forever or until object is deleted
|
||||
|
||||
|
||||
ROUTES
|
||||
------
|
||||
|
||||
@@ -20,7 +20,7 @@ CODING WORK
|
||||
|
||||
Overall plan for now: anything standing in the way of making the initial client shell UI needs to be done first, everything else can wait
|
||||
- Audit log
|
||||
- Route for retrieving as log format for reading (like reports: one for specific object id and type, one for user id as log of what they've been doing etc)
|
||||
- Make sure trial generated data generates log events so that we can properly test with huge dataset
|
||||
- Test with huge dataset
|
||||
- Remove CREATED from all objects now that event log tracks it
|
||||
- Localized text
|
||||
|
||||
@@ -239,7 +239,7 @@ namespace AyaNova.Api.Controllers
|
||||
});
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserId, attachToObject.ObjectId, attachToObject.ObjectType, AyaEvent.AttachmentCreate, v.DisplayFileName), ct);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -306,7 +306,7 @@ namespace AyaNova.Api.Controllers
|
||||
FileUtil.deleteFileAttachment(dbObj, ct);
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDelete, dbObj.DisplayFileName), ct);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
@@ -385,7 +385,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserId, dbObj.AttachToObjectId, dbObj.AttachToObjectType, AyaEvent.AttachmentDownload, dbObj.DisplayFileName), ct);
|
||||
|
||||
return PhysicalFile(filePath, mimetype, dbObj.DisplayFileName);
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
var ret = AyaNova.Core.License.LicenseInfoAsJson;
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(ret));
|
||||
}
|
||||
@@ -179,7 +179,7 @@ namespace AyaNova.Api.Controllers
|
||||
var ret = Core.License.RequestTrial(requestData.EmailAddress, requestData.RegisteredTo, log);
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(ret));
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace AyaNova.Api.Controllers
|
||||
await ct.SaveChangesAsync();
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Locale, AyaEvent.Created), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Locale, AyaEvent.Created), ct);
|
||||
|
||||
return CreatedAtAction("GetLocale", new { id = o.Id }, new ApiCreatedResponse(o));
|
||||
}
|
||||
@@ -241,7 +241,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, oDbParent.Id, AyaType.Locale, AyaEvent.Modified), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(biz.userId, oDbParent.Id, AyaType.Locale, AyaEvent.Modified), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken }));
|
||||
}
|
||||
@@ -310,7 +310,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, oFromDb.Id, AyaType.Locale, AyaEvent.Modified), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(biz.userId, oFromDb.Id, AyaType.Locale, AyaEvent.Modified), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken }));
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace AyaNova.Api.Controllers
|
||||
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.LogFile, AyaEvent.Retrieved,logname), ct);
|
||||
// EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.LogFile, AyaEvent.Retrieved,logname), ct);
|
||||
|
||||
return Content(System.IO.File.ReadAllText(logFilePath));
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace AyaNova.Api.Controllers
|
||||
string sResult = await GetTheMetrics("plain");
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
|
||||
|
||||
return Content(sResult);
|
||||
}
|
||||
@@ -99,7 +99,7 @@ namespace AyaNova.Api.Controllers
|
||||
JObject json = JObject.Parse(sResult);
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(json));
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace AyaNova.Api.Controllers
|
||||
serverState.SetState(desiredState, state.Reason);
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerState, AyaEvent.ServerStateChange, $"{state.ServerState}-{state.Reason}"), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerState, AyaEvent.ServerStateChange, $"{state.ServerState}-{state.Reason}"), ct);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace AyaNova.Api.Controllers
|
||||
await ct.SaveChangesAsync();
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Tag, AyaEvent.Created), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Tag, AyaEvent.Created), ct);
|
||||
|
||||
return CreatedAtAction("GetTag", new { id = o.Id }, new ApiCreatedResponse(o));
|
||||
}
|
||||
@@ -241,7 +241,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(biz.userId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken }));
|
||||
}
|
||||
@@ -309,7 +309,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(biz.userId, oFromDb.Id, AyaType.Tag, AyaEvent.Modified), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken }));
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace AyaNova.Api.Controllers
|
||||
JobsBiz.AddJob(j, ct);
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.TrialSeeder, AyaEvent.Created,size), ct);
|
||||
//EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.TrialSeeder, AyaEvent.Created,size), ct);
|
||||
|
||||
return Accepted(new { JobId = j.GId });//202 accepted
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Retrieved), ct);
|
||||
EventLogProcessor.AddEntryAndSave(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Retrieved), ct);
|
||||
|
||||
return Ok(new ApiOkResponse(o));
|
||||
}
|
||||
@@ -216,6 +216,8 @@ namespace AyaNova.Api.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
//Log
|
||||
EventLogProcessor.AddEntryNoSave(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Modified), ct);
|
||||
await ct.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
@@ -233,8 +235,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Modified), ct);
|
||||
|
||||
|
||||
return Ok(new ApiOkResponse(new { ConcurrencyToken = o.ConcurrencyToken }));
|
||||
}
|
||||
@@ -291,6 +292,8 @@ namespace AyaNova.Api.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
//Log
|
||||
EventLogProcessor.AddEntryNoSave(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Modified), ct);
|
||||
await ct.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
@@ -306,8 +309,7 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Modified), ct);
|
||||
|
||||
|
||||
return Ok(new ApiOkResponse(new { ConcurrencyToken = o.ConcurrencyToken }));
|
||||
}
|
||||
@@ -353,11 +355,12 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
//Log
|
||||
EventLogProcessor.AddEntryNoSave(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Created), ct);
|
||||
//save and success return
|
||||
await ct.SaveChangesAsync();
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntry(new Event(biz.userId, o.Id, AyaType.Widget, AyaEvent.Created), ct);
|
||||
|
||||
|
||||
return CreatedAtAction("GetWidget", new { id = o.Id }, new ApiCreatedResponse(o));
|
||||
}
|
||||
|
||||
@@ -378,12 +378,12 @@ namespace AyaNova
|
||||
lb.ValidateLocales();
|
||||
|
||||
#if (DEBUG)
|
||||
// Util.DbUtil.DropAndRecreateDb(_log);
|
||||
// AySchema.CheckAndUpdate(dbContext, _log);
|
||||
// lb.ValidateLocales();
|
||||
// AyaNova.Core.License.Initialize(apiServerState, dbContext, _log);
|
||||
// AyaNova.Core.License.Fetch(apiServerState, dbContext, _log);
|
||||
// Util.Seeder.SeedDatabase(dbContext, Util.Seeder.SeedLevel.SmallOneManShopTrialDataSet);
|
||||
Util.DbUtil.DropAndRecreateDb(_log);
|
||||
AySchema.CheckAndUpdate(dbContext, _log);
|
||||
lb.ValidateLocales();
|
||||
AyaNova.Core.License.Initialize(apiServerState, dbContext, _log);
|
||||
AyaNova.Core.License.Fetch(apiServerState, dbContext, _log);
|
||||
Util.Seeder.SeedDatabase(dbContext, Util.Seeder.SeedLevel.MediumLocalServiceCompanyTrialDataSet);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -17,11 +17,23 @@ namespace AyaNova.Biz
|
||||
|
||||
/// <summary>
|
||||
/// Add an entry to the log
|
||||
/// DOES NOT SAVE
|
||||
/// </summary>
|
||||
/// <param name="newEvent"></param>
|
||||
/// <param name="ct"></param>
|
||||
/// <returns></returns>
|
||||
internal static void AddEntry(Event newEvent, AyContext ct)
|
||||
internal static void AddEntryNoSave(Event newEvent, AyContext ct)
|
||||
{
|
||||
ct.Event.Add(newEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add and SAVE entry to the log
|
||||
/// </summary>
|
||||
/// <param name="newEvent"></param>
|
||||
/// <param name="ct"></param>
|
||||
/// <returns></returns>
|
||||
internal static void AddEntryAndSave(Event newEvent, AyContext ct)
|
||||
{
|
||||
ct.Event.Add(newEvent);
|
||||
ct.SaveChanges();
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace AyaNova.Models
|
||||
[Required]
|
||||
public long OwnerId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public decimal? DollarAmount { get; set; }
|
||||
public bool? Active { get; set; }
|
||||
public AuthorizationRoles Roles { get; set; }
|
||||
@@ -24,12 +23,6 @@ namespace AyaNova.Models
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
|
||||
public Widget()
|
||||
{
|
||||
Created = System.DateTime.UtcNow;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace AyaNova.Util
|
||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::PrepareDatabaseForSeeding WHEN NEW TABLES ADDED!!!!
|
||||
private const int DESIRED_SCHEMA_LEVEL = 9;
|
||||
|
||||
internal const long EXPECTED_COLUMN_COUNT = 76;
|
||||
internal const long EXPECTED_COLUMN_COUNT = 75;
|
||||
internal const long EXPECTED_INDEX_COUNT = 15;
|
||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::PrepareDatabaseForSeeding WHEN NEW TABLES ADDED!!!!
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace AyaNova.Util
|
||||
|
||||
//Add widget table
|
||||
//id, text, longtext, boolean, currency,
|
||||
exec("CREATE TABLE awidget (id BIGSERIAL PRIMARY KEY, ownerid bigint not null, name varchar(255) not null, created timestamp not null, " +
|
||||
exec("CREATE TABLE awidget (id BIGSERIAL PRIMARY KEY, ownerid bigint not null, name varchar(255) not null, " +
|
||||
"startdate timestamp, enddate timestamp, dollaramount money, active bool, roles int4)");
|
||||
|
||||
setSchemaLevel(++currentSchema);
|
||||
|
||||
@@ -119,6 +119,7 @@ namespace AyaNova.Util
|
||||
|
||||
//2000 widgets
|
||||
GenSeedWidget(2000, ct);
|
||||
//GenSeedWidget(100, ct);
|
||||
|
||||
break;
|
||||
//this is a large corporation with multiple branches in multiple locations all in the same country
|
||||
@@ -257,14 +258,13 @@ namespace AyaNova.Util
|
||||
//
|
||||
public static void GenSeedWidget(int count, AyContext ct)
|
||||
{
|
||||
|
||||
var s="blah";
|
||||
for (int x = 0; x < count; x++)
|
||||
{
|
||||
Widget o = new Widget();
|
||||
var f = new Bogus.Faker();
|
||||
o.Name = f.Commerce.ProductName();
|
||||
o.Active = f.Random.Bool();
|
||||
|
||||
o.StartDate = f.Date.Between(DateTime.Now, DateTime.Now.AddMinutes(60));
|
||||
o.EndDate = f.Date.Between(DateTime.Now.AddMinutes(90), DateTime.Now.AddHours(5));
|
||||
|
||||
@@ -273,9 +273,13 @@ namespace AyaNova.Util
|
||||
//this is nonsense but just to test an enum
|
||||
o.Roles = AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited;
|
||||
ct.Widget.Add(o);
|
||||
ct.SaveChanges();
|
||||
EventLogProcessor.AddEntry(new Event(o.OwnerId, o.Id, AyaType.Widget, AyaEvent.Created), ct);
|
||||
// ct.SaveChanges();
|
||||
|
||||
//Log
|
||||
EventLogProcessor.AddEntryNoSave(new Event(o.OwnerId, o.Id, AyaType.Widget, AyaEvent.Created), ct);
|
||||
}
|
||||
ct.SaveChanges();
|
||||
var v=s;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace raven_integration
|
||||
{
|
||||
"id": 0,
|
||||
"name": "string",
|
||||
"created": "2018-02-09T16:45:56.057Z",
|
||||
"dollarAmount": 0,
|
||||
"active": true,
|
||||
"roles": 0
|
||||
@@ -28,7 +27,6 @@ namespace raven_integration
|
||||
//CREATE
|
||||
dynamic w1 = new JObject();
|
||||
w1.name = Util.Uniquify("First Test WIDGET");
|
||||
w1.created = DateTime.Now.ToString();
|
||||
w1.dollarAmount = 1.11m;
|
||||
w1.active = true;
|
||||
w1.roles = 0;
|
||||
@@ -40,7 +38,6 @@ namespace raven_integration
|
||||
|
||||
dynamic w2 = new JObject();
|
||||
w2.name = Util.Uniquify("Second Test WIDGET");
|
||||
w2.created = DateTime.Now.ToString();
|
||||
w2.dollarAmount = 2.22m;
|
||||
w2.active = true;
|
||||
w2.roles = 0;
|
||||
@@ -161,7 +158,6 @@ namespace raven_integration
|
||||
|
||||
dynamic w2 = new JObject();
|
||||
w2.name = Util.Uniquify("PutConcurrencyViolationShouldFail");
|
||||
w2.created = DateTime.Now.ToString();
|
||||
w2.dollarAmount = 2.22m;
|
||||
w2.active = true;
|
||||
w2.roles = 0;
|
||||
@@ -199,7 +195,6 @@ namespace raven_integration
|
||||
|
||||
dynamic w2 = new JObject();
|
||||
w2.name = Util.Uniquify("PatchConcurrencyViolationShouldFail");
|
||||
w2.created = DateTime.Now.ToString();
|
||||
w2.dollarAmount = 2.22m;
|
||||
w2.active = true;
|
||||
w2.roles = 0;
|
||||
|
||||
Reference in New Issue
Block a user