diff --git a/app/controllers/admin/subscriptions_controller.rb b/app/controllers/admin/subscriptions_controller.rb index 3b892e2..c3ff1e4 100644 --- a/app/controllers/admin/subscriptions_controller.rb +++ b/app/controllers/admin/subscriptions_controller.rb @@ -16,6 +16,18 @@ module DiscoursePatrons return render_json_error e.message end end + + def destroy + begin + subscription = ::Stripe::Subscription.delete(params[:id]) + + render_json_dump subscription + + rescue ::Stripe::InvalidRequestError => e + return render_json_error e.message + end + end + end end end diff --git a/assets/javascripts/discourse/models/admin-subscription.js.es6 b/assets/javascripts/discourse/models/admin-subscription.js.es6 index e22ffd2..c464d80 100644 --- a/assets/javascripts/discourse/models/admin-subscription.js.es6 +++ b/assets/javascripts/discourse/models/admin-subscription.js.es6 @@ -2,6 +2,11 @@ import computed from "ember-addons/ember-computed-decorators"; import { ajax } from "discourse/lib/ajax"; const AdminSubscription = Discourse.Model.extend({ + @computed("status") + canceled(status) { + return status === "canceled"; + }, + @computed("metadata") metadataUserExists(metadata) { return metadata.user_id && metadata.username; @@ -12,6 +17,12 @@ const AdminSubscription = Discourse.Model.extend({ return Discourse.getURL( `/admin/users/${metadata.user_id}/${metadata.username}` ); + }, + + destroy() { + return ajax(`/patrons/admin/subscriptions/${this.id}`, { + method: "delete" + }).then(result => AdminSubscription.create(result)); } }); diff --git a/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-subscriptions.js.es6 b/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-subscriptions.js.es6 index ee7ea64..7644224 100644 --- a/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-subscriptions.js.es6 +++ b/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-subscriptions.js.es6 @@ -3,5 +3,27 @@ import AdminSubscription from "discourse/plugins/discourse-patrons/discourse/mod export default Discourse.Route.extend({ model() { return AdminSubscription.find(); + }, + + actions: { + cancelSubscription(subscription) { + bootbox.confirm( + I18n.t( + "discourse_patrons.user.subscriptions.operations.destroy.confirm" + ), + I18n.t("no_value"), + I18n.t("yes_value"), + confirmed => { + if (confirmed) { + subscription + .destroy() + .then(result => subscription.set("status", result.status)) + .catch(data => + bootbox.alert(data.jqXHR.responseJSON.errors.join("\n")) + ); + } + } + ); + } } }); diff --git a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-subscriptions.hbs b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-subscriptions.hbs index 86ca6aa..2f62c27 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-subscriptions.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-subscriptions.hbs @@ -7,6 +7,7 @@ {{i18n 'discourse_patrons.admin.subscriptions.subscription.plan'}} {{i18n 'discourse_patrons.admin.subscriptions.subscription.status'}} {{i18n 'discourse_patrons.admin.subscriptions.subscription.created_at'}} + {{#each model as |subscription|}} @@ -22,6 +23,7 @@ {{subscription.plan.id}} {{subscription.status}} {{format-unix-date subscription.created}} + {{d-button disabled=subscription.canceled label="cancel" action=(route-action "cancelSubscription" subscription) icon="times"}} {{/each}} diff --git a/config/routes.rb b/config/routes.rb index ca478bb..760bb23 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,7 +8,7 @@ DiscoursePatrons::Engine.routes.draw do namespace :admin do resources :plans - resources :subscriptions, only: [:index] + resources :subscriptions, only: [:index, :destroy] resources :products end diff --git a/plugin.rb b/plugin.rb index 9bc643d..eecf5bd 100644 --- a/plugin.rb +++ b/plugin.rb @@ -27,7 +27,6 @@ add_admin_route 'discourse_patrons.title', 'discourse-patrons.products' Discourse::Application.routes.append do get '/admin/plugins/discourse-patrons' => 'admin/plugins#index' - get '/admin/plugins/discourse-patrons/dashboard' => 'admin/plugins#index' get '/admin/plugins/discourse-patrons/products' => 'admin/plugins#index' get '/admin/plugins/discourse-patrons/products/:product_id' => 'admin/plugins#index' get '/admin/plugins/discourse-patrons/products/:product_id/plans' => 'admin/plugins#index' diff --git a/spec/requests/admin/subscriptions_controller_spec.rb b/spec/requests/admin/subscriptions_controller_spec.rb index 3ef8d4c..2f14649 100644 --- a/spec/requests/admin/subscriptions_controller_spec.rb +++ b/spec/requests/admin/subscriptions_controller_spec.rb @@ -14,6 +14,11 @@ module DiscoursePatrons get "/patrons/admin/subscriptions.json" expect(response.status).to eq(403) end + + it "does not destroy a subscription" do + ::Stripe::Subscription.expects(:delete).never + patch "/patrons/admin/subscriptions/sub_12345.json" + end end context 'authenticated' do @@ -21,10 +26,19 @@ module DiscoursePatrons before { sign_in(admin) } - it "gets the empty subscriptions" do - ::Stripe::Subscription.expects(:list) - get "/patrons/admin/subscriptions.json" - expect(response.status).to eq(200) + describe "index" do + it "gets the subscriptions" do + ::Stripe::Subscription.expects(:list) + get "/patrons/admin/subscriptions.json" + expect(response.status).to eq(200) + end + end + + describe "destroy" do + it "deletes a subscription" do + ::Stripe::Subscription.expects(:delete).with('sub_12345') + delete "/patrons/admin/subscriptions/sub_12345.json" + end end end end