module Sinatra::Shopify

Public Class Methods

registered(app) click to toggle source
# File lib/sinatra/shopify-sinatra-app.rb, line 123
def self.registered(app)
  app.helpers Shopify::Methods
  app.register Sinatra::ActiveRecordExtension

  app.set :database_file, File.expand_path('config/database.yml')

  app.set :erb, layout: :'layouts/application'
  app.set :views, File.expand_path('views')
  app.set :public_folder, File.expand_path('public')
  app.enable :inline_templates

  app.set :api_version, '2019-07'
  app.set :scope, 'read_products, read_orders'

  app.set :api_key, ENV['SHOPIFY_API_KEY']
  app.set :shared_secret, ENV['SHOPIFY_SHARED_SECRET']
  app.set :secret, ENV['SECRET']

  # csrf needs to be disabled for webhook routes
  app.set :webhook_routes, ['/uninstall']

  # add support for put/patch/delete
  app.use Rack::MethodOverride

  app.use Rack::Session::Cookie, key: 'rack.session',
                                 path: '/',
                                 secure: true,
                                 same_site: 'None',
                                 secret: app.settings.secret,
                                 expire_after: 60 * 30 # half an hour in seconds

  app.use Rack::Protection
  app.use Rack::Protection::AuthenticityToken, allow_if: lambda { |env|
    app.settings.webhook_routes.include?(env["PATH_INFO"])
  }

  OmniAuth.config.allowed_request_methods = [:post]

  app.use OmniAuth::Builder do
    provider :shopify,
      app.settings.api_key,
      app.settings.shared_secret,
      scope: app.settings.scope,
      setup: lambda { |env|
        shop = if env['REQUEST_METHOD'] == 'POST'
          env['rack.request.form_hash']['shop']
        else
          Rack::Utils.parse_query(env['QUERY_STRING'])['shop']
        end

        site_url = "https://#{shop}"
        env['omniauth.strategy'].options[:client_options][:site] = site_url
      }
  end

  ShopifyAPI::Session.setup(
    api_key: app.settings.api_key,
    secret: app.settings.shared_secret
  )

  app.get '/login' do
    erb :login, layout: false
  end

  app.get '/logout' do
    clear_session
    redirect '/login'
  end

  app.get '/auth/shopify/callback' do
    shop_name = params['shop']
    token = request.env['omniauth.auth']['credentials']['token']
    host = params['host']

    shop = Shop.find_or_initialize_by(name: shop_name)
    shop.token = token
    shop.save!

    session[:shopify] = {
      shop: shop_name,
      host: host,
      token: token
    }

    after_shopify_auth()

    return_params = session[:return_params]
    session.delete(:return_params)

    return_to = '/'
    return_to += "?#{return_params.to_query}" if return_params.present?

    redirect return_to
  end

  app.get '/auth/failure' do
    erb "<h1>Authentication Failed:</h1>
         <h3>message:<h3> <pre>#{params}</pre>", layout: false
  end
end

Public Instance Methods

shopify_webhook(route, &blk) click to toggle source
# File lib/sinatra/shopify-sinatra-app.rb, line 116
def shopify_webhook(route, &blk)
  settings.webhook_routes << route
  post(route) do
    receive_webhook(&blk)
  end
end