Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions src/Business/Grand.Business.Common/Services/Audit/AuditService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,21 @@ private IQueryable<AuditEntry> Query(AuditEntrySearch search)
query = query.Where(x => x.Source == search.Source.Value);
if (search.Kind.HasValue)
query = query.Where(x => x.Kind == search.Kind.Value);
if (!string.IsNullOrEmpty(search.EntityType))
query = query.Where(x => x.EntityType == search.EntityType);
if (!string.IsNullOrEmpty(search.EntityId))
query = query.Where(x => x.EntityId == search.EntityId);
var types = search.EntityType?.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
.ToList() ?? [];
//the history of one record also holds the records that belong to it (its notes)
if (types.Count == 1 && !string.IsNullOrEmpty(search.EntityId))
query = query.Where(x => (x.EntityType == types[0] && x.EntityId == search.EntityId)
|| (x.OwnerType == types[0] && x.OwnerId == search.EntityId));
else
{
if (types.Count == 1)
query = query.Where(x => x.EntityType == types[0]);
else if (types.Count > 1)
query = query.Where(x => types.Contains(x.EntityType));
if (!string.IsNullOrEmpty(search.EntityId))
query = query.Where(x => x.EntityId == search.EntityId);
}
if (search.EntityNames is { Count: > 0 })
{
var names = search.EntityNames.ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,13 @@ public virtual async Task ImportResourcesFromXml(Language language, string xml)

if (resource != null)
{
resource.Name = resource.Name.ToLowerInvariant();
//a resource the file does not change is not written
var area = Enum.TryParse<TranslationResourceArea>(item.Area, out var areaEnum) ? areaEnum : resource.Area;
if (resource.Value == item.Value && resource.Area == area)
continue;

resource.Value = item.Value;
if (Enum.TryParse<TranslationResourceArea>(item.Area, out var areaEnum))
resource.Area = areaEnum;
resource.Area = area;
await _translationRepository.UpdateAsync(resource);
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ public class AuditEntrySearch
public string SearchText { get; set; }
public AuditSource? Source { get; set; }
public AuditKind? Kind { get; set; }
/// <summary>
/// One entity type, or several separated by commas (the records one screen edits, e.g. "Permission,PermissionAction")
/// </summary>
public string EntityType { get; set; }

public string EntityId { get; set; }

/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions src/Core/Grand.Data/Audit/AuditIndexes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ await databaseContext.CreateIndex(repository,
await databaseContext.CreateIndex(repository,
OrderBuilder<AuditEntry>.Create().Ascending(x => x.EntityType).Ascending(x => x.EntityId)
.Descending(x => x.CreatedOnUtc).Descending(x => x.Id), "EntityType_EntityId_CreatedOnUtc_Id");
await databaseContext.CreateIndex(repository,
OrderBuilder<AuditEntry>.Create().Ascending(x => x.OwnerType).Ascending(x => x.OwnerId)
.Descending(x => x.CreatedOnUtc).Descending(x => x.Id), "OwnerType_OwnerId_CreatedOnUtc_Id");
await databaseContext.CreateIndex(repository,
OrderBuilder<AuditEntry>.Create().Ascending(x => x.ActorCustomerId).Descending(x => x.CreatedOnUtc)
.Descending(x => x.Id), "ActorCustomerId_CreatedOnUtc_Id");
Expand Down
7 changes: 7 additions & 0 deletions src/Core/Grand.Data/Audit/IAuditTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ Task BeforeWriteAsync<T>(string id, bool isInsert, Func<IReadOnlyCollection<stri

void RecordBulk<T>(string operation, string filter) where T : BaseEntity;

/// <summary>
/// Records the inserts of <typeparamref name="T" /> made until the returned scope ends as one bulk entry with
/// their count (an import of thousands of records) instead of one entry each; updates and deletes stay single
/// entries. With <paramref name="owner" />, the entry shows in that record's change history.
/// </summary>
IDisposable CountInserts<T>(string operation, string details, BaseEntity owner = null) where T : BaseEntity;

Task FlushAsync();

/// <summary>
Expand Down
7 changes: 7 additions & 0 deletions src/Core/Grand.Domain/Audit/AuditChange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ public class AuditChange
/// </summary>
public string Path { get; set; }

/// <summary>
/// Gets or sets the names of the list elements the path runs through, outermost first (an empty name where an
/// element has none), e.g. "Color family" for ProductSpecificationAttributes[id=…].DisplayOrder; null when
/// the path runs through no named element
/// </summary>
public IList<string> ElementNames { get; set; }

/// <summary>
/// Gets or sets the value before the change (null when masked or when the field was added)
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/Core/Grand.Domain/Audit/AuditEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ public class AuditEntry : BaseEntity
/// </summary>
public string EntityStoreId { get; set; }

/// <summary>
/// Gets or sets the type of the record the changed record belongs to (Order for an order note, see
/// <see cref="AuditOwnerAttribute" />); null when it belongs to none
/// </summary>
public string OwnerType { get; set; }

/// <summary>
/// Gets or sets the id of the record the changed record belongs to
/// </summary>
public string OwnerId { get; set; }

public IList<AuditChange> Changes { get; set; } = new List<AuditChange>();

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion src/Core/Grand.Domain/Audit/AuditNameAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ namespace Grand.Domain.Audit;

/// <summary>
/// Marks the property that names a record in the audit log (shown in the list, and the only trace of what a
/// deleted record was). Without it, the record's Name property is used.
/// deleted record was), or an element of a record's list. Without it, the Name property is used. On an
/// [AuditReference] property, the name is the referenced record's.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class AuditNameAttribute : Attribute;
9 changes: 9 additions & 0 deletions src/Core/Grand.Domain/Audit/AuditOwnerAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Grand.Domain.Audit;

/// <summary>
/// Marks the property holding the id of the record this one belongs to (the order of an order note), so the
/// entries of this record also show in that record's change history. The property carries
/// [AuditReference] naming the owner's type.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class AuditOwnerAttribute : Attribute;
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Blogs/BlogCategoryPost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ namespace Grand.Domain.Blogs;
public class BlogCategoryPost : SubBaseEntity
{
[AuditReference(typeof(BlogPost))]
[AuditName]
public string BlogPostId { get; set; }
}
2 changes: 2 additions & 0 deletions src/Core/Grand.Domain/Blogs/BlogComment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class BlogComment : BaseEntity
/// <summary>
/// Gets or sets the comment text
/// </summary>
[AuditName]
public string CommentText { get; set; }

/// <summary>
Expand All @@ -35,5 +36,6 @@ public class BlogComment : BaseEntity
/// Gets or sets the blog post identifier
/// </summary>
[AuditReference(typeof(BlogPost))]
[AuditOwner]
public string BlogPostId { get; set; }
}
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Catalog/BundleProduct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class BundleProduct : SubBaseEntity
/// Gets or sets the product identifier
/// </summary>
[AuditReference(typeof(Product))]
[AuditName]
public string ProductId { get; set; }

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Grand.Domain/Catalog/ProductAttributeCombination.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Grand.Domain.Audit;
using Grand.Domain.Common;

namespace Grand.Domain.Catalog;
Expand Down Expand Up @@ -38,6 +39,7 @@ public class ProductAttributeCombination : SubBaseEntity, ICloneable
/// <summary>
/// Gets or sets the SKU
/// </summary>
[AuditName]
public string Sku { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Catalog/ProductAttributeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class ProductAttributeMapping : SubBaseEntity, ITranslationEntity
/// Gets or sets the product attribute identifier
/// </summary>
[AuditReference(typeof(ProductAttribute))]
[AuditName]
public string ProductAttributeId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Catalog/ProductCategory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ProductCategory : SubBaseEntity
/// Gets or sets the category identifier
/// </summary>
[AuditReference(typeof(Category))]
[AuditName]
public string CategoryId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Catalog/ProductCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ProductCollection : SubBaseEntity
/// Gets or sets the collection identifier
/// </summary>
[AuditReference(typeof(Collection))]
[AuditName]
public string CollectionId { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class ProductCombinationWarehouseInventory : SubBaseEntity
/// Gets or sets the warehouse identifier
/// </summary>
[AuditReference(typeof(Warehouse))]
[AuditName]
public string WarehouseId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Catalog/ProductPrice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public class ProductPrice : SubBaseEntity
{
[AuditReference(typeof(Product))]
public string ProductId { get; set; }
[AuditName]
public string CurrencyCode { get; set; }
public double Price { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class ProductSpecificationAttribute : SubBaseEntity
/// Gets or sets the specification attribute Id
/// </summary>
[AuditReference(typeof(SpecificationAttribute))]
[AuditName]
public string SpecificationAttributeId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Catalog/ProductWarehouseInventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class ProductWarehouseInventory : SubBaseEntity
/// Gets or sets the warehouse identifier
/// </summary>
[AuditReference(typeof(Warehouse))]
[AuditName]
public string WarehouseId { get; set; }

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Grand.Domain/Catalog/RelatedProduct.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Grand.Domain.Audit;

namespace Grand.Domain.Catalog;

/// <summary>
Expand All @@ -8,6 +10,8 @@ public class RelatedProduct : SubBaseEntity
/// <summary>
/// Gets or sets the second product identifier
/// </summary>
[AuditReference(typeof(Product))]
[AuditName]
public string ProductId2 { get; set; }

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Grand.Domain/Catalog/SimilarProduct.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Grand.Domain.Audit;

namespace Grand.Domain.Catalog;

/// <summary>
Expand All @@ -13,6 +15,8 @@ public class SimilarProduct : SubBaseEntity
/// <summary>
/// Gets or sets the second product identifier
/// </summary>
[AuditReference(typeof(Product))]
[AuditName]
public string ProductId2 { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Customers/CustomerNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class CustomerNote : BaseEntity
/// Gets or sets the customer identifier
/// </summary>
[AuditReference(typeof(Customer))]
[AuditOwner]
public string CustomerId { get; set; }

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion src/Core/Grand.Domain/Discounts/DiscountRule.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Grand.Domain.Discounts;
using Grand.Domain.Audit;

namespace Grand.Domain.Discounts;

/// <summary>
/// Represents a discount requirement
Expand All @@ -8,6 +10,7 @@ public class DiscountRule : SubBaseEntity
/// <summary>
/// Gets or sets the discount requirement rule system name
/// </summary>
[AuditName]
public string DiscountRequirementRuleSystemName { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class KnowledgebaseArticleComment : BaseEntity
/// <summary>
/// Gets or sets the comment text
/// </summary>
[AuditName]
public string CommentText { get; set; }

/// <summary>
Expand All @@ -25,5 +26,6 @@ public class KnowledgebaseArticleComment : BaseEntity
/// Gets or sets the blog post identifier
/// </summary>
[AuditReference(typeof(KnowledgebaseArticle))]
[AuditOwner]
public string ArticleId { get; set; }
}
4 changes: 4 additions & 0 deletions src/Core/Grand.Domain/Localization/TranslationResource.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Grand.Domain.Audit;

namespace Grand.Domain.Localization;

/// <summary>
Expand All @@ -8,6 +10,8 @@ public class TranslationResource : BaseEntity
/// <summary>
/// Gets or sets the language identifier
/// </summary>
[AuditReference(typeof(Language))]
[AuditOwner]
public string LanguageId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/News/NewsComment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class NewsComment : SubBaseEntity
/// <summary>
/// Gets or sets the comment title
/// </summary>
[AuditName]
public string CommentTitle { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Orders/GiftVoucherUsageHistory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class GiftVoucherUsageHistory : SubBaseEntity
/// Gets or sets the order identifier
/// </summary>
[AuditReference(typeof(Order))]
[AuditName]
public string UsedWithOrderId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Orders/MerchandiseReturn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Grand.Domain.Orders;
/// </summary>
public class MerchandiseReturn : BaseEntity
{
[AuditName]
public int ReturnNumber { get; set; }

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Grand.Domain/Orders/MerchandiseReturnNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class MerchandiseReturnNote : BaseEntity
/// <summary>
/// Gets or sets the merchandise return identifier
/// </summary>
[AuditReference(typeof(MerchandiseReturn))]
[AuditOwner]
public string MerchandiseReturnId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Orders/OrderApprovalItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class OrderApprovalItem : SubBaseEntity
/// Gets or sets the product identifier
/// </summary>
[AuditReference(typeof(Product))]
[AuditName]
public string ProductId { get; set; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Core/Grand.Domain/Orders/OrderItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class OrderItem : SubBaseEntity
/// Gets or sets the product identifier
/// </summary>
[AuditReference(typeof(Product))]
[AuditName]
public string ProductId { get; set; }

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Grand.Domain/Orders/OrderNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ public class OrderNote : BaseEntity
/// Gets or sets the order identifier
/// </summary>
[AuditReference(typeof(Order))]
[AuditOwner]
public string OrderId { get; set; }

/// <summary>
/// Gets or sets the note
/// </summary>
[AuditName]
public string Note { get; set; }

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Grand.Domain/Orders/ShoppingCartItem.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Grand.Domain.Audit;
using Grand.Domain.Catalog;
using Grand.Domain.Common;

namespace Grand.Domain.Orders;
Expand Down Expand Up @@ -25,6 +27,8 @@ public class ShoppingCartItem : SubBaseEntity
/// <summary>
/// Gets or sets the product identifier
/// </summary>
[AuditReference(typeof(Product))]
[AuditName]
public string ProductId { get; set; }

/// <summary>
Expand Down
Loading
Loading