osm 1.2.7 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --format documentation
@@ -1,3 +1,8 @@
1
+ ## Version 1.2.8
2
+
3
+ * api.get\_user\_permissions now includes the quartermaster permission
4
+ * Fix administer permission level excluded from ApiAccess
5
+
1
6
  ## Version 1.2.7
2
7
 
3
8
  * Fix can't compare exception when a FlexiRecord has a nil name.
data/README.md CHANGED
@@ -7,7 +7,7 @@ Master branch:
7
7
  [![Code Climate](https://codeclimate.com/github/robertgauld/osm.png?branch=master)](https://codeclimate.com/github/robertgauld/osm)
8
8
 
9
9
  Staging branch:
10
- [![Build Status](https://secure.travis-ci.org/robertgauld/osm.png?branch=staging)](http://travis-ci.org/robertgauld/o
10
+ [![Build Status](https://secure.travis-ci.org/robertgauld/osm.png?branch=staging)](http://travis-ci.org/robertgauld/osm)
11
11
  [![Coveralls Status](https://coveralls.io/repos/robertgauld/osm/badge.png?branch=master)](https://coveralls.io/r/robertgauld/osm)
12
12
  [![Code Climate](https://codeclimate.com/github/robertgauld/osm.png?branch=staging)](https://codeclimate.com/github/robertgauld/osm)
13
13
 
@@ -6,10 +6,8 @@ gem 'activesupport', '~> 3.2'
6
6
  gem 'dirty_hashy', '~> 0.2.1'
7
7
  gem 'httparty', '~> 0.9'
8
8
  gem 'rake', '~> 10.1'
9
- gem 'rspec', '~> 2.0', '< 2.14'
9
+ gem 'rspec', '~> 2.0', '>= 2.14.1'
10
10
  gem 'fakeweb', '~> 1.3.0'
11
11
  gem 'osm', :path=>'../'
12
12
  gem 'coveralls', '~> 0.7'
13
13
  gem 'simplecov', '~> 0.7'
14
-
15
- #gemspec :path=>"../"
@@ -6,8 +6,12 @@ class ArrayOfValidator < ActiveModel::EachValidator
6
6
  record.errors.add(attribute, "items in the Array must be a #{options[:item_type].name}")
7
7
  else
8
8
  # We don't want to check the item is valid if it's the wrong type
9
- if !options[:item_valid].nil? && (value_item.valid? != options[:item_valid])
10
- record.errors.add(attribute, 'contains an invalid item')
9
+ unless options[:item_valid].nil?
10
+ # Check validity of item matches item_valid option
11
+ unless value_item.valid?.eql?(options[:item_valid])
12
+ message = "contains #{value_item.valid? ? 'a valid' : 'an invalid'} item"
13
+ record.errors.add(attribute, message)
14
+ end
11
15
  end
12
16
  end
13
17
  end
data/lib/osm.rb CHANGED
@@ -150,7 +150,7 @@ module Osm
150
150
  }
151
151
 
152
152
  return permissions.inject({}) do |new_hash, (key, value)|
153
- if ["badge", "member", "user", "register", "contact", "programme","events", "flexi", "finance"].include?(key)
153
+ if ["badge", "member", "user", "register", "contact", "programme","events", "flexi", "finance", "quartermaster"].include?(key)
154
154
  # This is a permission we care about
155
155
  new_hash[key.to_sym] = permissions_map[value.to_i]
156
156
  end
@@ -42,6 +42,7 @@ module Osm
42
42
  permissions_map = {
43
43
  10 => [:read],
44
44
  20 => [:read, :write],
45
+ 100 => [:read, :write, :administer]
45
46
  }
46
47
  result = Array.new
47
48
  ids = Array.new
@@ -269,7 +269,7 @@ module Osm
269
269
  end
270
270
  badges = nil
271
271
 
272
- if user_has_permission?(api, :write, :badge, section_id, options)
272
+ if has_permission?(api, :write, :badge, section_id, options)
273
273
  # We can shortcut and do it in one query
274
274
  badges = api.perform_query("users.php?action=getActivityRequirements&date=#{date.strftime(Osm::OSM_DATE_FORMAT)}&sectionid=#{section.id}&section=#{section.type}")
275
275
 
@@ -112,13 +112,22 @@ module Osm
112
112
  end
113
113
 
114
114
 
115
+ # Check if the user has access to a section
116
+ # @param [Osm::Api] api The api to use to make the request
117
+ # @param [Osm::Section, Fixnum, #to_i] section The Section (or its ID) the $
118
+ # @!macro options_get
119
+ # @return [Boolean] If the Api user has access the section
120
+ def self.has_access_to_section?(api, section, options={})
121
+ api.get_user_permissions(options).keys.include?(section.to_i)
122
+ end
123
+
115
124
  # Raise an exception if the user does not have access to a section
116
125
  # @param [Osm::Api] api The api to use to make the request
117
126
  # @param [Osm::Section, Fixnum, #to_i] section The Section (or its ID) the permission is required on
118
127
  # @!macro options_get
119
128
  # @raise [Osm::Forbidden] If the Api user can not access the section
120
129
  def self.require_access_to_section(api, section, options={})
121
- unless api.get_user_permissions(options).keys.include?(section.to_i)
130
+ unless has_access_to_section?(api, section, options)
122
131
  raise Osm::Forbidden, "You do not have access to that section"
123
132
  end
124
133
  end
@@ -138,7 +147,7 @@ module Osm
138
147
  # @param [Osm::Section, Fixnum, #to_i] section The Section (or its ID) the permission is required on
139
148
  # @!macro options_get
140
149
  def self.has_permission?(api, to, on, section, options={})
141
- user_has_permission(api, to, on, section, options) && api_has_permission(api, to, on, section, options)
150
+ user_has_permission?(api, to, on, section, options) && api_has_permission?(api, to, on, section, options)
142
151
  end
143
152
 
144
153
  # Check if the user has the relevant permission within OSM
@@ -165,13 +174,9 @@ module Osm
165
174
  # @param [Osm::Section, Fixnum, #to_i] section The Section (or its ID) the permission is required on
166
175
  # @!macro options_get
167
176
  def self.api_has_permission?(api, to, on, section, options={})
168
- section_id = section.to_i
169
- permissions = Osm::ApiAccess.get_ours(api, section_id, options).permissions
170
- permissions = permissions[on] || []
171
- unless permissions.include?(to)
172
- return false
173
- end
174
- return true
177
+ access = Osm::ApiAccess.get_ours(api, section, options)
178
+ return false if access.nil?
179
+ (access.permissions[on] || []).include?(to)
175
180
  end
176
181
 
177
182
  # Raise an exception if the user does not have the relevant permission
@@ -182,22 +187,24 @@ module Osm
182
187
  # @!macro options_get
183
188
  # @raise [Osm::Forbidden] If the Api user does not have the required permission
184
189
  def self.require_permission(api, to, on, section, options={})
190
+ section = Osm::Section.get(api, section.to_i, options) unless section.is_a?(Osm::Section)
191
+ section_name = section.try(:name)
185
192
  unless user_has_permission?(api, to, on, section, options)
186
- raise Osm::Forbidden, "Your OSM user does not have permission to #{to} on #{on} for #{Osm::Section.get(api, section.to_i, options).try(:name)}"
193
+ raise Osm::Forbidden, "Your OSM user does not have permission to #{to} on #{on} for #{section_name}."
187
194
  end
188
195
  unless api_has_permission?(api, to, on, section, options)
189
- raise Osm::Forbidden, "You have not granted the #{to} permissions on #{on} to the #{api.api_name} API for #{Osm::Section.get(api, section.to_i, options).try(:name)}"
196
+ raise Osm::Forbidden, "You have not granted the #{to} permissions on #{on} to the #{api.api_name} API for #{section_name}."
190
197
  end
191
198
  end
192
199
 
193
200
  # Raise an exception if the user does not have the relevant permission
194
201
  # @param [Osm::Api] api The api to use to make the request
195
- # @param [Symbol] level The OSM subscription level required (:bronze, :silver, :gold, :gold_plus)
202
+ # @param [Symbol, Fixnum] level The OSM subscription level required (:bronze, :silver, :gold, :gold_plus)
196
203
  # @param [Osm::Section, Fixnum, #to_i] section The Section (or its ID) the subscription is required on
197
204
  # @!macro options_get
198
205
  # @raise [Osm::Forbidden] If the Section does not have the required OSM Subscription (or higher)
199
206
  def self.require_subscription(api, level, section, options={})
200
- section = Osm::Section.get(api, section, options) if section.is_a?(Fixnum)
207
+ section = Osm::Section.get(api, section, options) unless section.is_a?(Osm::Section)
201
208
  if level.is_a?(Symbol) # Convert to Fixnum
202
209
  case level
203
210
  when :bronze
@@ -214,7 +221,7 @@ module Osm
214
221
  end
215
222
  if section.nil? || section.subscription_level < level
216
223
  level_name = Osm::SUBSCRIPTION_LEVEL_NAMES[level] || level
217
- raise Osm::Forbidden, "Insufficent OSM subscription level (#{level_name} required for #{section.name})"
224
+ raise Osm::Forbidden, "Insufficent OSM subscription level (#{level_name} required for #{section.name})."
218
225
  end
219
226
  end
220
227
 
@@ -225,7 +232,7 @@ module Osm
225
232
  # @param [Osm::Section, Fixnum, #to_i] section The Section (or its ID) the permission is required on
226
233
  # @!macro options_get
227
234
  def self.require_ability_to(api, to, on, section, options={})
228
- section = Osm::Section.get(api, section, options) if section.is_a?(Fixnum)
235
+ section = Osm::Section.get(api, section, options) unless section.is_a?(Osm::Section)
229
236
  require_permission(api, to, on, section, options)
230
237
  if section.youth_section? && [:register, :contact, :events, :flexi].include?(on)
231
238
  require_subscription(api, :silver, section, options)
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+
5
+ class FixnumTestModel < Osm::Model
6
+ attribute :array
7
+ validates :array, :array_of => {:item_type => Fixnum}
8
+ end
9
+
10
+ class TestItem
11
+ def initialize(attrs)
12
+ @valid = !!attrs[:valid]
13
+ end
14
+ def valid?
15
+ @valid
16
+ end
17
+ end
18
+
19
+ class ValidTestModel < Osm::Model
20
+ attribute :array
21
+ validates :array, :array_of => {:item_type => TestItem, :item_valid=>true}
22
+ end
23
+
24
+ class InvalidTestModel < Osm::Model
25
+ attribute :array
26
+ validates :array, :array_of => {:item_type => TestItem, :item_valid=>false}
27
+ end
28
+
29
+ class NovalidTestModel < Osm::Model
30
+ attribute :array
31
+ validates :array, :array_of => {:item_type => TestItem}
32
+ end
33
+
34
+
35
+ describe "array_of validator" do
36
+
37
+ it "Allows an empty array" do
38
+ i = FixnumTestModel.new(array: [])
39
+ i.valid?.should == true
40
+ i.errors.count.should == 0
41
+ end
42
+
43
+ describe ":item_type option" do
44
+
45
+ it "Allows arrays of the right type" do
46
+ i = FixnumTestModel.new(array: [1, 2, 3])
47
+ i.valid?.should == true
48
+ i.errors.count.should == 0
49
+ end
50
+
51
+ it "Forbids arrays containing >= 1 incorrect type" do
52
+ i = FixnumTestModel.new(array: [1, '2', 3])
53
+ i.valid?.should == false
54
+ i.errors.count.should == 1
55
+ i.errors.messages.should == {:array=>["items in the Array must be a Fixnum"]}
56
+ end
57
+
58
+ end
59
+
60
+ describe ":valid option" do
61
+
62
+ it "Allows (in)valid items unless valid option is passed" do
63
+ i = NovalidTestModel.new(array: [TestItem.new(valid: false), TestItem.new(valid: true)])
64
+ i.valid?.should == true
65
+ i.errors.count.should == 0
66
+ end
67
+
68
+ describe "Valid option is false" do
69
+
70
+ it "Contains all invalid items" do
71
+ i = InvalidTestModel.new(array: [TestItem.new(valid: false)])
72
+ i.valid?.should == true
73
+ i.errors.count.should == 0
74
+ end
75
+
76
+ it "Contains a valid item" do
77
+ i = InvalidTestModel.new(array: [TestItem.new(valid: true)])
78
+ i.valid?.should == false
79
+ i.errors.count.should == 1
80
+ i.errors.messages.should == {:array => ['contains a valid item']}
81
+ end
82
+
83
+ end
84
+
85
+ describe "Valid option is true" do
86
+
87
+ it "Contains all valid items" do
88
+ i = ValidTestModel.new(array: [TestItem.new(valid: true)])
89
+ i.valid?.should == true
90
+ i.errors.count.should == 0
91
+ end
92
+
93
+ it "Contains an invalid item" do
94
+ i = ValidTestModel.new(array: [TestItem.new(valid: false)])
95
+ i.valid?.should == false
96
+ i.errors.count.should == 1
97
+ i.errors.messages.should == {:array => ['contains an invalid item']} end
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -119,8 +119,8 @@ describe "Activity" do
119
119
  activity.location.should == :indoors
120
120
  activity.shared.should == 0
121
121
  activity.rating.should == 4
122
- activity.editable.should == true
123
- activity.deletable.should == false
122
+ activity.editable.should be_true
123
+ activity.deletable.should be_false
124
124
  activity.used.should == 3
125
125
  activity.versions[0].version.should == 0
126
126
  activity.versions[0].created_by.should == 1
@@ -35,7 +35,7 @@ describe "API Access" do
35
35
  {
36
36
  'apiid' => '1',
37
37
  'name' => 'API Name',
38
- 'permissions' => { 'read' => '10', 'readwrite' => '20' }
38
+ 'permissions' => { 'read' => '10', 'readwrite' => '20', 'administer' => '100' }
39
39
  }, {
40
40
  'apiid' => '2',
41
41
  'name' => 'API 2 Name',
@@ -54,7 +54,7 @@ describe "API Access" do
54
54
  api_access = api_accesses[0]
55
55
  api_access.id.should == 1
56
56
  api_access.name.should == 'API Name'
57
- api_access.permissions.should == {:read => [:read], :readwrite => [:read, :write]}
57
+ api_access.permissions.should == {:read => [:read], :readwrite => [:read, :write], :administer => [:read, :write, :administer]}
58
58
  end
59
59
 
60
60
  it "From cache" do
@@ -36,7 +36,7 @@ describe "Badge" do
36
36
  requirement.name.should == 'name'
37
37
  requirement.description.should == 'description'
38
38
  requirement.field.should == 'field'
39
- requirement.editable.should == true
39
+ requirement.editable.should be_true
40
40
  requirement.badge.osm_key.should == 'key'
41
41
  requirement.valid?.should be_true
42
42
  end
@@ -423,7 +423,7 @@ describe "Badge" do
423
423
  requirement.name.should == 'r_name'
424
424
  requirement.description.should == 'r_description'
425
425
  requirement.field.should == 'r_field'
426
- requirement.editable.should == true
426
+ requirement.editable.should be_true
427
427
  requirement.badge.osm_key.should == 'badge'
428
428
  end
429
429
 
@@ -445,7 +445,7 @@ describe "Badge" do
445
445
  requirement.name.should == 'r_name'
446
446
  requirement.description.should == 'r_description'
447
447
  requirement.field.should == 'r_field'
448
- requirement.editable.should == true
448
+ requirement.editable.should be_true
449
449
  requirement.badge.osm_key.should == 'badge'
450
450
  end
451
451
 
@@ -467,7 +467,7 @@ describe "Badge" do
467
467
  requirement.name.should == 'r_name'
468
468
  requirement.description.should == 'r_description'
469
469
  requirement.field.should == 'r_field'
470
- requirement.editable.should == true
470
+ requirement.editable.should be_true
471
471
  requirement.badge.osm_key.should == 'badge'
472
472
  end
473
473
 
@@ -489,7 +489,7 @@ describe "Badge" do
489
489
  requirement.name.should == 'r_name'
490
490
  requirement.description.should == 'r_description'
491
491
  requirement.field.should == 'r_field'
492
- requirement.editable.should == true
492
+ requirement.editable.should be_true
493
493
  requirement.badge.osm_key.should == 'badge'
494
494
  end
495
495
 
@@ -51,7 +51,7 @@ describe "Badges" do
51
51
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=outstandingBadges&section=cubs&sectionid=1&termid=2", :body => data.to_json, :content_type => 'application/json')
52
52
 
53
53
  db = Osm::Badges.get_due_badges(@api, Osm::Section.new(:id => 1, :type => :cubs), 2)
54
- db.empty?.should == false
54
+ db.empty?.should be_false
55
55
  db.badge_names.should == {'badge_name_1'=>'Badge Name', 'staged_staged_participation_2'=>'Participation (Level 2)'}
56
56
  db.by_member.should == {1=>['badge_name_1', 'staged_staged_participation_2'], 2=>['staged_staged_participation_2']}
57
57
  db.member_names.should == {1 => 'John Doe', 2 => 'Jane Doe'}
@@ -62,7 +62,7 @@ describe "Badges" do
62
62
  it "handles an empty array representing no due badges" do
63
63
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=outstandingBadges&section=cubs&sectionid=1&termid=2", :body => '[]', :content_type => 'application/json')
64
64
  db = Osm::Badges.get_due_badges(@api, Osm::Section.new(:id => 1, :type => :cubs), 2)
65
- db.should_not == nil
65
+ db.should_not be_nil
66
66
  end
67
67
 
68
68
 
@@ -32,7 +32,7 @@ describe "Event" do
32
32
  event.section_id.should == 2
33
33
  event.name.should == 'Event name'
34
34
  event.start.should == DateTime.new(2001, 1, 2, 12, 0, 0)
35
- event.finish.should == nil
35
+ event.finish.should be_nil
36
36
  event.cost.should == '1.23'
37
37
  event.location.should == 'Somewhere'
38
38
  event.notes.should == 'None'
@@ -41,10 +41,10 @@ describe "Event" do
41
41
  event.notepad.should == 'notepad'
42
42
  event.public_notepad.should == 'public notepad'
43
43
  event.confirm_by_date.should == Date.new(2002, 1, 2)
44
- event.allow_changes.should == true
45
- event.reminders.should == false
44
+ event.allow_changes.should be_true
45
+ event.reminders.should be_false
46
46
  event.attendance_limit.should == 3
47
- event.attendance_limit_includes_leaders.should == true
47
+ event.attendance_limit_includes_leaders.should be_true
48
48
  event.attendance_reminder.should == 14
49
49
  event.allow_booking.should be_false
50
50
  event.valid?.should be_true
@@ -196,16 +196,16 @@ describe "Event" do
196
196
  event.notepad.should == 'notepad'
197
197
  event.public_notepad.should == 'public notepad'
198
198
  event.confirm_by_date.should == Date.new(2002, 1, 2)
199
- event.allow_changes.should == true
200
- event.reminders.should == false
199
+ event.allow_changes.should be_true
200
+ event.reminders.should be_false
201
201
  event.attendance_limit.should == 3
202
- event.attendance_limit_includes_leaders.should == true
202
+ event.attendance_limit_includes_leaders.should be_true
203
203
  event.attendance_reminder.should == 7
204
- event.allow_booking.should == true
204
+ event.allow_booking.should be_true
205
205
  event.columns[0].id.should == 'f_1'
206
206
  event.columns[0].name.should == 'Name'
207
207
  event.columns[0].label.should == 'Label'
208
- event.columns[0].parent_required.should == true
208
+ event.columns[0].parent_required.should be_true
209
209
  event.valid?.should be_true
210
210
  end
211
211
 
@@ -282,7 +282,7 @@ describe "Event" do
282
282
  it "No limit" do
283
283
  event = Osm::Event.new(:attendance_limit => 0, :id => 1, :section_id => 2)
284
284
  event.spaces?(@api).should be_true
285
- event.spaces(@api).should == nil
285
+ event.spaces(@api).should be_nil
286
286
  end
287
287
 
288
288
  it "Under limit" do
@@ -975,4 +975,4 @@ describe "Event" do
975
975
 
976
976
  end
977
977
 
978
- end
978
+ end
@@ -103,6 +103,18 @@ describe "Flexi Record" do
103
103
  records.sort.should == [fr1, fr2, fr3]
104
104
  end
105
105
 
106
+ it "Compare handles a nil name" do
107
+ fr1 = Osm::FlexiRecord.new(section_id: 1, name: nil)
108
+ fr2 = Osm::FlexiRecord.new(section_id: 1, name: 'Something')
109
+ (fr1 <=> fr2).should == -1
110
+ end
111
+
112
+ it "Compare handles a nil section_id" do
113
+ fr1 = Osm::FlexiRecord.new(section_id: nil, name: 'a')
114
+ fr2 = Osm::FlexiRecord.new(section_id: 1, name: 'a')
115
+ (fr1 <=> fr2).should == -1
116
+ end
117
+
106
118
 
107
119
  describe "Using the API" do
108
120
 
@@ -29,7 +29,7 @@ describe "Grouping" do
29
29
  patrol.id.should == 1
30
30
  patrol.section_id.should == 2
31
31
  patrol.name.should == 'Patrol Name'
32
- patrol.active.should == true
32
+ patrol.active.should be_true
33
33
  patrol.points.should == 3
34
34
  patrol.valid?.should be_true
35
35
  end
@@ -101,4 +101,4 @@ describe "Grouping" do
101
101
 
102
102
  end
103
103
 
104
- end
104
+ end
@@ -20,8 +20,8 @@ describe "Invoice" do
20
20
  i.name.should == 'Name'
21
21
  i.extra_details.should == 'Extra Details'
22
22
  i.date.should == Date.new(2001, 2, 3)
23
- i.archived.should == true
24
- i.finalised.should == true
23
+ i.archived.should be_true
24
+ i.finalised.should be_true
25
25
  i.valid?.should be_true
26
26
  end
27
27
 
@@ -168,8 +168,8 @@ describe "Invoice" do
168
168
  invoice.name.should == 'Invoice 1'
169
169
  invoice.extra_details.should == 'Some more details'
170
170
  invoice.date.should == Date.new(2010, 1, 1)
171
- invoice.archived.should == false
172
- invoice.finalised.should == false
171
+ invoice.archived.should be_false
172
+ invoice.finalised.should be_false
173
173
  invoice.valid?.should be_true
174
174
  end
175
175
 
@@ -157,6 +157,7 @@ describe "Meeting" do
157
157
  end
158
158
 
159
159
  it "Fetch badge requirements for a meeting (from API)" do
160
+ Osm::Model.stub('has_permission?').and_return(true)
160
161
  badges_body = [{'a'=>'a'},{'a'=>'A'}]
161
162
  FakeWeb.register_uri(:post, 'https://www.onlinescoutmanager.co.uk/users.php?action=getActivityRequirements&date=2000-01-02&sectionid=3&section=cubs', :body => badges_body.to_json, :content_type => 'application/json')
162
163
  roles_body = [
@@ -169,6 +170,7 @@ describe "Meeting" do
169
170
  end
170
171
 
171
172
  it "Fetch badge requirements for a meeting (iterating through activities)" do
173
+ Osm::Model.stub('has_permission?').with(@api, :write, :badge, 3, {}).and_return(false)
172
174
  roles_body = [
173
175
  {"sectionConfig"=>"{\"subscription_level\":1,\"subscription_expires\":\"2013-01-05\",\"sectionType\":\"cubs\",\"columnNames\":{\"column_names\":\"names\"},\"numscouts\":10,\"hasUsedBadgeRecords\":true,\"hasProgramme\":true,\"extraRecords\":[],\"wizard\":\"false\",\"fields\":{\"fields\":true},\"intouch\":{\"intouch_fields\":true},\"mobFields\":{\"mobile_fields\":true}}", "groupname"=>"3rd Somewhere", "groupid"=>"3", "groupNormalised"=>"1", "sectionid"=>"3", "sectionname"=>"Section 1", "section"=>"beavers", "isDefault"=>"1", "permissions"=>{"badge"=>10, "member"=>20, "user"=>100, "register"=>100, "contact"=>100, "programme"=>10, "originator"=>1, "events"=>100, "finance"=>100, "flexi"=>100}},
174
176
  ]
@@ -253,7 +255,7 @@ describe "Meeting" do
253
255
  :start_time => '11:11',
254
256
  :finish_time => '22:22',
255
257
  :title => 'Title',
256
- }).should be_true
258
+ }).is_a?(Osm::Meeting).should be_true
257
259
  end
258
260
 
259
261
  it "Create a meeting (failed)" do
@@ -265,7 +267,7 @@ describe "Meeting" do
265
267
  :start_time => '11:11',
266
268
  :finish_time => '22:22',
267
269
  :title => 'Title',
268
- }).should be_false
270
+ }).should be_nil
269
271
  end
270
272
 
271
273
 
@@ -179,4 +179,232 @@ describe "Model" do
179
179
 
180
180
  end
181
181
 
182
+ describe "Access control" do
183
+
184
+ describe "user_has_permission?" do
185
+
186
+ before :each do
187
+ @api.stub(:get_user_permissions).and_return( { 1 => {foo: [:bar]} } )
188
+ end
189
+
190
+ it "Has permission" do
191
+ Osm::Model.user_has_permission?(@api, :bar, :foo, 1).should be_true
192
+ end
193
+
194
+ it "Doesn't have the level of permission" do
195
+ Osm::Model.user_has_permission?(@api, :barbar, :foo, 1).should be_false
196
+ end
197
+
198
+ it "Doesn't have access to section" do
199
+ Osm::Model.user_has_permission?(@api, :bar, :foo, 2).should be_false
200
+ end
201
+
202
+ end
203
+
204
+ describe "api_has_permission?" do
205
+
206
+ before :each do
207
+ Osm::ApiAccess.stub(:get_ours).and_return(Osm::ApiAccess.new(
208
+ id: @api.api_id,
209
+ name: @api.api_name,
210
+ permissions: {foo: [:bar]}
211
+ ))
212
+ end
213
+
214
+ it "Has permission" do
215
+ Osm::Model.api_has_permission?(@api, :bar, :foo, 1).should be_true
216
+ end
217
+
218
+ it "Doesn't have the level of permission" do
219
+ Osm::Model.api_has_permission?(@api, :barbar, :foo, 1).should be_false
220
+ end
221
+
222
+ it "Doesn't have access to the section" do
223
+ Osm::ApiAccess.stub(:get_ours).and_return(nil)
224
+ Osm::Model.api_has_permission?(@api, :bar, :foo, 2).should be_false
225
+ end
226
+
227
+ end
228
+
229
+ describe "has_permission?" do
230
+
231
+ it "Only returns true if the user can and they have granted the api permission" do
232
+ section = Osm::Section.new
233
+ options = {:foo => :bar}
234
+ expect(Osm::Model).to receive('user_has_permission?').with(@api, :can_do, :can_to, section, options).and_return(true)
235
+ expect(Osm::Model).to receive('api_has_permission?').with(@api, :can_do, :can_to, section, options).and_return(true)
236
+ Osm::Model.has_permission?(@api, :can_do, :can_to, section, options).should be_true
237
+ end
238
+
239
+ describe "Otherwise returns false" do
240
+ [ [true,false], [false, true], [false, false] ].each do |user, api|
241
+ it "User #{user ? 'can' : "can't"} and #{api ? 'has' : "hasn't"} given access" do
242
+ Osm::Model.stub('user_has_permission?').and_return(user)
243
+ Osm::Model.stub('api_has_permission?').and_return(api)
244
+ Osm::Model.has_permission?(@api, :can_do, :can_to, Osm::Section.new).should be_false
245
+ end
246
+ end
247
+ end
248
+
249
+ end
250
+
251
+ describe "has_access_to_section?" do
252
+
253
+ before :each do
254
+ @api.stub(:get_user_permissions).and_return( {1=>{}} )
255
+ end
256
+
257
+ it "Has access" do
258
+ Osm::Model.has_access_to_section?(@api, 1).should be_true
259
+ end
260
+
261
+ it "Doesn't have access" do
262
+ Osm::Model.has_access_to_section?(@api, 2).should be_false
263
+ end
264
+
265
+ end
266
+
267
+ describe "require_access_to_section" do
268
+
269
+ before :each do
270
+ Osm::Model.unstub(:require_access_to_section)
271
+ end
272
+
273
+ it "Does nothing when access is allowed" do
274
+ Osm::Model.stub('has_access_to_section?') { true }
275
+ expect{ Osm::Model.require_access_to_section(@api, 1) }.not_to raise_error
276
+ end
277
+
278
+ it "Raises exception when access is not allowed" do
279
+ Osm::Model.stub('has_access_to_section?') { false }
280
+ expect{ Osm::Model.require_access_to_section(@api, 1) }.to raise_error(Osm::Forbidden, "You do not have access to that section")
281
+ end
282
+
283
+ end
284
+
285
+ describe "require_permission" do
286
+
287
+ it "Does nothing when access is allowed" do
288
+ Osm::Model.stub('user_has_permission?').and_return(true)
289
+ Osm::Model.stub('api_has_permission?').and_return(true)
290
+ section = Osm::Section.new(name: 'A SECTION')
291
+ expect{ Osm::Model.require_permission(@api, :to, :on, section) }.not_to raise_error
292
+ end
293
+
294
+ it "Raises exception when user doesn't have access" do
295
+ Osm::Model.stub('user_has_permission?').and_return(false)
296
+ Osm::Model.stub('api_has_permission?').and_return(true)
297
+ section = Osm::Section.new(name: 'A SECTION')
298
+ expect{ Osm::Model.require_permission(@api, :can_do, :can_on, section) }.to raise_error(Osm::Forbidden, "Your OSM user does not have permission to can_do on can_on for A SECTION.")
299
+ end
300
+
301
+ it "Raises exception when api doesn't have access" do
302
+ Osm::Model.stub('user_has_permission?').and_return(true)
303
+ Osm::Model.stub('api_has_permission?').and_return(false)
304
+ section = Osm::Section.new(name: 'A SECTION')
305
+ expect{ Osm::Model.require_permission(@api, :can_to, :can_on, section) }.to raise_error(Osm::Forbidden, "You have not granted the can_to permissions on can_on to the API NAME API for A SECTION.")
306
+ end
307
+
308
+ end
309
+
310
+ describe "require_subscription" do
311
+
312
+ it "Checks against a number" do
313
+ section1 = Osm::Section.new(subscription_level: 1, name: 'NAME') # Bronze
314
+ section2 = Osm::Section.new(subscription_level: 2, name: 'NAME') # Silver
315
+ section3 = Osm::Section.new(subscription_level: 3, name: 'NAME') # Gold
316
+ section4 = Osm::Section.new(subscription_level: 4, name: 'NAME') # Gold+
317
+
318
+ expect{ Osm::Model.require_subscription(@api, 1, section1) }.not_to raise_error
319
+ expect{ Osm::Model.require_subscription(@api, 2, section1) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Silver required for NAME).")
320
+ expect{ Osm::Model.require_subscription(@api, 3, section1) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold required for NAME).")
321
+ expect{ Osm::Model.require_subscription(@api, 4, section1) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold+ required for NAME).")
322
+
323
+ expect{ Osm::Model.require_subscription(@api, 1, section2) }.not_to raise_error
324
+ expect{ Osm::Model.require_subscription(@api, 2, section2) }.not_to raise_error
325
+ expect{ Osm::Model.require_subscription(@api, 3, section2) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold required for NAME).")
326
+ expect{ Osm::Model.require_subscription(@api, 4, section2) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold+ required for NAME).")
327
+
328
+ expect{ Osm::Model.require_subscription(@api, 1, section3) }.not_to raise_error
329
+ expect{ Osm::Model.require_subscription(@api, 2, section3) }.not_to raise_error
330
+ expect{ Osm::Model.require_subscription(@api, 3, section3) }.not_to raise_error
331
+ expect{ Osm::Model.require_subscription(@api, 4, section3) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold+ required for NAME).")
332
+
333
+ expect{ Osm::Model.require_subscription(@api, 1, section4) }.not_to raise_error
334
+ expect{ Osm::Model.require_subscription(@api, 2, section4) }.not_to raise_error
335
+ expect{ Osm::Model.require_subscription(@api, 3, section4) }.not_to raise_error
336
+ expect{ Osm::Model.require_subscription(@api, 4, section4) }.not_to raise_error
337
+ end
338
+
339
+ it "Checks against a symbol" do
340
+ section1 = Osm::Section.new(subscription_level: 1, name: 'NAME') # Bronze
341
+ section2 = Osm::Section.new(subscription_level: 2, name: 'NAME') # Silver
342
+ section3 = Osm::Section.new(subscription_level: 3, name: 'NAME') # Gold
343
+ section4 = Osm::Section.new(subscription_level: 4, name: 'NAME') # Gold+
344
+
345
+ expect{ Osm::Model.require_subscription(@api, :bronze, section1) }.not_to raise_error
346
+ expect{ Osm::Model.require_subscription(@api, :silver, section1) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Silver required for NAME).")
347
+ expect{ Osm::Model.require_subscription(@api, :gold, section1) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold required for NAME).")
348
+ expect{ Osm::Model.require_subscription(@api, :gold_plus, section1) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold+ required for NAME).")
349
+
350
+ expect{ Osm::Model.require_subscription(@api, :bronze, section2) }.not_to raise_error
351
+ expect{ Osm::Model.require_subscription(@api, :silver, section2) }.not_to raise_error
352
+ expect{ Osm::Model.require_subscription(@api, :gold, section2) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold required for NAME).")
353
+ expect{ Osm::Model.require_subscription(@api, :gold_plus, section2) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold+ required for NAME).")
354
+
355
+ expect{ Osm::Model.require_subscription(@api, :bronze, section3) }.not_to raise_error
356
+ expect{ Osm::Model.require_subscription(@api, :silver, section3) }.not_to raise_error
357
+ expect{ Osm::Model.require_subscription(@api, :gold, section3) }.not_to raise_error
358
+ expect{ Osm::Model.require_subscription(@api, :gold_plus, section3) }.to raise_error(Osm::Forbidden, "Insufficent OSM subscription level (Gold+ required for NAME).")
359
+
360
+ expect{ Osm::Model.require_subscription(@api, :bronze, section4) }.not_to raise_error
361
+ expect{ Osm::Model.require_subscription(@api, :silver, section4) }.not_to raise_error
362
+ expect{ Osm::Model.require_subscription(@api, :gold, section4) }.not_to raise_error
363
+ expect{ Osm::Model.require_subscription(@api, :gold_plus, section4) }.not_to raise_error
364
+ end
365
+
366
+ end
367
+
368
+ describe "Require_abillity_to" do
369
+
370
+ before :each do
371
+ Osm::Model.unstub(:require_ability_to)
372
+ end
373
+
374
+ it "Requires permission" do
375
+ section = Osm::Section.new(type: :waiting)
376
+ options = {foo: 'bar'}
377
+ expect(Osm::Model).to receive(:require_permission).with(@api, :can_do, :can_on, section, options).and_return(true)
378
+ expect(Osm::Model).not_to receive(:require_subscription)
379
+ expect{ Osm::Model.require_ability_to(@api, :can_do, :can_on, section, options) }.not_to raise_error
380
+ end
381
+
382
+ describe "Requires the right subscription level for" do
383
+
384
+ before :each do
385
+ @section = Osm::Section.new(type: :beavers)
386
+ @options = {bar: 'foo'}
387
+ Osm::Model.stub(:require_permission).and_return(nil)
388
+ end
389
+
390
+ [:register, :contact, :events, :flexi].each do |can_on|
391
+ it ":#{can_on.to_s} (Silver)" do
392
+ expect(Osm::Model).to receive(:require_subscription).with(@api, :silver, @section, @options).and_return(true)
393
+ expect{ Osm::Model.require_ability_to(@api, :read, can_on, @section, @options) }.to_not raise_error
394
+ end
395
+ end
396
+
397
+ [:finance].each do |can_on|
398
+ it ":#{can_on.to_s} (Gold)" do
399
+ expect(Osm::Model).to receive(:require_subscription).with(@api, :gold, @section, @options).and_return(true)
400
+ expect{ Osm::Model.require_ability_to(@api, :read, can_on, @section, @options) }.to_not raise_error
401
+ end
402
+ end
403
+
404
+ end
405
+
406
+ end
407
+
408
+ end
409
+
182
410
  end
@@ -22,19 +22,19 @@ describe "Online Scout Manager" do
22
22
  end
23
23
 
24
24
  it "is given neither" do
25
- Osm::make_datetime('', '').should == nil
25
+ Osm::make_datetime('', '').should be_nil
26
26
  end
27
27
 
28
28
  it "is given an invalid date" do
29
- Osm::make_datetime('No date here1', '04:05:06').should == nil
29
+ Osm::make_datetime('No date here1', '04:05:06').should be_nil
30
30
  end
31
31
 
32
32
  it "is given an invalid time" do
33
- Osm::make_datetime('2001-02-03', 'No time here!').should == nil
33
+ Osm::make_datetime('2001-02-03', 'No time here!').should be_nil
34
34
  end
35
35
 
36
36
  it "is given just an invalid date" do
37
- Osm::make_datetime('No date here1', nil).should == nil
37
+ Osm::make_datetime('No date here1', nil).should be_nil
38
38
  end
39
39
  end
40
40
 
@@ -64,29 +64,29 @@ describe "Section" do
64
64
  section.group_id.should == 3
65
65
  section.group_name.should == '3rd Somewhere'
66
66
  section.flexi_records.should == []
67
- section.gocardless.should == true
67
+ section.gocardless.should be_true
68
68
  section.myscout_events_expires.should == Date.today + 61
69
69
  section.myscout_badges_expires.should == Date.today + 62
70
70
  section.myscout_programme_expires.should == Date.today + 63
71
71
  section.myscout_details_expires.should == Date.today + 64
72
- section.myscout_events.should == true
73
- section.myscout_badges.should == true
74
- section.myscout_programme.should == true
75
- section.myscout_payments.should == true
72
+ section.myscout_events.should be_true
73
+ section.myscout_badges.should be_true
74
+ section.myscout_programme.should be_true
75
+ section.myscout_payments.should be_true
76
76
  section.myscout_emails.should == {:email1 => true, :email2 => false}
77
77
  section.myscout_email_address_from.should == 'send_from@example.com'
78
78
  section.myscout_email_address_copy.should == ''
79
- section.myscout_badges_partial.should == true
80
- section.myscout_programme_summary.should == true
81
- section.myscout_programme_times.should == true
79
+ section.myscout_badges_partial.should be_true
80
+ section.myscout_programme_summary.should be_true
81
+ section.myscout_programme_times.should be_true
82
82
  section.myscout_programme_show.should == 20
83
83
  section.myscout_event_reminder_count.should == 4
84
84
  section.myscout_event_reminder_frequency.should == 5
85
85
  section.myscout_payment_reminder_count.should == 6
86
86
  section.myscout_payment_reminder_frequency.should == 7
87
- section.myscout_details.should == true
87
+ section.myscout_details.should be_true
88
88
  section.myscout_details_email_changes_to.should == 'notify-changes-to@example.com'
89
- section.sms_sent_test.should == true
89
+ section.sms_sent_test.should be_true
90
90
  section.sms_messages_sent.should == 8
91
91
  section.sms_messages_remaining.should == 9
92
92
  section.valid?.should be_true
@@ -97,7 +97,7 @@ describe "Section" do
97
97
  section = Osm::Section.new
98
98
 
99
99
  section.subscription_level.should == 1
100
- section.subscription_expires.should == nil
100
+ section.subscription_expires.should be_nil
101
101
  section.type.should == :unknown
102
102
  section.column_names.should == {}
103
103
  section.fields.should == {}
@@ -108,7 +108,7 @@ describe "Section" do
108
108
  section.myscout_email_address_copy.should == ''
109
109
  section.myscout_details_email_changes_to.should == ''
110
110
  section.myscout_programme_show.should == 0
111
- section.sms_sent_test.should == false
111
+ section.sms_sent_test.should be_false
112
112
  section.sms_messages_sent.should == 0
113
113
  section.sms_messages_remaining.should == 0
114
114
  end
@@ -144,29 +144,29 @@ describe "Section" do
144
144
  section.flexi_records.size.should == 1
145
145
  section.flexi_records[0].id.should == 111
146
146
  section.flexi_records[0].name.should == 'Flexi Record 1'
147
- section.gocardless.should == true
147
+ section.gocardless.should be_true
148
148
  section.myscout_events_expires.should == Date.new(2013, 1, 6)
149
149
  section.myscout_badges_expires.should == Date.new(2013, 1, 7)
150
150
  section.myscout_programme_expires.should == Date.new(2013, 1, 8)
151
151
  section.myscout_programme_show.should == 10
152
152
  section.myscout_details_expires.should == Date.new(2013, 1, 9)
153
- section.myscout_events.should == true
154
- section.myscout_badges.should == true
155
- section.myscout_programme.should == true
156
- section.myscout_payments.should == true
153
+ section.myscout_events.should be_true
154
+ section.myscout_badges.should be_true
155
+ section.myscout_programme.should be_true
156
+ section.myscout_payments.should be_true
157
157
  section.myscout_emails.should == {:email1 => true, :email2 => false}
158
158
  section.myscout_email_address_from.should == 'send_from@example.com'
159
159
  section.myscout_email_address_copy.should == ''
160
- section.myscout_badges_partial.should == true
161
- section.myscout_programme_summary.should == true
162
- section.myscout_programme_times.should == true
160
+ section.myscout_badges_partial.should be_true
161
+ section.myscout_programme_summary.should be_true
162
+ section.myscout_programme_times.should be_true
163
163
  section.myscout_event_reminder_count.should == 4
164
164
  section.myscout_event_reminder_frequency.should == 5
165
165
  section.myscout_payment_reminder_count.should == 6
166
166
  section.myscout_payment_reminder_frequency.should == 7
167
- section.myscout_details.should == true
167
+ section.myscout_details.should be_true
168
168
  section.myscout_details_email_changes_to.should == 'notify-changes-to@example.com'
169
- section.sms_sent_test.should == true
169
+ section.sms_sent_test.should be_true
170
170
  section.sms_messages_remaining.should == 8
171
171
  section.sms_messages_sent.should == 9
172
172
  section.valid?.should be_true
@@ -53,9 +53,9 @@ describe "Term" do
53
53
  term2 = Osm::Term.new(@attributes.merge(:start => (Date.today - 0), :finish => (Date.today + 0)))
54
54
  term3 = Osm::Term.new(@attributes.merge(:start => (Date.today + 1), :finish => (Date.today + 60)))
55
55
 
56
- term1.before?(Date.today).should == true
57
- term2.before?(Date.today).should == false
58
- term3.before?(Date.today).should == false
56
+ term1.before?(Date.today).should be_true
57
+ term2.before?(Date.today).should be_false
58
+ term3.before?(Date.today).should be_false
59
59
  end
60
60
 
61
61
  it "Works out if it is completly after a date" do
@@ -63,9 +63,9 @@ describe "Term" do
63
63
  term2 = Osm::Term.new(@attributes.merge(:start => (Date.today - 0), :finish => (Date.today + 0)))
64
64
  term3 = Osm::Term.new(@attributes.merge(:start => (Date.today + 1), :finish => (Date.today + 60)))
65
65
 
66
- term1.after?(Date.today).should == false
67
- term2.after?(Date.today).should == false
68
- term3.after?(Date.today).should == true
66
+ term1.after?(Date.today).should be_false
67
+ term2.after?(Date.today).should be_false
68
+ term3.after?(Date.today).should be_true
69
69
  end
70
70
 
71
71
  it "Works out if it has passed" do
@@ -73,9 +73,9 @@ describe "Term" do
73
73
  term2 = Osm::Term.new(@attributes.merge(:start => (Date.today - 0), :finish => (Date.today + 0)))
74
74
  term3 = Osm::Term.new(@attributes.merge(:start => (Date.today + 1), :finish => (Date.today + 60)))
75
75
 
76
- term1.past?().should == true
77
- term2.past?().should == false
78
- term3.past?().should == false
76
+ term1.past?().should be_true
77
+ term2.past?().should be_false
78
+ term3.past?().should be_false
79
79
  end
80
80
 
81
81
  it "Works out if it is in the future" do
@@ -83,9 +83,9 @@ describe "Term" do
83
83
  term2 = Osm::Term.new(@attributes.merge(:start => (Date.today - 0), :finish => (Date.today + 0)))
84
84
  term3 = Osm::Term.new(@attributes.merge(:start => (Date.today + 1), :finish => (Date.today + 60)))
85
85
 
86
- term1.future?().should == false
87
- term2.future?().should == false
88
- term3.future?().should == true
86
+ term1.future?().should be_false
87
+ term2.future?().should be_false
88
+ term3.future?().should be_true
89
89
  end
90
90
 
91
91
  it "Works out if it is the current term" do
@@ -93,9 +93,9 @@ describe "Term" do
93
93
  term2 = Osm::Term.new(@attributes.merge(:start=> (Date.today - 0), :finish => (Date.today + 0)))
94
94
  term3 = Osm::Term.new(@attributes.merge(:start => (Date.today + 1), :finish => (Date.today + 60)))
95
95
 
96
- term1.current?().should == false
97
- term2.current?().should == true
98
- term3.current?().should == false
96
+ term1.current?().should be_false
97
+ term2.current?().should be_true
98
+ term3.current?().should be_false
99
99
  end
100
100
 
101
101
  it "Works out if it contains a date" do
@@ -103,9 +103,9 @@ describe "Term" do
103
103
  term2 = Osm::Term.new(@attributes.merge(:start => (Date.today - 0), :finish => (Date.today + 0)))
104
104
  term3 = Osm::Term.new(@attributes.merge(:start => (Date.today + 1), :finish => (Date.today + 60)))
105
105
 
106
- term1.contains_date?(Date.today).should == false
107
- term2.contains_date?(Date.today).should == true
108
- term3.contains_date?(Date.today).should == false
106
+ term1.contains_date?(Date.today).should be_false
107
+ term2.contains_date?(Date.today).should be_true
108
+ term3.contains_date?(Date.today).should be_false
109
109
  end
110
110
 
111
111
  it "Date helpers return false for nil dates" do
@@ -20,6 +20,7 @@ FakeWeb.allow_net_connect = %r[^https://coveralls.io] # Allow coveralls to repor
20
20
 
21
21
 
22
22
  RSpec.configure do |config|
23
+
23
24
  # == Mock Framework
24
25
  #
25
26
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
@@ -27,7 +28,17 @@ RSpec.configure do |config|
27
28
  # config.mock_with :mocha
28
29
  # config.mock_with :flexmock
29
30
  # config.mock_with :rr
30
- config.mock_with :rspec
31
+ config.mock_with :rspec do |configuration|
32
+ # Using the expect syntax is preferable to the should syntax in some cases.
33
+ # The problem here is that the :should syntax that RSpec uses can fail in
34
+ # the case of proxy objects, and objects that include the delegate module.
35
+ # Essentially it requires that we define methods on every object in the
36
+ # system. Not owning every object means that we cannot ensure this works in
37
+ # a consistent manner. The expect syntax gets around this problem by not
38
+ # relying on RSpec specific methods being defined on every object in the
39
+ # system.
40
+ configuration.syntax = [:expect, :should]
41
+ end
31
42
 
32
43
  config.before(:each) do
33
44
  FakeWeb.clean_registry
@@ -54,8 +65,8 @@ RSpec.configure do |config|
54
65
  Osm::configure(@CONFIGURATION)
55
66
 
56
67
  @api = Osm::Api.new('user_id', 'secret')
57
- Osm::Model.stub(:require_ability_to) {}
58
- Osm::Model.stub(:require_access_to_section) {}
68
+ Osm::Model.stub(:require_ability_to).and_return(nil)
69
+ Osm::Model.stub(:require_access_to_section).and_return(nil)
59
70
  end
60
71
  end
61
72
 
data/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Osm
2
- VERSION = "1.2.7"
2
+ VERSION = "1.2.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.7
4
+ version: 1.2.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-15 00:00:00.000000000 Z
12
+ date: 2014-03-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -267,6 +267,7 @@ files:
267
267
  - lib/osm/sms.rb
268
268
  - lib/osm/term.rb
269
269
  - osm.gemspec
270
+ - spec/array_of_validator_spec.rb
270
271
  - spec/osm/activity_spec.rb
271
272
  - spec/osm/api_access_spec.rb
272
273
  - spec/osm/api_spec.rb