mobile-pass 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +201 -0
- data/README.md +90 -0
- data/app/controllers/passbook/logs_controller.rb +33 -0
- data/app/controllers/passbook/passes_controller.rb +34 -0
- data/app/controllers/passbook/registrations_controller.rb +169 -0
- data/app/models/passbook/registration.rb +24 -0
- data/config/routes.rb +36 -0
- data/lib/passbook/config.rb +74 -0
- data/lib/passbook/engine.rb +23 -0
- data/lib/passbook/pkpass.rb +111 -0
- data/lib/passbook-ruby.rb +45 -0
- data/lib/rails/generators/passbook/config/config_generator.rb +36 -0
- data/lib/rails/generators/passbook/config/templates/initializer.rb +35 -0
- data/lib/rails/generators/passbook/config/templates/migration.rb +31 -0
- data/lib/rails/generators/passbook/pkpass/pkpass_generator.rb +40 -0
- data/lib/rails/generators/passbook/pkpass/templates/icon.png +0 -0
- data/lib/rails/generators/passbook/pkpass/templates/icon@2x.png +0 -0
- data/lib/rails/generators/passbook/pkpass/templates/initializer.rb +27 -0
- data/lib/rails/generators/passbook/pkpass/templates/migration.rb +29 -0
- data/lib/rails/generators/passbook/pkpass/templates/model.rb +54 -0
- data/lib/rails/generators/passbook/pkpass/templates/pass.json +38 -0
- data/spec/config_spec.rb +45 -0
- data/spec/data/templates/pass.com.acme/pass.json +26 -0
- data/spec/pkpass_spec.rb +117 -0
- data/spec/spec_helper.rb +82 -0
- metadata +165 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
module Passbook
|
20
|
+
class Engine < Rails::Engine
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
require 'digest/sha1'
|
20
|
+
require 'json'
|
21
|
+
require 'openssl'
|
22
|
+
require 'zip/zip'
|
23
|
+
require 'zip/zipfilesystem'
|
24
|
+
|
25
|
+
module Passbook
|
26
|
+
class Pkpass
|
27
|
+
attr_accessor :files, :translations, :json, :pass_type_id, :serial_number, :config
|
28
|
+
|
29
|
+
def initialize(pass_type_id, serial_number)
|
30
|
+
self.pass_type_id = pass_type_id
|
31
|
+
self.serial_number = serial_number
|
32
|
+
self.translations = Hash.new
|
33
|
+
raise(ArgumentError, "Don't forget to run the generator to create the initializer") unless Config.instance.pass_config
|
34
|
+
self.config = Config.instance.pass_config[self.pass_type_id]
|
35
|
+
raise(ArgumentError, "Could not find configuration for #{self.pass_type_id}") unless self.config
|
36
|
+
|
37
|
+
if self.config.include? :files
|
38
|
+
self.files = self.config['files'].dup
|
39
|
+
else
|
40
|
+
self.files = Config.instance.load_files self.config['template_path']
|
41
|
+
end
|
42
|
+
|
43
|
+
if self.files.include? 'pass.json'
|
44
|
+
self.json = JSON.parse(self.files['pass.json'])
|
45
|
+
else
|
46
|
+
self.json = {}
|
47
|
+
puts "Warning: your template_path does not contain pass.json"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_file filename, content
|
52
|
+
self.files[filename] = content
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_translation_string source, destination, language
|
56
|
+
self.translations[language] = Hash.new unless self.translations.include?(language)
|
57
|
+
self.translations[language][source] = destination
|
58
|
+
end
|
59
|
+
|
60
|
+
def package
|
61
|
+
#TODO: write a library that checks that all the right files are included in the package
|
62
|
+
#those requirements are going to be different depending on pass_type_id
|
63
|
+
self.write_json
|
64
|
+
self.write_translation_strings
|
65
|
+
self.generate_json_manifest
|
66
|
+
self.sign_manifest
|
67
|
+
self.compress_pass_file
|
68
|
+
end
|
69
|
+
|
70
|
+
def write_json
|
71
|
+
self.files['pass.json'] = JSON.pretty_generate(self.json)
|
72
|
+
end
|
73
|
+
|
74
|
+
def write_translation_strings
|
75
|
+
self.translations.each do |language, trans|
|
76
|
+
self.files["#{language}.lproj/pass.strings"] ||= ""
|
77
|
+
trans.each do |key, value|
|
78
|
+
#TODO: escape key and value
|
79
|
+
self.files["#{language}.lproj/pass.strings"] << "\n\"#{key}\" = \"#{value}\";"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def generate_json_manifest
|
85
|
+
manifest = {}
|
86
|
+
self.files.each do |filename, content|
|
87
|
+
manifest[filename] = Digest::SHA1.hexdigest(content)
|
88
|
+
end
|
89
|
+
self.files['manifest.json'] = JSON.pretty_generate(manifest)
|
90
|
+
end
|
91
|
+
|
92
|
+
def sign_manifest
|
93
|
+
flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED
|
94
|
+
signed = OpenSSL::PKCS7::sign(config['p12_certificate'].certificate, config['p12_certificate'].key, self.files['manifest.json'], [Config.instance.wwdr_certificate], flag)
|
95
|
+
self.files['signature'] = signed.to_der.force_encoding('UTF-8')
|
96
|
+
end
|
97
|
+
|
98
|
+
def compress_pass_file
|
99
|
+
stringio = Zip::ZipOutputStream::write_buffer do |z|
|
100
|
+
self.files.each do |filename, content|
|
101
|
+
z.put_next_entry filename
|
102
|
+
z.print content
|
103
|
+
end
|
104
|
+
end
|
105
|
+
stringio.set_encoding "binary"
|
106
|
+
stringio.rewind
|
107
|
+
stringio
|
108
|
+
# stringio.sysread
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
require "passbook/config"
|
20
|
+
require "passbook/pkpass"
|
21
|
+
require "passbook/engine"
|
22
|
+
|
23
|
+
require "action_controller"
|
24
|
+
Mime::Type.register 'application/vnd.apple.pkpass', :pkpass
|
25
|
+
|
26
|
+
ActionController::Renderers.add :pkpass do |obj, options|
|
27
|
+
pkpass = Passbook::Pkpass.new Passbook.class_name_to_pass_type_id(obj.class.to_s), obj.serial_number
|
28
|
+
obj.update_pass pkpass if obj.respond_to? :update_pass
|
29
|
+
pkpass_io = pkpass.package
|
30
|
+
response.headers["last-modified"] = obj.updated_at.strftime("%Y-%m-%d %H:%M:%S")
|
31
|
+
send_data(pkpass_io.sysread, :type => 'application/vnd.apple.pkpass', :disposition=>'inline', :filename=>"#{obj.serial_number}.pkpass")
|
32
|
+
end
|
33
|
+
|
34
|
+
module Passbook
|
35
|
+
def self.pass_type_id_to_class pass_type_id
|
36
|
+
Passbook::Config.instance.pass_config[pass_type_id]['class'].constantize
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.class_name_to_pass_type_id class_name
|
40
|
+
Passbook::Config.instance.pass_config.each do |pass_type_id, config|
|
41
|
+
return pass_type_id if config['class']==class_name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
require 'fileutils'
|
20
|
+
|
21
|
+
module Passbook
|
22
|
+
module Generators
|
23
|
+
class ConfigGenerator < Rails::Generators::Base
|
24
|
+
source_root File.expand_path('../templates', __FILE__)
|
25
|
+
argument :wwdr_certificate_path, type: :string, optional: true, banner: "Absolute path to your WWDR certification file"
|
26
|
+
|
27
|
+
desc 'Create Passbook initializer'
|
28
|
+
def create_initializer_file
|
29
|
+
path = "#{Rails.root}/data/certificates"
|
30
|
+
FileUtils.mkdir_p path if wwdr_certificate_path.blank? && !File.exists?(path)
|
31
|
+
template 'initializer.rb', File.join('config', 'initializers', 'passbook.rb')
|
32
|
+
template 'migration.rb', File.join('db', 'migrate', "#{Time.now.strftime("%Y%m%d%H%M%S")}_create_passbook_registrations.rb")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
Passbook::Config.instance.configure do |passbook|
|
20
|
+
# Templates are preloaded in production and dynamically loaded in development by default
|
21
|
+
# You can control the behaviour by setting the 'preload_templates'
|
22
|
+
#
|
23
|
+
# passbook.preload_templates = true
|
24
|
+
|
25
|
+
|
26
|
+
# Enables the routes necessary for passes to be able to:
|
27
|
+
# 1) register with the server
|
28
|
+
# 2) log errors
|
29
|
+
# 3) list pkpasses to be updated
|
30
|
+
# 4) let passbook request for update
|
31
|
+
passbook.enable_routes = true
|
32
|
+
|
33
|
+
|
34
|
+
passbook.wwdr_intermediate_certificate_path= "<%= wwdr_certificate_path.blank? ? "#{Rails.root}/data/certificates/wwdr.pem":wwdr_certificate_path %>"
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class CreatePassbookRegistrations < ActiveRecord::Migration
|
20
|
+
def change
|
21
|
+
create_table :passbook_registrations do |t|
|
22
|
+
t.string :uuid
|
23
|
+
t.string :device_id
|
24
|
+
t.string :push_token
|
25
|
+
t.string :serial_number
|
26
|
+
t.string :pass_type_id
|
27
|
+
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
module Passbook
|
20
|
+
module Generators
|
21
|
+
class PkpassGenerator < Rails::Generators::NamedBase
|
22
|
+
source_root File.expand_path('../templates', __FILE__)
|
23
|
+
argument :pass_type_id, type: :string, default: 'pass.com.acme', optional: true, banner: "The Pass Type ID you registered at iOS Provisioning Portal"
|
24
|
+
argument :team_id, type: :string, optional: true, banner: "Team ID you got at the iOS Provisioning Portal when you registered the pass type id"
|
25
|
+
argument :cert_path, type: :string, optional: true, banner: "Absolute path to your pass.com.acme.p12 file"
|
26
|
+
argument :cert_password, type: :string, default: 'password', optional: true, banner: "Password for your P12 certificate"
|
27
|
+
|
28
|
+
desc 'Create and configure a model for a particular pkpass (ie. ticket)'
|
29
|
+
def create_initializer_file
|
30
|
+
template 'initializer.rb', File.join('config', 'initializers', "passbook_#{plural_name.singularize}.rb")
|
31
|
+
template 'model.rb', File.join('app', 'models', "#{plural_name.singularize}.rb")
|
32
|
+
route "get '/v1/passes/#{plural_name.singularize}' => 'Passbook::passes#get_pkpass', :defaults => { :pass_type_id => '#{pass_type_id}' }"
|
33
|
+
template 'migration.rb', File.join('db', 'migrate', "#{Time.now.strftime("%Y%m%d%H%M%S")}_create_#{plural_name}.rb")
|
34
|
+
template 'pass.json', File.join('data', 'templates', pass_type_id, "pass.json")
|
35
|
+
template 'icon.png', File.join('data', 'templates', pass_type_id, "icon.png")
|
36
|
+
template 'icon@2x.png', File.join('data', 'templates', pass_type_id, "icon@2x.png")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
Passbook::Config.instance.add_pkpass do |passbook|
|
20
|
+
passbook.pass_config["<%= pass_type_id %>"]={
|
21
|
+
"cert_path"=>"<%= cert_path.blank? ? "#{Rails.root}/data/certificates/#{pass_type_id}.p12" : cert_path %>",
|
22
|
+
"cert_password"=>"<%= cert_password %>",
|
23
|
+
"template_path"=>"<%= "#{Rails.root}/data/templates/#{pass_type_id}" %>",
|
24
|
+
"class"=>"<%= class_name %>"
|
25
|
+
}
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class Create<%= class_name.pluralize %> < ActiveRecord::Migration
|
20
|
+
def change
|
21
|
+
create_table :<%= plural_name %> do |t|
|
22
|
+
t.string :serial_number
|
23
|
+
t.string :authentication_token
|
24
|
+
t.string :card_id
|
25
|
+
|
26
|
+
t.timestamps
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class <%= class_name %> < ActiveRecord::Base
|
20
|
+
attr_protected :serial_number, :authentication_token
|
21
|
+
attr_accessible :card_id
|
22
|
+
before_create :set_pass_fields
|
23
|
+
|
24
|
+
def set_pass_fields
|
25
|
+
self.authentication_token = Base64.urlsafe_encode64(SecureRandom.base64(36))
|
26
|
+
self.serial_number||= Base64.urlsafe_encode64(SecureRandom.base64(36))
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.update_or_create params
|
30
|
+
<%= plural_name.singularize %>_pass = find_by_card_id params[:card_id]
|
31
|
+
<%= plural_name.singularize %>_pass ||=new
|
32
|
+
params.slice(*attr_accessible[:default].map(&:to_sym)).each do |attr, val|
|
33
|
+
<%= plural_name.singularize %>_pass.send :"#{attr}=", val
|
34
|
+
end
|
35
|
+
<%= plural_name.singularize %>_pass.save!
|
36
|
+
<%= plural_name.singularize %>_pass
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_for_updates
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_pass pkpass
|
44
|
+
update_json pkpass.json
|
45
|
+
end
|
46
|
+
|
47
|
+
def update_json pass_json
|
48
|
+
pass_json['authenticationToken'] = authentication_token
|
49
|
+
pass_json['serialNumber'] = serial_number
|
50
|
+
#don't forget to change the URL to whatever address your server is at
|
51
|
+
pass_json['webServiceURL'] = "http://192.168.x.x:3000"
|
52
|
+
#add more customization to your passbook's JSON right here
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "<%= pass_type_id %>",
|
4
|
+
"serialNumber" : "12345",
|
5
|
+
"teamIdentifier" : "<%= team_id %>",
|
6
|
+
"webServiceURL" : "http://192.168.91.151:3000",
|
7
|
+
"authenticationToken" : "",
|
8
|
+
"barcode" : {
|
9
|
+
"message" : "34534636",
|
10
|
+
"format" : "PKBarcodeFormatPDF417",
|
11
|
+
"messageEncoding" : "iso-8859-1"
|
12
|
+
},
|
13
|
+
"organizationName" : "ACME Inc.",
|
14
|
+
"description" : "",
|
15
|
+
"logoText" : "ACME",
|
16
|
+
"foregroundColor" : "rgb(22, 55, 110)",
|
17
|
+
"backgroundColor" : "rgb(50, 91, 185)",
|
18
|
+
"coupon" : {
|
19
|
+
"headerFields" : [
|
20
|
+
{
|
21
|
+
"label" : "TEST",
|
22
|
+
"key" : "test",
|
23
|
+
"value" : "#1",
|
24
|
+
"changeMessage" : "Test number changed to %@."
|
25
|
+
}
|
26
|
+
],
|
27
|
+
"primaryFields" : [
|
28
|
+
{
|
29
|
+
"key" : "passbook",
|
30
|
+
"label" : "",
|
31
|
+
"value" : "<%= class_name %>"
|
32
|
+
}
|
33
|
+
],
|
34
|
+
"secondaryFields" : [],
|
35
|
+
"auxiliaryFields" : [],
|
36
|
+
"backFields" : []
|
37
|
+
}
|
38
|
+
}
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
require 'spec_helper'
|
20
|
+
|
21
|
+
describe Passbook::Config do
|
22
|
+
# it "should throw ArgumentError because wwdr_intermediate_certificate_path is missing" do
|
23
|
+
# expect {Passbook::Config.instance.configure {}}.to raise_error(ArgumentError)
|
24
|
+
# end
|
25
|
+
|
26
|
+
it "should throw ArgumentError because cert_path is missing" do
|
27
|
+
expect{ Passbook::Config.instance.add_pkpass do |passbook|
|
28
|
+
passbook.wwdr_intermediate_certificate_path = "test"
|
29
|
+
passbook.wwdr_certificate = OpenSSL::X509::Certificate.new
|
30
|
+
passbook.pass_config["pass.com.acme"] = {"template_path"=>"tmp"}
|
31
|
+
end}.to raise_error(ArgumentError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should throw ArgumentError because cert_password is missing" do
|
35
|
+
expect{ Passbook::Config.instance.add_pkpass do |passbook|
|
36
|
+
passbook.wwdr_intermediate_certificate_path = "test"
|
37
|
+
passbook.wwdr_certificate = OpenSSL::X509::Certificate.new
|
38
|
+
passbook.pass_config["pass.com.acme"] = {
|
39
|
+
"cert_path"=>"tmp"
|
40
|
+
}
|
41
|
+
end}.to raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "pass.com.acme",
|
4
|
+
"serialNumber" : "werwer",
|
5
|
+
"teamIdentifier" : "sdfsdfsdf",
|
6
|
+
"webServiceURL" : "https://acme.com/passes/",
|
7
|
+
"authenticationToken" : "werwfdsfd",
|
8
|
+
"barcode" : {
|
9
|
+
"message" : "",
|
10
|
+
"format" : "PKBarcodeFormatPDF417",
|
11
|
+
"messageEncoding" : "iso-8859-1"
|
12
|
+
},
|
13
|
+
"organizationName" : "Acme",
|
14
|
+
"description" : "test",
|
15
|
+
"logoText" : "test",
|
16
|
+
"foregroundColor" : "rgb(0, 0, 0)",
|
17
|
+
"backgroundColor" : "rgb(0, 0, 0)",
|
18
|
+
"boardingPass" : {
|
19
|
+
"transitType" : "PKTransitTypeAir",
|
20
|
+
"headerFields" : [],
|
21
|
+
"primaryFields" : [],
|
22
|
+
"secondaryFields" : [],
|
23
|
+
"auxiliaryFields" : [],
|
24
|
+
"backFields" : []
|
25
|
+
}
|
26
|
+
}
|
data/spec/pkpass_spec.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
|
2
|
+
# Copyright 2012 Xtreme Labs
|
3
|
+
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
require 'spec_helper'
|
20
|
+
require 'json'
|
21
|
+
|
22
|
+
|
23
|
+
RSpec.configure do |c|
|
24
|
+
c.include Helpers
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Passbook::Pkpass do
|
28
|
+
before :all do
|
29
|
+
Passbook::Config.instance.configure do |passbook|
|
30
|
+
passbook.wwdr_certificate = OpenSSL::X509::Certificate.new
|
31
|
+
passbook.wwdr_intermediate_certificate_path = "#{Dir.pwd}/spec/data/certificates/wwdr.pem"
|
32
|
+
end
|
33
|
+
|
34
|
+
Passbook::Config.instance.add_pkpass do |passbook|
|
35
|
+
template_path = "#{Dir.pwd}/spec/data/templates"
|
36
|
+
cert_path = "#{Dir.pwd}/spec/data/certificates"
|
37
|
+
passbook.pass_config["pass.com.acme"]={
|
38
|
+
"cert_path"=>"#{cert_path}/pass.com.acme.p12",
|
39
|
+
"cert_password"=>"test",
|
40
|
+
"template_path"=>"#{template_path}/pass.com.acme",
|
41
|
+
"p12_certificate"=>create_p12
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
before :each do
|
47
|
+
@pass = Passbook::Pkpass.new("pass.com.acme", "test")
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
it "should throw ArgumentError because there is no config for 'test'" do
|
52
|
+
expect {Passbook::Pkpass.new("test", "test")}.to raise_error(ArgumentError, /configuration for test/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should make an instance of Pkpass" do
|
56
|
+
expect {Passbook::Pkpass.new("pass.com.acme", "test")}.to_not raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should have the added file in zip file" do
|
60
|
+
@pass.add_file "andrei.png", "haha"
|
61
|
+
pkpass_io = @pass.package
|
62
|
+
check_file_in_zip(pkpass_io, "andrei.png").should be_true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should have the added file in zip file(in a folder)" do
|
66
|
+
@pass.add_file "fr.lproj/andrei.png", "haha"
|
67
|
+
pkpass_io = @pass.package
|
68
|
+
check_file_in_zip(pkpass_io, "fr.lproj/andrei.png").should be_true
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should add an entry in the right pass.strings file" do
|
72
|
+
@pass.add_translation_string "yes", "qui", "fr"
|
73
|
+
pass_strings = file_from_zip(@pass.package, "fr.lproj/pass.strings")
|
74
|
+
pass_strings.should_not be_nil
|
75
|
+
pass_strings.should match /\"yes\" = \"qui\";/
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should only append to strings file" do
|
79
|
+
@pass.add_file "fr.lproj/pass.strings", "\"not\" = \"not\";"
|
80
|
+
@pass.add_translation_string "yes", "qui", "fr"
|
81
|
+
pass_strings = file_from_zip(@pass.package, "fr.lproj/pass.strings")
|
82
|
+
pass_strings.should_not be_nil
|
83
|
+
pass_strings.should match /\"not\" = \"not\";/
|
84
|
+
pass_strings.should match /\"yes\" = \"qui\";/
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should include all the files from template_path" do
|
88
|
+
pkpass_io = @pass.package
|
89
|
+
Dir.glob(@pass.config["template_path"]+"/**/**").each do |file|
|
90
|
+
next if File.directory? file
|
91
|
+
filename = Pathname.new(file).relative_path_from(Pathname.new(@pass.config['template_path']))
|
92
|
+
check_file_in_zip(pkpass_io, filename.to_s).should be_true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should include manifest.json" do
|
97
|
+
check_file_in_zip(@pass.package, "manifest.json").should be_true
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should have all the files in manifest.json and none more" do
|
101
|
+
files_json = JSON.parse(file_from_zip(@pass.package, "manifest.json"))
|
102
|
+
Dir.glob(@pass.config["template_path"]+"/**/**").each do |file|
|
103
|
+
next if File.directory? file
|
104
|
+
filename = Pathname.new(file).relative_path_from(Pathname.new(@pass.config['template_path'])).to_s
|
105
|
+
if files_json.include? filename
|
106
|
+
files_json.delete filename
|
107
|
+
else
|
108
|
+
fail
|
109
|
+
end
|
110
|
+
end
|
111
|
+
files_json.should be_empty
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should have a signature" do
|
115
|
+
check_file_in_zip(@pass.package, "signature").should be_true
|
116
|
+
end
|
117
|
+
end
|