passkit 0.8.2 → 0.9.0
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +5 -0
- data/app/controllers/concerns/passkit/pass_delivery.rb +15 -0
- data/app/controllers/passkit/api/v1/passes_controller.rb +22 -11
- data/app/controllers/passkit/dashboard/previews_controller.rb +3 -1
- data/lib/passkit/generator.rb +15 -12
- data/lib/passkit/version.rb +1 -1
- metadata +6 -23
- data/.env.test +0 -8
- data/.example.env +0 -8
- data/.semaphore/release.yml +0 -21
- data/.semaphore/semaphore.yml +0 -42
- data/.standard.yml +0 -2
- data/Gemfile +0 -12
- data/Rakefile +0 -20
- data/bin/console +0 -15
- data/bin/generate_test_certificates +0 -55
- data/bin/setup +0 -8
- data/docs/membership.png +0 -0
- data/docs/passkit_environment_variables.md +0 -53
- data/docs/step1.png +0 -0
- data/docs/step2.png +0 -0
- data/docs/step3.png +0 -0
- data/docs/step4.png +0 -0
- data/docs/step5.png +0 -0
- data/docs/wallet.png +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b483356d4bcfb7898d15381b4ac43899fbc8b147965e6579110c562a19bf0a21
|
|
4
|
+
data.tar.gz: d529619e1ebdd0ae04943b0fe07f1bc0c43df6f976218ed8c472ad50da1dcf99
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bee3e475d2beaed1f9305613893c9aee7cf9cbfee86e9ae95f46348f0d0e0a13f82b9428147f5132f5793d07c551b892104f3f9fac7478d50924183e03c344cb
|
|
7
|
+
data.tar.gz: 8e614ada638617a10ac3ff807f842e5ceef98d17048a283571809562872cd256ac2de7a05ae9f154eb6e8baf4874c50d03692f73d0719dc41d5d6aedd2932ca0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [0.9.0]
|
|
2
|
+
- [#50](https://github.com/coorasse/passkit/pull/50): **Breaking:** require rubyzip 3.4 or later, which fixes CVE-2026-85396, and Ruby 3.2 or later.
|
|
3
|
+
- [#47](https://github.com/coorasse/passkit/pull/47): Remove the generator's working directory once the `.pkpass` is built, and delete generated archives after sending them, so `tmp/passkit` no longer grows with every download.
|
|
4
|
+
- [#48](https://github.com/coorasse/passkit/pull/48): Answer `304 Not Modified` before generating and signing the pass when `If-Modified-Since` shows the device already has the current version.
|
|
5
|
+
|
|
6
|
+
## [0.8.3]
|
|
7
|
+
- Exclude development and test files from the packaged gem.
|
|
8
|
+
|
|
1
9
|
## [0.8.2]
|
|
2
10
|
- Set up the Semaphore CI pipeline with a manual promotion to release the gem.
|
|
3
11
|
- Self-signed certificates for the test suite, so it runs without an Apple Developer certificate.
|
data/README.md
CHANGED
|
@@ -173,6 +173,11 @@ Passkit::UrlGenerator.new(Passkit::UserTicket, User.find(1), :tickets)
|
|
|
173
173
|
and then use `.android` or `.ios` to get the URL to serve the Wallet Pass.
|
|
174
174
|
Again, check the example mailer included in the gem to see how to use it.
|
|
175
175
|
|
|
176
|
+
If you generate passes yourself with `Passkit::Factory.create_pass` or `Passkit::Generator#generate_and_sign`
|
|
177
|
+
instead of going through the bundled controllers, note that the returned `.pkpass` lives in `tmp/passkit`.
|
|
178
|
+
The bundled controllers delete it once it has been sent; if you serve it yourself, do the same, otherwise the
|
|
179
|
+
folder grows by one archive per download.
|
|
180
|
+
|
|
176
181
|
## Debug issues
|
|
177
182
|
|
|
178
183
|
* On Mac, you can open the *.pkpass files with "Pass Viewer". Open the `Console.app` to log possible error messages and filter by "Pass Viewer" process.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Passkit
|
|
2
|
+
# Passes are generated into tmp/passkit. Send the archive's contents and
|
|
3
|
+
# delete the file, so the folder does not grow by one archive per download.
|
|
4
|
+
module PassDelivery
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def send_pass_file(path, type:, filename: File.basename(path))
|
|
10
|
+
send_data File.binread(path), type: type, disposition: "attachment", filename: filename
|
|
11
|
+
ensure
|
|
12
|
+
FileUtils.rm_f(path)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -2,6 +2,8 @@ module Passkit
|
|
|
2
2
|
module Api
|
|
3
3
|
module V1
|
|
4
4
|
class PassesController < ActionController::API
|
|
5
|
+
include Passkit::PassDelivery
|
|
6
|
+
|
|
5
7
|
before_action :decrypt_payload, only: :create
|
|
6
8
|
|
|
7
9
|
def create
|
|
@@ -11,11 +13,15 @@ module Passkit
|
|
|
11
13
|
files = @generator.public_send(@payload[:collection_name]).collect do |collection_item|
|
|
12
14
|
Passkit::Factory.create_pass(@payload[:pass_class], collection_item)
|
|
13
15
|
end
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
begin
|
|
17
|
+
bundle = Passkit::Generator.compress_passes_files(files)
|
|
18
|
+
ensure
|
|
19
|
+
files.each { |file| FileUtils.rm_f(file) }
|
|
20
|
+
end
|
|
21
|
+
send_pass_file(bundle, type: "application/vnd.apple.pkpasses")
|
|
16
22
|
else
|
|
17
23
|
file = Passkit::Factory.create_pass(@payload[:pass_class], @generator)
|
|
18
|
-
|
|
24
|
+
send_pass_file(file, type: "application/vnd.apple.pkpass")
|
|
19
25
|
end
|
|
20
26
|
end
|
|
21
27
|
|
|
@@ -35,19 +41,24 @@ module Passkit
|
|
|
35
41
|
return
|
|
36
42
|
end
|
|
37
43
|
|
|
38
|
-
pass_output_path = Passkit::Generator.new(pass).generate_and_sign
|
|
39
|
-
|
|
40
44
|
response.headers["last-modified"] = pass.last_update.httpdate
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
head :not_modified
|
|
46
|
-
end
|
|
45
|
+
return head :not_modified unless pass_modified_since?(pass, request.headers["If-Modified-Since"])
|
|
46
|
+
|
|
47
|
+
pass_output_path = Passkit::Generator.new(pass).generate_and_sign
|
|
48
|
+
send_pass_file(pass_output_path, type: "application/vnd.apple.pkpass")
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
private
|
|
50
52
|
|
|
53
|
+
# Wallet sends back the Last-Modified it received with the previous
|
|
54
|
+
# download. When the pass has not changed since, there is nothing to
|
|
55
|
+
# generate or sign.
|
|
56
|
+
def pass_modified_since?(pass, if_modified_since)
|
|
57
|
+
return true if if_modified_since.nil?
|
|
58
|
+
|
|
59
|
+
pass.last_update.to_i > Time.zone.parse(if_modified_since).to_i
|
|
60
|
+
end
|
|
61
|
+
|
|
51
62
|
def decrypt_payload
|
|
52
63
|
@payload = Passkit::UrlEncrypt.decrypt(params[:payload])
|
|
53
64
|
if DateTime.parse(@payload[:valid_until]).past?
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Passkit
|
|
2
2
|
module Dashboard
|
|
3
3
|
class PreviewsController < ApplicationController
|
|
4
|
+
include Passkit::PassDelivery
|
|
5
|
+
|
|
4
6
|
def index
|
|
5
7
|
end
|
|
6
8
|
|
|
@@ -8,7 +10,7 @@ module Passkit
|
|
|
8
10
|
builder = Passkit.configuration.available_passes[params[:class_name]]
|
|
9
11
|
path = Factory.create_pass(params[:class_name].constantize, builder.call)
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
send_pass_file path, type: "application/vnd.apple.pkpass", filename: "pass.pkpass"
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
end
|
data/lib/passkit/generator.rb
CHANGED
|
@@ -21,17 +21,15 @@ module Passkit
|
|
|
21
21
|
generate_json_manifest
|
|
22
22
|
sign_manifest
|
|
23
23
|
compress_pass_file
|
|
24
|
+
ensure
|
|
25
|
+
remove_temporary_directory
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def self.compress_passes_files(files)
|
|
27
29
|
zip_path = TMP_FOLDER.join("#{SecureRandom.uuid}.pkpasses")
|
|
28
|
-
zipped_file = File.open(zip_path, "w")
|
|
29
30
|
|
|
30
|
-
Zip::
|
|
31
|
-
files.each
|
|
32
|
-
z.put_next_entry(File.basename(file))
|
|
33
|
-
z.print File.read(file)
|
|
34
|
-
end
|
|
31
|
+
Zip::File.open(zip_path, create: true) do |zip|
|
|
32
|
+
files.each { |file| zip.add(File.basename(file), file) }
|
|
35
33
|
end
|
|
36
34
|
zip_path
|
|
37
35
|
end
|
|
@@ -49,6 +47,12 @@ module Passkit
|
|
|
49
47
|
FileUtils.rm_rf(@temporary_path) if File.directory?(@temporary_path)
|
|
50
48
|
end
|
|
51
49
|
|
|
50
|
+
# Only the .pkpass is returned to the caller; the unpacked files it was
|
|
51
|
+
# built from have no further use once it exists.
|
|
52
|
+
def remove_temporary_directory
|
|
53
|
+
FileUtils.rm_rf(@temporary_path) if @temporary_path
|
|
54
|
+
end
|
|
55
|
+
|
|
52
56
|
def copy_pass_to_tmp_location
|
|
53
57
|
FileUtils.cp_r(@pass.pass_path, @temporary_path)
|
|
54
58
|
end
|
|
@@ -148,13 +152,12 @@ module Passkit
|
|
|
148
152
|
|
|
149
153
|
def compress_pass_file
|
|
150
154
|
zip_path = TMP_FOLDER.join("#{@pass.file_name}.pkpass")
|
|
151
|
-
|
|
155
|
+
FileUtils.rm_f(zip_path)
|
|
152
156
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
end
|
|
157
|
+
# Entries added from files have a known size, so rubyzip writes a plain zip without the Zip64 extra fields
|
|
158
|
+
# it adds to streamed entries since 3.0.
|
|
159
|
+
Zip::File.open(zip_path, create: true) do |zip|
|
|
160
|
+
Dir.glob(@temporary_path.join("**")).each { |file| zip.add(File.basename(file), file) }
|
|
158
161
|
end
|
|
159
162
|
zip_path
|
|
160
163
|
end
|
data/lib/passkit/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: passkit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alessandro Rodi
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '3.4'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '3.4'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: sqlite3
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -143,17 +143,10 @@ executables: []
|
|
|
143
143
|
extensions: []
|
|
144
144
|
extra_rdoc_files: []
|
|
145
145
|
files:
|
|
146
|
-
- ".env.test"
|
|
147
|
-
- ".example.env"
|
|
148
|
-
- ".semaphore/release.yml"
|
|
149
|
-
- ".semaphore/semaphore.yml"
|
|
150
|
-
- ".standard.yml"
|
|
151
146
|
- CHANGELOG.md
|
|
152
147
|
- CODE_OF_CONDUCT.md
|
|
153
|
-
- Gemfile
|
|
154
148
|
- LICENSE.txt
|
|
155
149
|
- README.md
|
|
156
|
-
- Rakefile
|
|
157
150
|
- app/assets/config/passkit_manifest.js
|
|
158
151
|
- app/assets/images/passkit/add_to_apple_wallet_de.png
|
|
159
152
|
- app/assets/images/passkit/add_to_apple_wallet_en.png
|
|
@@ -163,6 +156,7 @@ files:
|
|
|
163
156
|
- app/assets/images/passkit/add_to_walletpass_en.png
|
|
164
157
|
- app/assets/images/passkit/add_to_walletpass_fr.png
|
|
165
158
|
- app/assets/images/passkit/add_to_walletpass_it.png
|
|
159
|
+
- app/controllers/concerns/passkit/pass_delivery.rb
|
|
166
160
|
- app/controllers/passkit/api/v1/logs_controller.rb
|
|
167
161
|
- app/controllers/passkit/api/v1/passes_controller.rb
|
|
168
162
|
- app/controllers/passkit/api/v1/registrations_controller.rb
|
|
@@ -181,18 +175,7 @@ files:
|
|
|
181
175
|
- app/views/passkit/dashboard/previews/index.html.erb
|
|
182
176
|
- app/views/passkit/example_mailer/example_email.html.erb
|
|
183
177
|
- app/views/shared/passkit/_navigation.html.erb
|
|
184
|
-
- bin/console
|
|
185
|
-
- bin/generate_test_certificates
|
|
186
|
-
- bin/setup
|
|
187
178
|
- config/routes.rb
|
|
188
|
-
- docs/membership.png
|
|
189
|
-
- docs/passkit_environment_variables.md
|
|
190
|
-
- docs/step1.png
|
|
191
|
-
- docs/step2.png
|
|
192
|
-
- docs/step3.png
|
|
193
|
-
- docs/step4.png
|
|
194
|
-
- docs/step5.png
|
|
195
|
-
- docs/wallet.png
|
|
196
179
|
- lib/generators/passkit/install_generator.rb
|
|
197
180
|
- lib/generators/templates/create_passkit_tables.rb.tt
|
|
198
181
|
- lib/generators/templates/passkit.rb
|
|
@@ -232,14 +215,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
232
215
|
requirements:
|
|
233
216
|
- - ">="
|
|
234
217
|
- !ruby/object:Gem::Version
|
|
235
|
-
version: 2.
|
|
218
|
+
version: 3.2.0
|
|
236
219
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
220
|
requirements:
|
|
238
221
|
- - ">="
|
|
239
222
|
- !ruby/object:Gem::Version
|
|
240
223
|
version: '0'
|
|
241
224
|
requirements: []
|
|
242
|
-
rubygems_version: 4.0.
|
|
225
|
+
rubygems_version: 4.0.17
|
|
243
226
|
specification_version: 4
|
|
244
227
|
summary: Serve Wallet Passes for iOS and Android directly from your Rails app
|
|
245
228
|
test_files: []
|
data/.env.test
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
PASSKIT_WEB_SERVICE_HOST=https://localhost:3000
|
|
2
|
-
PASSKIT_CERTIFICATE_KEY=passkit
|
|
3
|
-
PASSKIT_PRIVATE_P12_CERTIFICATE=certificates/certificate.p12
|
|
4
|
-
PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE=certificates/intermediate.cer
|
|
5
|
-
PASSKIT_APPLE_TEAM_IDENTIFIER=XXXXXXXXXX
|
|
6
|
-
PASSKIT_PASS_TYPE_IDENTIFIER=pass.com.example.pass
|
|
7
|
-
PASSKIT_DASHBOARD_USERNAME=admin
|
|
8
|
-
PASSKIT_DASHBOARD_PASSWORD=admin
|
data/.example.env
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
PASSKIT_WEB_SERVICE_HOST=https://localhost:3000
|
|
2
|
-
PASSKIT_CERTIFICATE_KEY=theCertPassword
|
|
3
|
-
PASSKIT_PRIVATE_P12_CERTIFICATE=path/to/certificate.p12
|
|
4
|
-
PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE=path/to/AppleWWDRCA.cer
|
|
5
|
-
PASSKIT_APPLE_TEAM_IDENTIFIER=XXXXXXXXXX
|
|
6
|
-
PASSKIT_PASS_TYPE_IDENTIFIER=pass.com.example.pass
|
|
7
|
-
PASSKIT_DASHBOARD_USERNAME=admin
|
|
8
|
-
PASSKIT_DASHBOARD_PASSWORD=admin
|
data/.semaphore/release.yml
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
version: "v1.0"
|
|
2
|
-
name: Release gem
|
|
3
|
-
agent:
|
|
4
|
-
machine:
|
|
5
|
-
type: f1-standard-2
|
|
6
|
-
os_image: ubuntu2204
|
|
7
|
-
|
|
8
|
-
blocks:
|
|
9
|
-
- name: publish
|
|
10
|
-
execution_time_limit:
|
|
11
|
-
minutes: 10
|
|
12
|
-
task:
|
|
13
|
-
secrets:
|
|
14
|
-
- name: rubygems
|
|
15
|
-
jobs:
|
|
16
|
-
- name: build and push to rubygems.org
|
|
17
|
-
commands:
|
|
18
|
-
- checkout
|
|
19
|
-
- sem-version ruby 3.3
|
|
20
|
-
- gem build passkit.gemspec
|
|
21
|
-
- gem push passkit-*.gem < /dev/null
|
data/.semaphore/semaphore.yml
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
version: "v1.0"
|
|
2
|
-
name: passkit
|
|
3
|
-
agent:
|
|
4
|
-
machine:
|
|
5
|
-
type: f1-standard-2
|
|
6
|
-
os_image: ubuntu2204
|
|
7
|
-
auto_cancel:
|
|
8
|
-
running:
|
|
9
|
-
when: "true"
|
|
10
|
-
|
|
11
|
-
blocks:
|
|
12
|
-
- name: tests
|
|
13
|
-
execution_time_limit:
|
|
14
|
-
minutes: 10
|
|
15
|
-
task:
|
|
16
|
-
env_vars:
|
|
17
|
-
- name: RAILS_ENV
|
|
18
|
-
value: test
|
|
19
|
-
- name: BUNDLE_PATH
|
|
20
|
-
value: vendor/bundle
|
|
21
|
-
prologue:
|
|
22
|
-
commands:
|
|
23
|
-
- checkout --use-cache
|
|
24
|
-
- sem-version ruby 3.3
|
|
25
|
-
- cache restore gems-$(checksum passkit.gemspec)-$(checksum Gemfile)
|
|
26
|
-
- bundle install -j 4
|
|
27
|
-
- cache store gems-$(checksum passkit.gemspec)-$(checksum Gemfile) vendor/bundle
|
|
28
|
-
- bin/generate_test_certificates
|
|
29
|
-
jobs:
|
|
30
|
-
- name: linter
|
|
31
|
-
commands:
|
|
32
|
-
- bundle exec standardrb
|
|
33
|
-
- name: tests
|
|
34
|
-
commands:
|
|
35
|
-
- bundle exec rake test
|
|
36
|
-
- name: system tests
|
|
37
|
-
commands:
|
|
38
|
-
- bundle exec rake test:system
|
|
39
|
-
|
|
40
|
-
promotions:
|
|
41
|
-
- name: Release gem
|
|
42
|
-
pipeline_file: release.yml
|
data/.standard.yml
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "bundler/gem_tasks"
|
|
4
|
-
require "rake/testtask"
|
|
5
|
-
|
|
6
|
-
Rake::TestTask.new(:test) do |t|
|
|
7
|
-
t.libs << "test"
|
|
8
|
-
t.libs << "lib"
|
|
9
|
-
t.test_files = FileList["test/**/test_*.rb"]
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
Rake::TestTask.new("test:system") do |t|
|
|
13
|
-
t.libs << "test"
|
|
14
|
-
t.libs << "lib"
|
|
15
|
-
t.test_files = FileList["test/system/**/*_test.rb"]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
require "standard/rake"
|
|
19
|
-
|
|
20
|
-
task default: %i[test standard]
|
data/bin/console
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "bundler/setup"
|
|
5
|
-
require "passkit"
|
|
6
|
-
|
|
7
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
-
|
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
-
# require "pry"
|
|
12
|
-
# Pry.start
|
|
13
|
-
|
|
14
|
-
require "irb"
|
|
15
|
-
IRB.start(__FILE__)
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Generates a self-signed pass certificate and a fake "Apple intermediate"
|
|
5
|
-
# certificate, so that the test suite can sign passes without a real Apple
|
|
6
|
-
# Developer certificate.
|
|
7
|
-
|
|
8
|
-
require "openssl"
|
|
9
|
-
require "fileutils"
|
|
10
|
-
|
|
11
|
-
output_directory = File.expand_path("../test/dummy/certificates", __dir__)
|
|
12
|
-
password = ENV.fetch("PASSKIT_CERTIFICATE_KEY", "passkit")
|
|
13
|
-
|
|
14
|
-
FileUtils.mkdir_p(output_directory)
|
|
15
|
-
|
|
16
|
-
intermediate_key = OpenSSL::PKey::RSA.new(2048)
|
|
17
|
-
intermediate_certificate = OpenSSL::X509::Certificate.new
|
|
18
|
-
intermediate_certificate.version = 2
|
|
19
|
-
intermediate_certificate.serial = 1
|
|
20
|
-
intermediate_certificate.subject = OpenSSL::X509::Name.parse("/CN=Passkit Test Intermediate CA")
|
|
21
|
-
intermediate_certificate.issuer = intermediate_certificate.subject
|
|
22
|
-
intermediate_certificate.public_key = intermediate_key.public_key
|
|
23
|
-
intermediate_certificate.not_before = Time.now - 60
|
|
24
|
-
intermediate_certificate.not_after = Time.now + (10 * 365 * 24 * 60 * 60)
|
|
25
|
-
|
|
26
|
-
extension_factory = OpenSSL::X509::ExtensionFactory.new
|
|
27
|
-
extension_factory.subject_certificate = intermediate_certificate
|
|
28
|
-
extension_factory.issuer_certificate = intermediate_certificate
|
|
29
|
-
intermediate_certificate.add_extension(extension_factory.create_extension("basicConstraints", "CA:TRUE", true))
|
|
30
|
-
intermediate_certificate.add_extension(extension_factory.create_extension("keyUsage", "keyCertSign, cRLSign", true))
|
|
31
|
-
intermediate_certificate.sign(intermediate_key, OpenSSL::Digest.new("SHA256"))
|
|
32
|
-
|
|
33
|
-
pass_key = OpenSSL::PKey::RSA.new(2048)
|
|
34
|
-
pass_certificate = OpenSSL::X509::Certificate.new
|
|
35
|
-
pass_certificate.version = 2
|
|
36
|
-
pass_certificate.serial = 2
|
|
37
|
-
pass_certificate.subject = OpenSSL::X509::Name.parse("/CN=#{ENV.fetch("PASSKIT_PASS_TYPE_IDENTIFIER", "pass.com.example.pass")}")
|
|
38
|
-
pass_certificate.issuer = intermediate_certificate.subject
|
|
39
|
-
pass_certificate.public_key = pass_key.public_key
|
|
40
|
-
pass_certificate.not_before = Time.now - 60
|
|
41
|
-
pass_certificate.not_after = Time.now + (10 * 365 * 24 * 60 * 60)
|
|
42
|
-
|
|
43
|
-
extension_factory = OpenSSL::X509::ExtensionFactory.new
|
|
44
|
-
extension_factory.subject_certificate = pass_certificate
|
|
45
|
-
extension_factory.issuer_certificate = intermediate_certificate
|
|
46
|
-
pass_certificate.add_extension(extension_factory.create_extension("basicConstraints", "CA:FALSE", true))
|
|
47
|
-
pass_certificate.add_extension(extension_factory.create_extension("keyUsage", "digitalSignature", true))
|
|
48
|
-
pass_certificate.sign(intermediate_key, OpenSSL::Digest.new("SHA256"))
|
|
49
|
-
|
|
50
|
-
p12 = OpenSSL::PKCS12.create(password, "Passkit Test Certificate", pass_key, pass_certificate)
|
|
51
|
-
|
|
52
|
-
File.binwrite(File.join(output_directory, "intermediate.cer"), intermediate_certificate.to_der)
|
|
53
|
-
File.binwrite(File.join(output_directory, "certificate.p12"), p12.to_der)
|
|
54
|
-
|
|
55
|
-
puts "Certificates written to #{output_directory}"
|
data/bin/setup
DELETED
data/docs/membership.png
DELETED
|
Binary file
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# Setup Passkit Environment variables
|
|
2
|
-
|
|
3
|
-
### `PASSKIT_WEB_SERVICE_HOST`
|
|
4
|
-
|
|
5
|
-
This is the host where your Rails app is running. It is used to generate the URLs for the passes.
|
|
6
|
-
When the device wants to update the Pass, it will invoke services on this host.
|
|
7
|
-
In production, it will simply be your domain name, but in development you can use [ngrok](https://ngrok.com/) to expose your local server to the internet.
|
|
8
|
-
|
|
9
|
-
**Remember that it must always start with `https://`.**
|
|
10
|
-
|
|
11
|
-
### `PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE`
|
|
12
|
-
|
|
13
|
-
This is the easy one.
|
|
14
|
-
Head to https://www.apple.com/certificateauthority/ and download the latest Apple Intermediate Certificate Worldwide Developer Relations.
|
|
15
|
-
You might want to choose the one with the longest expiration date. PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE is the path to the certificate.
|
|
16
|
-
|
|
17
|
-
### `PASSKIT_APPLE_TEAM_IDENTIFIER`
|
|
18
|
-
|
|
19
|
-
You find this in your Apple Developer dashboard, under Membership.
|
|
20
|
-
|
|
21
|
-

|
|
22
|
-
|
|
23
|
-
### `PASSKIT_PASS_TYPE_IDENTIFIER`, `PASSKIT_PRIVATE_P12_CERTIFICATE` and `PASSKIT_CERTIFICATE_KEY`
|
|
24
|
-
|
|
25
|
-
Head to your Apple Developers console and generate a new certificate.
|
|
26
|
-
|
|
27
|
-

|
|
28
|
-
|
|
29
|
-

|
|
30
|
-
|
|
31
|
-

|
|
32
|
-
|
|
33
|
-
The identifier is the `PASSKIT_PASS_TYPE_IDENTIFIER` variable.
|
|
34
|
-
|
|
35
|
-
**Note**: When renewing your certificate, make sure that this identifier stays the same as before. Changing this identifier will
|
|
36
|
-
require existing passes to be regenerated, as they will otherwise no longer be updateable via the web service URL.
|
|
37
|
-
|
|
38
|
-
Now, create a certificate signing request: https://developer.apple.com/help/account/create-certificates/create-a-certificate-signing-request/
|
|
39
|
-
|
|
40
|
-
And create the certificate:
|
|
41
|
-
|
|
42
|
-

|
|
43
|
-
|
|
44
|
-
At the end, you'll have a `pass.cer` file.
|
|
45
|
-
|
|
46
|
-
Open it in the Keychain Access tool and export it (you must be in the My Certificates tab):
|
|
47
|
-
|
|
48
|
-

|
|
49
|
-
|
|
50
|
-
Set a password and get your p12 file. The path to this file is the `PASSKIT_PRIVATE_P12_CERTIFICATE` variable.
|
|
51
|
-
Save the password. This is the `PASSKIT_CERTIFICATE_KEY` variable.
|
|
52
|
-
|
|
53
|
-
`PKCS12_parse: unsupported`: you might encounter this issue: https://help.heroku.com/88GYDTB2/how-do-i-configure-openssl-to-allow-the-use-of-legacy-cryptographic-algorithms
|
data/docs/step1.png
DELETED
|
Binary file
|
data/docs/step2.png
DELETED
|
Binary file
|
data/docs/step3.png
DELETED
|
Binary file
|
data/docs/step4.png
DELETED
|
Binary file
|
data/docs/step5.png
DELETED
|
Binary file
|
data/docs/wallet.png
DELETED
|
Binary file
|