passkit 0.8.3 → 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 +5 -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 -5
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,8 @@
|
|
|
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
|
+
|
|
1
6
|
## [0.8.3]
|
|
2
7
|
- Exclude development and test files from the packaged gem.
|
|
3
8
|
|
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
|
|
@@ -156,6 +156,7 @@ files:
|
|
|
156
156
|
- app/assets/images/passkit/add_to_walletpass_en.png
|
|
157
157
|
- app/assets/images/passkit/add_to_walletpass_fr.png
|
|
158
158
|
- app/assets/images/passkit/add_to_walletpass_it.png
|
|
159
|
+
- app/controllers/concerns/passkit/pass_delivery.rb
|
|
159
160
|
- app/controllers/passkit/api/v1/logs_controller.rb
|
|
160
161
|
- app/controllers/passkit/api/v1/passes_controller.rb
|
|
161
162
|
- app/controllers/passkit/api/v1/registrations_controller.rb
|
|
@@ -214,14 +215,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
214
215
|
requirements:
|
|
215
216
|
- - ">="
|
|
216
217
|
- !ruby/object:Gem::Version
|
|
217
|
-
version: 2.
|
|
218
|
+
version: 3.2.0
|
|
218
219
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
220
|
requirements:
|
|
220
221
|
- - ">="
|
|
221
222
|
- !ruby/object:Gem::Version
|
|
222
223
|
version: '0'
|
|
223
224
|
requirements: []
|
|
224
|
-
rubygems_version: 4.0.
|
|
225
|
+
rubygems_version: 4.0.17
|
|
225
226
|
specification_version: 4
|
|
226
227
|
summary: Serve Wallet Passes for iOS and Android directly from your Rails app
|
|
227
228
|
test_files: []
|