Skip to content

Commit

Permalink
Merge pull request #1890 from Shopify/unified-admin-domain
Browse files Browse the repository at this point in the history
Add the `unified_admin_domain` configuration option for the unified admin domain.
  • Loading branch information
MatWrz authored Aug 1, 2024
2 parents d503c08 + 9b456e4 commit 6cc65fd
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Unreleased
----------
* Add the `unified_admin_domain` configuration option for the unified admin domain.

22.3.1 (July 26, 2024)
----------
Expand Down
4 changes: 4 additions & 0 deletions lib/shopify_app/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class Configuration
# configure myshopify domain for local shopify development
attr_accessor :myshopify_domain

# configure the unified admin domain for local shopify development
attr_accessor :unified_admin_domain

# ability to have webpacker installed but not used in this gem and the generators
attr_accessor :disable_webpacker

Expand All @@ -54,6 +57,7 @@ class Configuration
def initialize
@root_url = "/"
@myshopify_domain = "myshopify.com"
@unified_admin_domain = "shopify.com"
@scripttags_manager_queue_name = Rails.application.config.active_job.queue_name
@webhooks_manager_queue_name = Rails.application.config.active_job.queue_name
@disable_webpacker = ENV["SHOPIFY_APP_DISABLE_WEBPACKER"].present?
Expand Down
2 changes: 1 addition & 1 deletion lib/shopify_app/controller_concerns/frame_ancestors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module FrameAncestors
content_security_policy do |policy|
policy.frame_ancestors(-> do
domain_host = current_shopify_domain || "*.#{::ShopifyApp.configuration.myshopify_domain}"
"#{ShopifyAPI::Context.host_scheme}://#{domain_host} https://admin.shopify.com"
"#{ShopifyAPI::Context.host_scheme}://#{domain_host} https://admin.#{::ShopifyApp.configuration.unified_admin_domain}"
end)
end
end
Expand Down
6 changes: 5 additions & 1 deletion lib/shopify_app/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def unified_admin_path(shop)
if spin_env
"https://admin.web.#{spin_env}/store/#{shop}"
else
"https://admin.shopify.com/store/#{shop}"
"https://admin.#{unified_admin_domain}/store/#{shop}"
end
end

Expand All @@ -54,6 +54,10 @@ def myshopify_domain
ShopifyApp.configuration.myshopify_domain
end

def unified_admin_domain
ShopifyApp.configuration.unified_admin_domain
end

def trusted_domains
trusted_domains = TRUSTED_SHOPIFY_DOMAINS.dup
trusted_domains.append(myshopify_domain).uniq! if myshopify_domain
Expand Down
66 changes: 49 additions & 17 deletions test/controllers/concerns/embedded_app_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require "test_helper"
require "action_view/testing/resolvers"

class EmbeddedAppTest < ActionController::TestCase
class EmbeddedAppTest < ActionDispatch::IntegrationTest
class BaseTestController < ActionController::Base
abstract!

Expand All @@ -28,9 +28,11 @@ def index; end
def redirect_to_embed
redirect_to_embed_app_in_admin
end
end

tests EmbeddedAppTestController
def current_shopify_domain
nil
end
end

setup do
Rails.application.routes.draw do
Expand All @@ -39,50 +41,54 @@ def redirect_to_embed
end
end

teardown do
ShopifyApp.configuration = nil
end

test "uses the embedded app layout when running in embedded mode" do
ShopifyApp.configuration.embedded_app = true

get :index
get embedded_app_path
assert_template layout: "embedded_app"
end

test "uses the default layout when running in non-embedded mode" do
ShopifyApp.configuration.embedded_app = false

get :index
get embedded_app_path
assert_template layout: "application"
end

test "sets the ESDK headers when running in embedded mode" do
ShopifyApp.configuration.embedded_app = true

get :index
assert_equal @controller.response.headers["P3P"], 'CP="Not used"'
assert_not_includes @controller.response.headers, "X-Frame-Options"
get embedded_app_path
assert_equal response.headers["P3P"], 'CP="Not used"'
assert_not_includes response.headers, "X-Frame-Options"
end

test "does not touch the ESDK headers when running in non-embedded mode" do
ShopifyApp.configuration.embedded_app = false

get :index
assert_not_includes @controller.response.headers, "P3P"
assert_includes @controller.response.headers, "X-Frame-Options"
get embedded_app_path
assert_not_includes response.headers, "P3P"
assert_includes response.headers, "X-Frame-Options"
end

test "#redirect_to_embed_app_in_admin redirects to the embed app in the admin when the host param is present" do
ShopifyApp.configuration.embedded_app = true

shop = "my-shop.myshopify.com"
host = Base64.encode64("#{shop}/admin")
get :redirect_to_embed, params: { host: host }
get redirect_to_embed_path, params: { host: host }
assert_redirected_to "https://#{shop}/admin/apps/#{ShopifyApp.configuration.api_key}/redirect_to_embed"
end

test "#redirect_to_embed_app_in_admin redirects to the embed app in the admin when the shop param is present" do
ShopifyApp.configuration.embedded_app = true

shop = "my-shop.myshopify.com"
get :redirect_to_embed, params: { shop: shop }
get redirect_to_embed_path, params: { shop: shop }
assert_redirected_to "https://#{shop}/admin/apps/#{ShopifyApp.configuration.api_key}/redirect_to_embed"
end

Expand All @@ -91,29 +97,55 @@ def redirect_to_embed

shop = "my-shop.myshopify.com"
host = Base64.encode64("#{shop}/admin")
get :redirect_to_embed, params: { shop: shop, foo: "bar", host: host, id_token: "id_token" }
get redirect_to_embed_path, params: { shop: shop, foo: "bar", host: host, id_token: "id_token" }
assert_redirected_to "https://#{shop}/admin/apps/#{ShopifyApp.configuration.api_key}/redirect_to_embed?foo=bar"
end

test "Redirect to login URL when host nor shop param is present" do
ShopifyApp.configuration.embedded_app = true

get :redirect_to_embed
get redirect_to_embed_path
assert_redirected_to ShopifyApp.configuration.login_url
end

test "Redirect to root URL when decoded host is not a shopify domain" do
shop = "my-shop.fakeshopify.com"
host = Base64.encode64("#{shop}/admin")

get :redirect_to_embed, params: { host: host }
get redirect_to_embed_path, params: { host: host }
assert_redirected_to ShopifyApp.configuration.root_url
end

test "Redirect to root URL when shop is not a shopify domain" do
shop = "my-shop.fakeshopify.com"

get :redirect_to_embed, params: { shop: shop }
get redirect_to_embed_path, params: { shop: shop }
assert_redirected_to ShopifyApp.configuration.root_url
end

test "content security policy for frame ancestors contains current_shopify_domain" do
ShopifyApp.configuration.embedded_app = true
shop = "my-shop.myshopify.com"
EmbeddedAppTestController.any_instance.expects(:current_shopify_domain).returns(shop)

get redirect_to_embed_path
assert_includes response.headers["Content-Security-Policy"], shop
end

test "content security policy for frame ancestors contains myshopify_domain when current_shopify_domain is nil" do
ShopifyApp.configuration.embedded_app = true
ShopifyApp.configuration.myshopify_domain = "myshopify.io"
EmbeddedAppTestController.any_instance.expects(:current_shopify_domain).returns(nil)

get redirect_to_embed_path
assert_includes response.headers["Content-Security-Policy"], "*.#{ShopifyApp.configuration.myshopify_domain}"
end

test "content security policy for frame ancestors contains unified admin domain" do
ShopifyApp.configuration.embedded_app = true
ShopifyApp.configuration.unified_admin_domain = "shop.dev"

get redirect_to_embed_path
assert_includes response.headers["Content-Security-Policy"], ShopifyApp.configuration.unified_admin_domain
end
end
12 changes: 12 additions & 0 deletions test/shopify_app/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ class ConfigurationTest < ActiveSupport::TestCase
assert_equal "myshopify.io", ShopifyApp.configuration.myshopify_domain
end

test "defaults to unified_admin_domain" do
assert_equal "shopify.com", ShopifyApp.configuration.unified_admin_domain
end

test "can set unified_admin_domain" do
ShopifyApp.configure do |config|
config.unified_admin_domain = "myshopify.io"
end

assert_equal "myshopify.io", ShopifyApp.configuration.unified_admin_domain
end

test "can configure webhooks for creation" do
webhook = { topic: "carts/update", address: "example-app.com/webhooks", format: "json" }

Expand Down

0 comments on commit 6cc65fd

Please sign in to comment.