Base solution for your next web application
Open Closed

Register ID of other instances #12451


User avatar
0
sociomed created

We are using the host user to edit records of other instances and the ID of the user responsible for the action is not being saved. As shown in the image below:

We have verified that Aspnet Zero works exactly as shown in the code below. We want to know what to do to change this behavior, since we need the host user ID for the changes.

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

1 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @sociomed

    The operation performed here is marked as null when a tenant entity is modified by a different tenant or host user, since there cannot be users who made changes in the relevant tenant. If you want to set LastModifierUserId here, you need to override the SetModificationAuditProperties method in YourDbContext. This method uses the SetModificationAuditProperties method from the EntityAuditingHelper static class. You can write the operations in the SetModificationAuditProperties method in the method we override in YourDbContext. You can set the information of the user who made the change in the relevant place. However, one thing you should pay attention to here is that since the user who made the change will not be in the relevant tenant, it may create an inconsistent result in filtering operations.

    protected override void SetModificationAuditProperties(object entityAsObj, long? userId)
    {
        if (entityAsObj is IHasModificationTime)
        {
            var lastModificationTimeFilter = CurrentUnitOfWorkProvider?.Current?.AuditFieldConfiguration?.FirstOrDefault(e => e.FieldName == AbpAuditFields.LastModificationTime);
            if (lastModificationTimeFilter == null || lastModificationTimeFilter.IsSavingEnabled)
            {
                entityAsObj.As<IHasModificationTime>().LastModificationTime = Clock.Now;
            }
        }
    
        if (!(entityAsObj is IModificationAudited))
        {
            //Entity does not implement IModificationAudited
            return;
        }
    
        var lastModifierUserIdFilter = CurrentUnitOfWorkProvider?.Current?.AuditFieldConfiguration?.FirstOrDefault(e => e.FieldName == AbpAuditFields.LastModifierUserId);
        if (lastModifierUserIdFilter != null && !lastModifierUserIdFilter.IsSavingEnabled)
        {
            return;
        }
    
        var entity = entityAsObj.As<IModificationAudited>();
    
        if (MultiTenancyConfig?.IsEnabled == true)
        {
            if (MultiTenancyHelper.IsMultiTenantEntity(entity) &&
                !MultiTenancyHelper.IsTenantEntity(entity, AbpSession.TenantId))
            {
                //A tenant entity is modified by host or a different tenant
                entity.LastModifierUserId = AbpSession.UserId; //Example
                return;
            }
    
            if (AbpSession.TenantId.HasValue && MultiTenancyHelper.IsHostEntity(entity))
            {
                //Tenant user modified a host entity
                entity.LastModifierUserId = AbpSession.UserId; //Example
                return;
            }
        }
    
        //Finally, set LastModifierUserId!
        entity.LastModifierUserId = userId;
    }
    

    Add

    internal class MultiTenancyHelper
    {
        public static bool IsMultiTenantEntity(object entity)
        {
            return entity is IMayHaveTenant || entity is IMustHaveTenant;
        }
    
        /// <param name="entity">The entity to check</param>
        /// <param name="expectedTenantId">TenantId or null for host</param>
        public static bool IsTenantEntity(object entity, int? expectedTenantId)
        {
            return (entity is IMayHaveTenant && entity.As<IMayHaveTenant>().TenantId == expectedTenantId) ||
                   (entity is IMustHaveTenant && entity.As<IMustHaveTenant>().TenantId == expectedTenantId);
        }
    
        public static bool IsHostEntity(object entity)
        {
            MultiTenancySideAttribute attribute = entity.GetType().GetTypeInfo()
                .GetCustomAttributes(typeof(MultiTenancySideAttribute), true)
                .Cast<MultiTenancySideAttribute>()
                .FirstOrDefault();
    
            if (attribute == null)
            {
                return false;
            }
    
            return attribute.Side.HasFlag(MultiTenancySides.Host);
        }
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)