touchpass 0.0.8.1
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 +3 -0
- data/.rspec +2 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +38 -0
- data/Guardfile +9 -0
- data/Rakefile +1 -0
- data/app/controllers/touchpass/verifications_controller.rb +30 -0
- data/bin/tpcli.rb +248 -0
- data/config/routes.rb +8 -0
- data/lib/engine.rb +4 -0
- data/lib/generators/templates/config/initializers/devise.rb +204 -0
- data/lib/generators/templates/config/initializers/touchpass.rb +24 -0
- data/lib/generators/templates/config/locales/devise.en.yml +53 -0
- data/lib/generators/touchpass/install_generator.rb +36 -0
- data/lib/touchpass/client.rb +431 -0
- data/lib/touchpass/crypt.rb +51 -0
- data/lib/touchpass/device.rb +18 -0
- data/lib/touchpass/key_file_creator.rb +56 -0
- data/lib/touchpass/prp.rb +256 -0
- data/lib/touchpass/verification.rb +112 -0
- data/lib/touchpass/version.rb +3 -0
- data/lib/touchpass.rb +53 -0
- data/spec/bounding_box_spec.rb +26 -0
- data/spec/geocode_spec.rb +22 -0
- data/spec/helpers/client_spec_helper.rb +1 -0
- data/spec/helpers/gtp_spec_helper.rb +98 -0
- data/spec/key_file_creator_spec.rb +30 -0
- data/spec/proximity_spec.rb +283 -0
- data/spec/prp_spec.rb +86 -0
- data/spec/resolution_spec.rb +46 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/touchpass_client_spec.rb +319 -0
- data/touchpass.gemspec +27 -0
- metadata +146 -0
@@ -0,0 +1,256 @@
|
|
1
|
+
# Use BigDecimal for accuracy
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'geocoder'
|
4
|
+
|
5
|
+
begin
|
6
|
+
# TODO: use a disk cache?
|
7
|
+
Geocoder::Configuration.cache = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
module Touchpass
|
11
|
+
module Proximity
|
12
|
+
# PRP - Privacy Respecting Proximity
|
13
|
+
# Provides mechanisms that allows locations to be compared
|
14
|
+
# for proximity without revealing the actual location of
|
15
|
+
# either party.
|
16
|
+
class PRP
|
17
|
+
|
18
|
+
class BBoxResolution
|
19
|
+
# Bounding box resolutions:
|
20
|
+
STREET = 0.001 # 3 decimal places
|
21
|
+
LOCAL = 0.01 # 2 decimal places
|
22
|
+
METRO = 0.1 # 1 decimal place
|
23
|
+
REGIONAL = 1 # 0 decimal places
|
24
|
+
end
|
25
|
+
|
26
|
+
# Minumum and maximum value for latitude
|
27
|
+
MIN_LAT, MAX_LAT = BigDecimal.new("-90.0"), BigDecimal.new("90.0")
|
28
|
+
# Minumum and maximum value for longitude
|
29
|
+
MIN_LNG, MAX_LNG = BigDecimal.new("-180.0"), BigDecimal.new("180.0")
|
30
|
+
|
31
|
+
attr_reader :lat, :lng, :resolution
|
32
|
+
attr_reader :bounding_coordinates
|
33
|
+
attr :crypted_coordinates
|
34
|
+
|
35
|
+
# Given a coordinate (latitude and longitude) and an Bounding Box resolution, return a PRP geohash
|
36
|
+
def initialize(params={})
|
37
|
+
resolution = params[:resolution]
|
38
|
+
if resolution.nil? or resolution == ""
|
39
|
+
resolution = 'LOCAL'
|
40
|
+
end
|
41
|
+
|
42
|
+
if params.has_key? :lat and params.has_key? :lng
|
43
|
+
@lat, @lng = lat, lng
|
44
|
+
elsif params[:address]
|
45
|
+
addr = nil
|
46
|
+
if params[:address].is_a? String
|
47
|
+
addr = params[:address]
|
48
|
+
elsif params[:address].is_a? Hash
|
49
|
+
addr = build_address(params[:address])
|
50
|
+
end
|
51
|
+
|
52
|
+
coord = Geocoder.coordinates(addr) if addr
|
53
|
+
#puts "addr = #{addr}"
|
54
|
+
#puts "coord = #{coord.first}, #{coord.last}"
|
55
|
+
return false if coord.nil? # Should we raise exception here?
|
56
|
+
@lat, @lng = coord.first, coord.last
|
57
|
+
end
|
58
|
+
|
59
|
+
case resolution.upcase
|
60
|
+
when 'STREET'
|
61
|
+
@resolution = BBoxResolution::STREET
|
62
|
+
when 'LOCAL'
|
63
|
+
@resolution = BBoxResolution::LOCAL
|
64
|
+
when 'METRO'
|
65
|
+
@resolution = BBoxResolution::METRO
|
66
|
+
when 'REGIONAL'
|
67
|
+
@resolution = BBoxResolution::REGIONAL
|
68
|
+
else
|
69
|
+
raise Exception, "Unknown resolution '#{resolution}'."
|
70
|
+
end
|
71
|
+
|
72
|
+
# convert lat, lng to bigdecimal
|
73
|
+
@lat, @lng = BigDecimal.new(@lat.to_s), BigDecimal.new(@lng.to_s)
|
74
|
+
|
75
|
+
# calculate bounding coordinates
|
76
|
+
calculate_bounding_coordinates!(@resolution)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Calculates four coordinates that represent an anonymised version of the location.
|
80
|
+
# Anonymised means that regardless of the absolute value of lat and lng, the four
|
81
|
+
# coordinates will be a bounding box around the point.
|
82
|
+
# Returns an array of lat/lng coordinates that bound the coordinates.
|
83
|
+
# Notes:
|
84
|
+
# Size of the bounding box is determined by the granularity parameter
|
85
|
+
def calculate_bounding_coordinates!(resolution)
|
86
|
+
return @bounding_coordinates unless @bounding_coordinates.nil?
|
87
|
+
|
88
|
+
trunc = Touchpass::Proximity::PRP.truncate_size(resolution)
|
89
|
+
granularity = BigDecimal.new(resolution.to_s)
|
90
|
+
|
91
|
+
min_lat = @lat.truncate(trunc)
|
92
|
+
min_lng = @lng.truncate(trunc)
|
93
|
+
|
94
|
+
# Allow for different calcs depending on sign of lat and lng
|
95
|
+
if @lat > 0.0
|
96
|
+
max_lat = min_lat + granularity
|
97
|
+
else
|
98
|
+
max_lat = min_lat
|
99
|
+
min_lat = max_lat - granularity
|
100
|
+
end
|
101
|
+
if @lng > 0.0
|
102
|
+
max_lng = min_lng + granularity
|
103
|
+
else
|
104
|
+
max_lng = min_lng
|
105
|
+
min_lng = max_lng - granularity
|
106
|
+
end
|
107
|
+
|
108
|
+
@bounding_coordinates = {
|
109
|
+
:top_left => [max_lat, min_lng],
|
110
|
+
:top_right => [max_lat, max_lng],
|
111
|
+
:bottom_right => [min_lat, max_lng],
|
112
|
+
:bottom_left => [min_lat, min_lng]
|
113
|
+
}
|
114
|
+
|
115
|
+
# Calibrate lats and lngs
|
116
|
+
@bounding_coordinates.collect{|k, coords| coords[0] = Touchpass::Proximity::PRP.calibrate_lat(coords[0])}
|
117
|
+
@bounding_coordinates.collect{|k, coords| coords[1] = Touchpass::Proximity::PRP.calibrate_lng(coords[1])}
|
118
|
+
|
119
|
+
return @bounding_coordinates
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the bounding coordinates
|
123
|
+
def bounding_box
|
124
|
+
return @bounding_coordinates
|
125
|
+
end
|
126
|
+
|
127
|
+
def calibrated?
|
128
|
+
return false if @bounding_coordinates.nil? or @bounding_coordinates.empty?
|
129
|
+
for key in [:top_left, :top_right, :bottom_right, :bottom_left]
|
130
|
+
return false if !@bounding_coordinates.has_key?(key)
|
131
|
+
end
|
132
|
+
return true
|
133
|
+
end
|
134
|
+
|
135
|
+
# Test to see if the specified location is near this one, where
|
136
|
+
# 'near' means at least one of its bounding coordinates is shared between the two points
|
137
|
+
def proximate?(other_prp)
|
138
|
+
return Touchpass::Proximity::PRP.proximate?(self, other_prp)
|
139
|
+
end
|
140
|
+
|
141
|
+
def common_bounding_coordinates(other_prp)
|
142
|
+
return Touchpass::Proximity::PRP.common_bounding_coordinates(self, other_prp)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the hashed representation of the bounding coordinates
|
146
|
+
def encrypt(salt=nil)
|
147
|
+
crypted_1 = encrypt_point(@bounding_coordinates[:top_left], salt)
|
148
|
+
crypted_2 = encrypt_point(@bounding_coordinates[:top_right], salt)
|
149
|
+
crypted_3 = encrypt_point(@bounding_coordinates[:bottom_right], salt)
|
150
|
+
crypted_4 = encrypt_point(@bounding_coordinates[:bottom_left], salt)
|
151
|
+
@crypted_coordinates = crypted_1 + crypted_2 + crypted_3 + crypted_4
|
152
|
+
return @crypted_coordinates
|
153
|
+
end
|
154
|
+
|
155
|
+
def encrypt_point(point=[], salt=nil)
|
156
|
+
return if point.size!=2
|
157
|
+
|
158
|
+
# Format lat, lng with correct decimal places
|
159
|
+
# STREET : 3 decimal places (e.g. -33.860, 151.200)
|
160
|
+
# LOCAL : 2 decimal places (e.g. -33.86, 151.20)
|
161
|
+
# METRO : 1 decimal places (e.g. -33.8, 151.2)
|
162
|
+
# REGIONAL: 0 decimal places (e.g. -33, 151)
|
163
|
+
lat = Touchpass::Proximity::PRP.format_decimal(point.first, Touchpass::Proximity::PRP.truncate_size(@resolution))
|
164
|
+
lng = Touchpass::Proximity::PRP.format_decimal(point.last, Touchpass::Proximity::PRP.truncate_size(@resolution))
|
165
|
+
|
166
|
+
# MFS: 20100722
|
167
|
+
# Original approach hashed points in the corner independently. eg:
|
168
|
+
# return crypto_provider.hexdigest(lat.to_s) + crypto_provider.hexdigest(lng.to_s)
|
169
|
+
# Changed to string concat the points together *before* the hash so that we end up with hash values
|
170
|
+
# that are coming from 3,240,000 values (ie 1,800*1,800) as opposed to 2 hashes derived from a set of 1,800
|
171
|
+
# possible values.
|
172
|
+
str_to_encrypt = (lat.to_s) + "," + (lng.to_s) + salt.to_s
|
173
|
+
return Touchpass::Crypt.encrypt(str_to_encrypt)
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.truncate_size(resolution)
|
177
|
+
split = resolution.to_s.split(".")
|
178
|
+
return split.size==1 ? 0 : split.last.size
|
179
|
+
end
|
180
|
+
|
181
|
+
# Truncate decimal (not round)
|
182
|
+
# E.g.
|
183
|
+
# format_decimal(-33.860987, 3) #=> -33.860
|
184
|
+
# format_decimal(-33.860987, 2) #=> -33.86
|
185
|
+
# format_decimal(-33.860987, 1) #=> -33.8
|
186
|
+
# format_decimal(-33.860987, 0) #=> -33
|
187
|
+
# format_decimal(151.200948, 3) #=> 151.200
|
188
|
+
# format_decimal(151.200948, 2) #=> 151.20
|
189
|
+
# format_decimal(151.200948, 1) #=> 151.2
|
190
|
+
# format_decimal(151.200948, 0) #=> 151
|
191
|
+
def self.format_decimal(decimal, decimal_places)
|
192
|
+
# KM: 20110927
|
193
|
+
# Original approach was to round decimal. eg:
|
194
|
+
# {}"%.#{decimal_places}f" % decimal
|
195
|
+
# Changed to truncate without rounding
|
196
|
+
t = 10.0 ** decimal_places
|
197
|
+
"%.#{decimal_places}f" % ((decimal * t).truncate / t)
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.calibrate_lat(lat)
|
201
|
+
if lat == 0.0
|
202
|
+
# make sure -0.0 turned into 0.0
|
203
|
+
lat = BigDecimal("0.0")
|
204
|
+
elsif !(MIN_LAT..MAX_LAT).include?(lat)
|
205
|
+
# latitude must fall within its range
|
206
|
+
lat = (lat<MIN_LAT) ? MIN_LAT : MAX_LAT
|
207
|
+
end
|
208
|
+
return lat
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.calibrate_lng(lng)
|
212
|
+
if lng == 0.0
|
213
|
+
# make sure -0.0 turned into 0.0
|
214
|
+
lng = BigDecimal("0.0")
|
215
|
+
elsif !(MIN_LNG..MAX_LNG).include?(lng)
|
216
|
+
# longitude must fall within its range
|
217
|
+
lng = (lng<MIN_LNG) ? MIN_LNG : MAX_LNG
|
218
|
+
end
|
219
|
+
return lng
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.proximate?(prp, other_prp)
|
223
|
+
return !Touchpass::Proximity::PRP.common_bounding_coordinates(prp, other_prp).empty?
|
224
|
+
end
|
225
|
+
|
226
|
+
def self.common_bounding_coordinates(prp, other_prp)
|
227
|
+
return nil unless prp.bounding_coordinates
|
228
|
+
bounding_coords_1 = prp.bounding_coordinates.collect{|k, v| v}
|
229
|
+
bounding_coords_2 = other_prp.bounding_coordinates.collect{|k, v| v}
|
230
|
+
return bounding_coords_1 & bounding_coords_2
|
231
|
+
end
|
232
|
+
|
233
|
+
def print_bbox
|
234
|
+
for point in [:top_left, :top_right, :bottom_right, :bottom_left]
|
235
|
+
lat = Touchpass::Proximity::PRP.format_decimal(self.bounding_coordinates[point].first, Touchpass::Proximity::PRP.truncate_size(@resolution))
|
236
|
+
lng = Touchpass::Proximity::PRP.format_decimal(self.bounding_coordinates[point].last, Touchpass::Proximity::PRP.truncate_size(@resolution))
|
237
|
+
# lat = "%.#{Touchpass::Proximity::PRP.truncate_size(@resolution)}f" % self.bounding_coordinates[point].first
|
238
|
+
# lng = "%.#{Touchpass::Proximity::PRP.truncate_size(@resolution)}f" % self.bounding_coordinates[point].last
|
239
|
+
puts "#{point.to_s}: [#{lat.to_s}, #{lng.to_s}]"
|
240
|
+
end
|
241
|
+
return true
|
242
|
+
end
|
243
|
+
|
244
|
+
# Converts addresss Hash to String
|
245
|
+
# "120 Sussex Street, Sydney 2000, NSW Australia"
|
246
|
+
def build_address(attributes)
|
247
|
+
address = attributes[:address] + ","
|
248
|
+
address << " #{attributes[:city]}" if attributes[:city].present?
|
249
|
+
address << " #{attributes[:postcode]}" if attributes[:postcode].present?
|
250
|
+
address << ", #{attributes[:state]}" if attributes[:state].present?
|
251
|
+
address << " #{attributes[:country]}" if attributes[:country].present?
|
252
|
+
address
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Touchpass
|
2
|
+
module Rp
|
3
|
+
class Verification
|
4
|
+
include HTTParty
|
5
|
+
#debug_output
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.class.base_uri Touchpass.base_uri
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(to_party, options={})
|
12
|
+
http_options = { :body => {:to_party => to_party}, :headers => api_key_header }
|
13
|
+
|
14
|
+
# Get the verifying party devices so we can encrypt message/prp using the devices public key
|
15
|
+
device = Touchpass::Rp::Device.new
|
16
|
+
vp_devices = device.get_all(to_party)
|
17
|
+
|
18
|
+
# Generate token
|
19
|
+
token = Touchpass::Crypt.salt
|
20
|
+
hashed_token = Touchpass::Crypt.encrypt(token)
|
21
|
+
http_options[:body][:claimed_token] = hashed_token
|
22
|
+
|
23
|
+
# Encrypt token using verifying_party (to_party) devices
|
24
|
+
create_crypted_tokens(token, vp_devices, http_options)
|
25
|
+
|
26
|
+
# Generate Claimed PRP (for Location Verification)
|
27
|
+
create_prp(options[:address], vp_devices, http_options)
|
28
|
+
|
29
|
+
# Generate Claimed PRP (for Location Verification)
|
30
|
+
create_crypted_messages(options[:message], vp_devices, http_options)
|
31
|
+
|
32
|
+
response = self.class.post("/verifications.json", http_options)
|
33
|
+
return response.parsed_response
|
34
|
+
end
|
35
|
+
|
36
|
+
def cancel(id)
|
37
|
+
http_options = { :body => {}, :headers => api_key_header }
|
38
|
+
response = self.class.put("/verifications/#{id}/cancel.json", http_options)
|
39
|
+
return response.parsed_response
|
40
|
+
end
|
41
|
+
|
42
|
+
def show(id)
|
43
|
+
http_options = { :body => {}, :headers => api_key_header }
|
44
|
+
response = self.class.get("/verifications/#{id}.json", http_options)
|
45
|
+
return response.parsed_response
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def create_crypted_tokens(token, devices, http_options)
|
50
|
+
return if devices.nil? or (devices.is_a? Array and devices.empty?)
|
51
|
+
devices.each_with_index do |device, index|
|
52
|
+
device_id = device["id"]
|
53
|
+
pub_key = device["pub_key"]
|
54
|
+
public_key = Touchpass::Crypt.read_key(pub_key)
|
55
|
+
crypted_token = Base64.encode64(public_key.public_encrypt(token))
|
56
|
+
http_options[:body]["crypted_tokens[#{index}][device_id]"] = device_id
|
57
|
+
http_options[:body]["crypted_tokens[#{index}][value]"] = crypted_token
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_prp(address, devices, http_options)
|
62
|
+
return unless address.present?
|
63
|
+
|
64
|
+
http_options[:body][:location_verification] = true
|
65
|
+
|
66
|
+
# Convert address to PRP
|
67
|
+
http_options[:body][:resolution] = Touchpass.resolution # Resolution used to calculate PRP
|
68
|
+
prp = Touchpass::Proximity::PRP.new(:address => address, :resolution => Touchpass.resolution)
|
69
|
+
|
70
|
+
# Generate random salt
|
71
|
+
salt = Touchpass::Crypt.salt
|
72
|
+
|
73
|
+
# Encrypt PRP using salt
|
74
|
+
claimed_prp = prp.encrypt(salt)
|
75
|
+
http_options[:body][:claimed_prp] = claimed_prp
|
76
|
+
|
77
|
+
# Encrypt salt using verifiying_party (to_party) devices
|
78
|
+
if !devices.nil? and (devices.is_a? Array and !devices.empty?)
|
79
|
+
devices.each_with_index do |device, index|
|
80
|
+
device_id = device["id"]
|
81
|
+
pub_key = device["pub_key"]
|
82
|
+
public_key = Touchpass::Crypt.read_key(pub_key)
|
83
|
+
crypted_salt = Base64.encode64(public_key.public_encrypt(salt))
|
84
|
+
http_options[:body]["crypted_salts[#{index}][device_id]"] = device_id
|
85
|
+
http_options[:body]["crypted_salts[#{index}][value]"] = crypted_salt
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_crypted_messages(message, devices, http_options)
|
91
|
+
return if message.blank?
|
92
|
+
return if devices.nil? or (devices.is_a? Array and devices.empty?)
|
93
|
+
|
94
|
+
# Encrypt message using verifying party devices public key
|
95
|
+
devices.each_with_index do |device, index|
|
96
|
+
device_id = device["id"]
|
97
|
+
pub_key = device["pub_key"]
|
98
|
+
public_key = Touchpass::Crypt.read_key(pub_key)
|
99
|
+
crypted_message = Base64.encode64(public_key.public_encrypt(message))
|
100
|
+
http_options[:body]["crypted_messages[#{index}][device_id]"] = device_id
|
101
|
+
http_options[:body]["crypted_messages[#{index}][value]"] = crypted_message
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
def api_key_header
|
107
|
+
{ Touchpass::Client::API_KEY_HEADER => Touchpass.api_key }
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/touchpass.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "touchpass/version"
|
3
|
+
require 'touchpass/prp'
|
4
|
+
require 'touchpass/client'
|
5
|
+
require 'touchpass/crypt'
|
6
|
+
require 'touchpass/key_file_creator'
|
7
|
+
require 'touchpass/verification'
|
8
|
+
require 'touchpass/device'
|
9
|
+
|
10
|
+
module Touchpass
|
11
|
+
require 'engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
12
|
+
|
13
|
+
config = [:username, :api_key, :use_https, :host, :port, :resolution, :location_verification, :verified_message, :unverified_message]
|
14
|
+
|
15
|
+
# define getter and setter methods for each config
|
16
|
+
# normally we can use mattr_accessor :key for shortcut, but this only available in Rails environment
|
17
|
+
config.each do |symbol|
|
18
|
+
eval("@@#{symbol.to_s} = nil")
|
19
|
+
module_eval( "def self.#{symbol.to_s}() @@#{symbol.to_s}; end" )
|
20
|
+
module_eval( "def self.#{symbol.to_s}=(val) @@#{symbol.to_s} = val; end" )
|
21
|
+
end
|
22
|
+
|
23
|
+
# Default way to setup Touchpass. Run rails generate touchpass_install to create
|
24
|
+
# a fresh initializer with all configuration values.
|
25
|
+
def self.setup
|
26
|
+
yield self
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.base_uri
|
30
|
+
tp_base_uri = Touchpass.host
|
31
|
+
if Touchpass.port.present?
|
32
|
+
tp_base_uri += ":#{Touchpass.port}"
|
33
|
+
end
|
34
|
+
protocol = Touchpass.use_https ? "https://" : "http://"
|
35
|
+
tp_base_uri = protocol + tp_base_uri
|
36
|
+
end
|
37
|
+
|
38
|
+
module Role
|
39
|
+
RELYING_PARTY = "relying_party"
|
40
|
+
VERIFYING_PARTY = "verifying_party"
|
41
|
+
end
|
42
|
+
|
43
|
+
module MessagingType
|
44
|
+
APN = "apn"
|
45
|
+
APN_DEV = "apn-development"
|
46
|
+
#SMS = "sms" # not supported yet
|
47
|
+
|
48
|
+
def self.all
|
49
|
+
[APN, APN_DEV]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Bounding Box" do
|
4
|
+
|
5
|
+
context "using north of equator" do
|
6
|
+
it "should have 4 points (top_left, top_right, bottom_right, bottom_left)" do
|
7
|
+
prp = Touchpass::Proximity::PRP.new(north_of_equator)
|
8
|
+
prp.bounding_box.size.should eql(4)
|
9
|
+
for point in [:top_left, :top_right, :bottom_right, :bottom_left]
|
10
|
+
prp.bounding_box[point].should be
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "using orbitec office in sydney" do
|
16
|
+
it "should have 4 points (top_left, top_right, bottom_right, bottom_left)" do
|
17
|
+
Geocoder.should_receive(:coordinates).and_return([1, 2]) # dummy values
|
18
|
+
|
19
|
+
prp = Touchpass::Proximity::PRP.new(:address => orbitec_office)
|
20
|
+
prp.bounding_box.size.should eql(4)
|
21
|
+
for point in [:top_left, :top_right, :bottom_right, :bottom_left]
|
22
|
+
prp.bounding_box[point].should be
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Geocode" do
|
4
|
+
|
5
|
+
for address in addresses
|
6
|
+
|
7
|
+
it "should find geographic coordinates for address '#{address}'" do
|
8
|
+
dummy_lat = 10
|
9
|
+
dummy_lon = 11
|
10
|
+
|
11
|
+
# avoid hammering the geocode server
|
12
|
+
# (we just want to test Touchpass::Proximity::PRP, rather than Geocoder)
|
13
|
+
Geocoder.should_receive(:coordinates).and_return([dummy_lat, dummy_lon])
|
14
|
+
|
15
|
+
prp = Touchpass::Proximity::PRP.new(:address => address)
|
16
|
+
prp.lat.should == dummy_lat
|
17
|
+
prp.lng.should == dummy_lon
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'touchpass'
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'touchpass'
|
2
|
+
|
3
|
+
def orbitec_office
|
4
|
+
'120 Sussex St Sydney NSW 2000 Australia'
|
5
|
+
end
|
6
|
+
|
7
|
+
def apple_store_sydney
|
8
|
+
'367 George Street Sydney 2000 NSW Australia'
|
9
|
+
end
|
10
|
+
|
11
|
+
def mecca_espresso_king_st
|
12
|
+
'67 King Street Sydney 2000 NSW Australia'
|
13
|
+
end
|
14
|
+
|
15
|
+
def talga_rd_rothbury
|
16
|
+
'127 Talga Rd Rothbury NSW 2320 Australia'
|
17
|
+
end
|
18
|
+
|
19
|
+
def cessnock_post_office
|
20
|
+
'16/205 Wollombi Rd Cessnock NSW 2325 Australia'
|
21
|
+
end
|
22
|
+
|
23
|
+
def holdsworth_st_neutralbay
|
24
|
+
'2/10 Holdsworth St Neutral Bay New South Wales 2089'
|
25
|
+
end
|
26
|
+
|
27
|
+
def north_sydney_post_office
|
28
|
+
'92 Pacific Highway North Sydney NSW 2060 Australia'
|
29
|
+
end
|
30
|
+
|
31
|
+
def empire_state_building
|
32
|
+
'350 5th Avenue New York, NY 10118-3304, United States'
|
33
|
+
end
|
34
|
+
|
35
|
+
def chrysler_building
|
36
|
+
'Chrysler Building, New York, NY, United States'
|
37
|
+
end
|
38
|
+
|
39
|
+
def themet
|
40
|
+
'Metropolitan Museum of Art 5th Avenue New York NY United States'
|
41
|
+
end
|
42
|
+
|
43
|
+
def addresses
|
44
|
+
[orbitec_office, apple_store_sydney, mecca_espresso_king_st, talga_rd_rothbury, cessnock_post_office, holdsworth_st_neutralbay, north_sydney_post_office,
|
45
|
+
empire_state_building, chrysler_building, themet]
|
46
|
+
end
|
47
|
+
|
48
|
+
def resolutions
|
49
|
+
['street', 'local', 'metro', 'regional']
|
50
|
+
end
|
51
|
+
|
52
|
+
def north_of_equator
|
53
|
+
{ :lat => 0.0525, :lng => 151.2348 }
|
54
|
+
end
|
55
|
+
|
56
|
+
def south_of_equator
|
57
|
+
{ :lat => -0.0525, :lng => 151.2348 }
|
58
|
+
end
|
59
|
+
|
60
|
+
def east_of_gmt
|
61
|
+
{ :lat => 33.8, :lng => 0.0525 }
|
62
|
+
end
|
63
|
+
|
64
|
+
def west_of_gmt
|
65
|
+
{ :lat => 33.8, :lng => -0.0525 }
|
66
|
+
end
|
67
|
+
|
68
|
+
def north_west_of_equator_and_gmt
|
69
|
+
{ :lat => 0.0525, :lng => -0.0525 }
|
70
|
+
end
|
71
|
+
|
72
|
+
def north_east_of_equator_and_gmt
|
73
|
+
{ :lat => 0.0525, :lng => 0.0525 }
|
74
|
+
end
|
75
|
+
|
76
|
+
def south_east_of_equator_and_gmt
|
77
|
+
{ :lat => -0.0525, :lng => 0.0525 }
|
78
|
+
end
|
79
|
+
|
80
|
+
def south_west_of_equator_and_gmt
|
81
|
+
{ :lat => -0.0525, :lng => -0.0525 }
|
82
|
+
end
|
83
|
+
|
84
|
+
def cornercase1
|
85
|
+
{ :lat => -0.15, :lng => -0.15 }
|
86
|
+
end
|
87
|
+
|
88
|
+
def cornercase2
|
89
|
+
{ :lat => 0.15, :lng => 0.15 }
|
90
|
+
end
|
91
|
+
|
92
|
+
def cornercase3
|
93
|
+
{ :lat => 0.15, :lng => -0.15 }
|
94
|
+
end
|
95
|
+
|
96
|
+
def cornercase4
|
97
|
+
{ :lat => -0.15, :lng => 0.15 }
|
98
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Key File Creator" do
|
4
|
+
|
5
|
+
context "create public / private keys" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@device_id = "1"
|
9
|
+
@device_udid = "747c37dc35b66830e921148398e77f3b3f5e2c3b"
|
10
|
+
@key_file_helper = Touchpass::KeyFileCreator.new(@device_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should initialise" do
|
14
|
+
@key_file_helper.should be
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create public and private key files" do
|
18
|
+
@key_file_helper.generate_keys
|
19
|
+
|
20
|
+
# Read in the public and private keys from the generated files
|
21
|
+
expected_public_key = OpenSSL::PKey::RSA.new(File.read(File.join(Touchpass::KeyFileCreator.keys_path, @device_id, Touchpass::KeyFileCreator::PUBLIC_KEY))).to_s
|
22
|
+
expected_private_key = OpenSSL::PKey::RSA.new(File.read(File.join(Touchpass::KeyFileCreator.keys_path, @device_id, Touchpass::KeyFileCreator::PRIVATE_KEY))).to_s
|
23
|
+
|
24
|
+
@key_file_helper.public_key.to_s.should == expected_public_key
|
25
|
+
@key_file_helper.private_key.to_s.should == expected_private_key
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|