discourse_subscription_client 0.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +10 -0
- data/app/assets/config/discourse_subscription_client_manifest.js +1 -0
- data/app/assets/stylesheets/discourse_subscription_client/application.css +15 -0
- data/app/controllers/discourse_subscription_client/admin_controller.rb +46 -0
- data/app/controllers/discourse_subscription_client/notices_controller.rb +82 -0
- data/app/controllers/discourse_subscription_client/subscriptions_controller.rb +17 -0
- data/app/controllers/discourse_subscription_client/suppliers_controller.rb +62 -0
- data/app/jobs/regular/discourse_subscription_client/find_resources.rb +9 -0
- data/app/jobs/scheduled/discourse_subscription_client/update_notices.rb +11 -0
- data/app/jobs/scheduled/discourse_subscription_client/update_subscriptions.rb +11 -0
- data/app/models/subscription_client_notice.rb +223 -0
- data/app/models/subscription_client_request.rb +4 -0
- data/app/models/subscription_client_resource.rb +27 -0
- data/app/models/subscription_client_subscription.rb +54 -0
- data/app/models/subscription_client_supplier.rb +54 -0
- data/app/serializers/discourse_subscription_client/notice_serializer.rb +52 -0
- data/app/serializers/discourse_subscription_client/resource_serializer.rb +8 -0
- data/app/serializers/discourse_subscription_client/subscription_serializer.rb +12 -0
- data/app/serializers/discourse_subscription_client/supplier_serializer.rb +16 -0
- data/config/locales/server.en.yml +40 -0
- data/config/routes.rb +19 -0
- data/config/settings.yml +16 -0
- data/db/migrate/20220318160955_create_subscription_client_suppliers.rb +17 -0
- data/db/migrate/20220318181029_create_subscription_client_resources.rb +14 -0
- data/db/migrate/20220318181054_create_subscription_client_notices.rb +22 -0
- data/db/migrate/20220318181140_create_subscription_client_subscriptions.rb +19 -0
- data/db/migrate/20230220130259_create_subscription_client_requests.rb +16 -0
- data/lib/discourse_subscription_client/authorization.rb +100 -0
- data/lib/discourse_subscription_client/engine.rb +97 -0
- data/lib/discourse_subscription_client/notices.rb +154 -0
- data/lib/discourse_subscription_client/request.rb +136 -0
- data/lib/discourse_subscription_client/resources.rb +97 -0
- data/lib/discourse_subscription_client/subscriptions/result.rb +118 -0
- data/lib/discourse_subscription_client/subscriptions.rb +93 -0
- data/lib/discourse_subscription_client/version.rb +5 -0
- data/lib/discourse_subscription_client.rb +8 -0
- metadata +252 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DiscourseSubscriptionClient
|
4
|
+
class Request
|
5
|
+
SUPPLIER_ERROR_LIMIT = 3
|
6
|
+
RESOURCE_ERROR_LIMIT = 5
|
7
|
+
VALID_TYPES = %w[resource supplier].freeze
|
8
|
+
|
9
|
+
attr_reader :type,
|
10
|
+
:id
|
11
|
+
|
12
|
+
def initialize(type, id)
|
13
|
+
@type = type.to_s
|
14
|
+
@id = id
|
15
|
+
end
|
16
|
+
|
17
|
+
def perform(url, headers: {}, body: nil, opts: { method: "GET" })
|
18
|
+
return nil unless VALID_TYPES.include?(type)
|
19
|
+
|
20
|
+
if body
|
21
|
+
uri = URI.parse(url)
|
22
|
+
uri.query = CGI.unescape(body.to_query)
|
23
|
+
url = uri.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
headers.merge!({ "Origin" => Discourse.base_url_no_prefix })
|
27
|
+
|
28
|
+
connection = Excon.new(url, headers: headers)
|
29
|
+
|
30
|
+
begin
|
31
|
+
response = connection.request(opts)
|
32
|
+
rescue Excon::Error::Socket, Excon::Error::Timeout
|
33
|
+
response = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
if response && response.status == 200
|
37
|
+
expire_error
|
38
|
+
|
39
|
+
begin
|
40
|
+
data = JSON.parse(response.body).deep_symbolize_keys
|
41
|
+
rescue JSON::ParserError
|
42
|
+
return nil
|
43
|
+
end
|
44
|
+
|
45
|
+
data
|
46
|
+
else
|
47
|
+
create_error(url, response)
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def current_error(query_only: false)
|
53
|
+
@current_error ||= begin
|
54
|
+
query = SubscriptionClientRequest
|
55
|
+
.where("request_id = :request_id AND request_type = :request_type AND expired_at IS NULL", request_id: id, request_type: type)
|
56
|
+
|
57
|
+
return nil unless query.exists?
|
58
|
+
return query if query_only
|
59
|
+
|
60
|
+
query.first
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.current_error(type, id)
|
65
|
+
new(type, id).current_error
|
66
|
+
end
|
67
|
+
|
68
|
+
def limit
|
69
|
+
send("#{@type}_limit")
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_error(url, response)
|
73
|
+
if (error = current_error)
|
74
|
+
error.count = error.count.to_i + 1
|
75
|
+
else
|
76
|
+
error = SubscriptionClientRequest.new(
|
77
|
+
request_id: id,
|
78
|
+
request_type: type,
|
79
|
+
message: I18n.t("subscription_client.notices.connection_error", url: url),
|
80
|
+
count: 1
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
if response.present?
|
85
|
+
begin
|
86
|
+
body = JSON.parse(response.body)
|
87
|
+
rescue JSON::ParserError
|
88
|
+
body = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
error.response = {
|
92
|
+
status: response.status,
|
93
|
+
body: body
|
94
|
+
}
|
95
|
+
|
96
|
+
error.message = body["error"] if body && body["error"]
|
97
|
+
end
|
98
|
+
|
99
|
+
error.save
|
100
|
+
|
101
|
+
@current_error = nil
|
102
|
+
|
103
|
+
return unless reached_limit?
|
104
|
+
|
105
|
+
SubscriptionClientNotice.notify_connection_error(type, id)
|
106
|
+
|
107
|
+
return unless type === "supplier" && (supplier = SubscriptionClientSupplier.find_by_id(id))
|
108
|
+
|
109
|
+
supplier.deactivate_all_subscriptions!
|
110
|
+
end
|
111
|
+
|
112
|
+
def expire_error
|
113
|
+
if (query = current_error(query_only: true))
|
114
|
+
record = query.first
|
115
|
+
record.expired_at = Time.now
|
116
|
+
record.save
|
117
|
+
end
|
118
|
+
|
119
|
+
SubscriptionClientNotice.expire_connection_error(type, id)
|
120
|
+
end
|
121
|
+
|
122
|
+
def supplier_limit
|
123
|
+
SUPPLIER_ERROR_LIMIT
|
124
|
+
end
|
125
|
+
|
126
|
+
def resource_limit
|
127
|
+
RESOURCE_ERROR_LIMIT
|
128
|
+
end
|
129
|
+
|
130
|
+
def reached_limit?
|
131
|
+
return false unless current_error.present?
|
132
|
+
|
133
|
+
current_error.count.to_i >= limit
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DiscourseSubscriptionClient
|
4
|
+
class Resources
|
5
|
+
attr_accessor :suppliers,
|
6
|
+
:resources
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@suppliers = []
|
10
|
+
@resources = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find_all
|
14
|
+
RailsMultisite::ConnectionManagement.each_connection do
|
15
|
+
new.find_all
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_all
|
20
|
+
return unless DiscourseSubscriptionClient.database_exists?
|
21
|
+
|
22
|
+
setup_resources
|
23
|
+
find_resources
|
24
|
+
|
25
|
+
return unless @resources.any?
|
26
|
+
|
27
|
+
ActiveRecord::Base.transaction do
|
28
|
+
find_suppliers
|
29
|
+
save_resources
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup_resources
|
34
|
+
setup_plugins
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_resources
|
38
|
+
find_plugins
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_suppliers
|
42
|
+
supplier_urls = @resources.map { |resource| resource[:supplier_url] }.uniq.compact
|
43
|
+
|
44
|
+
supplier_urls.each do |url|
|
45
|
+
supplier = SubscriptionClientSupplier.find_by(url: url)
|
46
|
+
|
47
|
+
if supplier&.name
|
48
|
+
@suppliers << supplier
|
49
|
+
else
|
50
|
+
supplier ||= SubscriptionClientSupplier.create!(url: url)
|
51
|
+
request = DiscourseSubscriptionClient::Request.new(:supplier, supplier.id)
|
52
|
+
data = request.perform("#{url}/subscription-server")
|
53
|
+
|
54
|
+
if data
|
55
|
+
supplier.update(name: data[:supplier])
|
56
|
+
@suppliers << supplier
|
57
|
+
else
|
58
|
+
supplier.destroy!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def save_resources
|
65
|
+
@resources.each do |resource|
|
66
|
+
supplier = @suppliers.select { |s| s.url === resource[:supplier_url] }.first
|
67
|
+
|
68
|
+
next unless supplier.present?
|
69
|
+
|
70
|
+
attrs = {
|
71
|
+
supplier_id: supplier.id,
|
72
|
+
name: resource[:name]
|
73
|
+
}
|
74
|
+
SubscriptionClientResource.create!(attrs) unless SubscriptionClientResource.exists?(attrs)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup_plugins
|
79
|
+
Plugin::Metadata::FIELDS << :subscription_url unless Plugin::Metadata::FIELDS.include?(:subscription_url)
|
80
|
+
Plugin::Metadata.attr_accessor(:subscription_url)
|
81
|
+
end
|
82
|
+
|
83
|
+
def find_plugins
|
84
|
+
Dir["#{DiscourseSubscriptionClient.root}/plugins/*/plugin.rb"].sort.each do |path|
|
85
|
+
source = File.read(path)
|
86
|
+
metadata = Plugin::Metadata.parse(source)
|
87
|
+
|
88
|
+
next unless metadata.subscription_url.present?
|
89
|
+
|
90
|
+
@resources << {
|
91
|
+
name: metadata.name,
|
92
|
+
supplier_url: metadata.subscription_url
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ::DiscourseSubscriptionClient
|
4
|
+
class Subscriptions
|
5
|
+
class Result
|
6
|
+
REQUIRED_KEYS ||= %i[
|
7
|
+
resource_id
|
8
|
+
product_id
|
9
|
+
price_id
|
10
|
+
].freeze
|
11
|
+
OPTIONAL_KEYS ||= %i[
|
12
|
+
product_name
|
13
|
+
price_name
|
14
|
+
].freeze
|
15
|
+
KEYS = REQUIRED_KEYS + OPTIONAL_KEYS
|
16
|
+
|
17
|
+
attr_reader :errors,
|
18
|
+
:errored_suppliers,
|
19
|
+
:infos
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@errors = []
|
23
|
+
@infos = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def not_authorized(supplier)
|
27
|
+
error("not_authorized", supplier)
|
28
|
+
end
|
29
|
+
|
30
|
+
def retrieve_subscriptions(supplier, raw_data)
|
31
|
+
subscriptions_data = raw_data[:subscriptions].compact
|
32
|
+
|
33
|
+
unless subscriptions_data.present? && subscriptions_data.is_a?(Array)
|
34
|
+
error("invalid_response", supplier)
|
35
|
+
return []
|
36
|
+
end
|
37
|
+
|
38
|
+
# subscriptions must be properly formed
|
39
|
+
|
40
|
+
subscriptions_data =
|
41
|
+
subscriptions_data
|
42
|
+
.map(&:symbolize_keys)
|
43
|
+
.each { |data| data[:resource_id] = data[:resource] }
|
44
|
+
.select { |data| REQUIRED_KEYS.all? { |key| data.key?(key) } }
|
45
|
+
|
46
|
+
# we only care about subscriptions for resources on this instance
|
47
|
+
|
48
|
+
resources = SubscriptionClientResource.where(
|
49
|
+
supplier_id: supplier.id,
|
50
|
+
name: subscriptions_data.map { |data| data[:resource] }
|
51
|
+
)
|
52
|
+
|
53
|
+
subscriptions_data.each_with_object([]) do |data, result|
|
54
|
+
resource = resources.select { |r| r.name === data[:resource] }.first
|
55
|
+
|
56
|
+
if resource.present?
|
57
|
+
data[:resource_id] = resource.id
|
58
|
+
result << OpenStruct.new(
|
59
|
+
required: data.slice(*REQUIRED_KEYS),
|
60
|
+
create: data.slice(*KEYS),
|
61
|
+
subscription: nil
|
62
|
+
)
|
63
|
+
else
|
64
|
+
info("no_resource", supplier, resource: data[:resource])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def connection_error(supplier)
|
70
|
+
error("supplier_connection", supplier)
|
71
|
+
end
|
72
|
+
|
73
|
+
def no_suppliers
|
74
|
+
info("no_suppliers")
|
75
|
+
end
|
76
|
+
|
77
|
+
def no_subscriptions(supplier)
|
78
|
+
info("no_subscriptions", supplier)
|
79
|
+
end
|
80
|
+
|
81
|
+
def updated_subscription(supplier, subscription_ids: nil)
|
82
|
+
info("updated_subscription", supplier, subscription_ids: subscription_ids)
|
83
|
+
end
|
84
|
+
|
85
|
+
def created_subscription(supplier, subscription_ids: nil)
|
86
|
+
info("created_subscription", supplier, subscription_ids: subscription_ids)
|
87
|
+
end
|
88
|
+
|
89
|
+
def failed_to_create_subscription(supplier, subscription_ids: nil)
|
90
|
+
info("failed_to_create_subscription", supplier, subscription_ids: subscription_ids)
|
91
|
+
end
|
92
|
+
|
93
|
+
def info(key, supplier = nil, subscription_ids: nil, resource: nil)
|
94
|
+
attrs = {}
|
95
|
+
|
96
|
+
if supplier
|
97
|
+
attrs = {
|
98
|
+
supplier: supplier.name,
|
99
|
+
supplier_url: supplier.url,
|
100
|
+
deep_interpolation: true,
|
101
|
+
price: "",
|
102
|
+
resource_name: ""
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
attrs.merge!(subscription_ids) if subscription_ids.present?
|
107
|
+
attrs[:resource] if resource.present?
|
108
|
+
|
109
|
+
@infos << I18n.t("subscription_client.subscriptions.info.#{key}", **attrs)
|
110
|
+
end
|
111
|
+
|
112
|
+
def error(key, supplier)
|
113
|
+
@errors << I18n.t("subscription_client.subscriptions.error.#{key}", supplier: supplier.name,
|
114
|
+
supplier_url: supplier.url)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DiscourseSubscriptionClient
|
4
|
+
class Subscriptions
|
5
|
+
def initialize
|
6
|
+
@suppliers = SubscriptionClientSupplier.authorized
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.update
|
10
|
+
new.update
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
return unless SiteSetting.subscription_client_enabled
|
15
|
+
|
16
|
+
@result = DiscourseSubscriptionClient::Subscriptions::Result.new
|
17
|
+
|
18
|
+
if @suppliers.blank?
|
19
|
+
@result.no_suppliers
|
20
|
+
else
|
21
|
+
@suppliers.each do |supplier|
|
22
|
+
update_supplier(supplier)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if @result.errors.any?
|
27
|
+
@result.errors.each do |error|
|
28
|
+
Rails.logger.error "DiscourseSubscriptionClient::Subscriptions.update: #{error}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if SiteSetting.subscription_client_verbose_logs && @result.infos.any?
|
33
|
+
@result.infos.each do |info|
|
34
|
+
Rails.logger.info "DiscourseSubscriptionClient::Subscriptions.update: #{info}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@result.errors.blank?
|
39
|
+
end
|
40
|
+
|
41
|
+
def update_supplier(supplier)
|
42
|
+
resources = supplier.resources
|
43
|
+
return unless resources.present?
|
44
|
+
|
45
|
+
request = DiscourseSubscriptionClient::Request.new(:supplier, supplier.id)
|
46
|
+
headers = { "User-Api-Key" => supplier.api_key }
|
47
|
+
url = "#{supplier.url}/subscription-server/user-subscriptions"
|
48
|
+
|
49
|
+
response = request.perform(url, headers: headers, body: { resources: resources.map(&:name) })
|
50
|
+
return (supplier.deactivate_all_subscriptions! && @result.connection_error(supplier)) if response.nil?
|
51
|
+
|
52
|
+
subscription_data = @result.retrieve_subscriptions(supplier, response)
|
53
|
+
return supplier.deactivate_all_subscriptions! if @result.errors.any?
|
54
|
+
|
55
|
+
# deactivate any of the supplier's subscriptions not retrieved from supplier
|
56
|
+
if supplier.subscriptions.present?
|
57
|
+
supplier.subscriptions.each do |subscription|
|
58
|
+
has_match = false
|
59
|
+
subscription_data.each do |data|
|
60
|
+
if data_matches_subscription(data, subscription)
|
61
|
+
data.subscription = subscription
|
62
|
+
has_match = true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
subscription.deactivate! unless has_match
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
return @result.no_subscriptions(supplier) if subscription_data.blank?
|
70
|
+
|
71
|
+
subscription_data.each do |data|
|
72
|
+
if data.subscription.present?
|
73
|
+
data.subscription.update(subscribed: true)
|
74
|
+
data.subscription.touch
|
75
|
+
|
76
|
+
@result.updated_subscription(supplier, subscription_ids: data.required)
|
77
|
+
else
|
78
|
+
subscription = SubscriptionClientSubscription.create!(data.create.merge(subscribed: true))
|
79
|
+
|
80
|
+
if subscription
|
81
|
+
@result.created_subscription(supplier, subscription_ids: data.required)
|
82
|
+
else
|
83
|
+
@result.failed_to_create_subscription(supplier, subscription_ids: data.required)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def data_matches_subscription(data, subscription)
|
90
|
+
data.required.all? { |k, v| subscription.send(k.to_s) == v }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: discourse_subscription_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Angus McLeod
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-02-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: active_model_serializers
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.3
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: annotate
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: excon
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fabrication
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: message_bus
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mini_scheduler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rails
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 7.0.4.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 7.0.4.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec-activemodel-mocks
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec-rails
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: webmock
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
description: Adds a backend subscription client to a Discourse plugin.
|
182
|
+
email:
|
183
|
+
- angus@mcleod.org.au
|
184
|
+
executables: []
|
185
|
+
extensions: []
|
186
|
+
extra_rdoc_files: []
|
187
|
+
files:
|
188
|
+
- MIT-LICENSE
|
189
|
+
- README.md
|
190
|
+
- Rakefile
|
191
|
+
- app/assets/config/discourse_subscription_client_manifest.js
|
192
|
+
- app/assets/stylesheets/discourse_subscription_client/application.css
|
193
|
+
- app/controllers/discourse_subscription_client/admin_controller.rb
|
194
|
+
- app/controllers/discourse_subscription_client/notices_controller.rb
|
195
|
+
- app/controllers/discourse_subscription_client/subscriptions_controller.rb
|
196
|
+
- app/controllers/discourse_subscription_client/suppliers_controller.rb
|
197
|
+
- app/jobs/regular/discourse_subscription_client/find_resources.rb
|
198
|
+
- app/jobs/scheduled/discourse_subscription_client/update_notices.rb
|
199
|
+
- app/jobs/scheduled/discourse_subscription_client/update_subscriptions.rb
|
200
|
+
- app/models/subscription_client_notice.rb
|
201
|
+
- app/models/subscription_client_request.rb
|
202
|
+
- app/models/subscription_client_resource.rb
|
203
|
+
- app/models/subscription_client_subscription.rb
|
204
|
+
- app/models/subscription_client_supplier.rb
|
205
|
+
- app/serializers/discourse_subscription_client/notice_serializer.rb
|
206
|
+
- app/serializers/discourse_subscription_client/resource_serializer.rb
|
207
|
+
- app/serializers/discourse_subscription_client/subscription_serializer.rb
|
208
|
+
- app/serializers/discourse_subscription_client/supplier_serializer.rb
|
209
|
+
- config/locales/server.en.yml
|
210
|
+
- config/routes.rb
|
211
|
+
- config/settings.yml
|
212
|
+
- db/migrate/20220318160955_create_subscription_client_suppliers.rb
|
213
|
+
- db/migrate/20220318181029_create_subscription_client_resources.rb
|
214
|
+
- db/migrate/20220318181054_create_subscription_client_notices.rb
|
215
|
+
- db/migrate/20220318181140_create_subscription_client_subscriptions.rb
|
216
|
+
- db/migrate/20230220130259_create_subscription_client_requests.rb
|
217
|
+
- lib/discourse_subscription_client.rb
|
218
|
+
- lib/discourse_subscription_client/authorization.rb
|
219
|
+
- lib/discourse_subscription_client/engine.rb
|
220
|
+
- lib/discourse_subscription_client/notices.rb
|
221
|
+
- lib/discourse_subscription_client/request.rb
|
222
|
+
- lib/discourse_subscription_client/resources.rb
|
223
|
+
- lib/discourse_subscription_client/subscriptions.rb
|
224
|
+
- lib/discourse_subscription_client/subscriptions/result.rb
|
225
|
+
- lib/discourse_subscription_client/version.rb
|
226
|
+
homepage: https://github.com/paviliondev/discourse_subscription_client
|
227
|
+
licenses:
|
228
|
+
- GPL-2.0-only
|
229
|
+
metadata:
|
230
|
+
homepage_uri: https://github.com/paviliondev/discourse_subscription_client
|
231
|
+
source_code_uri: https://github.com/paviliondev/discourse_subscription_client
|
232
|
+
changelog_uri: https://github.com/paviliondev/discourse_subscription_client
|
233
|
+
post_install_message:
|
234
|
+
rdoc_options: []
|
235
|
+
require_paths:
|
236
|
+
- lib
|
237
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
238
|
+
requirements:
|
239
|
+
- - ">="
|
240
|
+
- !ruby/object:Gem::Version
|
241
|
+
version: 2.6.0
|
242
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
243
|
+
requirements:
|
244
|
+
- - ">"
|
245
|
+
- !ruby/object:Gem::Version
|
246
|
+
version: 1.3.1
|
247
|
+
requirements: []
|
248
|
+
rubygems_version: 3.3.26
|
249
|
+
signing_key:
|
250
|
+
specification_version: 4
|
251
|
+
summary: Discourse plugin subscription client.
|
252
|
+
test_files: []
|