myabc-dm-audited 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Dirkjan Bussink
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,4 @@
1
+ dm-audited
2
+ ==========
3
+
4
+ Add auditing to DataMapper Resources
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'spec/rake/spectask'
6
+ require 'pathname'
7
+
8
+ CLEAN.include '{log,pkg}/'
9
+
10
+ spec = Gem::Specification.load('dm-audited.gemspec')
11
+
12
+ task :default => [ :spec ]
13
+
14
+ WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
15
+ SUDO = WIN32 ? '' : ('sudo' unless ENV['SUDOLESS'])
16
+
17
+ Rake::GemPackageTask.new(spec) do |pkg|
18
+ pkg.gem_spec = spec
19
+ end
20
+
21
+ desc "Install #{spec.name} #{spec.version}"
22
+ task :install => [ :package ] do
23
+ sh "#{SUDO} gem install pkg/#{spec.name}-#{spec.version} --no-update-sources", :verbose => false
24
+ end
25
+
26
+ desc 'Run specifications'
27
+ Spec::Rake::SpecTask.new(:spec) do |t|
28
+ t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
29
+ t.spec_files = Pathname.glob(Pathname.new(__FILE__).dirname + 'spec/**/*_spec.rb')
30
+ end
@@ -0,0 +1,127 @@
1
+ require 'rubygems'
2
+ gem 'dm-core', '>=0.9.2'
3
+ gem 'dm-serializer', '>=0.9.2'
4
+ require 'dm-core'
5
+ require 'dm-timestamps'
6
+ require 'dm-serializer'
7
+
8
+ module DataMapper
9
+ module Audited
10
+ def self.included(base)
11
+ base.extend(ClassMethods)
12
+ end
13
+
14
+ module InstanceMethods
15
+
16
+ def create_audit(action)
17
+ # It needs to provide User.current_user if the user is to be saved
18
+ # The implementer needs to provide this and for example needs to make
19
+ # sure that the implementation is thread safe.
20
+ # The request is also optionally included if it can be found in the
21
+ # Application controller. Here again the implementer needs to provide
22
+ # this and make sure it's thread safe.
23
+ user = defined?(::User) && ::User.respond_to?(:current_user) && ::User.current_user ? ::User.current_user.id : nil
24
+ request = defined?(::Application) && ::Application.respond_to?(:current_request) ? ::Application.current_request : nil
25
+
26
+ changed_attributes = {}
27
+ @audited_attributes.each do |key, val|
28
+ changed_attributes[key] = [val, attributes[key]] unless val == attributes[key]
29
+ end
30
+
31
+ audit_attributes = {
32
+ :auditable_type => self.class.to_s,
33
+ :auditable_id => self.id,
34
+ :user_id => user,
35
+ :action => action,
36
+ :changes => changed_attributes
37
+ }
38
+
39
+ if request
40
+ params = request.params
41
+ if defined?(::Application) && defined?(Merb::Controller)
42
+ params = Application._filter_params(params)
43
+ end
44
+
45
+ audit_attributes.merge!(
46
+ :request_uri => request.uri,
47
+ :request_method => request.method,
48
+ :request_params => params
49
+ )
50
+ end
51
+
52
+ remove_instance_variable("@audited_attributes")
53
+ remove_instance_variable("@audited_new_record") if instance_variable_defined?("@audited_new_record")
54
+
55
+ Audit.create(audit_attributes) unless changed_attributes.empty? && action != 'destroy'
56
+ end
57
+
58
+ def audits
59
+ Audit.all(:auditable_type => self.class.to_s, :auditable_id => self.id.to_s, :order => [:created_at, :id])
60
+ end
61
+
62
+ end
63
+
64
+ module ClassMethods
65
+ def is_audited
66
+
67
+ include DataMapper::Audited::InstanceMethods
68
+
69
+ before :save do
70
+ @audited_attributes = original_attributes.clone
71
+ @audited_new_record = new?
72
+ end
73
+
74
+ before :destroy do
75
+ @audited_attributes = original_attributes.clone
76
+ end
77
+
78
+ after :save do
79
+ create_audit(@audited_new_record ? 'create' : 'update')
80
+ end
81
+
82
+ after :destroy do
83
+ create_audit('destroy')
84
+ end
85
+
86
+ end
87
+ end
88
+
89
+ class Audit
90
+ include DataMapper::Resource
91
+
92
+ property :id, Serial
93
+ property :auditable_type, String
94
+ property :auditable_id, Integer
95
+ property :user_id, Integer
96
+ property :request_uri, String, :length => 255
97
+ property :request_method, String
98
+ property :request_params, Text
99
+ property :action, String
100
+ property :changes, Text
101
+ property :created_at, DateTime
102
+
103
+ def auditable
104
+ auditable_type.constantize.get(auditable_id)
105
+ end
106
+
107
+ def changes=(properties)
108
+ attribute_set(:changes, properties.to_json)
109
+ end
110
+
111
+ def changes
112
+ @changes_hash ||= Mash.new(JSON.load(attribute_get(:changes)))
113
+ end
114
+
115
+ def request_params=(params)
116
+ attribute_set(:request_params, params.to_json)
117
+ end
118
+
119
+ def request_params
120
+ @request_params_hash ||= Mash.new(JSON.load(attribute_get(:request_params)))
121
+ @request_params_hash
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'pathname'
3
+
4
+ gem 'dm-core', '>=0.9.2'
5
+ require 'dm-core'
6
+
7
+ spec_dir_path = Pathname(__FILE__).dirname.expand_path
8
+
9
+ def load_driver(name, default_uri)
10
+ return false if ENV['ADAPTER'] != name.to_s
11
+
12
+ begin
13
+ DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
14
+ DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
15
+
16
+ FileUtils.touch LOG_PATH
17
+ DataMapper::Logger.new(LOG_PATH, 0)
18
+ at_exit { DataMapper.logger.close }
19
+ true
20
+ rescue Gem::LoadError => e
21
+ warn "Could not load #{lib}: #{e}"
22
+ false
23
+ end
24
+ end
25
+
26
+ ENV['ADAPTER'] ||= 'sqlite3'
27
+
28
+ LOG_PATH = Pathname(__FILE__).dirname.expand_path.to_s + '/sql.log'
29
+ HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
30
+ HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
31
+ HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
32
+
33
+ require spec_dir_path.parent + 'lib/dm-audited'
34
+
35
+ Dir[spec_dir_path + "fixtures/*.rb"].each do |fixture_file|
36
+ require fixture_file
37
+ end
@@ -0,0 +1,74 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ describe "DataMapper::Audited" do
5
+
6
+ before :all do
7
+ DataObjects::Sqlite3.logger = DataObjects::Logger.new('spec/sql.log', 0)
8
+
9
+ class Cow
10
+ include DataMapper::Resource
11
+ include DataMapper::Audited
12
+
13
+ property :id, Integer, :serial => true
14
+ property :name, String
15
+ property :breed, String
16
+
17
+ is_audited
18
+
19
+ auto_migrate!(:default)
20
+ end
21
+
22
+ module DataMapper
23
+ module Audited
24
+ class Audit
25
+ auto_migrate!(:default)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ it "is included when DataMapper::Audited is loaded" do
32
+ Cow.new.should be_kind_of(DataMapper::Audited)
33
+ end
34
+
35
+ it "should create a new Audit object when creating an object" do
36
+ c = Cow.new(:name => "Bertha")
37
+ c.save
38
+
39
+ audit = DataMapper::Audited::Audit.first(:auditable_type => c.class.to_s, :auditable_id => c.id.to_s)
40
+
41
+ audit.should_not be_nil
42
+ audit.changes[:name].should_not be_nil
43
+ audit.action.should eql("create")
44
+ end
45
+
46
+ it "should create a new Audit object when changing an object" do
47
+ c = Cow.create(:name => "Bertha")
48
+
49
+ c.name = "Cindy"
50
+ c.save
51
+
52
+ audits = DataMapper::Audited::Audit.all(:auditable_type => c.class.to_s, :auditable_id => c.id.to_s, :order => [:created_at])
53
+
54
+ audits.length.should == 2
55
+ audits.last.should_not be_nil
56
+
57
+ audits.last.changes[:name].should_not be_nil
58
+ audits.last.changes[:name].first.should eql("Bertha")
59
+ audits.last.changes[:name].last.should eql("Cindy")
60
+ audits.last.action.should eql("update")
61
+ end
62
+
63
+ it "should create a new Audit object when destroying an object" do
64
+ c = Cow.create(:name => "Bertha")
65
+
66
+ c.destroy
67
+
68
+ c.audits.length.should == 2
69
+ c.audits.last.should_not be_nil
70
+
71
+ c.audits.last.action.should eql("destroy")
72
+ end
73
+
74
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: myabc-dm-audited
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Dirkjan Bussink
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dm-core
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.10.0
24
+ version:
25
+ description: DataMapper plugin providing auditing for resources
26
+ email: d.bussink@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ files:
35
+ - lib/dm-audited.rb
36
+ - spec/spec.opts
37
+ - spec/spec_helper.rb
38
+ - spec/unit/audited_spec.rb
39
+ - Rakefile
40
+ - README
41
+ - LICENSE
42
+ has_rdoc: true
43
+ homepage: http://github.com/dbussink/dm-audited
44
+ licenses:
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.5
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: DataMapper plugin providing auditing for resources
69
+ test_files: []
70
+