shopify_app 22.5.2 → 23.0.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yaml +6 -0
  3. data/.github/workflows/build.yml +5 -5
  4. data/.github/workflows/close-waiting-for-response-issues.yml +1 -1
  5. data/.github/workflows/release.yml +2 -2
  6. data/.github/workflows/remove-labels-on-activity.yml +2 -3
  7. data/.github/workflows/rubocop.yml +2 -2
  8. data/CHANGELOG.md +22 -0
  9. data/Gemfile +1 -1
  10. data/Gemfile.lock +181 -122
  11. data/README.md +105 -25
  12. data/Rakefile +13 -0
  13. data/app/controllers/shopify_app/callback_controller.rb +2 -40
  14. data/app/controllers/shopify_app/extension_verification_controller.rb +1 -1
  15. data/app/jobs/shopify_app/script_tags_manager_job.rb +16 -0
  16. data/docs/Releasing.md +113 -19
  17. data/docs/Upgrading.md +72 -0
  18. data/docs/shopify_app/content-security-policy.md +50 -3
  19. data/docs/shopify_app/controller-concerns.md +20 -0
  20. data/docs/shopify_app/script-tags.md +52 -0
  21. data/docs/shopify_app/sessions.md +149 -22
  22. data/lib/generators/shopify_app/add_app_uninstalled_job/templates/app_uninstalled_job.rb.tt +2 -2
  23. data/lib/generators/shopify_app/add_privacy_jobs/templates/customers_data_request_job.rb.tt +2 -2
  24. data/lib/generators/shopify_app/add_privacy_jobs/templates/customers_redact_job.rb.tt +2 -2
  25. data/lib/generators/shopify_app/add_privacy_jobs/templates/shop_redact_job.rb.tt +2 -2
  26. data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb.tt +2 -2
  27. data/lib/generators/shopify_app/install/install_generator.rb +1 -1
  28. data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +18 -0
  29. data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_token_expiry_columns.erb +7 -0
  30. data/lib/generators/shopify_app/shop_model/templates/shop.rb +1 -1
  31. data/lib/generators/shopify_app/user_model/templates/user.rb +1 -1
  32. data/lib/shopify_app/auth/post_authenticate_tasks.rb +8 -0
  33. data/lib/shopify_app/auth/token_exchange.rb +7 -0
  34. data/lib/shopify_app/configuration.rb +5 -5
  35. data/lib/shopify_app/controller_concerns/login_protection.rb +12 -8
  36. data/lib/shopify_app/engine.rb +2 -5
  37. data/lib/shopify_app/errors.rb +2 -0
  38. data/lib/shopify_app/managers/script_tags_manager.rb +348 -0
  39. data/lib/shopify_app/session/shop_session_storage.rb +84 -2
  40. data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +6 -0
  41. data/lib/shopify_app/session/user_session_storage.rb +21 -2
  42. data/lib/shopify_app/session/user_session_storage_with_scopes.rb +6 -0
  43. data/lib/shopify_app/utils.rb +1 -1
  44. data/lib/shopify_app/version.rb +1 -1
  45. data/lib/shopify_app.rb +12 -7
  46. data/package.json +1 -1
  47. data/shopify_app.gemspec +9 -10
  48. data/translation.yml +1 -0
  49. data/yarn.lock +7 -9
  50. metadata +63 -46
  51. data/lib/shopify_app/middleware/jwt_middleware.rb +0 -48
  52. data/lib/shopify_app/session/jwt.rb +0 -73
  53. /data/{lib/shopify_app/jobs → app/jobs/shopify_app}/webhooks_manager_job.rb +0 -0
metadata CHANGED
@@ -1,28 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 22.5.2
4
+ version: 23.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: activeresource
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - ">="
17
- - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: '0'
26
12
  - !ruby/object:Gem::Dependency
27
13
  name: addressable
28
14
  requirement: !ruby/object:Gem::Requirement
@@ -41,16 +27,22 @@ dependencies:
41
27
  name: rails
42
28
  requirement: !ruby/object:Gem::Requirement
43
29
  requirements:
44
- - - ">"
30
+ - - ">="
45
31
  - !ruby/object:Gem::Version
46
- version: 5.2.1
32
+ version: '7.1'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '9'
47
36
  type: :runtime
48
37
  prerelease: false
49
38
  version_requirements: !ruby/object:Gem::Requirement
50
39
  requirements:
51
- - - ">"
40
+ - - ">="
52
41
  - !ruby/object:Gem::Version
53
- version: 5.2.1
42
+ version: '7.1'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '9'
54
46
  - !ruby/object:Gem::Dependency
55
47
  name: redirect_safely
56
48
  requirement: !ruby/object:Gem::Requirement
@@ -69,52 +61,46 @@ dependencies:
69
61
  name: shopify_api
70
62
  requirement: !ruby/object:Gem::Requirement
71
63
  requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: 14.7.0
75
- - - "<"
64
+ - - "~>"
76
65
  - !ruby/object:Gem::Version
77
- version: '15.0'
66
+ version: '16.0'
78
67
  type: :runtime
79
68
  prerelease: false
80
69
  version_requirements: !ruby/object:Gem::Requirement
81
70
  requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: 14.7.0
85
- - - "<"
71
+ - - "~>"
86
72
  - !ruby/object:Gem::Version
87
- version: '15.0'
73
+ version: '16.0'
88
74
  - !ruby/object:Gem::Dependency
89
75
  name: sprockets-rails
90
76
  requirement: !ruby/object:Gem::Requirement
91
77
  requirements:
92
78
  - - ">="
93
79
  - !ruby/object:Gem::Version
94
- version: 2.0.0
80
+ version: '0'
95
81
  type: :runtime
96
82
  prerelease: false
97
83
  version_requirements: !ruby/object:Gem::Requirement
98
84
  requirements:
99
85
  - - ">="
100
86
  - !ruby/object:Gem::Version
101
- version: 2.0.0
87
+ version: '0'
102
88
  - !ruby/object:Gem::Dependency
103
- name: jwt
89
+ name: byebug
104
90
  requirement: !ruby/object:Gem::Requirement
105
91
  requirements:
106
92
  - - ">="
107
93
  - !ruby/object:Gem::Version
108
- version: 2.2.3
109
- type: :runtime
94
+ version: '0'
95
+ type: :development
110
96
  prerelease: false
111
97
  version_requirements: !ruby/object:Gem::Requirement
112
98
  requirements:
113
99
  - - ">="
114
100
  - !ruby/object:Gem::Version
115
- version: 2.2.3
101
+ version: '0'
116
102
  - !ruby/object:Gem::Dependency
117
- name: byebug
103
+ name: csv
118
104
  requirement: !ruby/object:Gem::Requirement
119
105
  requirements:
120
106
  - - ">="
@@ -127,6 +113,20 @@ dependencies:
127
113
  - - ">="
128
114
  - !ruby/object:Gem::Version
129
115
  version: '0'
116
+ - !ruby/object:Gem::Dependency
117
+ name: jwt
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 2.2.3
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: 2.2.3
130
130
  - !ruby/object:Gem::Dependency
131
131
  name: minitest
132
132
  requirement: !ruby/object:Gem::Requirement
@@ -143,6 +143,20 @@ dependencies:
143
143
  version: '0'
144
144
  - !ruby/object:Gem::Dependency
145
145
  name: mocha
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: 2.1.0
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: 2.1.0
158
+ - !ruby/object:Gem::Dependency
159
+ name: mutex_m
146
160
  requirement: !ruby/object:Gem::Requirement
147
161
  requirements:
148
162
  - - ">="
@@ -243,16 +257,16 @@ dependencies:
243
257
  name: sqlite3
244
258
  requirement: !ruby/object:Gem::Requirement
245
259
  requirements:
246
- - - "~>"
260
+ - - ">="
247
261
  - !ruby/object:Gem::Version
248
- version: '1.4'
262
+ version: '0'
249
263
  type: :development
250
264
  prerelease: false
251
265
  version_requirements: !ruby/object:Gem::Requirement
252
266
  requirements:
253
- - - "~>"
267
+ - - ">="
254
268
  - !ruby/object:Gem::Version
255
- version: '1.4'
269
+ version: '0'
256
270
  - !ruby/object:Gem::Dependency
257
271
  name: webmock
258
272
  requirement: !ruby/object:Gem::Requirement
@@ -278,6 +292,7 @@ files:
278
292
  - ".github/ISSUE_TEMPLATE/config.yml"
279
293
  - ".github/ISSUE_TEMPLATE/feature-request.md"
280
294
  - ".github/PULL_REQUEST_TEMPLATE.md"
295
+ - ".github/dependabot.yaml"
281
296
  - ".github/workflows/build.yml"
282
297
  - ".github/workflows/cla.yml"
283
298
  - ".github/workflows/close-waiting-for-response-issues.yml"
@@ -308,6 +323,8 @@ files:
308
323
  - app/controllers/shopify_app/extension_verification_controller.rb
309
324
  - app/controllers/shopify_app/sessions_controller.rb
310
325
  - app/controllers/shopify_app/webhooks_controller.rb
326
+ - app/jobs/shopify_app/script_tags_manager_job.rb
327
+ - app/jobs/shopify_app/webhooks_manager_job.rb
311
328
  - app/views/shopify_app/layouts/app_bridge.html.erb
312
329
  - app/views/shopify_app/partials/_button_styles.html.erb
313
330
  - app/views/shopify_app/partials/_card_styles.html.erb
@@ -351,6 +368,7 @@ files:
351
368
  - docs/shopify_app/generators.md
352
369
  - docs/shopify_app/handling-access-scopes-changes.md
353
370
  - docs/shopify_app/logging.md
371
+ - docs/shopify_app/script-tags.md
354
372
  - docs/shopify_app/sessions.md
355
373
  - docs/shopify_app/testing.md
356
374
  - docs/shopify_app/webhooks.md
@@ -398,6 +416,7 @@ files:
398
416
  - lib/generators/shopify_app/routes/templates/routes.rb
399
417
  - lib/generators/shopify_app/shop_model/shop_model_generator.rb
400
418
  - lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb
419
+ - lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_token_expiry_columns.erb
401
420
  - lib/generators/shopify_app/shop_model/templates/db/migrate/create_shops.erb
402
421
  - lib/generators/shopify_app/shop_model/templates/shop.rb
403
422
  - lib/generators/shopify_app/shop_model/templates/shops.yml
@@ -432,14 +451,12 @@ files:
432
451
  - lib/shopify_app/controller_concerns/with_shopify_id_token.rb
433
452
  - lib/shopify_app/engine.rb
434
453
  - lib/shopify_app/errors.rb
435
- - lib/shopify_app/jobs/webhooks_manager_job.rb
436
454
  - lib/shopify_app/logger.rb
455
+ - lib/shopify_app/managers/script_tags_manager.rb
437
456
  - lib/shopify_app/managers/webhooks_manager.rb
438
- - lib/shopify_app/middleware/jwt_middleware.rb
439
457
  - lib/shopify_app/session/in_memory_session_store.rb
440
458
  - lib/shopify_app/session/in_memory_shop_session_store.rb
441
459
  - lib/shopify_app/session/in_memory_user_session_store.rb
442
- - lib/shopify_app/session/jwt.rb
443
460
  - lib/shopify_app/session/null_user_session_store.rb
444
461
  - lib/shopify_app/session/session_repository.rb
445
462
  - lib/shopify_app/session/session_storage.rb
@@ -469,14 +486,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
469
486
  requirements:
470
487
  - - ">="
471
488
  - !ruby/object:Gem::Version
472
- version: '3.0'
489
+ version: '3.2'
473
490
  required_rubygems_version: !ruby/object:Gem::Requirement
474
491
  requirements:
475
492
  - - ">="
476
493
  - !ruby/object:Gem::Version
477
494
  version: '0'
478
495
  requirements: []
479
- rubygems_version: 3.6.5
496
+ rubygems_version: 3.7.2
480
497
  specification_version: 4
481
498
  summary: This gem is used to get quickly started with the Shopify API
482
499
  test_files: []
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyApp
4
- class JWTMiddleware
5
- TOKEN_REGEX = /^Bearer (.+)$/
6
- ID_TOKEN_QUERY_PARAM = "id_token"
7
-
8
- def initialize(app)
9
- @app = app
10
- end
11
-
12
- def call(env)
13
- return call_next(env) unless ShopifyApp.configuration.embedded_app?
14
-
15
- token = token_from_authorization_header(env) || token_from_query_string(env)
16
- return call_next(env) unless token
17
-
18
- set_env_variables(token, env)
19
- call_next(env)
20
- end
21
-
22
- private
23
-
24
- def call_next(env)
25
- @app.call(env)
26
- end
27
-
28
- def token_from_authorization_header(env)
29
- env["HTTP_AUTHORIZATION"]&.match(TOKEN_REGEX)&.[](1)
30
- end
31
-
32
- def token_from_query_string(env)
33
- Rack::Utils.parse_nested_query(env["QUERY_STRING"])[ID_TOKEN_QUERY_PARAM]
34
- end
35
-
36
- def set_env_variables(token, env)
37
- jwt = ShopifyAPI::Auth::JwtPayload.new(token)
38
-
39
- env["jwt.token"] = token
40
- env["jwt.shopify_domain"] = jwt.shopify_domain
41
- env["jwt.shopify_user_id"] = jwt.shopify_user_id
42
- env["jwt.expire_at"] = jwt.expire_at
43
- rescue ShopifyAPI::Errors::InvalidJwtTokenError
44
- # ShopifyApp::JWT did not raise any exceptions, ensuring behaviour does not change
45
- nil
46
- end
47
- end
48
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyApp
4
- class JWT
5
- WARN_EXCEPTIONS = [
6
- ::JWT::DecodeError,
7
- ::JWT::ExpiredSignature,
8
- ::JWT::ImmatureSignature,
9
- ::JWT::VerificationError,
10
- ::ShopifyApp::InvalidAudienceError,
11
- ::ShopifyApp::InvalidDestinationError,
12
- ::ShopifyApp::MismatchedHostsError,
13
- ]
14
-
15
- def initialize(token)
16
- warn_deprecation
17
- @token = token
18
- set_payload
19
- end
20
-
21
- def shopify_domain
22
- @payload && ShopifyApp::Utils.sanitize_shop_domain(@payload["dest"])
23
- end
24
-
25
- def shopify_user_id
26
- @payload["sub"].to_i if @payload && @payload["sub"]
27
- end
28
-
29
- def expire_at
30
- @payload["exp"].to_i if @payload && @payload["exp"]
31
- end
32
-
33
- private
34
-
35
- def set_payload
36
- payload, _ = parse_token_data(ShopifyApp.configuration&.secret, ShopifyApp.configuration&.old_secret)
37
- @payload = validate_payload(payload)
38
- rescue *WARN_EXCEPTIONS
39
- nil
40
- end
41
-
42
- def parse_token_data(secret, old_secret)
43
- ::JWT.decode(@token, secret, true, { algorithm: "HS256" })
44
- rescue ::JWT::VerificationError
45
- raise unless old_secret
46
-
47
- ::JWT.decode(@token, old_secret, true, { algorithm: "HS256" })
48
- end
49
-
50
- def validate_payload(payload)
51
- dest_host = ShopifyApp::Utils.sanitize_shop_domain(payload["dest"])
52
- iss_host = ShopifyApp::Utils.sanitize_shop_domain(payload["iss"])
53
- api_key = ShopifyApp.configuration.api_key
54
-
55
- raise ::ShopifyApp::InvalidAudienceError,
56
- "'aud' claim does not match api_key" unless payload["aud"] == api_key
57
- raise ::ShopifyApp::InvalidDestinationError, "'dest' claim host not a valid shopify host" unless dest_host
58
-
59
- raise ::ShopifyApp::MismatchedHostsError,
60
- "'dest' claim host does not match 'iss' claim host" unless dest_host == iss_host
61
-
62
- payload
63
- end
64
-
65
- def warn_deprecation
66
- message = <<~EOS
67
- "ShopifyApp::JWT will be deprecated, use ShopifyAPI::Auth::JwtPayload to parse JWT token instead."
68
- EOS
69
-
70
- ShopifyApp::Logger.deprecated(message, "23.0.0")
71
- end
72
- end
73
- end