Impersonation and audit creation

Sep 7, 2009 at 2:32 PM


First of all I'd just like to say how useful this plugin is: it's saved me a lot of time developing the same thing myself.  I thought I'd just detail a couple of small changes I've made since downloading it on Friday.

  1. By default, the code executes as the calling user, which requires them to have create permissions on the Audit and AuditDetail entities (and assign if you link them to the entities you are auditing).  I decided to move away from this approach by creating a new relationship (to the systemuser entitiy) for each of those entities to replace the 'User' attribute (which is actually 'createdby').  I now execute the plugin as SYSTEM but create each entity with the relevant Lookup to the user that initiated the action that is being audited.  This allows me to audit everything without needing to grant users any permissions on the audit entities (except Read, where appropriate).
  2. We have a portal that exposes data from the CRM and allows editing of contact details, submission of applications, etc.  Unfortunately it doesn't manage state properly and simply sends updates between page changes in case any of the details have changed.  This result in a number of empty audit entries, e.g. there were no relevant field-level changes.  I decided to make a small modification to the code so that I only create the Audit record if I know for sure I'm going to be recording at least one field-level change.

Thanks again for hard work - much appreciated.



Apr 15, 2010 at 1:32 PM



can you explain me better this part: "(...) creating a new relationship (to the systemuser entitiy) for each of those entities to replace the 'User' attribute (which is actually 'createdby') (...)"?

I have a relation on the systemuser entity with the entities Audit and Audit Detail (but they were already created), then when I try to change the attribute User (on 'Createdby') all the fields are blocked... 

Thank you for your help.




Apr 16, 2010 at 12:14 PM


The relationships you already have are probably for the Created By and Modified By properties which are present on all entities.  

I created a new N:1 relationship from my audit entry to the SystemUser entry so that I could store which user was responsible for the creation of an audit record, without relying on the Created On property because my plugin runs asynchronously and doesn't impersonate the calling user:

ICrmService crmService = (ICrmService)context.CreateCrmService(false);

This means that 'Created By' is always 'SYSTEM', but it has the advantage that my users only need read access (where appropriate) to the audit and audit details entities.

I simply include this snippet of code in the Execute method of the Audit plugin to set the systemuser lookup value on the record I am creating (I do the same for audit detail, though I suppose it's not entirely necessary):

// as we're not impersonating we need to specify the user that made the change..
auditRecord.Properties["lu_userid"] = new Lookup(EntityName.systemuser.ToString(), context.InitiatingUserId);

Hope that helps.