mordor-auditing 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+