mordor-auditing 0.0.4

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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mordor-auditing (0.0.3)
5
+ mordor (= 0.2.1)
6
+
7
+ GEM
8
+ specs:
9
+ bson (1.4.0)
10
+ bson_ext (1.4.0)
11
+ diff-lcs (1.1.3)
12
+ extlib (0.9.15)
13
+ json (1.6.1)
14
+ mongo (1.4.0)
15
+ bson (= 1.4.0)
16
+ mordor (0.2.1)
17
+ bson_ext
18
+ extlib
19
+ json
20
+ mongo
21
+ rake (0.9.2)
22
+ rspec (2.6.0)
23
+ rspec-core (~> 2.6.0)
24
+ rspec-expectations (~> 2.6.0)
25
+ rspec-mocks (~> 2.6.0)
26
+ rspec-core (2.6.4)
27
+ rspec-expectations (2.6.0)
28
+ diff-lcs (~> 1.1.2)
29
+ rspec-mocks (2.6.0)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ mordor (= 0.2.1)
36
+ mordor-auditing!
37
+ rake
38
+ rspec (~> 2.0)
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ load('tasks/github-gem.rake')
2
+
3
+ # Register the gem release tasks in the gem namespace
4
+ GithubGem::RakeTasks.new(:gem) do |config|
5
+
6
+ # Note that the following values are all default values and can
7
+ # therefore be omitted if they are not changed.
8
+
9
+ config.gemspec_file = GithubGem.detect_gemspec_file
10
+ config.main_include = GithubGem.detect_main_include
11
+ config.root_dir = Dir.pwd
12
+ config.test_pattern = 'test/**/*_test.rb'
13
+ config.spec_pattern = 'spec/**/*_spec.rb'
14
+ config.local_branch = 'master'
15
+ config.remote = 'origin'
16
+ config.remote_branch = 'master'
17
+ end
data/auditing.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "mordor-auditing"
3
+
4
+ # Do not set the version and date field manually, this is done by the release script
5
+ s.version = "0.0.4"
6
+ s.date = "2011-12-27"
7
+
8
+ s.summary = "mordor-auditing"
9
+ s.description = <<-eos
10
+ Auditing classes based on the Mordor gem, used to audit requests and modifications on objects
11
+ eos
12
+
13
+ s.add_development_dependency('rake')
14
+ s.add_development_dependency('rspec', '~> 2.0')
15
+
16
+ s.add_development_dependency('mordor', '0.2.1')
17
+
18
+ s.add_runtime_dependency('mordor', '0.2.1')
19
+
20
+ s.authors = ['Jan-Willem Koelewijn', 'Dirkjan Bussink']
21
+ s.email = ['janwillem.koelewijn@nedap.com', 'dirkjan.bussink@nedap.com']
22
+ s.homepage = 'http://www.nedap.com'
23
+
24
+ # The files and test_files directives are set automatically by the release script.
25
+ # Do not change them by hand, but make sure to add the files to the git repository.
26
+ s.files = %w(.gitignore Gemfile Gemfile.lock Rakefile auditing.gemspec lib/auditing.rb lib/auditing/modification.rb lib/auditing/request.rb lib/auditing/version.rb spec/auditing/modification_spec.rb spec/auditing/request_spec.rb spec/spec.opts spec/spec_helper.rb tasks/github-gem.rake)
27
+ end
@@ -0,0 +1,57 @@
1
+ module Auditing
2
+ class Modification
3
+ include Mordor::Resource
4
+
5
+ attribute :request_id, :index => true
6
+ attribute :object_type
7
+ attribute :object_id
8
+ attribute :changes
9
+ attribute :action
10
+ attribute :at, :index => true
11
+
12
+ def request_id=(id)
13
+ if id.is_a?(String) && id != ""
14
+ id = BSON::ObjectId.from_string(id)
15
+ end
16
+ @request_id = id
17
+ end
18
+
19
+ def request
20
+ Auditing::Request.find_by_id(request_id)
21
+ end
22
+
23
+ def request=(request)
24
+ self.request_id = request._id
25
+ end
26
+
27
+ def self.find_by_request(id)
28
+ find_by_request_id(id)
29
+ end
30
+
31
+ def self.find_by_request_id(id)
32
+ if id.is_a?(String)
33
+ id = BSON::ObjectId.from_string(id)
34
+ end
35
+ Mordor::Collection.new(self, self.collection.find(:request_id => id))
36
+ end
37
+
38
+ def to_hash
39
+ {
40
+ :request_id => request_id,
41
+ :object_type => object_type,
42
+ :object_id => object_id,
43
+ :changes => changes,
44
+ :action => action,
45
+ :at => at
46
+ }
47
+ end
48
+
49
+ def changes=(changes)
50
+ @changes = replace_params(changes)
51
+ end
52
+
53
+ def self.collection_name
54
+ 'audit_modifications'
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,75 @@
1
+ module Auditing
2
+ class Request
3
+ include Mordor::Resource
4
+
5
+ attribute :url
6
+ attribute :url_parts
7
+ attribute :method
8
+ attribute :params
9
+ attribute :user_id, :finder_method => :find_by_user, :index => true
10
+ attribute :real_user_id
11
+ attribute :at, :index => true
12
+
13
+ def to_hash
14
+ {
15
+ :user_id => user_id,
16
+ :real_user_id => real_user_id,
17
+ :params => params,
18
+ :url => url,
19
+ :url_parts => url_parts,
20
+ :method => method,
21
+ :at => at
22
+ }
23
+ end
24
+
25
+ def url=(url)
26
+ self.url_parts = url_to_parts(url)
27
+ @url = url
28
+ end
29
+
30
+ def modifications
31
+ Modification.find_by_request(_id.to_s)
32
+ end
33
+
34
+ def url_parts=(parts)
35
+ @url_parts = self.replace_params(parts)
36
+ end
37
+
38
+ def params=(params)
39
+ @params = self.replace_params(params)
40
+ end
41
+
42
+ def self.find_by_url(url, partial = false)
43
+ if partial
44
+ Mordor::Collection.new(self, self.collection.find(:url => /.*#{url}.*/))
45
+ else
46
+ Mordor::Collection.new(self, self.collection.find(:url => url))
47
+ end
48
+ end
49
+
50
+ def self.find_by_url_parts(params = {})
51
+ parts_params = {}
52
+ params.each do |key, value|
53
+ parts_params["url_parts.#{key}"] = value
54
+ end
55
+ Mordor::Collection.new(self, self.collection.find(parts_params))
56
+ end
57
+
58
+ private
59
+
60
+ def self.collection_name
61
+ 'audit_requests'
62
+ end
63
+
64
+ def url_to_parts(url)
65
+ result = {}
66
+ if url
67
+ url.scan(/([\w|_]+)\/([\d|-]+)/).each do |key, value|
68
+ key = key.gsub(/\W|\./, "_")
69
+ result[key.to_sym] = value.match(/-/) ? value : value.to_i
70
+ end
71
+ end
72
+ result
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,3 @@
1
+ module Auditing
2
+ VERSION = "0.0.1"
3
+ end
data/lib/auditing.rb ADDED
@@ -0,0 +1,98 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+ require 'extlib'
4
+ require 'mordor'
5
+ require 'auditing/version'
6
+ require 'auditing/request'
7
+ require 'auditing/modification'
8
+
9
+ unless Object.const_defined?('BigDecimal')
10
+ BigDecimal = Float
11
+ end
12
+
13
+ class Date
14
+ def to_time(form = :utc)
15
+ Time.send("#{form}", year, month, day)
16
+ end
17
+
18
+ def to_gm
19
+ Time.gm(year, month, day).to_datetime
20
+ end
21
+
22
+ def to_local
23
+ Time.local(year, month, day).to_datetime
24
+ end
25
+
26
+ def to_datetime
27
+ DateTime.civil(self.year, self.mon, self.day)
28
+ end
29
+
30
+ def show(format = nil)
31
+ case format
32
+ when :human
33
+ strftime("%d-%m-%Y")
34
+ else
35
+ to_s
36
+ end
37
+ end
38
+
39
+ def full_string
40
+ strftime("%A %d %B %Y")
41
+ end
42
+ end
43
+
44
+ class DateTime
45
+ def to_datetime
46
+ self
47
+ end
48
+
49
+ def to_date
50
+ Date.civil(self.year, self.mon, self.day)
51
+ end
52
+
53
+ def show(format = nil)
54
+ case format
55
+ when :human
56
+ strftime("%d-%m-%Y %H:%M")
57
+ when :full
58
+ strftime("%d-%m-%Y %H:%M:%S")
59
+ else
60
+ to_s
61
+ end
62
+ end
63
+ end
64
+
65
+ class Time
66
+
67
+ def to_date
68
+ Date.civil(year, month, day)
69
+ end if RUBY_VERSION < '1.8.6'
70
+
71
+ def show(format = nil)
72
+ return self.to_date.show(format) if [hour,min] == [0,0]
73
+ case format
74
+ when :human
75
+ strftime("%d-%m-%Y %H:%m")
76
+ when :full
77
+ strftime("%d-%m-%Y %H:%M:%S")
78
+ else
79
+ to_s
80
+ end
81
+ end
82
+ end
83
+
84
+ module Mordor
85
+ CONFIG = {
86
+ :hostname => 'localhost',
87
+ :port => 27017,
88
+ :database => 'development'
89
+ }
90
+
91
+ def connection
92
+ @connection ||= Mongo::Connection.new(CONFIG[:hostname], CONFIG[:port])
93
+ @connection.autenticate(CONFIG[:username], CONFIG[:password]) if CONFIG[:username]
94
+ @connection.db(CONFIG[:database])
95
+ end
96
+ module_function :connection
97
+
98
+ end
@@ -0,0 +1,145 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
2
+
3
+ module AuditingModificationSpecHelper
4
+ def compare_modifications(stored_mods, retrieved_mods)
5
+ if retrieved_mods.is_a?(BSON::OrderedHash)
6
+ retrieved_mods['_id'].should == stored_mods._id
7
+ retrieved_mods['request_id'].should == (stored_mods.request_id ? stored_mods.request_id : nil)
8
+ retrieved_mods['object_type'].should == stored_mods.object_type
9
+ retrieved_mods['object_id'].should == stored_mods.object_id
10
+ retrieved_mods['changes'].size.should == stored_mods.changes.size
11
+ retrieved_mods['changes'].each do |k,v|
12
+ stored_mods.changes[k].should == v
13
+ end
14
+ retrieved_mods['action'].should == stored_mods.action
15
+ retrieved_mods['at'].should == stored_mods.at.to_time
16
+ else
17
+ retrieved_mods._id.should == stored_mods._id
18
+ retrieved_mods.request_id.should == (stored_mods.request_id ? stored_mods.request_id : nil)
19
+ retrieved_mods.object_type.should == stored_mods.object_type
20
+ retrieved_mods.object_id.should == stored_mods.object_id
21
+ retrieved_mods.changes.each do |key, value|
22
+ stored_mods.changes[key].should == value
23
+ end
24
+ retrieved_mods.action.should == stored_mods.action
25
+ retrieved_mods.at.should == stored_mods.at.to_time
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "with respect to modifications" do
31
+ include AuditingModificationSpecHelper
32
+
33
+ before :each do
34
+ clean_sheet
35
+ end
36
+
37
+ it "should correctly initialize" do
38
+ options = {
39
+ :object_type => 'String',
40
+ :object_id => 2,
41
+ :changes => {:length => [2, 4]},
42
+ :action => 'put',
43
+ :at => DateTime.now.to_time
44
+ }
45
+ mod = Auditing::Modification.new(options)
46
+ options.each do |key, value|
47
+ ret_val = mod.send(key)
48
+ if value.is_a?(Hash)
49
+ value.each do |k, v|
50
+ ret_val[k.to_s].should == v
51
+ end
52
+ else
53
+ ret_val.should == value
54
+ end
55
+ end
56
+ end
57
+
58
+ context "with respect to saving and retrieving" do
59
+ it "should correctly save the modification" do
60
+ options = {
61
+ :object_type => 'String',
62
+ :object_id => 2,
63
+ :changes => {:length => [2, 4]},
64
+ :action => 'put',
65
+ :at => DateTime.now.to_time
66
+ }
67
+
68
+ mod = Auditing::Modification.new(options)
69
+ mod.save.should be_true
70
+ mod._id.should_not be_nil
71
+
72
+ Auditing::Modification.collection.count.should == 1
73
+
74
+ other_mod = mod.class.collection.find_one(:_id => mod._id)
75
+
76
+ compare_modifications(mod, other_mod)
77
+ end
78
+ end
79
+
80
+ describe "with respect to retrieval" do
81
+ before :each do
82
+ options = {
83
+ :object_type => 'String',
84
+ :object_id => 2,
85
+ :changes => {:length => [2, 4]},
86
+ :action => 'put',
87
+ :at => DateTime.now.to_time
88
+ }
89
+
90
+ @modification = Auditing::Modification.new(options)
91
+ @modification.save.should be_true
92
+ @modification._id.should_not be_nil
93
+ end
94
+
95
+ it "should correctly retrieve saved modifications by its _id" do
96
+ mod = Auditing::Modification.find_by_id(@modification._id)
97
+ compare_modifications(@modification, mod)
98
+ end
99
+
100
+ it "should correctly retrieve requests on a certain day" do
101
+ mods = Auditing::Modification.find_by_day(Date.today)
102
+ mods.size.should == 1
103
+ compare_modifications(@modification, mods.first)
104
+
105
+ mods = Auditing::Modification.find_by_day(DateTime.now)
106
+ mods.size.should == 1
107
+ compare_modifications(@modification, mods.first)
108
+ end
109
+
110
+ it "should correctly retrieve requests by object_type" do
111
+ mods = Auditing::Modification.find_by_object_type(@modification.object_type)
112
+ mods.size.should == 1
113
+ compare_modifications(@modification, mods.first)
114
+ end
115
+
116
+ it "should correctly retrieve requests by object_id" do
117
+ mods = Auditing::Modification.find_by_object_id(@modification.object_id)
118
+ mods.size.should == 1
119
+ compare_modifications(@modification, mods.first)
120
+ end
121
+
122
+ it "should correctly retrieve requests by action" do
123
+ mods = Auditing::Modification.find_by_action(@modification.action)
124
+ mods.size.should == 1
125
+ compare_modifications(@modification, mods.first)
126
+ end
127
+
128
+ it "should correctly retrieve requests by request_id" do
129
+ @modification.request_id = "4e79b0b20e02e145a9000001"
130
+ @modification.save.should be_true
131
+ mods = Auditing::Modification.find_by_request_id(@modification.request_id)
132
+ mods.size.should == 1
133
+ compare_modifications(@modification, mods.first)
134
+ end
135
+
136
+ it "should correctly retrieve requests by request" do
137
+ @modification.request_id = "4e79b0b20e02e145a9000001"
138
+ @modification.save.should be_true
139
+ mods = Auditing::Modification.find_by_request(@modification.request_id)
140
+ mods.size.should == 1
141
+ compare_modifications(@modification, mods.first)
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,323 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
2
+
3
+ module AuditingRequestSpecHelper
4
+ def compare_requests(stored_request, retrieved_request)
5
+ if retrieved_request.is_a?(BSON::OrderedHash)
6
+ retrieved_request['url'].should == stored_request.url
7
+ retrieved_request['method'].should == stored_request.method
8
+ retrieved_request['params'].should be_instance_of(BSON::OrderedHash)
9
+ retrieved_request['params'].should have_key("test_param1")
10
+ retrieved_request['params']['test_param1'].should == stored_request.params['test_param1']
11
+ retrieved_request['params'].should have_key("test_param2")
12
+ retrieved_request['params']['test_param2'].should == stored_request.params['test_param2']
13
+ retrieved_request['user_id'].should == stored_request.user_id
14
+ retrieved_request['real_user_id'].should == stored_request.real_user_id
15
+ retrieved_request['at'].gmtime.to_s.should == stored_request.at.gmtime.to_s
16
+ else
17
+ retrieved_request.url == stored_request.url
18
+ retrieved_request.method == stored_request.method
19
+ retrieved_request.user_id == stored_request.user_id
20
+ retrieved_request.real_user_id == stored_request.real_user_id
21
+ retrieved_request.at == stored_request.at
22
+ end
23
+ end
24
+
25
+ def compare_modifications(stored_mods, retrieved_mods)
26
+ if retrieved_mods.is_a?(BSON::OrderedHash)
27
+ retrieved_mods['_id'].should == stored_mods._id
28
+ retrieved_mods['request_id'].should == (stored_mods.request_id ? stored_mods.request_id : "")
29
+ retrieved_mods['object_type'].should == stored_mods.object_type
30
+ retrieved_mods['object_id'].should == stored_mods.object_id
31
+ retrieved_mods['changes'].size.should == stored_mods.changes.size
32
+ retrieved_mods['changes'].each do |k,v|
33
+ stored_mods.changes[k].should == v
34
+ end
35
+ retrieved_mods['action'].should == stored_mods.action
36
+ retrieved_mods['at'].to_s.should == stored_mods.at.to_time.to_s
37
+ else
38
+ retrieved_mods._id.should == stored_mods._id
39
+ retrieved_mods.request_id.should == (stored_mods.request_id ? stored_mods.request_id : "")
40
+ retrieved_mods.object_type.should == stored_mods.object_type
41
+ retrieved_mods.object_id.should == stored_mods.object_id
42
+ retrieved_mods.changes.each do |key, value|
43
+ stored_mods.changes[key].should == value
44
+ end
45
+ retrieved_mods.action.should == stored_mods.action
46
+ retrieved_mods.at.should == stored_mods.at.to_time
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "with respect to auditing requests" do
52
+ include AuditingRequestSpecHelper
53
+
54
+ before :each do
55
+ clean_sheet
56
+ end
57
+
58
+ it "should correctly initialize" do
59
+ options = {
60
+ :url => 'http://test.com',
61
+ :method => 'get',
62
+ :params => {:test_param1 => '1', :test_param2 => '2'},
63
+ :user_id => 3,
64
+ :real_user_id => 5,
65
+ :at => Time.now
66
+ }
67
+
68
+ request = Auditing::Request.new(options)
69
+ options.each do |key, value|
70
+ ret_val = request.send(key)
71
+ if value.is_a?(Hash)
72
+ value.each do |k, v|
73
+ ret_val[k.to_s].should == v
74
+ end
75
+ else
76
+ ret_val.should == value
77
+ end
78
+ end
79
+ end
80
+
81
+ it "should correctly replace Date params with Times" do
82
+ options = {
83
+ :params => {:first => Date.today}
84
+ }
85
+ request = Auditing::Request.new(options)
86
+ request.params["first"].should be_instance_of(Time)
87
+ end
88
+
89
+ it "should correctly replace DateTime params with Time's" do
90
+ options = {
91
+ :params => {:first => DateTime.now}
92
+ }
93
+ request = Auditing::Request.new(options)
94
+ request.params["first"].should be_instance_of(Time)
95
+ end
96
+
97
+ context "with respect to saving" do
98
+ it "should correctly save the request" do
99
+ options = {
100
+ :url => 'http://test.com',
101
+ :method => 'get',
102
+ :params => {:test_param1 => '1', :test_param2 => '2'},
103
+ :user_id => 3,
104
+ :real_user_id => 5,
105
+ :at => Time.now
106
+ }
107
+ request = Auditing::Request.new(options)
108
+ request.save.should be_true
109
+ request._id.should_not be_nil
110
+
111
+ Auditing::Request.collection.count.should == 1
112
+
113
+ other_request = request.class.collection.find_one(:_id => request._id)
114
+
115
+ compare_requests(request, other_request)
116
+ end
117
+ end
118
+
119
+ describe "with respect to retrieval" do
120
+ before(:each) do
121
+ @request_time = DateTime.now.to_time
122
+ options = {
123
+ :url => 'http://test.com',
124
+ :method => 'get',
125
+ :params => {:test_param1 => '1', :test_param2 => '2'},
126
+ :user_id => 3,
127
+ :real_user_id => 5,
128
+ :at => @request_time
129
+ }
130
+ @request = Auditing::Request.new(options)
131
+ @request.save.should be_true
132
+ Auditing::Request.collection.find(:_id => @request._id).count.should == 1
133
+ end
134
+
135
+ it "should correctly retrieve a request by its _id" do
136
+ req = Auditing::Request.find_by_id(@request._id)
137
+ compare_requests(@request, req)
138
+ end
139
+
140
+ it "should correctly retrieve requests on a certain day" do
141
+ reqs = Auditing::Request.find_by_day(Date.today)
142
+ reqs.size.should == 1
143
+ compare_requests(@request, reqs.first)
144
+
145
+ reqs = Auditing::Request.find_by_day(DateTime.now)
146
+ reqs.size.should == 1
147
+ compare_requests(@request, reqs.first)
148
+ end
149
+
150
+ it "should correctly retrieve requests by url" do
151
+ reqs = Auditing::Request.find_by_url(@request.url)
152
+ reqs.size.should == 1
153
+ compare_requests(@request, reqs.first)
154
+ end
155
+
156
+ it "should correctly retrieve requests by part of an url" do
157
+ reqs = Auditing::Request.find_by_url(@request.url[0, @request.url.length - 2], true)
158
+ reqs.size.should == 1
159
+ compare_requests(@request, reqs.first)
160
+ end
161
+
162
+ it "should correctly retrieve requests by user_id" do
163
+ reqs = Auditing::Request.find_by_user(@request.user_id)
164
+ reqs.size.should == 1
165
+ compare_requests(@request, reqs.first)
166
+ end
167
+
168
+ it "should correctly retrieve requests by real_user_id" do
169
+ reqs = Auditing::Request.find_by_real_user_id(@request.real_user_id)
170
+ reqs.size.should == 1
171
+ compare_requests(@request, reqs.first)
172
+ end
173
+
174
+ it "should correctly retrieve requests by method" do
175
+ reqs = Auditing::Request.find_by_method(@request.method)
176
+ reqs.size.should == 1
177
+ compare_requests(@request, reqs.first)
178
+ end
179
+
180
+ describe "with respect to modifications" do
181
+ before :each do
182
+ options = {
183
+ :request_id => @request._id,
184
+ :object_type => "Audited::Request",
185
+ :object_id => @request._id.to_s,
186
+ :changes => {:url => [@request.url, "#{@request.url}/request"]},
187
+ :action => 'get',
188
+ :at => @request_time,
189
+ :request_id => @request._id
190
+ }
191
+ @modification = Auditing::Modification.new(options)
192
+ @modification.save.should be_true
193
+ @modification._id.should_not be_nil
194
+ Auditing::Modification.collection.count == 1
195
+ end
196
+
197
+ it "should correctly retrieve the corresponding modifications" do
198
+ @request.modifications.should_not be_nil
199
+ @request.modifications.size.should == 1
200
+ compare_modifications(@modification, @request.modifications.first)
201
+ end
202
+
203
+ it "should correctly retrieve the same request through the modifications" do
204
+ @request.modifications.should_not be_nil
205
+ @request.modifications.size.should == 1
206
+ compare_modifications(@modification, @request.modifications.first)
207
+ compare_requests(@request, @request.modifications.first.request)
208
+ end
209
+ end
210
+
211
+ end
212
+
213
+ describe "with respect to urls" do
214
+ before :each do
215
+ options = {
216
+ :url => '/week/2011-39/staffing_agencies/123/customers/12/arrangements/123',
217
+ :method => 'get',
218
+ :params => {:test_param1 => '1', :test_param2 => '2'},
219
+ :user_id => 3,
220
+ :real_user_id => 5,
221
+ :at => Time.now
222
+ }
223
+ @request = Auditing::Request.new(options)
224
+ @request.save.should be_true
225
+ end
226
+
227
+ it "should create url parts when saved" do
228
+ @request.url_parts.should_not be_nil
229
+ end
230
+
231
+ it "should create correct url parts" do
232
+ parts = @request.url_parts
233
+ parts.keys.should include "week"
234
+ parts.keys.should include "staffing_agencies"
235
+ parts.keys.should include "customers"
236
+ parts.keys.should include "arrangements"
237
+
238
+ parts["week"].should == "2011-39"
239
+ parts["staffing_agencies"].should == 123
240
+ parts["customers"].should == 12
241
+ parts["arrangements"].should == 123
242
+ end
243
+
244
+ it "should correctly get weeks" do
245
+ options = {
246
+ :url => '/week/2011-9/staffing_agencies/123/customers/12/arrangements/123',
247
+ :method => 'get',
248
+ :params => {:test_param1 => '1', :test_param2 => '2'},
249
+ :user_id => 3,
250
+ :real_user_id => 5,
251
+ :at => Time.now
252
+ }
253
+ request = Auditing::Request.new(options)
254
+ request.save.should be_true
255
+ request.url_parts.keys.should include "week"
256
+ request.url_parts["week"].should == "2011-9"
257
+
258
+ options = {
259
+ :url => '/week/weeknumber/staffing_agencies/123/customers/12/arrangements/123',
260
+ :method => 'get',
261
+ :params => {:test_param1 => '1', :test_param2 => '2'},
262
+ :user_id => 3,
263
+ :real_user_id => 5,
264
+ :at => Time.now
265
+ }
266
+ request = Auditing::Request.new(options)
267
+ request.save.should be_true
268
+ request.url_parts.keys.should_not include "week"
269
+ end
270
+
271
+ it "should corretly retrieve requests based on parts of the url" do
272
+ options = {
273
+ :url => '/week/2011-9/staffing_agencies/1234/customers/12/arrangements/123',
274
+ :method => 'get',
275
+ :params => {:test_param1 => '1', :test_param2 => '2'},
276
+ :user_id => 3,
277
+ :real_user_id => 5,
278
+ :at => Time.now
279
+ }
280
+ request = Auditing::Request.new(options)
281
+ request.save.should be_true
282
+
283
+ options2 = {
284
+ :url => '/week/2011-9/staffing_agencies/13/customers/124/arrangements/123',
285
+ :method => 'get',
286
+ :params => {:test_param1 => '1', :test_param2 => '2'},
287
+ :user_id => 3,
288
+ :real_user_id => 5,
289
+ :at => Time.now
290
+ }
291
+ request2 = Auditing::Request.new(options2)
292
+ request2.save.should be_true
293
+
294
+ search_options = {
295
+ :week => "2011-9"
296
+ }
297
+ results = Auditing::Request.find_by_url_parts(search_options)
298
+ results.size.should == 2
299
+
300
+ match = (results.first._id == request._id || results.first._id == request2._id)
301
+ match.should be_true
302
+
303
+ search_options = {
304
+ :staffing_agencies => 1234
305
+ }
306
+
307
+ results = Auditing::Request.find_by_url_parts(search_options)
308
+ results.size.should == 1
309
+ results.first._id.should == request._id
310
+
311
+ search_options = {
312
+ :week => "2011-9",
313
+ :arrangements => 123
314
+ }
315
+ results = Auditing::Request.find_by_url_parts(search_options)
316
+ results.size.should == 2
317
+
318
+ match = (results.first._id == request._id || results.first._id == request2._id)
319
+ match.should be_true
320
+
321
+ end
322
+ end
323
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+ require 'mordor'
4
+
5
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
6
+ require 'auditing'
7
+
8
+ module Mordor
9
+ CONFIG = {
10
+ :hostname => 'localhost',
11
+ :port => 27017,
12
+ :database => 'test'
13
+ }
14
+ end
15
+
16
+ def clean_sheet
17
+ @connection ||= Mongo::Connection.new(Mordor::CONFIG[:hostname], Mordor::CONFIG[:port])
18
+ @db ||= @connection[Mordor::CONFIG[:database]]
19
+ [Auditing::Request, Auditing::Modification].each do |klass|
20
+ @db[klass.collection_name].drop
21
+ end
22
+ end
23
+
@@ -0,0 +1,368 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+ require 'date'
5
+ require 'set'
6
+
7
+ module GithubGem
8
+
9
+ # Detects the gemspc file of this project using heuristics.
10
+ def self.detect_gemspec_file
11
+ FileList['*.gemspec'].first
12
+ end
13
+
14
+ # Detects the main include file of this project using heuristics
15
+ def self.detect_main_include
16
+ if File.exist?(File.expand_path("../lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb", detect_gemspec_file))
17
+ "lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb"
18
+ elsif FileList['lib/*.rb'].length == 1
19
+ FileList['lib/*.rb'].first
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ class RakeTasks
26
+
27
+ include Rake::DSL if Rake.const_defined?('DSL')
28
+
29
+ attr_reader :gemspec, :modified_files
30
+ attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch
31
+
32
+ # Initializes the settings, yields itself for configuration
33
+ # and defines the rake tasks based on the gemspec file.
34
+ def initialize(task_namespace = :gem)
35
+ @gemspec_file = GithubGem.detect_gemspec_file
36
+ @task_namespace = task_namespace
37
+ @main_include = GithubGem.detect_main_include
38
+ @modified_files = Set.new
39
+ @root_dir = Dir.pwd
40
+ @test_pattern = 'test/**/*_test.rb'
41
+ @spec_pattern = 'spec/**/*_spec.rb'
42
+ @local_branch = 'master'
43
+ @remote = 'origin'
44
+ @remote_branch = 'master'
45
+
46
+ yield(self) if block_given?
47
+
48
+ load_gemspec!
49
+ define_tasks!
50
+ end
51
+
52
+ protected
53
+
54
+ def git
55
+ @git ||= ENV['GIT'] || 'git'
56
+ end
57
+
58
+ # Define Unit test tasks
59
+ def define_test_tasks!
60
+ require 'rake/testtask'
61
+
62
+ namespace(:test) do
63
+ Rake::TestTask.new(:basic) do |t|
64
+ t.pattern = test_pattern
65
+ t.verbose = true
66
+ t.libs << 'test'
67
+ end
68
+ end
69
+
70
+ desc "Run all unit tests for #{gemspec.name}"
71
+ task(:test => ['test:basic'])
72
+ end
73
+
74
+ # Defines RSpec tasks
75
+ def define_rspec_tasks!
76
+ require 'rspec/core/rake_task'
77
+
78
+ namespace(:spec) do
79
+ desc "Verify all RSpec examples for #{gemspec.name}"
80
+ RSpec::Core::RakeTask.new(:basic) do |t|
81
+ t.pattern = spec_pattern
82
+ end
83
+
84
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
85
+ RSpec::Core::RakeTask.new(:specdoc) do |t|
86
+ t.pattern = spec_pattern
87
+ t.rspec_opts = ['--format', 'documentation', '--color']
88
+ end
89
+
90
+ desc "Run RCov on specs for #{gemspec.name}"
91
+ RSpec::Core::RakeTask.new(:rcov) do |t|
92
+ t.pattern = spec_pattern
93
+ t.rcov = true
94
+ t.rcov_opts = ['--exclude', '"spec/*,gems/*"', '--rails']
95
+ end
96
+ end
97
+
98
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
99
+ task(:spec => ['spec:specdoc'])
100
+ end
101
+
102
+ # Defines the rake tasks
103
+ def define_tasks!
104
+
105
+ define_test_tasks! if has_tests?
106
+ define_rspec_tasks! if has_specs?
107
+
108
+ namespace(@task_namespace) do
109
+ desc "Updates the filelist in the gemspec file"
110
+ task(:manifest) { manifest_task }
111
+
112
+ desc "Builds the .gem package"
113
+ task(:build => :manifest) { build_task }
114
+
115
+ desc "Sets the version of the gem in the gemspec"
116
+ task(:set_version => [:check_version, :check_current_branch]) { version_task }
117
+ task(:check_version => :fetch_origin) { check_version_task }
118
+
119
+ task(:fetch_origin) { fetch_origin_task }
120
+ task(:check_current_branch) { check_current_branch_task }
121
+ task(:check_clean_status) { check_clean_status_task }
122
+ task(:check_not_diverged => :fetch_origin) { check_not_diverged_task }
123
+
124
+ #checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version]
125
+ checks = [:check_current_branch, :check_clean_status]
126
+ checks.unshift('spec:basic') if has_specs?
127
+ checks.unshift('test:basic') if has_tests?
128
+ # checks.push << [:check_rubyforge] if gemspec.rubyforge_project
129
+
130
+ desc "Perform all checks that would occur before a release"
131
+ task(:release_checks => checks)
132
+
133
+ release_tasks = [:release_checks, :set_version, :build, :github_release, :gemcutter_release]
134
+ # release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
135
+
136
+ desc "Release a new version of the gem using the VERSION environment variable"
137
+ task(:release => release_tasks) { release_task }
138
+
139
+ namespace(:release) do
140
+ desc "Release the next version of the gem, by incrementing the last version segment by 1"
141
+ task(:next => [:next_version] + release_tasks) { release_task }
142
+
143
+ desc "Release the next version of the gem, using a patch increment (0.0.1)"
144
+ task(:patch => [:next_patch_version] + release_tasks) { release_task }
145
+
146
+ desc "Release the next version of the gem, using a minor increment (0.1.0)"
147
+ task(:minor => [:next_minor_version] + release_tasks) { release_task }
148
+
149
+ desc "Release the next version of the gem, using a major increment (1.0.0)"
150
+ task(:major => [:next_major_version] + release_tasks) { release_task }
151
+ end
152
+
153
+ # task(:check_rubyforge) { check_rubyforge_task }
154
+ # task(:rubyforge_release) { rubyforge_release_task }
155
+ task(:gemcutter_release) { gemcutter_release_task }
156
+ task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task }
157
+ task(:tag_version) { tag_version_task }
158
+ task(:commit_modified_files) { commit_modified_files_task }
159
+
160
+ task(:next_version) { next_version_task }
161
+ task(:next_patch_version) { next_version_task(:patch) }
162
+ task(:next_minor_version) { next_version_task(:minor) }
163
+ task(:next_major_version) { next_version_task(:major) }
164
+
165
+ desc "Updates the gem release tasks with the latest version on Github"
166
+ task(:update_tasks) { update_tasks_task }
167
+ end
168
+ end
169
+
170
+ # Updates the files list and test_files list in the gemspec file using the list of files
171
+ # in the repository and the spec/test file pattern.
172
+ def manifest_task
173
+ # Load all the gem's files using "git ls-files"
174
+ repository_files = `#{git} ls-files`.split("\n")
175
+ test_files = Dir[test_pattern] + Dir[spec_pattern]
176
+
177
+ update_gemspec(:files, repository_files)
178
+ update_gemspec(:test_files, repository_files & test_files)
179
+ end
180
+
181
+ # Builds the gem
182
+ def build_task
183
+ sh "gem build -q #{gemspec_file}"
184
+ Dir.mkdir('pkg') unless File.exist?('pkg')
185
+ sh "mv #{gemspec.name}-#{gemspec.version}.gem pkg/#{gemspec.name}-#{gemspec.version}.gem"
186
+ end
187
+
188
+ def newest_version
189
+ `#{git} tag`.split("\n").map { |tag| tag.split('-').last }.compact.map { |v| Gem::Version.new(v) }.max || Gem::Version.new('0.0.0')
190
+ end
191
+
192
+ def next_version(increment = nil)
193
+ next_version = newest_version.segments
194
+ increment_index = case increment
195
+ when :micro then 3
196
+ when :patch then 2
197
+ when :minor then 1
198
+ when :major then 0
199
+ else next_version.length - 1
200
+ end
201
+
202
+ next_version[increment_index] ||= 0
203
+ next_version[increment_index] = next_version[increment_index].succ
204
+ ((increment_index + 1)...next_version.length).each { |i| next_version[i] = 0 }
205
+
206
+ Gem::Version.new(next_version.join('.'))
207
+ end
208
+
209
+ def next_version_task(increment = nil)
210
+ ENV['VERSION'] = next_version(increment).version
211
+ puts "Releasing version #{ENV['VERSION']}..."
212
+ end
213
+
214
+ # Updates the version number in the gemspec file, the VERSION constant in the main
215
+ # include file and the contents of the VERSION file.
216
+ def version_task
217
+ update_gemspec(:version, ENV['VERSION']) if ENV['VERSION']
218
+ update_gemspec(:date, Date.today)
219
+
220
+ update_version_file(gemspec.version)
221
+ update_version_constant(gemspec.version)
222
+ end
223
+
224
+ def check_version_task
225
+ raise "#{ENV['VERSION']} is not a valid version number!" if ENV['VERSION'] && !Gem::Version.correct?(ENV['VERSION'])
226
+ proposed_version = Gem::Version.new((ENV['VERSION'] || gemspec.version).dup)
227
+ raise "This version (#{proposed_version}) is not higher than the highest tagged version (#{newest_version})" if newest_version >= proposed_version
228
+ end
229
+
230
+ # Checks whether the current branch is not diverged from the remote branch
231
+ def check_not_diverged_task
232
+ raise "The current branch is diverged from the remote branch!" if `#{git} rev-list HEAD..#{remote}/#{remote_branch}`.split("\n").any?
233
+ end
234
+
235
+ # Checks whether the repository status ic clean
236
+ def check_clean_status_task
237
+ raise "The current working copy contains modifications" if `#{git} ls-files -m`.split("\n").any?
238
+ end
239
+
240
+ # Checks whether the current branch is correct
241
+ def check_current_branch_task
242
+ raise "Currently not on #{local_branch} branch!" unless `#{git} branch`.split("\n").detect { |b| /^\* / =~ b } == "* #{local_branch}"
243
+ end
244
+
245
+ # Fetches the latest updates from Github
246
+ def fetch_origin_task
247
+ sh git, 'fetch', remote
248
+ end
249
+
250
+ # Commits every file that has been changed by the release task.
251
+ def commit_modified_files_task
252
+ really_modified = `#{git} ls-files -m #{modified_files.entries.join(' ')}`.split("\n")
253
+ if really_modified.any?
254
+ really_modified.each { |file| sh git, 'add', file }
255
+ sh git, 'commit', '-m', "Released #{gemspec.name} gem version #{gemspec.version}."
256
+ end
257
+ end
258
+
259
+ # Adds a tag for the released version
260
+ def tag_version_task
261
+ sh git, 'tag', '-a', "#{gemspec.name}-#{gemspec.version}", '-m', "Released #{gemspec.name} gem version #{gemspec.version}."
262
+ end
263
+
264
+ # Pushes the changes and tag to github
265
+ def github_release_task
266
+ sh git, 'push', '--tags', remote, remote_branch
267
+ end
268
+
269
+ def gemcutter_release_task
270
+ sh "gem", 'push', "pkg/#{gemspec.name}-#{gemspec.version}.gem"
271
+ end
272
+
273
+ # Gem release task.
274
+ # All work is done by the task's dependencies, so just display a release completed message.
275
+ def release_task
276
+ puts
277
+ puts "Release successful."
278
+ end
279
+
280
+ private
281
+
282
+ # Checks whether this project has any RSpec files
283
+ def has_specs?
284
+ FileList[spec_pattern].any?
285
+ end
286
+
287
+ # Checks whether this project has any unit test files
288
+ def has_tests?
289
+ FileList[test_pattern].any?
290
+ end
291
+
292
+ # Loads the gemspec file
293
+ def load_gemspec!
294
+ @gemspec = eval(File.read(@gemspec_file))
295
+ end
296
+
297
+ # Updates the VERSION file with the new version
298
+ def update_version_file(version)
299
+ if File.exists?('VERSION')
300
+ File.open('VERSION', 'w') { |f| f << version.to_s }
301
+ modified_files << 'VERSION'
302
+ end
303
+ end
304
+
305
+ # Updates the VERSION constant in the main include file if it exists
306
+ def update_version_constant(version)
307
+ if main_include && File.exist?(main_include)
308
+ file_contents = File.read(main_include)
309
+ if file_contents.sub!(/^(\s+VERSION\s*=\s*)[^\s].*$/) { $1 + version.to_s.inspect }
310
+ File.open(main_include, 'w') { |f| f << file_contents }
311
+ modified_files << main_include
312
+ end
313
+ end
314
+ end
315
+
316
+ # Updates an attribute of the gemspec file.
317
+ # This function will open the file, and search/replace the attribute using a regular expression.
318
+ def update_gemspec(attribute, new_value, literal = false)
319
+
320
+ unless literal
321
+ new_value = case new_value
322
+ when Array then "%w(#{new_value.join(' ')})"
323
+ when Hash, String then new_value.inspect
324
+ when Date then new_value.strftime('%Y-%m-%d').inspect
325
+ else raise "Cannot write value #{new_value.inspect} to gemspec file!"
326
+ end
327
+ end
328
+
329
+ spec = File.read(gemspec_file)
330
+ regexp = Regexp.new('^(\s+\w+\.' + Regexp.quote(attribute.to_s) + '\s*=\s*)[^\s].*$')
331
+ if spec.sub!(regexp) { $1 + new_value }
332
+ File.open(gemspec_file, 'w') { |f| f << spec }
333
+ modified_files << gemspec_file
334
+
335
+ # Reload the gemspec so the changes are incorporated
336
+ load_gemspec!
337
+
338
+ # Also mark the Gemfile.lock file as changed because of the new version.
339
+ modified_files << 'Gemfile.lock' if File.exist?(File.join(root_dir, 'Gemfile.lock'))
340
+ end
341
+ end
342
+
343
+ # Updates the tasks file using the latest file found on Github
344
+ def update_tasks_task
345
+ require 'net/https'
346
+ require 'uri'
347
+
348
+ uri = URI.parse('https://raw.github.com/wvanbergen/github-gem/master/tasks/github-gem.rake')
349
+ http = Net::HTTP.new(uri.host, uri.port)
350
+ http.use_ssl = true
351
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
352
+ response = http.request(Net::HTTP::Get.new(uri.path))
353
+
354
+ if Net::HTTPSuccess === response
355
+ open(__FILE__, "w") { |file| file.write(response.body) }
356
+ relative_file = File.expand_path(__FILE__).sub(%r[^#{@root_dir}/], '')
357
+ if `#{git} ls-files -m #{relative_file}`.split("\n").any?
358
+ sh git, 'add', relative_file
359
+ sh git, 'commit', '-m', "Updated to latest gem release management tasks."
360
+ else
361
+ puts "Release managament tasks already are at the latest version."
362
+ end
363
+ else
364
+ raise "Download failed with HTTP status #{response.code}!"
365
+ end
366
+ end
367
+ end
368
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mordor-auditing
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 4
10
+ version: 0.0.4
11
+ platform: ruby
12
+ authors:
13
+ - Jan-Willem Koelewijn
14
+ - Dirkjan Bussink
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-12-27 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rake
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 2
47
+ - 0
48
+ version: "2.0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: mordor
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - "="
58
+ - !ruby/object:Gem::Version
59
+ hash: 21
60
+ segments:
61
+ - 0
62
+ - 2
63
+ - 1
64
+ version: 0.2.1
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: mordor
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - "="
74
+ - !ruby/object:Gem::Version
75
+ hash: 21
76
+ segments:
77
+ - 0
78
+ - 2
79
+ - 1
80
+ version: 0.2.1
81
+ type: :runtime
82
+ version_requirements: *id004
83
+ description: " Auditing classes based on the Mordor gem, used to audit requests and modifications on objects\n"
84
+ email:
85
+ - janwillem.koelewijn@nedap.com
86
+ - dirkjan.bussink@nedap.com
87
+ executables: []
88
+
89
+ extensions: []
90
+
91
+ extra_rdoc_files: []
92
+
93
+ files:
94
+ - .gitignore
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - Rakefile
98
+ - auditing.gemspec
99
+ - lib/auditing.rb
100
+ - lib/auditing/modification.rb
101
+ - lib/auditing/request.rb
102
+ - lib/auditing/version.rb
103
+ - spec/auditing/modification_spec.rb
104
+ - spec/auditing/request_spec.rb
105
+ - spec/spec.opts
106
+ - spec/spec_helper.rb
107
+ - tasks/github-gem.rake
108
+ has_rdoc: true
109
+ homepage: http://www.nedap.com
110
+ licenses: []
111
+
112
+ post_install_message:
113
+ rdoc_options: []
114
+
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ requirements: []
136
+
137
+ rubyforge_project:
138
+ rubygems_version: 1.3.7
139
+ signing_key:
140
+ specification_version: 3
141
+ summary: mordor-auditing
142
+ test_files: []
143
+