Skip to content

Resolve "Audit log"

Davide Silvestri requested to merge 1152-audit-log into develop

Merge Request Checklist

  • changelog.md has been updated if required
  • New/updated Premium features are separated correctly in the premium folder
  • The latest Chrome and Firefox have been used to test any new frontend features
  • Documentation has been updated
  • Quality Standards are met
  • Performance: tables are still fast with 100k+ rows, 100+ field tables
  • The redoc API pages have been updated for any REST API changes
  • Our custom API docs are updated for changes to endpoints accessed via api tokens
  • The UI/UX has been updated following UI Style Guide

NOTES:

Run to update current locales:

./baserow makemessages -l en -l it -l es -l fr -l de -l cs -l mr -l nb_NO -l nl -l pl -l pt_BR -l ru -l zh_Hans
./baserow compilemessages -l en -l it -l es -l fr -l de -l cs -l mr -l nb_NO -l nl -l pl -l pt_BR -l ru -l zh_Hans 

TODO

  • Move the undo and redo methods of the ActionType in a UndoRedoActionTypeMixin.
  • Create an UndoRedoActionType(UndoRedoActionTypeMixin, ActionType) and make all the undo/redo actions inherits from UndoRedoActionType
  • Add the can_be_undone boolean flag to the Action model that state whether the action can be undone - issubclass(action, 'UndoRedoActionType) and the django migration.
  • Add get_type_description and get_event_description to all the ActionTypes to describe the action done as a human translatable string
  • Add all the parameters needed to render the action_type's description in the Params class following this convention:
    • add the group_id and the group_name wherever is possible/makes sense
    • add parameters needed to create sentences like "Table {table_name} ({table_id}) created in database {database_name} ({database_id})
    • prefix all the parameters with the word original to store values changes
  • Move the register_action business logic in the ActionHandler
  • Create an action_done signal to be emitted from the ActionHandler immediately after the register_action has been called with the action parameters.
  • Add all the non-undoable ActionTypes in the core (e.g. user_created, user_deleted, trash emptied, etc.) and in the database (webhooks maybe?)
  • Add the AuditLogEntry model in the enterprise/audit_log folder
  • Add the action_done receiver and the AuditLogHandler to store every action as an audit_log entry saving the following data:
    • user_id and user_email (no FK here so data will be available even if the user is deleted)
    • group_id and group_name
    • timestamp
    • ip_address (it will be stored in the user as for the session_id *)
    • action_id and action_type
    • params
  • Create the AdminListingViews for the AuditLogEntry to show in the audit_log admin section and a AdminListingView for every filter we need to show there.
  • Create the UI to show the CrudTable and the PaginatedDropdowns for the filters.
  • Add the export to CSV functionality, taking inspiration from the ExportJob logic
  • Add enterprise license checks for audit log
  • Add and environment variable to clean oldest entries in the audit log
  • Check if it's possible to reliably get the IP address from the request. Is the request.META["REMOTE_ADDR"] enough or should we use something like the django-ipware app maybe?

Missing actions:

  • user level: update_password, premium_user_deactivated, premium_user_permanently_deleted
  • table level: differentiate the create_table from the import_table, export_table_data, do we want a download_file action be submitted when a user download a file ?
  • trash level: permanently_delete items
  • other actions are described here: https://baserow.io/database/25016/table/54352

Notes:

  • the audit log doesn't have real-time updates, so to see new entries a page refresh is needed
  • to see the translated strings, be sure to have the translations in the django.po files, run the makemessages first, the compilemessages after, and refresh the audit log page in the end.
  • At the moment, every update operation doesn't explicitly say which property has been updated, so for example if user update the language or a view became visible to public via slug, the audit log entry will show only an update user or update view entry. Does it make sense to add the JSON parameters in the CSV export and/or in the UI so an auditor can see which properties have been changed?
  • The update view filter operation is called for every character typed in the UI. This could results in a lot of similar entries, one for every change in the UI. I think it could make sense in the future to collapse them in a single entry with the final filter value.

How to test: Without an enterprise license, everything should work as expected

With an enterprise license, an Audit Log entry should appear in the left sidebar admin menu:

  • every undoable action should appear in the audit log entry
  • if you create/restore/delete a snapshot or create/update/schedule_delete a user, an entry should appear in the audit log (look for ActionTypes that extends the base ActionType for more non-undoable actions

The exportJobModal should return the latest 4 exported files if no job is running or the running job and the last 3 exported files. Since the exportJob could take minutes to export the data, once the auditLog page is loaded the last jobs are retrieved for the user and the job progress will be restored if needed.

Closes #1152 (closed)

Edited by Davide Silvestri

Merge request reports