|
| 1 | +# Breaking change notice for version 16.0.0 |
| 2 | + |
| 3 | +## Minimum Ruby Version Requirement |
| 4 | + |
| 5 | +The minimum required Ruby version has been updated from 3.0 to 3.2. |
| 6 | + |
| 7 | +### Why this change? |
| 8 | + |
| 9 | +Ruby 3.0 and 3.1 have reached End of Life (EOL). |
| 10 | + |
| 11 | +### Migration Guide |
| 12 | + |
| 13 | +If you're currently using Ruby 3.0 or 3.1, you'll need to upgrade to Ruby 3.2 or higher before upgrading to shopify-api-ruby v16.0.0. |
| 14 | + |
| 15 | +**Note:** Ruby 3.2+ includes performance improvements and new features. Most applications should not require code changes beyond updating the Ruby version itself. |
| 16 | +## Removal of `Session#serialize` and `Session.deserialize` methods |
| 17 | + |
| 18 | +The `Session#serialize` and `Session.deserialize` methods have been removed due to a security vulnerability. The `deserialize` method used `Oj.load` without safe mode, which allows instantiation of arbitrary Ruby objects. |
| 19 | + |
| 20 | +These methods were originally created for session persistence when the library handled session storage. After session storage was deprecated in v12.3.0, applications became responsible for their own session persistence, making these methods unnecessary for their original purpose. |
| 21 | + |
| 22 | +### Why this change? |
| 23 | + |
| 24 | +**No impact on most applications:** The `shopify_app gem` stores individual session attributes in database columns and reconstructs sessions using `Session.new()`, which is the recommended pattern. |
| 25 | + |
| 26 | +## Migration Guide |
| 27 | + |
| 28 | +If your application was using `Session#serialize` and `Session.deserialize` for session persistence, you'll need to refactor to store individual session attributes and reconstruct sessions using `Session.new()`. |
| 29 | + |
| 30 | +### Previous implementation (removed in v16.0.0) |
| 31 | + |
| 32 | +```ruby |
| 33 | +# Storing a session |
| 34 | +session = ShopifyAPI::Auth::Session.new( |
| 35 | + shop: "example.myshopify.com", |
| 36 | + access_token: "shpat_xxxxx", |
| 37 | + scope: "read_products,write_orders" |
| 38 | +) |
| 39 | + |
| 40 | +serialized_data = session.serialize |
| 41 | +# Store serialized_data in Redis, database, etc. |
| 42 | +redis.set("session:#{session.id}", serialized_data) |
| 43 | + |
| 44 | +# Retrieving a session |
| 45 | +serialized_data = redis.get("session:#{session_id}") |
| 46 | +session = ShopifyAPI::Auth::Session.deserialize(serialized_data) |
| 47 | +``` |
| 48 | + |
| 49 | +### New implementation (required in v16.0.0) |
| 50 | + |
| 51 | +Store individual session attributes and reconstruct using `Session.new()`: |
| 52 | + |
| 53 | +## Reference: shopify_app gem implementation |
| 54 | + |
| 55 | +The [shopify_app gem](https://github.com/Shopify/shopify_app) provides a reference implementation of session storage that follows these best practices: |
| 56 | + |
| 57 | +**Shop Session Storage** ([source](https://github.com/Shopify/shopify_app/blob/main/lib/shopify_app/session/shop_session_storage.rb)): |
| 58 | +```ruby |
| 59 | +# Stores attributes in database columns |
| 60 | +def store(auth_session) |
| 61 | + shop = find_or_initialize_by(shopify_domain: auth_session.shop) |
| 62 | + shop.shopify_token = auth_session.access_token |
| 63 | + shop.save! |
| 64 | +end |
| 65 | + |
| 66 | +# Reconstructs using Session.new() |
| 67 | +def retrieve(id) |
| 68 | + shop = find_by(id: id) |
| 69 | + return unless shop |
| 70 | + |
| 71 | + ShopifyAPI::Auth::Session.new( |
| 72 | + shop: shop.shopify_domain, |
| 73 | + access_token: shop.shopify_token |
| 74 | + ) |
| 75 | +end |
| 76 | +``` |
0 commit comments