get rid of commented out code
[dbsrgits/DBIx-Class-Journal.git] / lib / DBIx / Class / Journal.pm
1 package DBIx::Class::Journal;
2
3 use base qw/DBIx::Class/;
4
5 use strict;
6 use warnings;
7
8 our $VERSION = '0.900001_02';
9
10 ## On create/insert, add new entry to AuditLog
11
12 sub _journal_schema {
13     my $self = shift;
14     $self->result_source->schema->_journal_schema;
15 }
16
17 sub insert
18 {
19     my ($self, @args) = @_;
20
21     return if($self->in_storage);
22
23     my $res = $self->next::method(@args);
24
25     $self->journal_log_insert();
26
27     return $res;
28 }
29
30 sub journal_log_insert
31 {
32     my ($self) = @_;
33
34     if ( $self->in_storage ) {
35         my $j = $self->_journal_schema;
36         my $change_id = $j->journal_create_change()->id;
37         $j->journal_update_or_create_log_entry( $self, create_id => $change_id );
38         $j->journal_record_in_history( $self, audit_change_id => $change_id );
39     }
40 }
41
42 ## On delete, update delete_id of AuditLog
43
44 sub delete
45 {
46     my ($self, @rest) = @_;
47     $self->next::method(@rest);
48     $self->journal_log_delete(@rest);
49 }
50
51 sub journal_log_delete
52 {
53     my ($self) = @_;
54
55     unless ($self->in_storage) {
56         my $j = $self->_journal_schema;
57         $j->journal_update_or_create_log_entry( $self, delete_id => $j->journal_create_change->id );
58     }
59 }
60
61 ## On update, copy previous row's contents to AuditHistory
62
63 sub update
64 {
65     my ($self, $upd, @rest) = @_;
66     $self->journal_log_update($upd, @rest);
67     $self->next::method($upd, @rest);
68 }
69
70 sub journal_log_update
71 {
72     my ($self, $upd, @rest) = @_;
73
74     if($self->in_storage)
75     {
76         my $j = $self->_journal_schema;
77
78         my $change = $j->journal_create_change;
79         my $prev = $self->result_source->resultset->find( $self->ident_condition );
80         $j->journal_record_in_history( $prev, audit_change_id => $change );
81     }
82 }
83
84 =head1 NAME
85
86 DBIx::Class::Journal - auditing for tables managed by DBIx::Class
87
88 =head1 SYNOPSIS
89
90   package My::Schema;
91   use base 'DBIx::Class::Schema';
92
93   __PACKAGE__->load_components(qw/+DBIx::Class::Schema::Journal/);
94
95   __PACKAGE__->journal_connection(['dbi:SQLite:t/var/Audit.db']);
96   __PACKAGE__->journal_user(['My::Schema::User', {'foreign.userid' => 'self.user_id'}]);
97
98
99  ########
100
101   $schema->changeset_user($user->id);
102   my $new_artist = $schema->txn_do( sub {
103    return = $schema->resultset('Artist')->create({ name => 'Fred' });
104   });
105
106
107 =head1 DESCRIPTION
108
109 The purpose of this L<DBIx::Class> component module is to create an
110 audit-trail for all changes made to the data in your database (via a
111 DBIx::Class schema). It creates changesets and assigns each
112 create/update/delete operation an id. The creation and deletion date
113 of each row is stored, as well as the previous contents of any row
114 that gets changed.
115
116 All queries which want auditing should be called using
117 L<DBIx::Class::Schema/txn_do>, which is used to create changesets for
118 each transaction.
119
120 To track who did which changes, the user_id (an integer) of the
121 current user can be set, a session_id can also be set, both are
122 optional.
123
124 To access the auditing schema to look at the auditdata or revert a
125 change, use C<< $schema->_journal_schema >>.
126
127 =head2 TABLES
128
129 The journal schema contains a number of tables.
130
131 =over
132
133 =item ChangeSet
134
135 Each changeset row has an auto-incremented ID, optional user_id and
136 session_id, and a set_date which defaults to the current datetime.
137
138 A ChangeSet has_many Changes.
139
140 =item ChangeLog
141
142 Each change/operation done in the transaction is recorded as a row in
143 the ChangeLog table. It contains an auto-incrementing ID, the
144 changeset_id and an order column for the ordering of each change in
145 the changeset.
146
147 =item AuditLog
148
149 For every table in the original database that is to be audited, an
150 AuditLog table is created. Each auditlog row has an id which will
151 contain the primary key of the table it is associated with. (NB:
152 currently only supports integer-based single column PKs). The
153 create_id and delete_id fields contain the IDs of the Changes that
154 created or deleted this row.
155
156 =item AuditHistory
157
158 For every table in the original database to be audited, an
159 AuditHistory table is created. Each row has a change_id field
160 containing the ID of the ChangeLog row. The other fields correspond to
161 all the fields from the original table. Each time a column value in
162 the original table is changed, the entire row contents before the
163 change are added as a new row in this table.
164
165 =back
166
167 =head2 METHODS
168
169 =over
170
171 =item journal_connection \@connect_info
172
173 Set the connection information for the database to save your audit
174 information to.
175
176 Leaving this blank assumes you want to store the audit data into your current
177 database. The storage object will be shared by the regular schema and the
178 journalling schema.
179
180 =item journal_sources \@source_names
181
182 Set a list of source names you would like to audit, if unset, all
183 sources are used.
184
185 NOTE: Currently only sources with a single-column PK are supported, so
186 use this method if you have sources with multi-column PKs.
187
188 =item journal_storage_type $type
189
190 Enter the special storage type of your journal schema if needed. See
191 L<DBIx::Class::Storage::DBI> for more information on storage types.
192
193 =item journal_user \@rel
194
195 The user_id column in the L</ChangeSet> will be linked to your user id
196 with a belongs_to relation, if this is set with the appropriate
197 arguments.
198
199 =item journal_deploy_on_connect $bool
200
201 If set to a true value will cause C<journal_schema_deploy> to be called on
202 C<connect>.
203
204 Not reccomended, but present for backwards compatibility.
205
206 =item changeset_user $user_id
207
208 Set the user_id for the following changeset(s). This must be an integer.
209
210 =item changeset_session $session_id
211
212 Set the session_id for the following changeset(s). This must be an integer.
213
214 =item txn_do $code_ref, @args
215
216 Overloaded L<DBIx::Class::Schema/txn_do>, this must be used to start a
217 new changeset to cover a group of changes. Each subsequent change to
218 an audited table will use the changeset_id created in the most recent
219 txn_do call.
220
221 Currently nested C<txn_do> calls cause a single ChangeSet object to be created.
222
223 =back
224
225 =head1 SEE ALSO
226
227 L<DBIx::Class> - You'll need it to use this.
228
229 =head1 NOTES
230
231 Only single-column integer primary key'd tables are supported for auditing so far.
232
233 Updates made via L<DBIx::Class::ResultSet/update> are not yet supported.
234
235 No API for viewing or restoring changes yet.
236
237 Patches for the above welcome ;)
238
239 =head1 AUTHOR
240
241 Jess Robinson <castaway@desert-island.me.uk>
242
243 Matt S. Trout <mst@shadowcatsystems.co.uk> (ideas and prodding)
244
245 =head1 LICENCE
246
247 You may distribute this code under the same terms as Perl itself.
248
249 =cut
250
251 1;