Skip to content

Commit 67da0d9

Browse files
committed
implemented the reward admin controller
1 parent 7601a72 commit 67da0d9

File tree

6 files changed

+322
-11
lines changed

6 files changed

+322
-11
lines changed

app/controllers/discourse_kofi/admin/rewards_controller.rb

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,111 @@ def index
2020
end
2121

2222
def show
23-
#TODO
23+
render_reward(find_reward)
2424
end
2525

2626
def create
27-
#TODO
27+
reward = Reward.new
28+
errors = update_reward_from_params(reward, new: true)
29+
if errors.present?
30+
render_json_error errors
31+
else
32+
StaffActionLogger.new(current_user).log_custom(
33+
"kofi_reward_creation",
34+
log_details(reward)
35+
)
36+
render_reward(reward)
37+
end
2838
end
2939

3040
def update
31-
#TODO
41+
reward = find_reward
42+
errors = update_reward_from_params(reward)
43+
if errors.present?
44+
render_json_error errors
45+
else
46+
StaffActionLogger.new(current_user).log_custom(
47+
"kofi_reward_change",
48+
log_details(reward, update: true)
49+
)
50+
render_reward(reward)
51+
end
3252
end
3353

3454
def destroy
35-
#TODO
55+
Reward.transaction do
56+
reward = find_reward
57+
StaffActionLogger.new(current_user).log_custom(
58+
"kofi_reward_deletion",
59+
log_details(reward)
60+
)
61+
reward.destroy!
62+
end
63+
render json: success_json
64+
end
65+
66+
private
67+
68+
def render_reward(reward)
69+
if reward.subscription
70+
render_serialized(reward, SubscriptionRewardSerializer)
71+
else
72+
render_serialized(reward, RewardSerializer)
73+
end
74+
end
75+
76+
def find_reward
77+
params.require(:id)
78+
reward = Reward.find(params[:id])
79+
raise Discourse::NotFound unless reward
80+
reward
81+
end
82+
83+
def update_reward_from_params(reward, opts = {})
84+
errors = []
85+
Reward.transaction do
86+
allowed = Reward.column_names.map(&:to_sym)
87+
allowed -= %i[id created_at updated_at]
88+
allowed -= %i[subscription] unless opts[:new]
89+
params.permit(*allowed)
90+
91+
allowed.each do |key|
92+
reward.public_send("#{key}=", params[key]) if params[key]
93+
end
94+
95+
reward.id = nil if opts[:new]
96+
reward.save!
97+
end
98+
99+
if opts[:new].blank?
100+
#TODO schedule mass reward
101+
end
102+
103+
errors
104+
rescue ActiveRecord::RecordInvalid
105+
errors.push(*reward.errors.full_messages)
106+
errors
107+
end
108+
109+
REWARD_FIELDS =
110+
Reward.attribute_names.excluding("id", "created_at", "updated_at")
111+
112+
def log_details(reward, update = false)
113+
details = {}
114+
if update
115+
details[:subscription] = reward.subscription
116+
reward.previous_changes.each do |f, values|
117+
details[f.to_sym] = values[1] if REWARD_FIELDS.include?(f)
118+
end
119+
else
120+
details =
121+
REWARD_FIELDS
122+
.map { |f| [f, reward.public_send(f)] }
123+
.select { |f, v| v.present? }
124+
.to_h
125+
end
126+
details[:reward_id] = reward.id
127+
details
36128
end
37129
end
38130
end

app/models/discourse_kofi/reward.rb

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@ class Reward < ActiveRecord::Base
3434
validate :valid_payment_types, unless: :subscription?
3535

3636
def valid_payment_types
37-
payment_types.each do |payment_type|
38-
if !Payment::PAYMENT_TYPES.keys.include?(payment_type.to_sym)
39-
errors.add(
40-
:payment_types,
41-
"'#{payment_type}' is not a valid payment type"
42-
)
37+
if !payment_types.kind_of?(Array)
38+
errors.add(:payment_types, "must be an array")
39+
elsif payment_types.empty?
40+
errors.add(:payment_types, "must contain at least one value")
41+
else
42+
payment_types.each do |payment_type|
43+
if !Payment::PAYMENT_TYPES.keys.include?(payment_type.to_sym)
44+
errors.add(
45+
:payment_types,
46+
"'#{payment_type}' is not a valid payment type"
47+
)
48+
end
4349
end
4450
end
4551
end

app/serializers/discourse_kofi/base_reward_serializer.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ class IdNameSerializer < ApplicationSerializer
88
end
99

1010
class BaseRewardSerializer < ApplicationSerializer
11-
attributes :id
11+
root "reward"
12+
13+
attributes :id, :subscription
1214

1315
has_one :group, serializer: IdNameSerializer, embed: :objects
1416
end
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe DiscourseKofi::Admin::RewardsController do
4+
fab!(:admin)
5+
6+
before do
7+
SiteSetting.kofi_enabled = true
8+
sign_in(admin)
9+
end
10+
11+
fab!(:reward)
12+
fab!(:subscription_reward)
13+
14+
describe "#index" do
15+
it "returns all rewards" do
16+
get "/ko-fi/admin/rewards.json"
17+
expect(response.status).to eq(200)
18+
parsed = response.parsed_body
19+
expect(parsed[:rewards]).to contain_exactly(include(id: reward.id))
20+
expect(parsed[:subscriptions]).to contain_exactly(
21+
include(id: subscription_reward.id)
22+
)
23+
end
24+
end
25+
26+
describe "#show" do
27+
it "returns a reward" do
28+
get "/ko-fi/admin/rewards/#{reward.id}.json"
29+
expect(response.status).to eq(200)
30+
parsed = response.parsed_body
31+
expect(parsed[:reward][:id]).to eq reward.id
32+
expect(parsed[:reward][:subscription]).to be false
33+
expect(parsed[:reward][:amount]).to eq reward.amount.as_json
34+
35+
expect(parsed[:reward][:tier_name]).to be_nil
36+
end
37+
38+
it "returns a subscription reward" do
39+
get "/ko-fi/admin/rewards/#{subscription_reward.id}.json"
40+
expect(response.status).to eq(200)
41+
parsed = response.parsed_body
42+
expect(parsed[:reward][:id]).to eq subscription_reward.id
43+
expect(parsed[:reward][:subscription]).to be true
44+
expect(parsed[:reward][:tier_name]).to eq subscription_reward.tier_name
45+
46+
expect(parsed[:reward][:amount]).to be_nil
47+
end
48+
49+
it "cannot find an unknown reward" do
50+
get "/ko-fi/admin/rewards/99999999999999999.json"
51+
expect(response.status).to eq(404)
52+
end
53+
end
54+
55+
describe "#create" do
56+
fab!(:badge)
57+
fab!(:group)
58+
59+
it "can create a new reward" do
60+
StaffActionLogger
61+
.any_instance
62+
.expects(:log_custom)
63+
.with("kofi_reward_creation", anything)
64+
.once
65+
66+
post "/ko-fi/admin/rewards.json",
67+
params: {
68+
subscription: false,
69+
badge_id: badge.id,
70+
group_id: group.id,
71+
amount: 123.45,
72+
payment_types: %i[donation subscription]
73+
}
74+
75+
expect(response.status).to eq(200)
76+
parsed = response.parsed_body
77+
expect(parsed[:reward][:id]).not_to be_nil
78+
expect(parsed[:reward][:subscription]).to be false
79+
expect(parsed[:reward][:badge][:id]).to eq badge.id
80+
expect(parsed[:reward][:group][:id]).to eq group.id
81+
expect(parsed[:reward][:amount]).to eq "123.45"
82+
expect(parsed[:reward][:payment_types]).to match_array(
83+
%w[donation subscription]
84+
)
85+
end
86+
87+
it "can create a new subscription reward" do
88+
StaffActionLogger
89+
.any_instance
90+
.expects(:log_custom)
91+
.with("kofi_reward_creation", anything)
92+
.once
93+
94+
post "/ko-fi/admin/rewards.json",
95+
params: {
96+
subscription: true,
97+
group_id: group.id,
98+
tier_name: "premium"
99+
}
100+
101+
expect(response.status).to eq(200)
102+
parsed = response.parsed_body
103+
expect(parsed[:reward][:id]).not_to be_nil
104+
expect(parsed[:reward][:subscription]).to be true
105+
expect(parsed[:reward][:group][:id]).to eq group.id
106+
expect(parsed[:reward][:tier_name]).to eq "premium"
107+
end
108+
109+
it "cannot create an invalid reward" do
110+
StaffActionLogger
111+
.any_instance
112+
.expects(:log_custom)
113+
.with("kofi_reward_creation", anything)
114+
.never
115+
116+
post "/ko-fi/admin/rewards.json",
117+
params: {
118+
subscription: false,
119+
group_id: group.id,
120+
tier_name: "premium"
121+
}
122+
123+
expect(response.status).to eq(422)
124+
parsed = response.parsed_body
125+
expect(parsed[:errors]).to match_array(
126+
[
127+
"Tier name must be blank",
128+
"Payment types can't be blank",
129+
"Amount is not a number",
130+
"Payment types must be an array"
131+
]
132+
)
133+
end
134+
135+
describe "#update" do
136+
it "can update a reward" do
137+
StaffActionLogger
138+
.any_instance
139+
.expects(:log_custom)
140+
.with("kofi_reward_change", anything)
141+
.once
142+
143+
patch "/ko-fi/admin/rewards/#{reward.id}.json",
144+
params: {
145+
group_id: nil,
146+
amount: 123.45,
147+
payment_types: %w[donation subscription]
148+
}
149+
150+
expect(response.status).to eq(200)
151+
parsed = response.parsed_body
152+
expect(parsed[:reward][:id]).to eq reward.id
153+
expect(parsed[:reward][:subscription]).to be false
154+
expect(parsed[:reward][:group]).to be_nil
155+
expect(parsed[:reward][:amount]).to eq "123.45"
156+
expect(parsed[:reward][:payment_types]).to match_array(
157+
%w[donation subscription]
158+
)
159+
end
160+
161+
it "cannot change the subscription kind" do
162+
patch "/ko-fi/admin/rewards/#{reward.id}.json",
163+
params: {
164+
subscription: true
165+
}
166+
167+
expect(response.status).to eq(200)
168+
parsed = response.parsed_body
169+
expect(parsed[:reward][:subscription]).to be false
170+
end
171+
172+
it "cannot make invalid changes" do
173+
patch "/ko-fi/admin/rewards/#{reward.id}.json",
174+
params: {
175+
tier_name: "something"
176+
}
177+
178+
expect(response.status).to eq(422)
179+
end
180+
181+
it "cannot unpdate an unknown reward" do
182+
patch "/ko-fi/admin/rewards/9999999999999.json", params: {}
183+
184+
expect(response.status).to eq(404)
185+
end
186+
end
187+
188+
describe "#destroy" do
189+
it "can delete a reward" do
190+
StaffActionLogger
191+
.any_instance
192+
.expects(:log_custom)
193+
.with("kofi_reward_deletion", anything)
194+
.once
195+
196+
delete "/ko-fi/admin/rewards/#{reward.id}.json"
197+
expect(response.status).to eq(200)
198+
199+
get "/ko-fi/admin/rewards/#{reward.id}.json"
200+
expect(response.status).to eq(404)
201+
end
202+
203+
it "cannot delete an unknown rewared" do
204+
delete "/ko-fi/admin/rewards/9999999999999.json"
205+
expect(response.status).to eq(404)
206+
end
207+
end
208+
end
209+
end

spec/serializers/reward_serializer_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
json = DiscourseKofi::RewardSerializer.new(reward, { root: false }).as_json
88

99
expect(json[:id]).not_to be_nil
10+
expect(json[:subscription]).to be false
1011
expect(json[:badge]).not_to be_nil
1112
expect(json[:badge][:id]).to eq reward.badge.id
1213
expect(json[:badge][:name]).to eq reward.badge.name

spec/serializers/subscription_reward_serializer_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
).as_json
1212

1313
expect(json[:id]).not_to be_nil
14+
expect(json[:subscription]).to be true
1415
expect(json[:group]).not_to be_nil
1516
expect(json[:group][:id]).to eq reward.group.id
1617
expect(json[:group][:name]).to eq reward.group.name

0 commit comments

Comments
 (0)