Is it possible to add Tags to audit log?

We're having an issue with some users removing tags from records. Since Tags are a related object and not a field, I'm not sure if or how it's possible to audit those changes. 

Has anyone had this request/issue and what was your solution?

  • Hi Ben,

    I'd be curious if others have found a way to solve this, but I came across two related ideas: 78354 and 76578. Unfortunately, both are categorized as "No Plan to Implement at this time." I'll have a case created for you and associated with those two ideas to help with future tracking but invite anyone else to share their experience if they've found a solution for this!

    -Alex


    Alex Nassi
    Digital CX Operations Director
    SugarCRM

  • NOTE: This code was written for this post and barely tested, needs work.

    A Tag is, at its lowest level, a relationship between the Tags Module and the module you are tagging (an entry in tag_bean_rel)
    This means that you can leverage the before/after relationship add/delete logic hooks to add entries to the Audit Log.

    in custom/modules/Tags/logic_hooks.php

    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_relationship_add'][] = Array(0, 'tag_added_audit_log', 'custom/modules/Tags/TagsLogic.php','TagsLogic', 'tag_added_audit_log');
    $hook_array['after_relationship_delete'][] = Array(0, 'tag_removed_audit_log', 'custom/modules/Tags/TagsLogic.php','TagsLogic', 'tag_removed_audit_log');
    

    You need two functions, one for each of the events (add/remove) but they are essentially identical except I set:

    for the ADD:

    before value = ''

    after value = the tag 

    for the REMOVE

    before value = the tag

    after value = ''

    <?php
    class TagsLogic {
      //call after relationship add
      function tag_added_audit_log ($bean,$event,$arguments) {
        global $db;
        $module = $arguments['related_module'];
        $bean_id = $arguments['related_id'];
        $parentBean =  BeanFactory::retrieveBean($module, $bean_id);
        if(!empty($parentBean) && $db->tableExists($parentBean->get_audit_table_name())) {
            $changes = array(
              'field_name' => 'Tags',
              'data_type' => 'tag',
              'before' => '',
              'after' => $bean->name,
            );
            $sql = $bean->auditSQL($parentBean, $changes, '');
          $db->query($bean->auditSQL($parentBean, $changes, ''));
        }
      }
    
    
      //call after relationship delete
      function tag_removed_audit_log ($bean,$event,$arguments) {
        global $db;
        $module = $arguments['related_module'];
        $bean_id = $arguments['related_id'];
        $parentBean =  BeanFactory::retrieveBean($module, $bean_id);
        if(!empty($parentBean) && $db->tableExists($parentBean->get_audit_table_name())) {
          $changes = array(
            'field_name' => 'Tags',
            'data_type' => 'tag',
            'before' => $bean->name,
            'after' => '',
          );
          $sql = $bean->auditSQL($parentBean, $changes, '');
          $db->query($bean->auditSQL($parentBean, $changes, ''));
        }
      }
    }

    By putting the logic hook on the side of the Tags module it triggers for all tags on any module using tags and it puts the audit in that module's audit table IF an audit table exists.

    NOTE: even though in the back end the query is correctly setting the current_user_id for the person who made the change, it is not showing in the audit log. I suspect this is because I left out the event_id

    Check data/SugarBean.php you will see that the public function auditSQL(SugarBean $bean, $changes, $event_id) expects an event_id.

    Based on the post by Harald here:  What is the event_id for? you may need to figure out how to add a properly formatted audit_events record to link to the audit table, I suspect it is using some information from that event to populate that column.

    in audit_event.source I see things like:

    '{"subject":{"_type":"user","id":"3341c0ac-cbf5-7ee0-4df2-5419adf1b88b","_module":"Users","client":{"_type":"rest-api"}},"attributes":{"platform":"base"}}'

    and

    '{"subject":{"_type":"logic-hook","class":"UpdateLog","method":"update_log","label":null},"attributes":[]}'

    Make sure you do a QRR after adding the code, and make sure to test it thoroughly, I'm NOT using this code, I wrote it tonight for you and briefly tested to make sure it works. 

    What can I say, I like puzzles :)

    Hope this helps

    FrancescaS

  • Hi  ,

    If your main concern is being able to restore Tags that were previously associated with the record, our plugin, Upsert Trash Bin, accomplishes that with the 'Restore Relationships' feature. When viewing a record, you can select the 'Restore Relatonships' option and reinstate any prior relationships including tags:

    Contact us via our website if you'd like to a more in-depth demo of the plugin!

    Chris

  • Hi Chris,

    Our main issue is having the need to see the history of tags on the record. It's not just to restore a removed tag. We are more interested in the timing during an investigation of history of the record.

    But thank you for that idea!

  • Hi Francesca,

    Thanks for that idea! I'll have to share that with my admin and see if that's something that we could look further into.

  • Thank you Alex! Could you possibly add Francesca's idea below to the notes in that case? Maybe the developers could leverage her idea to implement something. Thanks!

  • Thanks for the suggestion! I added some internal notes to 78354. Thanks  too for working that out!


    Alex Nassi
    Digital CX Operations Director
    SugarCRM