DBIx-Class-Journal

 view release on metacpan or  search on metacpan

lib/DBIx/Class/Journal.pm  view on Meta::CPAN

package DBIx::Class::Journal;

use base qw/DBIx::Class/;

use strict;
use warnings;

our $VERSION = '0.900201';
$VERSION = eval $VERSION; # no errors in dev versions

## On create/insert, add new entry to AuditLog and new content to AuditHistory

sub _journal_schema {
    my $self = shift;
    $self->result_source->schema->_journal_schema;
}

sub insert {
    my ($self, @args) = @_;
    return if $self->in_storage;

    my $res = $self->next::method(@args);
    $self->journal_log_insert;

    return $res;
}

sub journal_log_insert {
    my ($self) = @_;

    if ( $self->in_storage ) {
        my $j = $self->_journal_schema;
        my $change_id = $j->journal_create_change()->id;
        $j->journal_update_or_create_log_entry( $self, create_id => $change_id );
        $j->journal_record_in_history( $self, audit_change_id => $change_id );
    }
}

## On delete, update delete_id of AuditLog

sub delete {
    my $self = shift;
    my $ret = $self->next::method(@_);
    $self->journal_log_delete(@_);
    return $ret
}

sub journal_log_delete {
    my ($self) = @_;

    unless ($self->in_storage) {
        my $j = $self->_journal_schema;
        $j->journal_update_or_create_log_entry( $self, delete_id => $j->journal_create_change->id );
    }
}

## On update, copy row's new contents to AuditHistory

sub update {
    my $self = shift;
    my $ret = $self->next::method(@_);
    $self->journal_log_update(@_);
    return $ret
}

sub journal_log_update {
    my $self = shift;

    if ($self->in_storage) {
        my $j = $self->_journal_schema;
        my $change_id = $j->journal_create_change->id;
        $j->journal_record_in_history( $self, audit_change_id => $change_id );
    }
}

=head1 NAME

DBIx::Class::Journal - Auditing for tables managed by DBIx::Class

=head1 SYNOPSIS

Load the module into your L<DBIx::Class> Schema Class:

 package My::Schema;
 use base 'DBIx::Class::Schema';

 __PACKAGE__->load_components(qw/Schema::Journal/);

Optionally set where the journal is stored:

 __PACKAGE__->journal_connection(['dbi:SQLite:t/var/Audit.db']);

And then call C<< $schema->bootstrap_journal >> (I<once only>) to create all
the tables necessary for the journal, in your database.

Later on, in your application, wrap operations in transactions, and optionally
associate a user with the changeset:

 $schema->changeset_user($user->id);
 my $new_artist = $schema->txn_do( sub {
    return $schema->resultset('Artist')->create({ name => 'Fred' });
 });

=head1 DESCRIPTION

The purpose of this L<DBIx::Class> component module is to create an
audit-trail for all changes made to the data in your database (via a
DBIx::Class schema). It creates I<changesets> and assigns each
create/update/delete operation an I<id>. The creation and deletion date of
each row is stored, as well as the historical contents of any row that gets
changed.

All queries which need auditing B<must> be called using
L<DBIx::Class::Schema/txn_do>, which is used to create changesets for each
transaction.

To track who did which changes, the C<user_id> (an integer) of the current
user can be set, and a C<session_id> can also be set; both are optional. To
access the auditing schema to look at the auditdata or revert a change, use



( run in 2.404 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )