From 6499d17cb120248c99997402091bc22434ffdad3 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Fri, 16 Jun 2017 11:37:54 +1000 Subject: [PATCH] Adding feature toggle config variable for Stripe Connect --- .../stripe_connect_settings_controller.rb | 39 ++++++++ .../spree/app_configuration_decorator.rb | 3 + ...d_stripe_connect_settings.html.haml.deface | 4 + .../stripe_connect_settings/edit.html.haml | 50 +++++++++++ config/locales/en.yml | 26 ++++++ config/routes.rb | 2 + ...stripe_connect_settings_controller_spec.rb | 89 +++++++++++++++++++ 7 files changed, 213 insertions(+) create mode 100644 app/controllers/admin/stripe_connect_settings_controller.rb create mode 100644 app/overrides/spree/admin/shared/_configuration_menu/add_stripe_connect_settings.html.haml.deface create mode 100644 app/views/admin/stripe_connect_settings/edit.html.haml create mode 100644 spec/controllers/admin/stripe_connect_settings_controller_spec.rb diff --git a/app/controllers/admin/stripe_connect_settings_controller.rb b/app/controllers/admin/stripe_connect_settings_controller.rb new file mode 100644 index 0000000000..4e81f89e3c --- /dev/null +++ b/app/controllers/admin/stripe_connect_settings_controller.rb @@ -0,0 +1,39 @@ +module Admin + class StripeConnectSettingsController < Spree::Admin::BaseController + before_filter :load_settings, only: [:edit] + + def edit + begin + return @stripe_account = { status: :empty_api_key } if Stripe.api_key.blank? + attrs = [:id, :business_name, :charges_enabled] + @obfuscated_secret_key = obfuscated_secret_key + @stripe_account = Stripe::Account.retrieve.to_hash.slice(*attrs).merge(status: :ok) + rescue Stripe::AuthenticationError => e + @stripe_account = { status: :auth_fail } + end + end + + def update + Spree::Config.set(params[:settings]) + resource = t('admin.controllers.stripe_connect_settings.resource') + flash[:success] = t(:successfully_updated, :resource => resource) + redirect_to_edit + end + + private + + def load_settings + klass = Struct.new(:stripe_connect_enabled) + @settings = klass.new(Spree::Config[:stripe_connect_enabled]) + end + + def redirect_to_edit + redirect_to main_app.edit_admin_stripe_connect_settings_path + end + + def obfuscated_secret_key + key = Stripe.api_key + key.first(8) + "****" + key.last(4) + end + end +end diff --git a/app/models/spree/app_configuration_decorator.rb b/app/models/spree/app_configuration_decorator.rb index 925106f3db..a702cecf15 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/app/models/spree/app_configuration_decorator.rb @@ -39,4 +39,7 @@ Spree::AppConfiguration.class_eval do # Invoices & Receipts preference :invoice_style2?, :boolean, default: false preference :enable_receipt_printing?, :boolean, default: false + + # Stripe Connect + preference :stripe_connect_enabled, :boolean, default: false end diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_stripe_connect_settings.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_stripe_connect_settings.html.haml.deface new file mode 100644 index 0000000000..c7b3f4789a --- /dev/null +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_stripe_connect_settings.html.haml.deface @@ -0,0 +1,4 @@ +// insert_bottom "[data-hook='admin_configurations_sidebar_menu']" + +%li + = link_to t('.stripe_connect'), main_app.edit_admin_stripe_connect_settings_path diff --git a/app/views/admin/stripe_connect_settings/edit.html.haml b/app/views/admin/stripe_connect_settings/edit.html.haml new file mode 100644 index 0000000000..bd5d32cf6c --- /dev/null +++ b/app/views/admin/stripe_connect_settings/edit.html.haml @@ -0,0 +1,50 @@ += render :partial => 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t('.title') + +%fieldset.no-border-bottom + %legend + = t('.settings') + = form_for @settings, as: :settings, url: main_app.admin_stripe_connect_settings_path, :method => :put do |f| + .row + .twelve.columns.alpha.omega + .field + - disabled = !@settings.stripe_connect_enabled && @stripe_account[:status] != :ok + = f.label :stripe_connect_enabled, t('.stripe_connect_enabled') + = f.check_box :stripe_connect_enabled, disabled: disabled + .row + .twelve.columns.alpha.omega.form-buttons{"data-hook" => "buttons"} + = button t(:update), 'icon-refresh', value: "update" + +%fieldset.no-border-bottom + %legend= t('.status') + - if @stripe_account[:status] == :ok + .alert-box.ok + .status + %strong= t(".status") + ":" + = t(".ok") + %i.icon-ok + .business_name + %strong= t(".business_name") + ":" + = @stripe_account[:business_name] + .charges_enabled + %strong + - enabled_text = t(@stripe_account[:charges_enabled] ? :say_yes : :say_no) + = t(".charges_enabled") + ":" + = enabled_text + .account_id + %strong= t(".account_id") + ":" + = @stripe_account[:id] + .secret_key + %strong= t('.instance_secret_key') + ":" + = @obfuscated_secret_key + .publishable_key + %strong= t('.instance_publishable_key') + ":" + = ENV["STRIPE_INSTANCE_PUBLISHABLE_KEY"] + - if !@stripe_account[:charges_enabled] + .alert-box.warning + = t(".charges_enabled_warning") + - else + .alert-box.error + = t(".#{@stripe_account[:status]}_error") diff --git a/config/locales/en.yml b/config/locales/en.yml index 66be05de9f..a92f6fc59b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -665,6 +665,7 @@ en: shared: user_guide_link: user_guide: User Guide + invoice_settings: edit: title: Invoice Settings @@ -735,6 +736,28 @@ en: description: Invoices for import into Xero packing: name: Packing Reports + + stripe_connect_settings: + edit: + title: "Stripe Connect" + settings: "Settings" + stripe_connect_enabled: Enable shops to accept payments using Stripe Connect? + no_api_key_msg: No Stripe account exists for this enterprise. + status: Status + ok: Ok + instance_secret_key: Instance Secret Key + account_id: Account ID + business_name: Business Name + charges_enabled: Charges Enabled + charges_enabled_warning: "Warning: Charges are not enabled for your account" + auth_fail_error: The API key you provided is invalid + empty_api_key_error: No Stripe API key has been provided. To set your API key, please follow the instructions at + + # Admin controllers + controllers: + stripe_connect_settings: + resource: Stripe Connect configuration + # Frontend views # # These keys are referenced relatively like `t('.message')` in @@ -2120,6 +2143,9 @@ Please follow the instructions there to make your enterprise visible on the Open bulk_coop_allocation: 'Bulk Co-op - Allocation' bulk_coop_packing_sheets: 'Bulk Co-op - Packing Sheets' bulk_coop_customer_payments: 'Bulk Co-op - Customer Payments' + shared: + configuration_menu: + stripe_connect: Stripe Connect variants: autocomplete: producer_name: Producer diff --git a/config/routes.rb b/config/routes.rb index cf6f6bda4f..bb1422063c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -171,6 +171,8 @@ Openfoodnetwork::Application.routes.draw do end resource :invoice_settings, only: [:edit, :update] + + resource :stripe_connect_settings, only: [:edit, :update] end namespace :api do diff --git a/spec/controllers/admin/stripe_connect_settings_controller_spec.rb b/spec/controllers/admin/stripe_connect_settings_controller_spec.rb new file mode 100644 index 0000000000..6a029d2bf7 --- /dev/null +++ b/spec/controllers/admin/stripe_connect_settings_controller_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe Admin::StripeConnectSettingsController, type: :controller do + let(:user) { create(:user) } + let(:admin) { create(:admin_user) } + + before do + Spree::Config.set(stripe_connect_enabled: true) + end + + describe "edit" do + context "as an enterprise user" do + before { allow(controller).to receive(:spree_current_user) { user } } + + it "does not allow access" do + spree_get :edit + expect(response).to redirect_to spree.unauthorized_path + end + end + + context "as super admin" do + before { allow(controller).to receive(:spree_current_user) { admin } } + + context "when a Stripe API key is not set" do + before { Stripe.api_key = nil } + + it "sets the account status to :empty_api_key" do + spree_get :edit + expect(assigns(:stripe_account)[:status]).to eq :empty_api_key + expect(assigns(:settings).stripe_connect_enabled).to be true + end + end + + context "when a Stripe API key is set" do + before { Stripe.api_key = "sk_test_xxxx" } + + context "and the request to retrieve Stripe account info fails" do + before do + stub_request(:get, "https://api.stripe.com/v1/account"). + to_return(:status => 401, :body => "{\"error\": {\"message\": \"Invalid API Key provided: sk_test_****xxxx\"}}") + end + + it "sets the account status to :auth_fail" do + spree_get :edit + expect(assigns(:stripe_account)[:status]).to eq :auth_fail + expect(assigns(:settings).stripe_connect_enabled).to be true + end + end + + context "and the request to retrieve Stripe account info succeeds" do + before do + stub_request(:get, "https://api.stripe.com/v1/account"). + to_return(:status => 200, :body => "{ \"id\": \"acct_1234\", \"business_name\": \"OFN\" }") + end + + it "sets the account status to :ok, loads settings into Struct" do + spree_get :edit + expect(assigns(:stripe_account)[:status]).to eq :ok + expect(assigns(:obfuscated_secret_key)).to eq "sk_test_****xxxx" + expect(assigns(:settings).stripe_connect_enabled).to be true + end + end + end + end + end + + describe "update" do + let(:params) { { settings: { stripe_connect_enabled: false } } } + + context "as an enterprise user" do + before { allow(controller).to receive(:spree_current_user) { user } } + + it "does not allow access" do + spree_get :update, params + expect(response).to redirect_to spree.unauthorized_path + end + end + + context "as super admin" do + before {allow(controller).to receive(:spree_current_user) { admin } } + + it "sets global config to the specified values" do + expect(Spree::Config.stripe_connect_enabled).to be true + spree_get :update, params + expect(Spree::Config.stripe_connect_enabled).to be false + end + end + end +end