Author SHA1 Message Date
Nat b1f303a1c8 UX: Surface stripe AuthenticationError on the Admin Dashboard 2024-01-04 15:52:24 +08:00
107 changed files with 2493 additions and 2806 deletions
-1
View File
@@ -1,3 +1,2 @@
< 3.3.0.beta1-dev: 0dcf17de59bdf82c0233bb630dad0ce407d1ae76
3.1.999: c4f8220a5572ef9a42a9a71500e001d0df206c43 3.1.999: c4f8220a5572ef9a42a9a71500e001d0df206c43
2.9.0.beta9: 39b7253c082270e33839f4b0821fbf75abfdd826 2.9.0.beta9: 39b7253c082270e33839f4b0821fbf75abfdd826
+6
View File
@@ -0,0 +1,6 @@
{
"globals": {
"Stripe": true
},
"extends": "eslint-config-discourse"
}
-1
View File
@@ -1 +0,0 @@
module.exports = require("@discourse/lint-configs/eslint");
+1
View File
@@ -0,0 +1 @@
{}
-1
View File
@@ -1 +0,0 @@
module.exports = require("@discourse/lint-configs/prettier");
-1
View File
@@ -1 +0,0 @@
module.exports = require("@discourse/lint-configs/template-lint");
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
plugins: ["ember-template-lint-plugin-discourse"],
extends: "discourse:recommended",
};
+21 -56
View File
@@ -7,71 +7,36 @@ GIT
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
activesupport (7.1.3.2)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
ast (2.4.2) ast (2.4.2)
base64 (0.2.0) json (2.6.2)
bigdecimal (3.1.6) parallel (1.22.1)
concurrent-ruby (1.2.3) parser (3.1.2.1)
connection_pool (2.4.1)
drb (2.2.1)
i18n (1.14.3)
concurrent-ruby (~> 1.0)
racc (~> 1.7)
json (2.7.1)
language_server-protocol (3.17.0.3)
minitest (5.22.2)
mutex_m (0.2.0)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1) ast (~> 2.4.1)
racc prettier_print (1.2.0)
prettier_print (1.2.1)
racc (1.7.3)
rainbow (3.1.1) rainbow (3.1.1)
regexp_parser (2.9.0) regexp_parser (2.6.0)
rexml (3.2.6) rexml (3.2.5)
rubocop (1.62.0) rubocop (1.36.0)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.3.0.2) parser (>= 3.1.2.1)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0) regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0) rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.31.1, < 2.0) rubocop-ast (>= 1.20.1, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0) unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.31.1) rubocop-ast (1.21.0)
parser (>= 3.3.0.4) parser (>= 3.1.1.0)
rubocop-capybara (2.20.0) rubocop-discourse (3.0)
rubocop (~> 1.41) rubocop (>= 1.1.0)
rubocop-discourse (3.7.1) rubocop-rspec (>= 2.0.0)
activesupport (>= 6.1) rubocop-rspec (2.13.2)
rubocop (>= 1.59.0) rubocop (~> 1.33)
rubocop-capybara (>= 2.0.0) ruby-progressbar (1.11.0)
rubocop-factory_bot (>= 2.0.0) syntax_tree (5.1.0)
rubocop-rspec (>= 2.25.0)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-rspec (2.27.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0) prettier_print (>= 1.2.0)
tzinfo (2.0.6) unicode-display_width (2.3.0)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
PLATFORMS PLATFORMS
ruby ruby
@@ -82,4 +47,4 @@ DEPENDENCIES
translations-manager! translations-manager!
BUNDLED WITH BUNDLED WITH
2.5.4 2.3.4
+2
View File
@@ -4,6 +4,8 @@ module DiscourseSubscriptions
module Stripe module Stripe
extend ActiveSupport::Concern extend ActiveSupport::Concern
AUTH_PROBLEM_IDENTIFIER = "#{DiscourseSubscriptions::PLUGIN_NAME}.stripe_auth_error"
def set_api_key def set_api_key
::Stripe.api_key = SiteSetting.discourse_subscriptions_secret_key ::Stripe.api_key = SiteSetting.discourse_subscriptions_secret_key
end end
@@ -5,9 +5,6 @@ module DiscourseSubscriptions
class CouponsController < ::Admin::AdminController class CouponsController < ::Admin::AdminController
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group include DiscourseSubscriptions::Group
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key before_action :set_api_key
def index def index
@@ -5,8 +5,6 @@ module DiscourseSubscriptions
class PlansController < ::Admin::AdminController class PlansController < ::Admin::AdminController
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key before_action :set_api_key
def index def index
@@ -5,8 +5,6 @@ module DiscourseSubscriptions
class ProductsController < ::Admin::AdminController class ProductsController < ::Admin::AdminController
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key before_action :set_api_key
def index def index
@@ -3,8 +3,6 @@
module DiscourseSubscriptions module DiscourseSubscriptions
module Admin module Admin
class SubscriptionsController < ::Admin::AdminController class SubscriptionsController < ::Admin::AdminController
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group include DiscourseSubscriptions::Group
before_action :set_api_key before_action :set_api_key
@@ -2,8 +2,6 @@
module DiscourseSubscriptions module DiscourseSubscriptions
class AdminController < ::Admin::AdminController class AdminController < ::Admin::AdminController
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
def index def index
head 200 head 200
end end
@@ -5,8 +5,6 @@ module DiscourseSubscriptions
include DiscourseSubscriptions::Group include DiscourseSubscriptions::Group
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
layout false layout false
skip_before_action :check_xhr skip_before_action :check_xhr
@@ -4,14 +4,24 @@ module DiscourseSubscriptions
class SubscribeController < ::ApplicationController class SubscribeController < ::ApplicationController
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group include DiscourseSubscriptions::Group
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key before_action :set_api_key
requires_login except: %i[index contributors show] requires_login except: %i[index contributors show]
def index def index
head 200 begin
product_ids = Product.all.pluck(:external_id)
products = []
if product_ids.present? && is_stripe_configured?
response = ::Stripe::Product.list({ ids: product_ids, active: true })
products = response[:data].map { |p| serialize_product(p) }
end
render_json_dump products
rescue ::Stripe::InvalidRequestError => e
render_json_error e.message
end
end end
def contributors def contributors
@@ -4,9 +4,6 @@ module DiscourseSubscriptions
module User module User
class PaymentsController < ::ApplicationController class PaymentsController < ::ApplicationController
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key before_action :set_api_key
requires_login requires_login
@@ -5,9 +5,6 @@ module DiscourseSubscriptions
class SubscriptionsController < ::ApplicationController class SubscriptionsController < ::ApplicationController
include DiscourseSubscriptions::Stripe include DiscourseSubscriptions::Stripe
include DiscourseSubscriptions::Group include DiscourseSubscriptions::Group
requires_plugin DiscourseSubscriptions::PLUGIN_NAME
before_action :set_api_key before_action :set_api_key
requires_login requires_login
@@ -51,8 +51,6 @@ module DiscourseSubscriptions
"KR" "KR"
when "sgd" when "sgd"
"S$" "S$"
when "zar"
"R"
else else
"$" "$"
end end
@@ -17,26 +17,39 @@ module DiscourseSubscriptions
product_ids = product_ids.include?(campaign_product) ? [campaign_product] : [] product_ids = product_ids.include?(campaign_product) ? [campaign_product] : []
end end
amount = 0.00 begin
subscriptions = get_subscription_data amount = 0.00
subscriptions = filter_to_subscriptions_products(subscriptions, product_ids) subscriptions = get_subscription_data
subscriptions = filter_to_subscriptions_products(subscriptions, product_ids)
# Fetch product purchases # Fetch product purchases
one_time_payments = get_one_time_payments(product_ids) one_time_payments = get_one_time_payments(product_ids)
one_time_payments.each { |c| amount += c[:price].to_f / 100.00 } one_time_payments.each { |c| amount += c[:price].to_f / 100.00 }
# get number of subscribers # get number of subscribers
SiteSetting.discourse_subscriptions_campaign_subscribers = subscriptions&.length.to_i SiteSetting.discourse_subscriptions_campaign_subscribers = subscriptions&.length.to_i
# calculate amount raised # calculate amount raised
subscriptions&.each do |sub| subscriptions&.each do |sub|
sub_amount = calculate_monthly_amount(sub) sub_amount = calculate_monthly_amount(sub)
amount += sub_amount / 100.00 amount += sub_amount / 100.00
end
SiteSetting.discourse_subscriptions_campaign_amount_raised = amount.round(2)
check_goal_status
rescue ::Stripe::AuthenticationError
message =
I18n.t(
"discourse_subscriptions.auth.invalid",
settingsUrl: "admin/site_settings/category/discourse_subscriptions",
)
AdminDashboardData.add_found_scheduled_check_problem(
AdminDashboardData::Problem.new(message, identifier: AUTH_PROBLEM_IDENTIFIER),
)
else
AdminDashboardData.clear_found_problem(AUTH_PROBLEM_IDENTIFIER)
end end
SiteSetting.discourse_subscriptions_campaign_amount_raised = amount.round(2)
check_goal_status
end end
def create_campaign def create_campaign
@@ -1,11 +1,11 @@
import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { equal } from "@ember/object/computed"; import { equal } from "@ember/object/computed";
import { setting } from "discourse/lib/computed";
import Component from "@ember/component";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
import { ajax } from "discourse/lib/ajax";
import { setting } from "discourse/lib/computed";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
const SIDEBAR_BODY_CLASS = "subscription-campaign-sidebar"; const SIDEBAR_BODY_CLASS = "subscription-campaign-sidebar";
@@ -58,14 +58,12 @@ export default Component.extend({
} }
if (this.currentUser && this.showContributors) { if (this.currentUser && this.showContributors) {
return ajax("/subscriptions/contributors", { method: "get" }).then( return ajax("/s/contributors", { method: "get" }).then((result) => {
(result) => { this.setProperties({
this.setProperties({ contributors: result,
contributors: result, loading: false,
loading: false, });
}); });
}
);
} }
}, },
@@ -98,7 +96,6 @@ export default Component.extend({
}, },
willDestroyElement() { willDestroyElement() {
this._super(...arguments);
document.body.classList.remove(SIDEBAR_BODY_CLASS); document.body.classList.remove(SIDEBAR_BODY_CLASS);
}, },
@@ -1,10 +1,10 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { fn, hash } from "@ember/helper";
import DButton from "discourse/components/d-button"; import DButton from "discourse/components/d-button";
import DModal from "discourse/components/d-modal"; import DModal from "discourse/components/d-modal";
import Component from "@glimmer/component";
import { fn, hash } from "@ember/helper";
import i18n from "discourse-common/helpers/i18n"; import i18n from "discourse-common/helpers/i18n";
import { Input } from "@ember/component";
import { tracked } from "@glimmer/tracking";
export default class AdminCancelSubscription extends Component { export default class AdminCancelSubscription extends Component {
@tracked refund; @tracked refund;
@@ -1,6 +1,6 @@
import Component from "@ember/component";
import { isEmpty } from "@ember/utils";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils";
import Component from "@ember/component";
export default Component.extend({ export default Component.extend({
classNames: ["product-list"], classNames: ["product-list"],
@@ -1,6 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import ComboBoxComponent from "select-kit/components/combo-box";
export default ComboBoxComponent.extend({ export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["subscribe-ca-province-select"], pluginApiIdentifiers: ["subscribe-ca-province-select"],
@@ -24,8 +24,5 @@ export default Component.extend({
}, },
}); });
}, },
didDestroyElement() {},
didDestroyElement() {
this._super(...arguments);
},
}); });
@@ -1,6 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import ComboBoxComponent from "select-kit/components/combo-box";
export default ComboBoxComponent.extend({ export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["subscribe-country-select"], pluginApiIdentifiers: ["subscribe-country-select"],
@@ -1,6 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import ComboBoxComponent from "select-kit/components/combo-box";
export default ComboBoxComponent.extend({ export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["subscribe-us-state-select"], pluginApiIdentifiers: ["subscribe-us-state-select"],
@@ -1,6 +1,6 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { popupAjaxError } from "discourse/lib/ajax-error";
import AdminCoupon from "discourse/plugins/discourse-subscriptions/discourse/models/admin-coupon"; import AdminCoupon from "discourse/plugins/discourse-subscriptions/discourse/models/admin-coupon";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({ export default Controller.extend({
creating: null, creating: null,
@@ -1,6 +1,6 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { inject as service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { inject as service } from "@ember/service";
export default Controller.extend({ export default Controller.extend({
router: service(), router: service(),
@@ -1,8 +1,8 @@
import discourseComputed from "discourse-common/utils/decorators";
import DiscourseURL from "discourse/lib/url";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import DiscourseURL from "discourse/lib/url";
import discourseComputed from "discourse-common/utils/decorators";
const RECURRING = "recurring"; const RECURRING = "recurring";
const ONE_TIME = "one_time"; const ONE_TIME = "one_time";
@@ -41,7 +41,6 @@ export default Controller.extend({
{ id: "DKK", name: "DKK" }, { id: "DKK", name: "DKK" },
{ id: "SGD", name: "SGD" }, { id: "SGD", name: "SGD" },
{ id: "JPY", name: "JPY" }, { id: "JPY", name: "JPY" },
{ id: "ZAR", name: "ZAR" },
]; ];
}, },

Some files were not shown because too many files have changed in this diff Show More