Skip to content

Commit

Permalink
Merge pull request #1597 from Shopify/klenotiw/add-gdpr-jobs-generator
Browse files Browse the repository at this point in the history
Add GDPR and Uninstall Jobs to Generator
  • Loading branch information
klenotiw authored Dec 1, 2022
2 parents 43c2cea + 67de851 commit 6a5ba61
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Unreleased
* Emit a deprecation notice for wrongly-rescued exceptions [#1530](https://github.com/Shopify/shopify_app/pull/1530)
* Log a deprecation warning for the use of incompatible controller concerns [#1560](https://github.com/Shopify/shopify_app/pull/1560)
* Fixes bug with expired sessions for embedded apps returning a 500 instead of 401 [#1580](https://github.com/Shopify/shopify_app/pull/1580)
* Generator properly handles uninstall [#1597](https://github.com/Shopify/shopify_app/pull/1597)

21.2.0 (Oct 25, 2022)
----------
Expand Down
13 changes: 13 additions & 0 deletions docs/shopify_app/webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#### Table of contents

[Manage webhooks using `ShopifyApp::WebhooksManager`](#manage-webhooks-using-shopifyappwebhooksmanager)
[Mandatory GDPR Webhooks](#mandatory-gdpr-webhooks)

## Manage webhooks using `ShopifyApp::WebhooksManager`

Expand Down Expand Up @@ -70,3 +71,15 @@ rails g shopify_app:add_webhook --topic carts/update --path webhooks/carts_updat
```

Where `--topic` is the topic and `--path` is the path the webhook should be sent to.

## Mandatory GDPR Webhooks

We have three mandatory GDPR webhooks

1. `customers/data_request`
2. `customer/redact`
3. `shop/redact`

The `generate shopify_app` command generated three job templates corresponding to all three of these webhooks.
To pass our approval process you will need to set these webhooks in your partner dashboard.
You can read more about that [here](https://shopify.dev/apps/webhooks/configuration/mandatory-webhooks).
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require "rails/generators/base"

module ShopifyApp
module Generators
class AddAppUninstalledJobGenerator < Rails::Generators::Base
source_root File.expand_path("../templates", __FILE__)

def create_job
template("app_uninstalled_job.rb", "app/jobs/app_uninstalled_job.rb")
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class AppUninstalledJob < ActiveJob::Base
extend ShopifyAPI::Webhooks::Handler

class << self
def handle(topic:, shop:, body:)
perform_later(topic: topic, shop_domain: shop, webhook: body)
end
end

def perform(topic:, shop_domain:, webhook:)
shop = Shop.find_by(shopify_domain: shop_domain)

if shop.nil?
logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")

raise ActiveRecord::RecordNotFound, "Shop Not Found"
end

logger.info("#{self.class} started for shop '#{shop_domain}'")
shop.destroy
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require "rails/generators/base"

module ShopifyApp
module Generators
class AddGdprJobsGenerator < Rails::Generators::Base
source_root File.expand_path("../templates", __FILE__)

def add_customer_data_request_job
template("customers_data_request_job.rb", "app/jobs/customers_data_request_job.rb")
end

def add_shop_redact_job
template("shop_redact_job.rb", "app/jobs/shop_redact_job.rb")
end

def add_customer_redact_job
template("customers_redact_job.rb", "app/jobs/customers_redact_job.rb")
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class CustomersDataRequestJob < ActiveJob::Base
extend ShopifyAPI::Webhooks::Handler

class << self
def handle(topic:, shop:, body:)
perform_later(topic: topic, shop_domain: shop, webhook: body)
end
end

def perform(topic:, shop_domain:, webhook:)
shop = Shop.find_by(shopify_domain: shop_domain)

if shop.nil?
logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")

raise ActiveRecord::RecordNotFound, "Shop Not Found"
end

shop.with_shopify_session do
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class CustomersRedactJob < ActiveJob::Base
extend ShopifyAPI::Webhooks::Handler

class << self
def handle(topic:, shop:, body:)
perform_later(topic: topic, shop_domain: shop, webhook: body)
end
end

def perform(topic:, shop_domain:, webhook:)
shop = Shop.find_by(shopify_domain: shop_domain)

if shop.nil?
logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")

raise ActiveRecord::RecordNotFound, "Shop Not Found"
end

shop.with_shopify_session do
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class ShopRedactJob < ActiveJob::Base
extend ShopifyAPI::Webhooks::Handler

class << self
def handle(topic:, shop:, body:)
perform_later(topic: topic, shop_domain: shop, webhook: body)
end
end

def perform(topic:, shop_domain:, webhook:)
shop = Shop.find_by(shopify_domain: shop_domain)

if shop.nil?
logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")

raise ActiveRecord::RecordNotFound, "Shop Not Found"
end

shop.with_shopify_session do
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class <%= @job_class_name %> < ActiveJob::Base

if shop.nil?
logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")
return

raise ActiveRecord::RecordNotFound, "Shop Not Found"
end

shop.with_shopify_session do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ ShopifyApp.configure do |config|
config.shop_session_repository = 'Shop'
config.log_level = :info
config.reauth_on_access_scope_changes = true
config.webhooks = [
{ topic: "app/uninstalled", address: "webhooks/app_uninstalled"},
{ topic: "customers/data_request", address: "webhooks/customers_data_request" },
{ topic: "customer/redact", address: "webhooks/customers_redact"},
{ topic: "shop/redact", address: "webhooks/shop_redact"}
]

config.api_key = ENV.fetch('SHOPIFY_API_KEY', '').presence
config.secret = ENV.fetch('SHOPIFY_API_SECRET', '').presence
Expand Down
2 changes: 2 additions & 0 deletions lib/generators/shopify_app/shopify_app_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ def initialize(args, *options)
end

def run_all_generators
generate("shopify_app:add_app_uninstalled_job")
generate("shopify_app:add_gdpr_jobs")
generate("shopify_app:install #{@opts.join(" ")}")
generate("shopify_app:shop_model #{@opts.join(" ")}")
generate("shopify_app:authenticated_controller")
Expand Down
26 changes: 26 additions & 0 deletions test/generators/add_app_uninstalled_job_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require "test_helper"
require "generators/shopify_app/add_app_uninstalled_job/add_app_uninstalled_job_generator"

class AddAppUninstalledJobGeneratorTest < Rails::Generators::TestCase
tests ShopifyApp::Generators::AddAppUninstalledJobGenerator
destination File.expand_path("../tmp", File.dirname(__FILE__))

setup do
ShopifyApp.configure do |config|
config.embedded_app = true
end

prepare_destination
provide_existing_application_file
provide_existing_routes_file
provide_existing_application_controller
end

test "creates app uninstalled job file" do
run_generator

assert_file "app/jobs/app_uninstalled_job.rb"
end
end
28 changes: 28 additions & 0 deletions test/generators/add_gdpr_jobs_generator_job_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require "test_helper"
require "generators/shopify_app/add_gdpr_jobs/add_gdpr_jobs_generator"

class AddGdprJobsGeneratorJobTest < Rails::Generators::TestCase
tests ShopifyApp::Generators::AddGdprJobsGenerator
destination File.expand_path("../tmp", File.dirname(__FILE__))

setup do
ShopifyApp.configure do |config|
config.embedded_app = true
end

prepare_destination
provide_existing_application_file
provide_existing_routes_file
provide_existing_application_controller
end

test "creates app uninstalled job file" do
run_generator

assert_file "app/jobs/customers_data_request_job.rb"
assert_file "app/jobs/shop_redact_job.rb"
assert_file "app/jobs/customers_redact_job.rb"
end
end

0 comments on commit 6a5ba61

Please sign in to comment.