Skip to content

Commit c23b71c

Browse files
GbArcgbarc-dt
andauthored
[TBT-300] plan share prd (#1362)
* plan share wip * specs * admin_revoked * share delete changed, admin_revoked in renderer * share api cleanup * a. state workaround * added credits_consumed to plan_share --------- Co-authored-by: GbArc <[email protected]>
1 parent 00ac20e commit c23b71c

File tree

13 files changed

+142
-2
lines changed

13 files changed

+142
-2
lines changed

lib/travis/api/app/endpoint/authorization.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ def create_state
319319

320320
def state_ok?(state, provider = :github)
321321
cookie_state = request.cookies[cookie_name(provider)]
322+
state = CGI.unescape(state)
322323
state == cookie_state and redis.srem('github:states', state.to_s.split(":::", 1))
323324
end
324325

lib/travis/api/v3/billing_client.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ def create_auto_refill(plan_id, is_enabled)
235235
handle_errors_and_respond(response)
236236
end
237237

238+
def share(plan_id, receiver)
239+
response = connection.post("/v2/subscriptions/#{plan_id}/share", {plan: plan_id, receiver: receiver, requested_by: @user_id })
240+
handle_errors_and_respond(response)
241+
end
242+
243+
def delete_share(plan_id, receiver)
244+
response = connection.delete("/v2/subscriptions/#{plan_id}/share", {plan: plan_id, receiver: receiver, requested_by: @user_id })
245+
handle_errors_and_respond(response)
246+
end
247+
238248
def update_auto_refill(addon_id, threshold, amount)
239249
response = connection.patch('/auto_refill', {id: addon_id, threshold: threshold, amount: amount})
240250
handle_errors_and_respond(response)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Travis::API::V3
2+
class Models::PlanShare
3+
attr_reader :plan_id, :donor, :receiver, :shared_by, :created_at, :admin_revoked, :credits_consumed
4+
def initialize(attributes = {})
5+
@plan_id = attributes.fetch('plan_id')
6+
@donor = attributes.fetch('donor')
7+
@receiver = attributes.fetch('receiver')
8+
@shared_by = attributes.fetch('shared_by')
9+
@created_at = attributes.fetch('created_at')
10+
@admin_revoked = attributes.fetch('admin_revoked')
11+
@credits_consumed = attributes.fetch('credits_consumed')
12+
end
13+
end
14+
end

lib/travis/api/v3/models/v2_subscription.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class Models::V2Subscription
44

55
attr_reader :id, :plan, :permissions, :source, :billing_info, :credit_card_info, :owner, :status, :valid_to, :canceled_at,
66
:client_secret, :payment_intent, :addons, :auto_refill, :available_standalone_addons, :created_at, :scheduled_plan_name,
7-
:cancellation_requested, :current_trial, :defer_pause
7+
:cancellation_requested, :current_trial, :defer_pause, :plan_shares
88

99
def initialize(attributes = {})
1010
@id = attributes.fetch('id')
@@ -38,6 +38,7 @@ def initialize(attributes = {})
3838
@current_trial = Models::V2Trial.new(current_trial)
3939
end
4040
@defer_pause = attributes.fetch('defer_pause', false)
41+
@plan_shares = attributes['plan_shares'] && attributes['plan_shares'].map { |sp| Models::PlanShare.new(sp) }
4142
end
4243
end
4344

lib/travis/api/v3/queries/v2_subscription.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ def update_auto_refill(user_id, addon_id)
9393
client.update_auto_refill(addon_id, threshold, amount)
9494
end
9595

96+
def share(user_id, receiver_id)
97+
client = BillingClient.new(user_id)
98+
client.share(params['subscription.id'], receiver_id)
99+
end
100+
101+
def delete_share(user_id, receiver_id)
102+
client = BillingClient.new(user_id)
103+
client.delete_share(params['subscription.id'], receiver_id)
104+
end
105+
96106
private
97107

98108
def recaptcha_client
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Travis::API::V3
2+
class Renderer::PlanShare < ModelRenderer
3+
representation(:standard, :plan_id, :donor, :receiver, :shared_by, :created_at, :admin_revoked, :credits_consumed)
4+
representation(:minimal, :plan_id, :donor, :receiver, :shared_by, :created_at, :admin_revoked, :credits_consumed)
5+
end
6+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Travis::API::V3
2+
class Renderer::PlanShares < CollectionRenderer
3+
type :plan_shares
4+
collection_key :plan_shares
5+
end
6+
end

lib/travis/api/v3/renderer/v2_subscription.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module Travis::API::V3
22
class Renderer::V2Subscription < ModelRenderer
3-
representation(:standard, :id, :plan, :addons, :auto_refill, :status, :valid_to, :canceled_at, :source, :owner, :client_secret, :billing_info, :credit_card_info, :payment_intent, :created_at, :scheduled_plan_name, :cancellation_requested, :current_trial, :defer_pause)
3+
representation(:standard, :id, :plan, :addons, :auto_refill, :status, :valid_to, :canceled_at, :source, :owner, :client_secret, :billing_info, :credit_card_info, :payment_intent, :created_at, :scheduled_plan_name, :cancellation_requested, :current_trial, :defer_pause, :plan_shares)
44

55
def billing_info
66
Renderer.render_model(model.billing_info, mode: :standard) unless model.billing_info.nil?
@@ -21,6 +21,7 @@ def payment_intent
2121
def current_trial
2222
Renderer.render_model(model.current_trial,mode: :standard) unless model.current_trial.nil?
2323
end
24+
2425
end
2526

2627
class Renderer::V2BillingInfo < ModelRenderer

lib/travis/api/v3/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ module Routes
446446
get :auto_refill, '/auto_refill'
447447
patch :toggle_auto_refill, '/auto_refill'
448448
patch :update_auto_refill, '/update_auto_refill'
449+
post :share, '/share'
450+
delete :share, '/share'
449451
end
450452

451453
hidden_resource :trials do
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Travis::API::V3
2+
class Services::V2Subscription::Share < Service
3+
params :receiver_id, :receiver
4+
def run!
5+
raise LoginRequired unless access_control.full_access_or_logged_in?
6+
if @env['REQUEST_METHOD'] == 'DELETE' then
7+
query.delete_share(access_control.user.id, params['receiver_id'])
8+
else
9+
query.share(access_control.user.id, params['receiver_id'])
10+
end
11+
no_content
12+
end
13+
end
14+
end
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
describe Travis::API::V3::Services::V2Subscription::Share, set_app: true, billing_spec_helper: true do
2+
let(:billing_url) { 'http://billingfake.travis-ci.com' }
3+
let(:billing_auth_key) { 'secret' }
4+
let(:receiver) { FactoryBot.create(:org) }
5+
let(:data) { {'plan'=> subscription_id, 'receiver_id' => receiver.id } }
6+
7+
before do
8+
Travis.config.billing.url = billing_url
9+
Travis.config.billing.auth_key = billing_auth_key
10+
end
11+
12+
context 'unauthenticated' do
13+
it 'responds 403 for post' do
14+
post('/v3/v2_subscription/123/share', {})
15+
16+
expect(last_response.status).to eq(403)
17+
end
18+
19+
it 'responds 403 for delete' do
20+
delete('/v3/v2_subscription/123/share', {})
21+
22+
expect(last_response.status).to eq(403)
23+
end
24+
end
25+
26+
context 'authenticated create share' do
27+
let(:user) { FactoryBot.create(:user) }
28+
let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) }
29+
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}",
30+
'CONTENT_TYPE' => 'application/json' }}
31+
let(:subscription_id) { rand(999) }
32+
33+
let!(:stubbed_request) do
34+
stub_billing_request(:post, "/v2/subscriptions/#{subscription_id}/share", auth_key: billing_auth_key, user_id: user.id)
35+
.with(body: {
36+
'plan' => subscription_id.to_s,
37+
'receiver' => receiver.id,
38+
'requested_by' => user.id
39+
})
40+
.to_return(status: 204)
41+
end
42+
43+
it 'shares the subscription' do
44+
post("/v3/v2_subscription/#{subscription_id}/share", JSON.generate(data), headers)
45+
46+
expect(last_response.status).to eq(204)
47+
expect(stubbed_request).to have_been_made.once
48+
end
49+
end
50+
51+
context 'authenticated delete share' do
52+
let(:user) { FactoryBot.create(:user) }
53+
let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) }
54+
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}",
55+
'CONTENT_TYPE' => 'application/json' }}
56+
let(:subscription_id) { rand(999) }
57+
58+
let!(:stubbed_request) do
59+
stub_request(:delete, "#{billing_url}/v2/subscriptions/#{subscription_id}/share?plan=#{subscription_id}&receiver=#{receiver.id}&requested_by=#{user.id}").with(
60+
headers: {
61+
'X-Travis-User-Id' => user.id
62+
}
63+
)
64+
.to_return(status: 204)
65+
end
66+
67+
it 'deletes subscription share' do
68+
delete("/v3/v2_subscription/#{subscription_id}/share", JSON.generate(data), headers)
69+
expect(last_response.status).to eq(204)
70+
expect(stubbed_request).to have_been_made.once
71+
end
72+
end
73+
end

spec/v3/services/v2_subscriptions/all_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
'cancellation_requested' => false,
8888
'current_trial' => nil,
8989
'defer_pause' => false,
90+
'plan_shares' => nil,
9091
'plan' => {
9192
'@type' => 'v2_plan_config',
9293
'@representation' => 'standard',

spec/v3/services/v2_subscriptions/create_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
'cancellation_requested' => false,
213213
'current_trial' => nil,
214214
'defer_pause' => false,
215+
'plan_shares' => nil,
215216
'plan' => {
216217
'@type' => 'v2_plan_config',
217218
'@representation' => 'standard',

0 commit comments

Comments
 (0)