shopify_app 8.2.6 → 8.3.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/.gitignore +2 -0
 - data/.rubocop.yml +7 -0
 - data/CHANGELOG.md +5 -0
 - data/README.md +3 -5
 - data/app/assets/javascripts/shopify_app/itp_polyfill.js +30 -0
 - data/app/assets/javascripts/shopify_app/redirect.js +30 -16
 - data/app/controllers/shopify_app/sessions_controller.rb +42 -5
 - data/app/views/shopify_app/sessions/enable_cookies.html.erb +386 -0
 - data/config/locales/en.yml +4 -0
 - data/config/routes.rb +1 -0
 - data/lib/generators/shopify_app/install/templates/_flash_messages.html.erb +2 -2
 - data/lib/shopify_app/controller_concerns/login_protection.rb +58 -18
 - data/lib/shopify_app/engine.rb +4 -1
 - data/lib/shopify_app/version.rb +1 -1
 - data/translation.yml +7 -0
 - metadata +6 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 67993e953b33ffe850f9db651c7ecc411d5933b2
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: ca5981beba2ea540681d77363dc1ae6c4bd009de
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 7665bf0987e8738cbeb9d8c0e92fa3e3d2055ffe60c80d6b50795d7f2db83e18d7df4fb89da81fc6226cacfc6fbb7fe0059d34a36071d5e90f259cb870004444
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 353060a370d4ba42c86ebc95b0d09f1ee32d3eb106db177df4dec3f2580e0acb30fef419715db35b3a023337d2dd7874718a2e3277ea0729fbb52676394ba72e
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.rubocop.yml
    ADDED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -143,7 +143,7 @@ After running the `install` generator, you can start your app with `bundle exec 
     | 
|
| 
       143 
143 
     | 
    
         
             
            $ rails generate shopify_app:shop_model
         
     | 
| 
       144 
144 
     | 
    
         
             
            ```
         
     | 
| 
       145 
145 
     | 
    
         | 
| 
       146 
     | 
    
         
            -
            The install generator doesn't create any database tables or models for you. If you are starting a new app its quite likely that you will want a shops table and model to store the tokens when your app is installed (most of our internally developed apps do!). This generator creates a shop model and a migration. This model includes the `ShopifyApp::SessionStorage` concern which adds two methods to make it compatible as a `SessionRepository`. After running this generator you'll notice the `session_repository` in your `config/initializers/shopify_app.rb` will be set to the `Shop` model. This means that internally ShopifyApp will try and load tokens from this model.
         
     | 
| 
      
 146 
     | 
    
         
            +
            The `install` generator doesn't create any database tables or models for you. If you are starting a new app its quite likely that you will want a shops table and model to store the tokens when your app is installed (most of our internally developed apps do!). This generator creates a shop model and a migration. This model includes the `ShopifyApp::SessionStorage` concern which adds two methods to make it compatible as a `SessionRepository`. After running this generator you'll notice the `session_repository` in your `config/initializers/shopify_app.rb` will be set to the `Shop` model. This means that internally ShopifyApp will try and load tokens from this model.
         
     | 
| 
       147 
147 
     | 
    
         | 
| 
       148 
148 
     | 
    
         
             
            *Note that you will need to run rake db:migrate after this generator*
         
     | 
| 
       149 
149 
     | 
    
         | 
| 
         @@ -413,8 +413,6 @@ Tunneling is also useful for working the the embedded app sdk to solve mixed con 
     | 
|
| 
       413 
413 
     | 
    
         | 
| 
       414 
414 
     | 
    
         
             
            Questions or problems?
         
     | 
| 
       415 
415 
     | 
    
         
             
            ----------------------
         
     | 
| 
       416 
     | 
    
         
            -
            http://api.shopify.com <= Read up on the possible API calls!
         
     | 
| 
       417 
416 
     | 
    
         | 
| 
       418 
     | 
    
         
            -
             
     | 
| 
       419 
     | 
    
         
            -
             
     | 
| 
       420 
     | 
    
         
            -
            http://docs.shopify.com/api/the-basics/getting-started <= Read the docs!
         
     | 
| 
      
 417 
     | 
    
         
            +
            - [Ask questions!](https://ecommerce.shopify.com/c/shopify-apis-and-technology)
         
     | 
| 
      
 418 
     | 
    
         
            +
            - [Read the docs!](https://help.shopify.com/api/guides)
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            (function() {
         
     | 
| 
      
 2 
     | 
    
         
            +
              function setCookieAndRedirect() {
         
     | 
| 
      
 3 
     | 
    
         
            +
                document.cookie = "shopify.cookies_persist=true";
         
     | 
| 
      
 4 
     | 
    
         
            +
                window.location.href = window.shopOrigin + "/admin/apps/" + window.apiKey;
         
     | 
| 
      
 5 
     | 
    
         
            +
              }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              function shouldDisplayPrompt() {
         
     | 
| 
      
 8 
     | 
    
         
            +
                if (navigator.userAgent.indexOf('com.jadedpixel.pos') !== -1) {
         
     | 
| 
      
 9 
     | 
    
         
            +
                  return false;
         
     | 
| 
      
 10 
     | 
    
         
            +
                }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                if (navigator.userAgent.indexOf('Shopify Mobile/iOS') !== -1) {
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return false;
         
     | 
| 
      
 14 
     | 
    
         
            +
                }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                return Boolean(document.hasStorageAccess);
         
     | 
| 
      
 17 
     | 
    
         
            +
              }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              document.addEventListener("DOMContentLoaded", function() {
         
     | 
| 
      
 20 
     | 
    
         
            +
                if (shouldDisplayPrompt()) {
         
     | 
| 
      
 21 
     | 
    
         
            +
                  var itpContent = document.querySelector('#CookiePartitionPrompt');
         
     | 
| 
      
 22 
     | 
    
         
            +
                  itpContent.style.display = 'block';
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  var button = document.querySelector('#AcceptCookies');
         
     | 
| 
      
 25 
     | 
    
         
            +
                  button.addEventListener('click', setCookieAndRedirect);
         
     | 
| 
      
 26 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 27 
     | 
    
         
            +
                  setCookieAndRedirect();
         
     | 
| 
      
 28 
     | 
    
         
            +
                }
         
     | 
| 
      
 29 
     | 
    
         
            +
              });
         
     | 
| 
      
 30 
     | 
    
         
            +
            })();
         
     | 
| 
         @@ -1,19 +1,33 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            (function() {
         
     | 
| 
      
 2 
     | 
    
         
            +
              function redirect() {
         
     | 
| 
      
 3 
     | 
    
         
            +
                var redirectTargetElement = document.getElementById("redirection-target");
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
       8 
     | 
    
         
            -
              } else {
         
     | 
| 
       9 
     | 
    
         
            -
                // If the current window is the 'child', change the parent's URL with postMessage
         
     | 
| 
       10 
     | 
    
         
            -
                normalizedLink = document.createElement('a');
         
     | 
| 
       11 
     | 
    
         
            -
                normalizedLink.href = targetInfo.url;
         
     | 
| 
      
 5 
     | 
    
         
            +
                if (!redirectTargetElement) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  return;
         
     | 
| 
      
 7 
     | 
    
         
            +
                }
         
     | 
| 
       12 
8 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                 
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
                var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                if (window.top == window.self) {
         
     | 
| 
      
 12 
     | 
    
         
            +
                  // If the current window is the 'parent', change the URL by setting location.href
         
     | 
| 
      
 13 
     | 
    
         
            +
                  window.top.location.href = targetInfo.url;
         
     | 
| 
      
 14 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 15 
     | 
    
         
            +
                  // If the current window is the 'child', change the parent's URL with postMessage
         
     | 
| 
      
 16 
     | 
    
         
            +
                  normalizedLink = document.createElement('a');
         
     | 
| 
      
 17 
     | 
    
         
            +
                  normalizedLink.href = targetInfo.url;
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  data = JSON.stringify({
         
     | 
| 
      
 20 
     | 
    
         
            +
                    message: 'Shopify.API.remoteRedirect',
         
     | 
| 
      
 21 
     | 
    
         
            +
                    data: {location: normalizedLink.href}
         
     | 
| 
      
 22 
     | 
    
         
            +
                  });
         
     | 
| 
      
 23 
     | 
    
         
            +
                  window.parent.postMessage(data, targetInfo.myshopifyUrl);
         
     | 
| 
      
 24 
     | 
    
         
            +
                }
         
     | 
| 
       18 
25 
     | 
    
         
             
              }
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              document.addEventListener("DOMContentLoaded", redirect);
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              // In the turbolinks context, neither DOMContentLoaded nor turbolinks:load
         
     | 
| 
      
 30 
     | 
    
         
            +
              // consistently fires. This ensures that we at least attempt to fire in the
         
     | 
| 
      
 31 
     | 
    
         
            +
              // turbolinks situation as well.
         
     | 
| 
      
 32 
     | 
    
         
            +
              redirect();
         
     | 
| 
      
 33 
     | 
    
         
            +
            })();
         
     | 
| 
         @@ -14,6 +14,11 @@ module ShopifyApp 
     | 
|
| 
       14 
14 
     | 
    
         
             
                  authenticate
         
     | 
| 
       15 
15 
     | 
    
         
             
                end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
                def enable_cookies
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @shop = sanitized_shop_name
         
     | 
| 
      
 19 
     | 
    
         
            +
                  render_invalid_shop_error unless @shop
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       17 
22 
     | 
    
         
             
                def callback
         
     | 
| 
       18 
23 
     | 
    
         
             
                  if auth_hash
         
     | 
| 
       19 
24 
     | 
    
         
             
                    login_shop
         
     | 
| 
         @@ -37,15 +42,47 @@ module ShopifyApp 
     | 
|
| 
       37 
42 
     | 
    
         
             
                private
         
     | 
| 
       38 
43 
     | 
    
         | 
| 
       39 
44 
     | 
    
         
             
                def authenticate
         
     | 
| 
       40 
     | 
    
         
            -
                   
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
      
 45 
     | 
    
         
            +
                  return render_invalid_shop_error unless sanitized_shop_name.present?
         
     | 
| 
      
 46 
     | 
    
         
            +
                  session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  if redirect_for_cookie_access?
         
     | 
| 
      
 49 
     | 
    
         
            +
                    fullpage_redirect_to enable_cookies_path(shop: sanitized_shop_name)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  elsif authenticate_in_context?
         
     | 
| 
      
 51 
     | 
    
         
            +
                    authenticate_in_context
         
     | 
| 
       43 
52 
     | 
    
         
             
                  else
         
     | 
| 
       44 
     | 
    
         
            -
                     
     | 
| 
       45 
     | 
    
         
            -
                    redirect_to return_address
         
     | 
| 
      
 53 
     | 
    
         
            +
                    authenticate_at_top_level
         
     | 
| 
       46 
54 
     | 
    
         
             
                  end
         
     | 
| 
       47 
55 
     | 
    
         
             
                end
         
     | 
| 
       48 
56 
     | 
    
         | 
| 
      
 57 
     | 
    
         
            +
                def render_invalid_shop_error
         
     | 
| 
      
 58 
     | 
    
         
            +
                  flash[:error] = I18n.t('invalid_shop_url')
         
     | 
| 
      
 59 
     | 
    
         
            +
                  redirect_to return_address
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def authenticate_in_context
         
     | 
| 
      
 63 
     | 
    
         
            +
                  clear_top_level_oauth_cookie
         
     | 
| 
      
 64 
     | 
    
         
            +
                  redirect_to "#{main_app.root_path}auth/shopify"
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                def authenticate_at_top_level
         
     | 
| 
      
 68 
     | 
    
         
            +
                  set_top_level_oauth_cookie
         
     | 
| 
      
 69 
     | 
    
         
            +
                  fullpage_redirect_to login_url(top_level: true)
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def authenticate_in_context?
         
     | 
| 
      
 73 
     | 
    
         
            +
                  return true unless ShopifyApp.configuration.embedded_app?
         
     | 
| 
      
 74 
     | 
    
         
            +
                  return true if params[:top_level]
         
     | 
| 
      
 75 
     | 
    
         
            +
                  session['shopify.top_level_oauth']
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def redirect_for_cookie_access?
         
     | 
| 
      
 79 
     | 
    
         
            +
                  return false unless ShopifyApp.configuration.embedded_app?
         
     | 
| 
      
 80 
     | 
    
         
            +
                  return false if params[:top_level]
         
     | 
| 
      
 81 
     | 
    
         
            +
                  return false if session['shopify.cookies_persist']
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  true
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
       49 
86 
     | 
    
         
             
                def login_shop
         
     | 
| 
       50 
87 
     | 
    
         
             
                  sess = ShopifyAPI::Session.new(shop_name, token)
         
     | 
| 
       51 
88 
     | 
    
         | 
| 
         @@ -0,0 +1,386 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <!DOCTYPE html>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <html lang="<%= I18n.locale %>">
         
     | 
| 
      
 3 
     | 
    
         
            +
            <head>
         
     | 
| 
      
 4 
     | 
    
         
            +
              <meta charset="utf-8" />
         
     | 
| 
      
 5 
     | 
    
         
            +
              <style>
         
     | 
| 
      
 6 
     | 
    
         
            +
                html,
         
     | 
| 
      
 7 
     | 
    
         
            +
                body {
         
     | 
| 
      
 8 
     | 
    
         
            +
                  min-height:100%;
         
     | 
| 
      
 9 
     | 
    
         
            +
                  height:100%; 
         
     | 
| 
      
 10 
     | 
    
         
            +
                  font-size:1.5rem;
         
     | 
| 
      
 11 
     | 
    
         
            +
                  font-weight:400;
         
     | 
| 
      
 12 
     | 
    
         
            +
                  line-height:2rem;
         
     | 
| 
      
 13 
     | 
    
         
            +
                  text-transform:initial;
         
     | 
| 
      
 14 
     | 
    
         
            +
                  letter-spacing:initial;
         
     | 
| 
      
 15 
     | 
    
         
            +
                  font-weight:400;
         
     | 
| 
      
 16 
     | 
    
         
            +
                  color:#212b36;
         
     | 
| 
      
 17 
     | 
    
         
            +
                  font-family:-apple-system, BlinkMacSystemFont, San Francisco, Roboto, Segoe UI, Helvetica Neue, sans-serif;
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                @media (min-width: 40em) {
         
     | 
| 
      
 21 
     | 
    
         
            +
                  html,
         
     | 
| 
      
 22 
     | 
    
         
            +
                  body {
         
     | 
| 
      
 23 
     | 
    
         
            +
                    font-size:1.4rem;
         
     | 
| 
      
 24 
     | 
    
         
            +
                  }
         
     | 
| 
      
 25 
     | 
    
         
            +
                }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                html {
         
     | 
| 
      
 28 
     | 
    
         
            +
                  position:relative;
         
     | 
| 
      
 29 
     | 
    
         
            +
                  font-size:62.5%;
         
     | 
| 
      
 30 
     | 
    
         
            +
                  -webkit-font-smoothing:antialiased;
         
     | 
| 
      
 31 
     | 
    
         
            +
                  -moz-osx-font-smoothing:grayscale;
         
     | 
| 
      
 32 
     | 
    
         
            +
                  -webkit-text-size-adjust:100%;
         
     | 
| 
      
 33 
     | 
    
         
            +
                  -ms-text-size-adjust:100%;
         
     | 
| 
      
 34 
     | 
    
         
            +
                  text-size-adjust:100%;
         
     | 
| 
      
 35 
     | 
    
         
            +
                  text-rendering:optimizeLegibility;
         
     | 
| 
      
 36 
     | 
    
         
            +
                }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                body {
         
     | 
| 
      
 39 
     | 
    
         
            +
                  min-height:100%;
         
     | 
| 
      
 40 
     | 
    
         
            +
                  margin:0;
         
     | 
| 
      
 41 
     | 
    
         
            +
                  padding:0;
         
     | 
| 
      
 42 
     | 
    
         
            +
                  background-color:#f4f6f8;
         
     | 
| 
      
 43 
     | 
    
         
            +
                }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                *,
         
     | 
| 
      
 46 
     | 
    
         
            +
                *::before,
         
     | 
| 
      
 47 
     | 
    
         
            +
                *::after{
         
     | 
| 
      
 48 
     | 
    
         
            +
                  box-sizing:border-box; }
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                h1,
         
     | 
| 
      
 51 
     | 
    
         
            +
                h2,
         
     | 
| 
      
 52 
     | 
    
         
            +
                h3,
         
     | 
| 
      
 53 
     | 
    
         
            +
                h4,
         
     | 
| 
      
 54 
     | 
    
         
            +
                h5,
         
     | 
| 
      
 55 
     | 
    
         
            +
                h6,
         
     | 
| 
      
 56 
     | 
    
         
            +
                p {
         
     | 
| 
      
 57 
     | 
    
         
            +
                  margin:0;
         
     | 
| 
      
 58 
     | 
    
         
            +
                  font-size:1em;
         
     | 
| 
      
 59 
     | 
    
         
            +
                  font-weight:400;
         
     | 
| 
      
 60 
     | 
    
         
            +
                }
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                #CookiePartitionPrompt {
         
     | 
| 
      
 63 
     | 
    
         
            +
                  display: none;
         
     | 
| 
      
 64 
     | 
    
         
            +
                }
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                .Polaris-Page {
         
     | 
| 
      
 67 
     | 
    
         
            +
                  margin:0 auto;
         
     | 
| 
      
 68 
     | 
    
         
            +
                  padding:0;
         
     | 
| 
      
 69 
     | 
    
         
            +
                  max-width:99.8rem; 
         
     | 
| 
      
 70 
     | 
    
         
            +
                }
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                @media (min-width: 30.625em) {
         
     | 
| 
      
 73 
     | 
    
         
            +
                  .Polaris-Page {
         
     | 
| 
      
 74 
     | 
    
         
            +
                    padding:0 2rem;
         
     | 
| 
      
 75 
     | 
    
         
            +
                  }
         
     | 
| 
      
 76 
     | 
    
         
            +
                }
         
     | 
| 
      
 77 
     | 
    
         
            +
                @media (min-width: 46.5em) {
         
     | 
| 
      
 78 
     | 
    
         
            +
                  .Polaris-Page {
         
     | 
| 
      
 79 
     | 
    
         
            +
                    padding:0 3.2rem;
         
     | 
| 
      
 80 
     | 
    
         
            +
                  }
         
     | 
| 
      
 81 
     | 
    
         
            +
                }
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                .Polaris-Page__Content {
         
     | 
| 
      
 84 
     | 
    
         
            +
                  margin:2rem 0;
         
     | 
| 
      
 85 
     | 
    
         
            +
                }
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                @media (min-width: 46.5em) {
         
     | 
| 
      
 88 
     | 
    
         
            +
                  .Polaris-Page__Content {
         
     | 
| 
      
 89 
     | 
    
         
            +
                    margin-top:2rem;
         
     | 
| 
      
 90 
     | 
    
         
            +
                  }
         
     | 
| 
      
 91 
     | 
    
         
            +
                }
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                @media (min-width: 46.5em) {
         
     | 
| 
      
 94 
     | 
    
         
            +
                  .Polaris-Page {
         
     | 
| 
      
 95 
     | 
    
         
            +
                    display: flex;
         
     | 
| 
      
 96 
     | 
    
         
            +
                    justify-content: center;
         
     | 
| 
      
 97 
     | 
    
         
            +
                    align-items: center;
         
     | 
| 
      
 98 
     | 
    
         
            +
                    height: 100vh;
         
     | 
| 
      
 99 
     | 
    
         
            +
                  }
         
     | 
| 
      
 100 
     | 
    
         
            +
                }
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                .Polaris-Layout {
         
     | 
| 
      
 103 
     | 
    
         
            +
                  display:-webkit-box;
         
     | 
| 
      
 104 
     | 
    
         
            +
                  display:-ms-flexbox;
         
     | 
| 
      
 105 
     | 
    
         
            +
                  display:flex;
         
     | 
| 
      
 106 
     | 
    
         
            +
                  -ms-flex-wrap:wrap;
         
     | 
| 
      
 107 
     | 
    
         
            +
                  flex-wrap:wrap;
         
     | 
| 
      
 108 
     | 
    
         
            +
                  -webkit-box-pack:center;
         
     | 
| 
      
 109 
     | 
    
         
            +
                  -ms-flex-pack:center;
         
     | 
| 
      
 110 
     | 
    
         
            +
                  justify-content:center;
         
     | 
| 
      
 111 
     | 
    
         
            +
                  -webkit-box-align:start;
         
     | 
| 
      
 112 
     | 
    
         
            +
                  -ms-flex-align:start;
         
     | 
| 
      
 113 
     | 
    
         
            +
                  align-items:flex-start;
         
     | 
| 
      
 114 
     | 
    
         
            +
                  margin-top:-2rem;
         
     | 
| 
      
 115 
     | 
    
         
            +
                  margin-left:-2rem;
         
     | 
| 
      
 116 
     | 
    
         
            +
                }
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                .Polaris-Layout__Section {
         
     | 
| 
      
 119 
     | 
    
         
            +
                  -webkit-box-flex:2;
         
     | 
| 
      
 120 
     | 
    
         
            +
                  -ms-flex:2 2 48rem;
         
     | 
| 
      
 121 
     | 
    
         
            +
                  flex:2 2 48rem;
         
     | 
| 
      
 122 
     | 
    
         
            +
                  min-width:51%;
         
     | 
| 
      
 123 
     | 
    
         
            +
                }
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                .Polaris-Layout__Section--fullWidth {
         
     | 
| 
      
 126 
     | 
    
         
            +
                  -webkit-box-flex:1;
         
     | 
| 
      
 127 
     | 
    
         
            +
                  -ms-flex:1 1 100%;
         
     | 
| 
      
 128 
     | 
    
         
            +
                  flex:1 1 100%;
         
     | 
| 
      
 129 
     | 
    
         
            +
                }
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                .Polaris-Layout__Section {
         
     | 
| 
      
 132 
     | 
    
         
            +
                  max-width:calc(100% - 2rem);
         
     | 
| 
      
 133 
     | 
    
         
            +
                  margin-top:2rem;
         
     | 
| 
      
 134 
     | 
    
         
            +
                  margin-left:2rem;
         
     | 
| 
      
 135 
     | 
    
         
            +
                }
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                .Polaris-Stack {
         
     | 
| 
      
 138 
     | 
    
         
            +
                  margin-top:-1.6rem;
         
     | 
| 
      
 139 
     | 
    
         
            +
                  margin-left:-1.6rem;
         
     | 
| 
      
 140 
     | 
    
         
            +
                  display:-webkit-box;
         
     | 
| 
      
 141 
     | 
    
         
            +
                  display:-ms-flexbox;
         
     | 
| 
      
 142 
     | 
    
         
            +
                  display:flex;
         
     | 
| 
      
 143 
     | 
    
         
            +
                  -ms-flex-wrap:wrap;
         
     | 
| 
      
 144 
     | 
    
         
            +
                  flex-wrap:wrap;
         
     | 
| 
      
 145 
     | 
    
         
            +
                  -webkit-box-align:stretch;
         
     | 
| 
      
 146 
     | 
    
         
            +
                  -ms-flex-align:stretch;
         
     | 
| 
      
 147 
     | 
    
         
            +
                  align-items:stretch;
         
     | 
| 
      
 148 
     | 
    
         
            +
                }
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                .Polaris-Stack > .Polaris-Stack__Item {
         
     | 
| 
      
 151 
     | 
    
         
            +
                  margin-top:1.6rem;
         
     | 
| 
      
 152 
     | 
    
         
            +
                  margin-left:1.6rem;
         
     | 
| 
      
 153 
     | 
    
         
            +
                  max-width:calc(100% - 1.6rem);
         
     | 
| 
      
 154 
     | 
    
         
            +
                }
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                .Polaris-Stack__Item {
         
     | 
| 
      
 157 
     | 
    
         
            +
                  -webkit-box-flex:0;
         
     | 
| 
      
 158 
     | 
    
         
            +
                  -ms-flex:0 0 auto;
         
     | 
| 
      
 159 
     | 
    
         
            +
                  flex:0 0 auto;
         
     | 
| 
      
 160 
     | 
    
         
            +
                  min-width:0;
         
     | 
| 
      
 161 
     | 
    
         
            +
                }
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                .Polaris-Heading {
         
     | 
| 
      
 164 
     | 
    
         
            +
                  font-size:1.7rem;
         
     | 
| 
      
 165 
     | 
    
         
            +
                  font-weight:600;
         
     | 
| 
      
 166 
     | 
    
         
            +
                  line-height:2.4rem;
         
     | 
| 
      
 167 
     | 
    
         
            +
                  margin:0;
         
     | 
| 
      
 168 
     | 
    
         
            +
                }
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                @media (min-width: 40em) {
         
     | 
| 
      
 171 
     | 
    
         
            +
                  .Polaris-Heading {
         
     | 
| 
      
 172 
     | 
    
         
            +
                    font-size:1.6rem;
         
     | 
| 
      
 173 
     | 
    
         
            +
                  }
         
     | 
| 
      
 174 
     | 
    
         
            +
                }
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                .Polaris-Card {
         
     | 
| 
      
 177 
     | 
    
         
            +
                  overflow:hidden;
         
     | 
| 
      
 178 
     | 
    
         
            +
                  background-color:white;
         
     | 
| 
      
 179 
     | 
    
         
            +
                  box-shadow:0 0 0 1px rgba(63, 63, 68, 0.05), 0 1px 3px 0 rgba(63, 63, 68, 0.15);
         
     | 
| 
      
 180 
     | 
    
         
            +
                }
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                .Polaris-Card + .Polaris-Card {
         
     | 
| 
      
 183 
     | 
    
         
            +
                  margin-top:2rem;
         
     | 
| 
      
 184 
     | 
    
         
            +
                }
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                @media (min-width: 30.625em) {
         
     | 
| 
      
 187 
     | 
    
         
            +
                  .Polaris-Card {
         
     | 
| 
      
 188 
     | 
    
         
            +
                    border-radius:3px;
         
     | 
| 
      
 189 
     | 
    
         
            +
                  }
         
     | 
| 
      
 190 
     | 
    
         
            +
                }
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                .Polaris-Card__Header {
         
     | 
| 
      
 193 
     | 
    
         
            +
                  padding:2rem 2rem 0;
         
     | 
| 
      
 194 
     | 
    
         
            +
                }
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                .Polaris-Card__Section {
         
     | 
| 
      
 197 
     | 
    
         
            +
                  padding:2rem;
         
     | 
| 
      
 198 
     | 
    
         
            +
                }
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                .Polaris-Card__Section + .Polaris-Card__Section {
         
     | 
| 
      
 201 
     | 
    
         
            +
                  border-top:1px solid #dfe3e8;
         
     | 
| 
      
 202 
     | 
    
         
            +
                }
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                .Polaris-Card__Section--subdued {
         
     | 
| 
      
 205 
     | 
    
         
            +
                  background-color:#f9fafb;
         
     | 
| 
      
 206 
     | 
    
         
            +
                }
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                .Polaris-Stack--distributionTrailing {
         
     | 
| 
      
 210 
     | 
    
         
            +
                  -webkit-box-pack:end;
         
     | 
| 
      
 211 
     | 
    
         
            +
                  -ms-flex-pack:end;
         
     | 
| 
      
 212 
     | 
    
         
            +
                  justify-content:flex-end;
         
     | 
| 
      
 213 
     | 
    
         
            +
                }
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                .Polaris-Stack--vertical {
         
     | 
| 
      
 216 
     | 
    
         
            +
                  -webkit-box-orient:vertical;
         
     | 
| 
      
 217 
     | 
    
         
            +
                  -webkit-box-direction:normal;
         
     | 
| 
      
 218 
     | 
    
         
            +
                  -ms-flex-direction:column;
         
     | 
| 
      
 219 
     | 
    
         
            +
                  flex-direction:column;
         
     | 
| 
      
 220 
     | 
    
         
            +
                }
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                .Polaris-Button {
         
     | 
| 
      
 223 
     | 
    
         
            +
                  fill:#637381;
         
     | 
| 
      
 224 
     | 
    
         
            +
                  position:relative;
         
     | 
| 
      
 225 
     | 
    
         
            +
                  display:-webkit-inline-box;
         
     | 
| 
      
 226 
     | 
    
         
            +
                  display:-ms-inline-flexbox;
         
     | 
| 
      
 227 
     | 
    
         
            +
                  display:inline-flex;
         
     | 
| 
      
 228 
     | 
    
         
            +
                  -webkit-box-align:center;
         
     | 
| 
      
 229 
     | 
    
         
            +
                  -ms-flex-align:center;
         
     | 
| 
      
 230 
     | 
    
         
            +
                  align-items:center;
         
     | 
| 
      
 231 
     | 
    
         
            +
                  -webkit-box-pack:center;
         
     | 
| 
      
 232 
     | 
    
         
            +
                  -ms-flex-pack:center;
         
     | 
| 
      
 233 
     | 
    
         
            +
                  justify-content:center;
         
     | 
| 
      
 234 
     | 
    
         
            +
                  min-height:3.6rem;
         
     | 
| 
      
 235 
     | 
    
         
            +
                  min-width:3.6rem;
         
     | 
| 
      
 236 
     | 
    
         
            +
                  margin:0;
         
     | 
| 
      
 237 
     | 
    
         
            +
                  padding:0.7rem 1.6rem;
         
     | 
| 
      
 238 
     | 
    
         
            +
                  background:linear-gradient(to bottom, white, #f9fafb);
         
     | 
| 
      
 239 
     | 
    
         
            +
                  border:1px solid #c4cdd5;
         
     | 
| 
      
 240 
     | 
    
         
            +
                  box-shadow:0 1px 0 0 rgba(22, 29, 37, 0.05);
         
     | 
| 
      
 241 
     | 
    
         
            +
                  border-radius:3px;
         
     | 
| 
      
 242 
     | 
    
         
            +
                  line-height:1;
         
     | 
| 
      
 243 
     | 
    
         
            +
                  color:#212b36;
         
     | 
| 
      
 244 
     | 
    
         
            +
                  text-align:center;
         
     | 
| 
      
 245 
     | 
    
         
            +
                  cursor:pointer;
         
     | 
| 
      
 246 
     | 
    
         
            +
                  -webkit-user-select:none;
         
     | 
| 
      
 247 
     | 
    
         
            +
                  -moz-user-select:none;
         
     | 
| 
      
 248 
     | 
    
         
            +
                  -ms-user-select:none;
         
     | 
| 
      
 249 
     | 
    
         
            +
                  user-select:none;
         
     | 
| 
      
 250 
     | 
    
         
            +
                  text-decoration:none;
         
     | 
| 
      
 251 
     | 
    
         
            +
                  transition-property:background, border, box-shadow;
         
     | 
| 
      
 252 
     | 
    
         
            +
                  transition-duration:200ms;
         
     | 
| 
      
 253 
     | 
    
         
            +
                  transition-timing-function:cubic-bezier(0.64, 0, 0.35, 1);
         
     | 
| 
      
 254 
     | 
    
         
            +
                }
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
                .Polaris-Button:hover {
         
     | 
| 
      
 257 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #f9fafb, #f4f6f8);
         
     | 
| 
      
 258 
     | 
    
         
            +
                  border-color:#c4cdd5;
         
     | 
| 
      
 259 
     | 
    
         
            +
                }
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                .Polaris-Button:focus {
         
     | 
| 
      
 262 
     | 
    
         
            +
                  border-color:#5c6ac4;
         
     | 
| 
      
 263 
     | 
    
         
            +
                  outline:0;
         
     | 
| 
      
 264 
     | 
    
         
            +
                  box-shadow:0 0 0 1px #5c6ac4;
         
     | 
| 
      
 265 
     | 
    
         
            +
                }
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                .Polaris-Button:active {
         
     | 
| 
      
 268 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #f4f6f8, #f4f6f8);
         
     | 
| 
      
 269 
     | 
    
         
            +
                  border-color:#c4cdd5;
         
     | 
| 
      
 270 
     | 
    
         
            +
                  box-shadow:0 0 0 0 transparent, inset 0 1px 1px 0 rgba(99, 115, 129, 0.1), inset 0 1px 4px 0 rgba(99, 115, 129, 0.2);
         
     | 
| 
      
 271 
     | 
    
         
            +
                }
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
                .Polaris-Button.Polaris-Button--disabled {
         
     | 
| 
      
 274 
     | 
    
         
            +
                  fill:#919eab;
         
     | 
| 
      
 275 
     | 
    
         
            +
                  transition:none;
         
     | 
| 
      
 276 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #f4f6f8, #f4f6f8);
         
     | 
| 
      
 277 
     | 
    
         
            +
                  color:#919eab;
         
     | 
| 
      
 278 
     | 
    
         
            +
                }
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
                .Polaris-Button__Content {
         
     | 
| 
      
 281 
     | 
    
         
            +
                  font-size:1.5rem;
         
     | 
| 
      
 282 
     | 
    
         
            +
                  font-weight:400;
         
     | 
| 
      
 283 
     | 
    
         
            +
                  line-height:1.6rem;
         
     | 
| 
      
 284 
     | 
    
         
            +
                  text-transform:initial;
         
     | 
| 
      
 285 
     | 
    
         
            +
                  letter-spacing:initial;
         
     | 
| 
      
 286 
     | 
    
         
            +
                  position:relative;
         
     | 
| 
      
 287 
     | 
    
         
            +
                  display:-webkit-box;
         
     | 
| 
      
 288 
     | 
    
         
            +
                  display:-ms-flexbox;
         
     | 
| 
      
 289 
     | 
    
         
            +
                  display:flex;
         
     | 
| 
      
 290 
     | 
    
         
            +
                  -webkit-box-pack:center;
         
     | 
| 
      
 291 
     | 
    
         
            +
                  -ms-flex-pack:center;
         
     | 
| 
      
 292 
     | 
    
         
            +
                  justify-content:center;
         
     | 
| 
      
 293 
     | 
    
         
            +
                  -webkit-box-align:center;
         
     | 
| 
      
 294 
     | 
    
         
            +
                  -ms-flex-align:center;
         
     | 
| 
      
 295 
     | 
    
         
            +
                  align-items:center;
         
     | 
| 
      
 296 
     | 
    
         
            +
                  min-width:1px;
         
     | 
| 
      
 297 
     | 
    
         
            +
                  min-height:1px;
         
     | 
| 
      
 298 
     | 
    
         
            +
                }
         
     | 
| 
      
 299 
     | 
    
         
            +
                  
         
     | 
| 
      
 300 
     | 
    
         
            +
                @media (min-width: 40em) {
         
     | 
| 
      
 301 
     | 
    
         
            +
                  .Polaris-Button__Content {
         
     | 
| 
      
 302 
     | 
    
         
            +
                    font-size:1.4rem;
         
     | 
| 
      
 303 
     | 
    
         
            +
                  } 
         
     | 
| 
      
 304 
     | 
    
         
            +
                }
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                .Polaris-Button--primary {
         
     | 
| 
      
 307 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #6371c7, #5563c1);
         
     | 
| 
      
 308 
     | 
    
         
            +
                  border-color:#3f4eae;
         
     | 
| 
      
 309 
     | 
    
         
            +
                  box-shadow:inset 0 1px 0 0 #6774c8, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 0 transparent;
         
     | 
| 
      
 310 
     | 
    
         
            +
                  color:white;
         
     | 
| 
      
 311 
     | 
    
         
            +
                  fill:white;
         
     | 
| 
      
 312 
     | 
    
         
            +
                }
         
     | 
| 
      
 313 
     | 
    
         
            +
             
     | 
| 
      
 314 
     | 
    
         
            +
                .Polaris-Button--primary:hover {
         
     | 
| 
      
 315 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #5c6ac4, #4959bd);
         
     | 
| 
      
 316 
     | 
    
         
            +
                  border-color:#3f4eae;
         
     | 
| 
      
 317 
     | 
    
         
            +
                  color:white;
         
     | 
| 
      
 318 
     | 
    
         
            +
                  text-decoration:none;
         
     | 
| 
      
 319 
     | 
    
         
            +
                }
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
                .Polaris-Button--primary:focus {
         
     | 
| 
      
 322 
     | 
    
         
            +
                  border-color:#202e78;
         
     | 
| 
      
 323 
     | 
    
         
            +
                  box-shadow:inset 0 1px 0 0 #6f7bcb, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 1px #202e78;
         
     | 
| 
      
 324 
     | 
    
         
            +
                }
         
     | 
| 
      
 325 
     | 
    
         
            +
             
     | 
| 
      
 326 
     | 
    
         
            +
                .Polaris-Button--primary:active {
         
     | 
| 
      
 327 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #3f4eae, #3f4eae);
         
     | 
| 
      
 328 
     | 
    
         
            +
                  border-color:#38469b;
         
     | 
| 
      
 329 
     | 
    
         
            +
                  box-shadow:inset 0 0 0 0 transparent, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 1px 0 #38469b;
         
     | 
| 
      
 330 
     | 
    
         
            +
                }
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
      
 332 
     | 
    
         
            +
                .Polaris-Button--primary.Polaris-Button--disabled {
         
     | 
| 
      
 333 
     | 
    
         
            +
                  fill:white;
         
     | 
| 
      
 334 
     | 
    
         
            +
                  background:linear-gradient(to bottom, #bac0e6, #bac0e6);
         
     | 
| 
      
 335 
     | 
    
         
            +
                  border-color:#a7aedf;
         
     | 
| 
      
 336 
     | 
    
         
            +
                  box-shadow:none;
         
     | 
| 
      
 337 
     | 
    
         
            +
                  color:white;
         
     | 
| 
      
 338 
     | 
    
         
            +
                }
         
     | 
| 
      
 339 
     | 
    
         
            +
              </style>
         
     | 
| 
      
 340 
     | 
    
         
            +
              <base target="_top">
         
     | 
| 
      
 341 
     | 
    
         
            +
              <title>Redirecting…</title>
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
              <script>
         
     | 
| 
      
 344 
     | 
    
         
            +
                window.apiKey = "<%= ShopifyApp.configuration.api_key %>";
         
     | 
| 
      
 345 
     | 
    
         
            +
                window.shopOrigin = "https://<%= @shop %>";
         
     | 
| 
      
 346 
     | 
    
         
            +
              </script>
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
              <%= javascript_include_tag('shopify_app/itp_polyfill', crossorigin: 'anonymous', integrity: true) %>
         
     | 
| 
      
 349 
     | 
    
         
            +
            </head>
         
     | 
| 
      
 350 
     | 
    
         
            +
            <body>
         
     | 
| 
      
 351 
     | 
    
         
            +
              <main id="CookiePartitionPrompt">
         
     | 
| 
      
 352 
     | 
    
         
            +
                <div class="Polaris-Page">
         
     | 
| 
      
 353 
     | 
    
         
            +
                  <div class="Polaris-Page__Content">
         
     | 
| 
      
 354 
     | 
    
         
            +
                    <div class="Polaris-Layout">
         
     | 
| 
      
 355 
     | 
    
         
            +
                      <div class="Polaris-Layout__Section">
         
     | 
| 
      
 356 
     | 
    
         
            +
                        <div class="Polaris-Stack Polaris-Stack--vertical">
         
     | 
| 
      
 357 
     | 
    
         
            +
                          <div class="Polaris-Stack__Item">
         
     | 
| 
      
 358 
     | 
    
         
            +
                            <div class="Polaris-Card">
         
     | 
| 
      
 359 
     | 
    
         
            +
                              <div class="Polaris-Card__Header">
         
     | 
| 
      
 360 
     | 
    
         
            +
                                <h1 class="Polaris-Heading"><%= I18n.t('enable_cookies_heading', app: ShopifyApp.configuration.application_name) %></h1>
         
     | 
| 
      
 361 
     | 
    
         
            +
                              </div>
         
     | 
| 
      
 362 
     | 
    
         
            +
                              <div class="Polaris-Card__Section">
         
     | 
| 
      
 363 
     | 
    
         
            +
                                <p><%= I18n.t('enable_cookies_body', app: ShopifyApp.configuration.application_name) %></p>
         
     | 
| 
      
 364 
     | 
    
         
            +
                              </div>
         
     | 
| 
      
 365 
     | 
    
         
            +
                              <div class="Polaris-Card__Section Polaris-Card__Section--subdued">
         
     | 
| 
      
 366 
     | 
    
         
            +
                                <p><%= I18n.t('enable_cookies_footer') %></p>
         
     | 
| 
      
 367 
     | 
    
         
            +
                              </div>
         
     | 
| 
      
 368 
     | 
    
         
            +
                            </div>
         
     | 
| 
      
 369 
     | 
    
         
            +
                          </div>
         
     | 
| 
      
 370 
     | 
    
         
            +
                          <div class="Polaris-Stack__Item">
         
     | 
| 
      
 371 
     | 
    
         
            +
                            <div class="Polaris-Stack Polaris-Stack--distributionTrailing">
         
     | 
| 
      
 372 
     | 
    
         
            +
                              <div class="Polaris-Stack__Item">
         
     | 
| 
      
 373 
     | 
    
         
            +
                                <button type="button" class="Polaris-Button Polaris-Button--primary" id="AcceptCookies">
         
     | 
| 
      
 374 
     | 
    
         
            +
                                  <span class="Polaris-Button__Content"><span><%= I18n.t('enable_cookies_action') %></span></span>
         
     | 
| 
      
 375 
     | 
    
         
            +
                                </button>
         
     | 
| 
      
 376 
     | 
    
         
            +
                              </div>
         
     | 
| 
      
 377 
     | 
    
         
            +
                            </div>
         
     | 
| 
      
 378 
     | 
    
         
            +
                          </div>
         
     | 
| 
      
 379 
     | 
    
         
            +
                        </div>
         
     | 
| 
      
 380 
     | 
    
         
            +
                      </div>
         
     | 
| 
      
 381 
     | 
    
         
            +
                    </div>
         
     | 
| 
      
 382 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 383 
     | 
    
         
            +
                </div>
         
     | 
| 
      
 384 
     | 
    
         
            +
              </main>
         
     | 
| 
      
 385 
     | 
    
         
            +
            </body>
         
     | 
| 
      
 386 
     | 
    
         
            +
            </html>
         
     | 
    
        data/config/locales/en.yml
    CHANGED
    
    | 
         @@ -2,3 +2,7 @@ en: 
     | 
|
| 
       2 
2 
     | 
    
         
             
              logged_out: 'Successfully logged out'
         
     | 
| 
       3 
3 
     | 
    
         
             
              could_not_log_in: 'Could not log in to Shopify store'
         
     | 
| 
       4 
4 
     | 
    
         
             
              invalid_shop_url: 'Invalid shop domain'
         
     | 
| 
      
 5 
     | 
    
         
            +
              enable_cookies_heading: "Enable cookies from %{app}"
         
     | 
| 
      
 6 
     | 
    
         
            +
              enable_cookies_body: "You must manually enable cookies in this browser in order to use %{app} within Shopify."
         
     | 
| 
      
 7 
     | 
    
         
            +
              enable_cookies_footer: 'Cookies let the app authenticate you by temporarily storing your preferences and personal information. They expire after 30 days.'
         
     | 
| 
      
 8 
     | 
    
         
            +
              enable_cookies_action: 'Enable cookies'
         
     | 
    
        data/config/routes.rb
    CHANGED
    
    | 
         @@ -2,6 +2,7 @@ ShopifyApp::Engine.routes.draw do 
     | 
|
| 
       2 
2 
     | 
    
         
             
              controller :sessions do
         
     | 
| 
       3 
3 
     | 
    
         
             
                get 'login' => :new, :as => :login
         
     | 
| 
       4 
4 
     | 
    
         
             
                post 'login' => :create, :as => :authenticate
         
     | 
| 
      
 5 
     | 
    
         
            +
                get 'enable_cookies' => :enable_cookies, :as => :enable_cookies
         
     | 
| 
       5 
6 
     | 
    
         
             
                get 'auth/shopify/callback' => :callback
         
     | 
| 
       6 
7 
     | 
    
         
             
                get 'logout' => :destroy, :as => :logout
         
     | 
| 
       7 
8 
     | 
    
         
             
              end
         
     | 
| 
         @@ -5,11 +5,11 @@ 
     | 
|
| 
       5 
5 
     | 
    
         
             
              if (!document.documentElement.hasAttribute("data-turbolinks-preview")) {
         
     | 
| 
       6 
6 
     | 
    
         
             
                document.addEventListener(eventName, function flash() {
         
     | 
| 
       7 
7 
     | 
    
         
             
                  <% if flash[:notice] %>
         
     | 
| 
       8 
     | 
    
         
            -
                    ShopifyApp.flashNotice( 
     | 
| 
      
 8 
     | 
    
         
            +
                    ShopifyApp.flashNotice(<%== flash[:notice].to_json %>);
         
     | 
| 
       9 
9 
     | 
    
         
             
                  <% end %>
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                  <% if flash[:error] %>
         
     | 
| 
       12 
     | 
    
         
            -
                    ShopifyApp.flashError( 
     | 
| 
      
 12 
     | 
    
         
            +
                    ShopifyApp.flashError(<%== flash[:error].to_json %>);
         
     | 
| 
       13 
13 
     | 
    
         
             
                  <% end %>
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                  document.removeEventListener(eventName, flash)
         
     | 
| 
         @@ -5,19 +5,19 @@ module ShopifyApp 
     | 
|
| 
       5 
5 
     | 
    
         
             
                class ShopifyDomainNotFound < StandardError; end
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
                included do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  after_action :set_test_cookie
         
     | 
| 
       8 
9 
     | 
    
         
             
                  rescue_from ActiveResource::UnauthorizedAccess, :with => :close_session
         
     | 
| 
       9 
10 
     | 
    
         
             
                end
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
                def shopify_session
         
     | 
| 
       12 
     | 
    
         
            -
                   
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                     
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    redirect_to_login
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return redirect_to_login unless shop_session
         
     | 
| 
      
 14 
     | 
    
         
            +
                  clear_top_level_oauth_cookie
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 17 
     | 
    
         
            +
                    ShopifyAPI::Base.activate_session(shop_session)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 19 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 20 
     | 
    
         
            +
                    ShopifyAPI::Base.clear_session
         
     | 
| 
       21 
21 
     | 
    
         
             
                  end
         
     | 
| 
       22 
22 
     | 
    
         
             
                end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
         @@ -28,8 +28,7 @@ module ShopifyApp 
     | 
|
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                def login_again_if_different_shop
         
     | 
| 
       30 
30 
     | 
    
         
             
                  if shop_session && params[:shop] && params[:shop].is_a?(String) && (shop_session.url != params[:shop])
         
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
       32 
     | 
    
         
            -
                    session[:shopify_domain] = nil
         
     | 
| 
      
 31 
     | 
    
         
            +
                    clear_shop_session
         
     | 
| 
       33 
32 
     | 
    
         
             
                    redirect_to_login
         
     | 
| 
       34 
33 
     | 
    
         
             
                  end
         
     | 
| 
       35 
34 
     | 
    
         
             
                end
         
     | 
| 
         @@ -48,25 +47,42 @@ module ShopifyApp 
     | 
|
| 
       48 
47 
     | 
    
         
             
                end
         
     | 
| 
       49 
48 
     | 
    
         | 
| 
       50 
49 
     | 
    
         
             
                def close_session
         
     | 
| 
      
 50 
     | 
    
         
            +
                  clear_shop_session
         
     | 
| 
      
 51 
     | 
    
         
            +
                  redirect_to login_url
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def clear_shop_session
         
     | 
| 
       51 
55 
     | 
    
         
             
                  session[:shopify] = nil
         
     | 
| 
       52 
56 
     | 
    
         
             
                  session[:shopify_domain] = nil
         
     | 
| 
       53 
     | 
    
         
            -
                   
     | 
| 
      
 57 
     | 
    
         
            +
                  session[:shopify_user] = nil
         
     | 
| 
       54 
58 
     | 
    
         
             
                end
         
     | 
| 
       55 
59 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                def login_url
         
     | 
| 
      
 60 
     | 
    
         
            +
                def login_url(top_level: false)
         
     | 
| 
       57 
61 
     | 
    
         
             
                  url = ShopifyApp.configuration.login_url
         
     | 
| 
       58 
62 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                   
     | 
| 
       60 
     | 
    
         
            -
                    query = { shop: sanitized_params[:shop] }.to_query
         
     | 
| 
       61 
     | 
    
         
            -
                    url = "#{url}?#{query}"
         
     | 
| 
       62 
     | 
    
         
            -
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  query_params = login_url_params(top_level: top_level)
         
     | 
| 
       63 
64 
     | 
    
         | 
| 
      
 65 
     | 
    
         
            +
                  url = "#{url}?#{query_params.to_query}" if query_params.present?
         
     | 
| 
       64 
66 
     | 
    
         
             
                  url
         
     | 
| 
       65 
67 
     | 
    
         
             
                end
         
     | 
| 
       66 
68 
     | 
    
         | 
| 
      
 69 
     | 
    
         
            +
                def login_url_params(top_level:)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  query_params = {}
         
     | 
| 
      
 71 
     | 
    
         
            +
                  query_params[:shop] = sanitized_params[:shop] if params[:shop].present?
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  has_referer_shop_name = referer_sanitized_shop_name.present?
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  if has_referer_shop_name
         
     | 
| 
      
 76 
     | 
    
         
            +
                    query_params[:shop] ||= referer_sanitized_shop_name
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  query_params[:top_level] = true if top_level
         
     | 
| 
      
 80 
     | 
    
         
            +
                  query_params
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
       67 
83 
     | 
    
         
             
                def fullpage_redirect_to(url)
         
     | 
| 
       68 
84 
     | 
    
         
             
                  if ShopifyApp.configuration.embedded_app?
         
     | 
| 
       69 
     | 
    
         
            -
                    render 'shopify_app/shared/redirect', locals: { url: url, current_shopify_domain: current_shopify_domain }
         
     | 
| 
      
 85 
     | 
    
         
            +
                    render 'shopify_app/shared/redirect', layout: false, locals: { url: url, current_shopify_domain: current_shopify_domain }
         
     | 
| 
       70 
86 
     | 
    
         
             
                  else
         
     | 
| 
       71 
87 
     | 
    
         
             
                    redirect_to url
         
     | 
| 
       72 
88 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -83,6 +99,17 @@ module ShopifyApp 
     | 
|
| 
       83 
99 
     | 
    
         
             
                  @sanitized_shop_name ||= sanitize_shop_param(params)
         
     | 
| 
       84 
100 
     | 
    
         
             
                end
         
     | 
| 
       85 
101 
     | 
    
         | 
| 
      
 102 
     | 
    
         
            +
                def referer_sanitized_shop_name
         
     | 
| 
      
 103 
     | 
    
         
            +
                  return unless request.referer.present?
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  @referer_sanitized_shop_name ||= begin
         
     | 
| 
      
 106 
     | 
    
         
            +
                    referer_uri = URI(request.referer)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    query_params = Rack::Utils.parse_query(referer_uri.query)
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                    sanitize_shop_param(query_params.with_indifferent_access)
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
       86 
113 
     | 
    
         
             
                def sanitize_shop_param(params)
         
     | 
| 
       87 
114 
     | 
    
         
             
                  return unless params[:shop].present?
         
     | 
| 
       88 
115 
     | 
    
         
             
                  ShopifyApp::Utils.sanitize_shop_domain(params[:shop])
         
     | 
| 
         @@ -95,5 +122,18 @@ module ShopifyApp 
     | 
|
| 
       95 
122 
     | 
    
         
             
                    end
         
     | 
| 
       96 
123 
     | 
    
         
             
                  end
         
     | 
| 
       97 
124 
     | 
    
         
             
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                def set_test_cookie
         
     | 
| 
      
 127 
     | 
    
         
            +
                  return unless ShopifyApp.configuration.embedded_app?
         
     | 
| 
      
 128 
     | 
    
         
            +
                  session['shopify.cookies_persist'] = true
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                def clear_top_level_oauth_cookie
         
     | 
| 
      
 132 
     | 
    
         
            +
                  session.delete('shopify.top_level_oauth')
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                def set_top_level_oauth_cookie
         
     | 
| 
      
 136 
     | 
    
         
            +
                  session['shopify.top_level_oauth'] = true
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
       98 
138 
     | 
    
         
             
              end
         
     | 
| 
       99 
139 
     | 
    
         
             
            end
         
     | 
    
        data/lib/shopify_app/engine.rb
    CHANGED
    
    | 
         @@ -4,7 +4,10 @@ module ShopifyApp 
     | 
|
| 
       4 
4 
     | 
    
         
             
                isolate_namespace ShopifyApp
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
                initializer "shopify_app.assets.precompile" do |app|
         
     | 
| 
       7 
     | 
    
         
            -
                  app.config.assets.precompile += %w 
     | 
| 
      
 7 
     | 
    
         
            +
                  app.config.assets.precompile += %w[
         
     | 
| 
      
 8 
     | 
    
         
            +
                    shopify_app/redirect.js
         
     | 
| 
      
 9 
     | 
    
         
            +
                    shopify_app/itp_polyfill.js
         
     | 
| 
      
 10 
     | 
    
         
            +
                  ]
         
     | 
| 
       8 
11 
     | 
    
         
             
                end
         
     | 
| 
       9 
12 
     | 
    
         
             
              end
         
     | 
| 
       10 
13 
     | 
    
         
             
            end
         
     | 
    
        data/lib/shopify_app/version.rb
    CHANGED
    
    
    
        data/translation.yml
    ADDED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: shopify_app
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 8. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 8.3.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Shopify
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2018- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2018-09-10 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rails
         
     | 
| 
         @@ -130,16 +130,19 @@ extra_rdoc_files: [] 
     | 
|
| 
       130 
130 
     | 
    
         
             
            files:
         
     | 
| 
       131 
131 
     | 
    
         
             
            - ".github/ISSUE_TEMPLATE.md"
         
     | 
| 
       132 
132 
     | 
    
         
             
            - ".gitignore"
         
     | 
| 
      
 133 
     | 
    
         
            +
            - ".rubocop.yml"
         
     | 
| 
       133 
134 
     | 
    
         
             
            - ".travis.yml"
         
     | 
| 
       134 
135 
     | 
    
         
             
            - CHANGELOG.md
         
     | 
| 
       135 
136 
     | 
    
         
             
            - Gemfile
         
     | 
| 
       136 
137 
     | 
    
         
             
            - LICENSE
         
     | 
| 
       137 
138 
     | 
    
         
             
            - README.md
         
     | 
| 
       138 
139 
     | 
    
         
             
            - Rakefile
         
     | 
| 
      
 140 
     | 
    
         
            +
            - app/assets/javascripts/shopify_app/itp_polyfill.js
         
     | 
| 
       139 
141 
     | 
    
         
             
            - app/assets/javascripts/shopify_app/redirect.js
         
     | 
| 
       140 
142 
     | 
    
         
             
            - app/controllers/shopify_app/authenticated_controller.rb
         
     | 
| 
       141 
143 
     | 
    
         
             
            - app/controllers/shopify_app/sessions_controller.rb
         
     | 
| 
       142 
144 
     | 
    
         
             
            - app/controllers/shopify_app/webhooks_controller.rb
         
     | 
| 
      
 145 
     | 
    
         
            +
            - app/views/shopify_app/sessions/enable_cookies.html.erb
         
     | 
| 
       143 
146 
     | 
    
         
             
            - app/views/shopify_app/sessions/new.html.erb
         
     | 
| 
       144 
147 
     | 
    
         
             
            - app/views/shopify_app/shared/redirect.html.erb
         
     | 
| 
       145 
148 
     | 
    
         
             
            - config/locales/de.yml
         
     | 
| 
         @@ -198,6 +201,7 @@ files: 
     | 
|
| 
       198 
201 
     | 
    
         
             
            - lib/shopify_app/version.rb
         
     | 
| 
       199 
202 
     | 
    
         
             
            - shipit.rubygems.yml
         
     | 
| 
       200 
203 
     | 
    
         
             
            - shopify_app.gemspec
         
     | 
| 
      
 204 
     | 
    
         
            +
            - translation.yml
         
     | 
| 
       201 
205 
     | 
    
         
             
            homepage: 
         
     | 
| 
       202 
206 
     | 
    
         
             
            licenses: []
         
     | 
| 
       203 
207 
     | 
    
         
             
            metadata: {}
         
     |