/// <summary> /// Fids the specified audit in the local repository /// </summary> public IEnumerable <AuditData> Find(Expression <Func <AuditData, bool> > query, int offset, int?count, out int totalResults) { try { var conn = this.CreateConnection(); using (conn.Lock()) { var builder = new QueryBuilder(this.m_mapper); var sql = builder.CreateQuery(query).Build(); sql = sql.OrderBy <DbAuditData>(o => o.Timestamp, SortOrderType.OrderByDescending); // Total results totalResults = conn.ExecuteScalar <Int32>($"SELECT COUNT(*) FROM ({sql.SQL})", sql.Arguments.ToArray()); // Query control if (count.HasValue) { sql.Limit(count.Value); } if (offset > 0) { if (count == 0) { sql.Limit(100).Offset(offset); } else { sql.Offset(offset); } } sql = sql.Build(); var itm = conn.Query <DbAuditData.QueryResult>(sql.SQL, sql.Arguments.ToArray()); AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.Success, sql.ToString(), itm.Select(o => new Guid(o.Id)).ToArray()); return(itm.Select(o => this.ToModelInstance(conn, o)).ToList()); } } catch (Exception e) { AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.EpicFail, query.ToString()); this.m_tracer.TraceError("Could not query audit {0}: {1}", query, e); throw; } }
/// <summary> /// Prune the audit database /// </summary> public void Prune() { var config = ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>(); try { this.m_tracer.TraceInfo("Prune audits older than {0}", config?.AuditRetention); if (config?.AuditRetention == null) { return; // keep audits forever } var conn = this.CreateConnection(); using (conn.Lock()) { try { conn.BeginTransaction(); DateTime cutoff = DateTime.Now.Subtract(config.AuditRetention); Expression <Func <DbAuditData, bool> > epred = o => o.CreationTime < cutoff; conn.Table <DbAuditData>().Delete(epred); // Delete objects conn.Execute($"DELETE FROM {conn.GetMapping<DbAuditObject>().TableName} WHERE NOT({conn.GetMapping<DbAuditObject>().FindColumnWithPropertyName(nameof(DbAuditObject.AuditId)).Name} IN " + $"(SELECT {conn.GetMapping<DbAuditData>().FindColumnWithPropertyName(nameof(DbAuditData.Id)).Name} FROM {conn.GetMapping<DbAuditData>().TableName})" + ")"); AuditUtil.AuditAuditLogUsed(ActionType.Delete, OutcomeIndicator.Success, epred.ToString()); conn.Commit(); } catch { conn.Rollback(); } } } catch (Exception e) { this.m_tracer.TraceError("Error pruning audit database: {0}", e); throw; } }
/// <summary> /// Get the specified audit data from the database /// </summary> public AuditData Get(object id) { try { Guid pk = Guid.Empty; if (id is Guid) { pk = (Guid)id; } else if (id is String) { pk = Guid.Parse(id.ToString()); } else { throw new ArgumentException("Parameter must be GUID or parsable as GUID", nameof(id)); } // Fetch var conn = this.CreateConnection(); using (conn.Lock()) { var builder = new QueryBuilder(this.m_mapper); var sql = builder.CreateQuery <AuditData>(o => o.CorrelationToken == pk).Limit(1).Build(); var res = conn.Query <DbAuditData.QueryResult>(sql.SQL, sql.Arguments.ToArray()).FirstOrDefault(); AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.Success, sql.ToString(), pk); return(this.ToModelInstance(conn, res, false)); } } catch (Exception e) { AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.EpicFail, id.ToString()); this.m_tracer.TraceError("Error retrieving audit {0} : {1}", id, e); throw; } }