passbook 0.2.1 → 0.3.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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2U1MTYxOTRhMDk5YmJmYWRhMDcxNWEyZTU0MjAzMmIyZGU5ZGQ4NA==
5
+ data.tar.gz: !binary |-
6
+ Yzk2Mzk1NzA5OTEzYTNkZTI2ZWM3YTZiYWZkMjBiNjE5ZDhiMzJkZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OWVjYzI2ODJlNTcxNzdiZDcxMDBkOGJmMTdjMzJiNTBhMTJkOTBjZWExZTdm
10
+ ODdhMzkzNGYyOGRhM2VkNGJlNDg3YzBhNTY5NDhlMmM2YjI3ZGNkMWJmYWEy
11
+ OGJhN2E2ZjU4ZTU1YTNlOWUyMzcxYTQ1MDRiNmFhNzk0NjgyNmI=
12
+ data.tar.gz: !binary |-
13
+ ODY0NDc4NWNhZWNhMjFiN2M0NjQwNjA3ODM0ZDlmNzRkYTIzZjdiYmRiNWY5
14
+ NjAyNDE1NGZhMzcxMmQ2OWJiZDk4OGIxNmRjMDdhMzZiMGNlNzk2ZjEzNjM2
15
+ YmE3YjM2OWQxYzM3MDA2MzFjNWJmYzE5YTIwNGY0NjFiYzQ0YmU=
data/Gemfile CHANGED
@@ -1,13 +1,15 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in passbook.gemspec
4
- gem 'rubyzip'
4
+ gem 'rubyzip', '~> 1.0.0'
5
5
  gem 'grocer'
6
+ gem 'commander'
7
+ gem 'terminal-table'
6
8
 
7
9
  group :test, :development do
8
10
  gem 'rack-test'
9
11
  gem 'activesupport'
10
- gem 'jeweler'
12
+ gem 'jeweler', :git => 'git://github.com/foxnewsnetwork/jeweler.git', :branch => 'ruby-2.0.0-ifying'
11
13
  gem 'simplecov'
12
14
  gem 'rspec'
13
15
  gem 'rake'
data/Gemfile.lock CHANGED
@@ -1,41 +1,51 @@
1
- GEM
2
- remote: https://rubygems.org/
1
+ GIT
2
+ remote: git://github.com/foxnewsnetwork/jeweler.git
3
+ revision: f05c62e168cfc29bd82cebe06df8fd11e1ef09ee
4
+ branch: ruby-2.0.0-ifying
3
5
  specs:
4
- activesupport (3.2.8)
5
- i18n (~> 0.6)
6
- multi_json (~> 1.0)
7
- diff-lcs (1.1.3)
8
- git (1.2.5)
9
- grocer (0.3.0)
10
- i18n (0.6.1)
11
6
  jeweler (1.8.4)
12
- bundler (~> 1.0)
7
+ bundler (~> 1.3.0.pre)
13
8
  git (>= 1.2.5)
14
9
  rake
15
10
  rdoc
16
- json (1.7.5)
17
- json (1.7.5-java)
18
- multi_json (1.3.6)
19
- rack (1.4.1)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ activesupport (3.2.14)
16
+ i18n (~> 0.6, >= 0.6.4)
17
+ multi_json (~> 1.0)
18
+ commander (4.1.5)
19
+ highline (~> 1.6.11)
20
+ diff-lcs (1.2.4)
21
+ git (1.2.6)
22
+ grocer (0.4.1)
23
+ highline (1.6.19)
24
+ i18n (0.6.5)
25
+ json (1.8.0)
26
+ json (1.8.0-java)
27
+ multi_json (1.8.0)
28
+ rack (1.5.2)
20
29
  rack-test (0.6.2)
21
30
  rack (>= 1.0)
22
- rake (0.9.2.2)
23
- rdoc (3.12)
31
+ rake (10.1.0)
32
+ rdoc (4.0.1)
24
33
  json (~> 1.4)
25
- rspec (2.11.0)
26
- rspec-core (~> 2.11.0)
27
- rspec-expectations (~> 2.11.0)
28
- rspec-mocks (~> 2.11.0)
29
- rspec-core (2.11.1)
30
- rspec-expectations (2.11.3)
31
- diff-lcs (~> 1.1.3)
32
- rspec-mocks (2.11.3)
33
- rubyzip (0.9.9)
34
+ rspec (2.14.1)
35
+ rspec-core (~> 2.14.0)
36
+ rspec-expectations (~> 2.14.0)
37
+ rspec-mocks (~> 2.14.0)
38
+ rspec-core (2.14.5)
39
+ rspec-expectations (2.14.3)
40
+ diff-lcs (>= 1.1.3, < 2.0)
41
+ rspec-mocks (2.14.3)
42
+ rubyzip (1.0.0)
34
43
  simplecov (0.7.1)
35
44
  multi_json (~> 1.0)
36
45
  simplecov-html (~> 0.7.1)
37
46
  simplecov-html (0.7.1)
38
- yard (0.8.3)
47
+ terminal-table (1.4.5)
48
+ yard (0.8.7.2)
39
49
 
40
50
  PLATFORMS
41
51
  java
@@ -43,11 +53,13 @@ PLATFORMS
43
53
 
44
54
  DEPENDENCIES
45
55
  activesupport
56
+ commander
46
57
  grocer
47
- jeweler
58
+ jeweler!
48
59
  rack-test
49
60
  rake
50
61
  rspec
51
- rubyzip
62
+ rubyzip (~> 1.0.0)
52
63
  simplecov
64
+ terminal-table
53
65
  yard
data/README.md CHANGED
@@ -128,7 +128,7 @@ Your pass will need to have a field called 'webServiceURL' with the base url to
128
128
  ...
129
129
  ```
130
130
 
131
- Passbook-ios includes rack middleware to make the job of supporting the passbook endpoints easier. You will need to configure the middleware as outlined above and then implement a class called Passbook::PassbookNotification. Below is an annotated implementation.
131
+ Passbook includes rack middleware to make the job of supporting the passbook endpoints easier. You will need to configure the middleware as outlined above and then implement a class called Passbook::PassbookNotification. Below is an annotated implementation.
132
132
 
133
133
  ```
134
134
  module Passbook
@@ -144,9 +144,13 @@ module Passbook
144
144
  the_passes_serial_number = options['serialNumber']
145
145
  the_devices_device_library_identifier = options['deviceLibraryIdentifier']
146
146
  the_devices_push_token = options['pushToken']
147
+ the_pass_type_identifier = options["passTypeIdentifier"]
148
+ the_authentication_token = options['authToken']
147
149
 
148
150
  # this is if the pass registered successfully
149
151
  # change the code to 200 if the pass has already been registered
152
+ # 404 if pass not found for serialNubmer and passTypeIdentifier
153
+ # 401 if authorization failed
150
154
  # or another appropriate code if something went wrong.
151
155
  {:status => 201}
152
156
  end
@@ -157,6 +161,7 @@ module Passbook
157
161
 
158
162
  def self.passes_for_device(options)
159
163
  device_library_identifier = options['deviceLibraryIdentifier']
164
+ passes_updated_since = options['passesUpdatedSince']
160
165
 
161
166
  # the 'lastUpdated' uses integers values to tell passbook if the pass is
162
167
  # more recent than the current one. If you just set it is the same value
@@ -171,6 +176,8 @@ module Passbook
171
176
  # a solid unique pair of identifiers to identify the pass are
172
177
  serial_number = options['serialNumber']
173
178
  device_library_identifier = options['deviceLibraryIdentifier']
179
+ the_pass_type_identifier = options["passTypeIdentifier"]
180
+ the_authentication_token = options['authToken']
174
181
  # return a status 200 to indicate that the pass was successfully unregistered.
175
182
  {:status => 200}
176
183
  end
@@ -187,7 +194,7 @@ module Passbook
187
194
 
188
195
  # This is called whenever there is something from the update process that is a warning
189
196
  # or error
190
- def self.log(log)
197
+ def self.passbook_log(log)
191
198
  # this is a VERY crude logging example. use the logger of your choice here.
192
199
  p "#{Time.now} #{log}"
193
200
  end
data/Rakefile CHANGED
@@ -19,6 +19,7 @@ Jeweler::Tasks.new do |gem|
19
19
  gem.description = %Q{This gem allows you to create IOS Passbooks. Unlike some, this works with Rails but does not require it.}
20
20
  gem.email = ['thomas@lauro.fr', 'lgleason@polyglotprogramminginc.com']
21
21
  gem.authors = ['Thomas Lauro', 'Lance Gleason']
22
+ gem.executables = ['pk']
22
23
  # dependencies defined in Gemfile
23
24
  end
24
25
  Jeweler::RubygemsDotOrgTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.3.1
data/bin/pk ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'commander/import'
4
+ require 'terminal-table'
5
+
6
+ $:.push File.expand_path("../../lib", __FILE__)
7
+ require 'passbook'
8
+ require 'utils/command_utils'
9
+
10
+ HighLine.track_eof = false # Fix for built-in Ruby
11
+ Signal.trap("INT") {} # Suppress backtrace when exiting command
12
+
13
+ program :version, '0.1'
14
+ program :description, 'A command-line interface for generating and previewing passbook passes'
15
+
16
+ program :help, 'Author', 'Thomas Lauro <>, Lance Gleason <lgleason@polyglotprogramminginc.com>'
17
+ program :help, 'Website', 'https://github.com/frozon/passbook'
18
+ program :help_formatter, :compact
19
+
20
+ default_command :help
21
+
22
+ require 'commands/commands'
@@ -0,0 +1,62 @@
1
+ command :build do |c|
2
+ c.syntax = 'pk build [PASSNAME]'
3
+ c.summary = 'Creates a .pkpass archive'
4
+ c.description = ''
5
+
6
+ c.example 'description', 'pk archive mypass -o mypass.pkpass'
7
+ c.option '-w', '--wwdc_certificate /path/to/wwdc_cert.pem', 'Pass certificate'
8
+ c.option '-k', '--p12_key /path/to/cert.p12'
9
+ c.option '-c', '--p12_certificate /path/to/cert.p12'
10
+ c.option '-p', '--password password', 'certificate password'
11
+ c.option '-o', '--output /path/to/out.pkpass', '.pkpass output filepath'
12
+
13
+ c.action do |args, options|
14
+ determine_directory! unless @directory = args.first
15
+ validate_directory!
16
+
17
+ @filepath = options.output || "#{@directory}.pkpass"
18
+ validate_output_filepath!
19
+
20
+ @certificate = options.wwdc_certificate
21
+ validate_certificate!
22
+
23
+ @password = (options.password ? options.password : (ask("Enter certificate password:"){|q| q.echo = false}))
24
+
25
+ Passbook.configure do |passbook|
26
+ passbook.wwdc_cert = @certificate
27
+ passbook.p12_key = options.p12_key
28
+ passbook.p12_certificate = options.p12_certificate
29
+ passbook.p12_password = @password
30
+ end
31
+
32
+ assets = CommandUtils.get_assets @directory
33
+ pass_json = File.read(assets.delete(assets.detect{|file| File.basename(file) == 'pass.json'}))
34
+ pass = Passbook::PKPass.new(pass_json)
35
+ pass.addFiles assets
36
+
37
+ begin
38
+ pass_stream = pass.stream
39
+ pass_string = pass_stream.string
40
+
41
+ File.open(@filepath, 'w') do |f|
42
+ f.write pass_string
43
+ end
44
+ rescue OpenSSL::PKCS12::PKCS12Error => error
45
+ say_error "Error: #{error.message}"
46
+ say_warning "You may be getting this error because the certificate password is either incorrect or missing"
47
+ abort
48
+ rescue => error
49
+ say_error "Error: #{error.message}" and abort
50
+ end
51
+ end
52
+ end
53
+
54
+ alias_command :archive, :build
55
+ alias_command :b, :build
56
+
57
+ private
58
+
59
+ def validate_output_filepath!
60
+ say_error "Filepath required" and abort if @filepath.nil? or @filepath.empty?
61
+ say_error "#{@filepath} already exists" and abort if File.exist?(@filepath)
62
+ end
@@ -0,0 +1,31 @@
1
+ $:.push File.expand_path('../', __FILE__)
2
+
3
+ require 'commands/build'
4
+ require 'commands/generate'
5
+ #require 'commands/serve'
6
+ # this was added for testability because I couldn't figure out something better.
7
+
8
+ private
9
+
10
+ def determine_directory!
11
+ files = Dir['*/pass.json']
12
+ @directory ||= case files.length
13
+ when 0 then nil
14
+ when 1 then File.dirname(files.first)
15
+ else
16
+ @directory = choose "Select a directory:", *files.collect{|f| File.dirname(f)}
17
+ end
18
+ end
19
+
20
+ def validate_directory!
21
+ say_error "Missing argument" and abort if @directory.nil?
22
+ say_error "Directory #{@directory} does not exist" and abort unless File.directory?(@directory)
23
+ say_error "Directory #{@directory} is not a valid pass" and abort unless File.exist?(File.join(@directory, "pass.json"))
24
+ end
25
+
26
+ def validate_certificate!
27
+ say_error "Missing or invalid certificate file" and abort if @certificate.nil? or not File.exist?(@certificate)
28
+ end
29
+
30
+
31
+
@@ -0,0 +1,44 @@
1
+ require 'fileutils'
2
+
3
+ command :generate do |c|
4
+ c.syntax = 'pk generate PASSNAME'
5
+ c.summary = 'Generates a template pass directory'
6
+ c.description = ''
7
+
8
+ c.example 'description', 'pk generate mypass'
9
+ c.option '-T', '--type [boardingPass|coupon|eventTicket|storeCard|generic]', 'Type of pass'
10
+
11
+ c.action do |args, options|
12
+ @directory = args.first
13
+ @directory ||= ask "Enter a passbook name: "
14
+ say_error "Missing pass name" and abort if @directory.nil? or @directory.empty?
15
+ say_error "Directory #{@directory} already exists" and abort if File.directory?(@directory)
16
+ say_error "File exists at #{@directory}" and abort if File.exist?(@directory)
17
+
18
+ @type = options.type
19
+ determine_type! unless @type
20
+ validate_type!
21
+
22
+ FileUtils.mkdir_p @directory
23
+ FileUtils.cp File.join(CommandUtils.get_current_directory, '..', 'commands/templates', "#{@type}.json"), File.join(@directory, 'pass.json')
24
+ ['icon.png', 'icon@2x.png'].each do |file|
25
+ FileUtils.touch File.join(@directory, file)
26
+ end
27
+
28
+ say_ok "Pass generated in #{@directory}"
29
+ end
30
+ end
31
+
32
+ alias_command :new, :generate
33
+ alias_command :g, :generate
34
+
35
+ private
36
+
37
+ def determine_type!
38
+ @type ||= choose "Select a pass type", *Passbook::PKPass::TYPES
39
+ end
40
+
41
+ def validate_type!
42
+ say_error %{Invalid type: "#{@type}", expected one of: [#{Passbook::PKPass::TYPES.join(', ')}]} and abort unless Passbook::PKPass::TYPES.include?(@type)
43
+ end
44
+
@@ -0,0 +1,56 @@
1
+ {
2
+ "formatVersion" : 1,
3
+ "passTypeIdentifier" : "pass.com.example.boarding-pass",
4
+ "description" : "Example Boarding Pass",
5
+ "teamIdentifier": "Example",
6
+ "organizationName": "Example",
7
+ "serialNumber" : "123456",
8
+ "foregroundColor": "#866B23",
9
+ "backgroundColor": "#FFD248",
10
+ "boardingPass" : {
11
+ "primaryFields" : [
12
+ {
13
+ "key" : "origin",
14
+ "label" : "Atlanta",
15
+ "value" : "ATL"
16
+ },
17
+ {
18
+ "key" : "destination",
19
+ "label" : "Johannesburg",
20
+ "value" : "JNB"
21
+ }
22
+ ],
23
+ "secondaryFields" : [
24
+ {
25
+ "key" : "boarding-gate",
26
+ "label" : "Gate",
27
+ "value" : "F12"
28
+ }
29
+ ],
30
+ "auxiliaryFields" : [
31
+ {
32
+ "key" : "seat",
33
+ "label" : "Seat",
34
+ "value" : "7A"
35
+ },
36
+ {
37
+ "key" : "passenger-name",
38
+ "label" : "Passenger",
39
+ "value" : "Honey Badger"
40
+ }
41
+ ],
42
+ "transitType" : "PKTransitTypeAir",
43
+ "barcode" : {
44
+ "message" : "DL123",
45
+ "format" : "PKBarcodeFormatQR",
46
+ "messageEncoding" : "iso-8859-1"
47
+ },
48
+ "backFields" : [
49
+ {
50
+ "key" : "terms",
51
+ "label" : "Terms and Conditions",
52
+ "value" : "Valid for date of travel only"
53
+ }
54
+ ]
55
+ }
56
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "formatVersion" : 1,
3
+ "passTypeIdentifier" : "pass.com.example.coupon",
4
+ "description" : "Example Coupon",
5
+ "teamIdentifier": "Example",
6
+ "organizationName": "Example",
7
+ "serialNumber" : "123456",
8
+ "foregroundColor": "#FFFFFF",
9
+ "backgroundColor": "#C799FF",
10
+ "generic" : {
11
+ "primaryFields" : [
12
+
13
+ ],
14
+ "secondaryFields" : [
15
+
16
+ ],
17
+ "auxiliaryFields" : [
18
+
19
+ ],
20
+ "barcode" : {
21
+ "message" : "ABCD 123 EFGH 456 IJKL 789 MNOP",
22
+ "format" : "PKBarcodeFormatPDF417",
23
+ "messageEncoding" : "iso-8859-1"
24
+ },
25
+ "backFields" : [
26
+ {
27
+ "key" : "terms",
28
+ "label" : "Terms and Conditions",
29
+ "value" : "T's and C's Apply"
30
+ }
31
+ ]
32
+ }
33
+ }