Skip to content

Commit dd5f486

Browse files
committed
apply review feedback
1 parent fd03d2a commit dd5f486

2 files changed

Lines changed: 69 additions & 59 deletions

File tree

app/controllers/v3/organizations_controller.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def create
5151
message = VCAP::CloudController::OrganizationCreateMessage.new(hashed_params[:body])
5252
unprocessable!(message.errors.full_messages) unless message.valid?
5353

54-
unauthorized! if message.requested?(:suspended) && message.suspended && !permission_queryer.can_write_globally?
54+
unauthorized! if suspended_by_non_admin?(message)
5555

5656
org = nil
5757

@@ -81,7 +81,7 @@ def update
8181
message = VCAP::CloudController::OrganizationUpdateMessage.new(hashed_params[:body])
8282
unprocessable!(message.errors.full_messages) unless message.valid?
8383

84-
unauthorized! if message.requested?(:suspended) && message.suspended && !permission_queryer.can_write_globally?
84+
unauthorized! if suspended_by_non_admin?(message)
8585

8686
org = OrganizationUpdate.new(user_audit_info).update(org, message)
8787

@@ -227,6 +227,11 @@ def isolation_segment_not_found!
227227
resource_not_found!(:isolation_segment)
228228
end
229229

230+
def suspended_by_non_admin?(message)
231+
message.requested?(:suspended) && message.suspended && !permission_queryer.can_write_globally?
232+
end
233+
234+
230235
def fetch_org(guid)
231236
Organization.where(guid:).first
232237
end

spec/request/organizations_spec.rb

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -171,32 +171,35 @@ module VCAP::CloudController
171171
end
172172

173173
context 'when a non-admin sets the suspended field' do
174+
let(:org) { Organization.make }
175+
let(:space) { Space.make(organization: org) }
176+
174177
before do
175178
VCAP::CloudController::FeatureFlag.make(name: 'user_org_creation', enabled: true)
176179
end
177180

178-
it 'returns 403 NotAuthorized for suspended: true' do
179-
suspended_request_body = { name: 'sneaky-org', suspended: true }.to_json
180-
181-
expect do
182-
post '/v3/organizations', suspended_request_body, user_header
183-
end.not_to change(Organization, :count)
181+
context 'with suspended: true' do
182+
let(:api_call) do
183+
->(user_headers) { post '/v3/organizations', { name: "org-#{SecureRandom.uuid}", suspended: true }.to_json, user_headers }
184+
end
185+
let(:expected_codes_and_responses) do
186+
h = Hash.new({ code: 403, errors: CF_NOT_AUTHORIZED }.freeze)
187+
h['admin'] = { code: 201 }
188+
h
189+
end
184190

185-
expect(last_response.status).to eq(403)
186-
expect(last_response).to have_error_message('You are not authorized to perform the requested action')
191+
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
187192
end
188193

189-
it 'allows suspended: false (the default) as a no-op' do
190-
request_body = { name: 'noop-suspended-org', suspended: false }.to_json
191-
192-
expect do
193-
post '/v3/organizations', request_body, user_header
194-
end.to change(Organization, :count).by 1
194+
context 'with suspended: false (no-op)' do
195+
let(:api_call) do
196+
->(user_headers) { post '/v3/organizations', { name: "org-#{SecureRandom.uuid}", suspended: false }.to_json, user_headers }
197+
end
198+
let(:expected_codes_and_responses) do
199+
Hash.new({ code: 201 }.freeze)
200+
end
195201

196-
expect(last_response.status).to eq(201)
197-
created_org = Organization.last
198-
expect(created_org.name).to eq('noop-suspended-org')
199-
expect(created_org).not_to be_suspended
202+
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
200203
end
201204
end
202205
end
@@ -1338,54 +1341,56 @@ module VCAP::CloudController
13381341
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
13391342
end
13401343

1341-
context 'when a OrgManager mutates the suspended field' do
1342-
let(:org_manager) { VCAP::CloudController::User.make }
1343-
let(:org_manager_header) { headers_for(org_manager) }
1344-
1345-
before do
1346-
organization1.add_user(org_manager)
1347-
organization1.add_manager(org_manager)
1348-
end
1344+
context 'when a non-admin mutates the suspended field' do
1345+
let(:org) { Organization.make }
1346+
let(:space) { Space.make(organization: org) }
13491347

1350-
it 'returns 403 NotAuthorized when attempting to suspend an active org' do
1351-
patch "/v3/organizations/#{organization1.guid}",
1352-
{ suspended: true }.to_json,
1353-
org_manager_header.merge('CONTENT_TYPE' => 'application/json')
1348+
context 'on an active org with suspended: true' do
1349+
let(:api_call) do
1350+
->(user_headers) { patch "/v3/organizations/#{org.guid}", { suspended: true }.to_json, user_headers.merge('CONTENT_TYPE' => 'application/json') }
1351+
end
1352+
let(:expected_codes_and_responses) do
1353+
h = Hash.new({ code: 403, errors: CF_NOT_AUTHORIZED }.freeze)
1354+
h['admin'] = { code: 200 }
1355+
h['no_role'] = { code: 404 }
1356+
h
1357+
end
13541358

1355-
expect(last_response.status).to eq(403)
1356-
expect(last_response).to have_error_message('You are not authorized to perform the requested action')
1357-
expect(organization1.reload).not_to be_suspended
1359+
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
13581360
end
13591361

1360-
it 'returns CF-OrgSuspended when attempting to un-suspend a suspended org' do
1361-
organization1.update(status: VCAP::CloudController::Organization::SUSPENDED)
1362-
1363-
patch "/v3/organizations/#{organization1.guid}",
1364-
{ suspended: false }.to_json,
1365-
org_manager_header.merge('CONTENT_TYPE' => 'application/json')
1366-
1367-
expect(last_response.status).to eq(403)
1368-
expect(last_response).to have_error_message('The organization is suspended')
1369-
expect(organization1.reload).to be_suspended
1370-
end
1362+
context 'on a suspended org with suspended: false (un-suspend)' do
1363+
let(:api_call) do
1364+
->(user_headers) { patch "/v3/organizations/#{org.guid}", { suspended: false }.to_json, user_headers.merge('CONTENT_TYPE' => 'application/json') }
1365+
end
1366+
let(:expected_codes_and_responses) do
1367+
h = Hash.new({ code: 403, errors: CF_NOT_AUTHORIZED }.freeze)
1368+
h['admin'] = { code: 200 }
1369+
h['org_manager'] = { code: 403, errors: CF_ORG_SUSPENDED }
1370+
h['no_role'] = { code: 404 }
1371+
h
1372+
end
13711373

1372-
it 'allows benign updates that do not touch the suspended field' do
1373-
patch "/v3/organizations/#{organization1.guid}",
1374-
{ name: 'renamed-by-manager' }.to_json,
1375-
org_manager_header.merge('CONTENT_TYPE' => 'application/json')
1374+
before do
1375+
org.update(status: VCAP::CloudController::Organization::SUSPENDED)
1376+
end
13761377

1377-
expect(last_response.status).to eq(200)
1378-
expect(organization1.reload.name).to eq('renamed-by-manager')
1378+
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
13791379
end
13801380

1381-
it 'allows a no-op suspended update (suspended matches current state)' do
1382-
patch "/v3/organizations/#{organization1.guid}",
1383-
{ name: 'still-active', suspended: false }.to_json,
1384-
org_manager_header.merge('CONTENT_TYPE' => 'application/json')
1381+
context 'on an active org with suspended: false (no-op)' do
1382+
let(:api_call) do
1383+
->(user_headers) { patch "/v3/organizations/#{org.guid}", { suspended: false }.to_json, user_headers.merge('CONTENT_TYPE' => 'application/json') }
1384+
end
1385+
let(:expected_codes_and_responses) do
1386+
h = Hash.new({ code: 403, errors: CF_NOT_AUTHORIZED }.freeze)
1387+
h['admin'] = { code: 200 }
1388+
h['org_manager'] = { code: 200 }
1389+
h['no_role'] = { code: 404 }
1390+
h
1391+
end
13851392

1386-
expect(last_response.status).to eq(200)
1387-
expect(organization1.reload.name).to eq('still-active')
1388-
expect(organization1.reload).not_to be_suspended
1393+
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
13891394
end
13901395
end
13911396
end

0 commit comments

Comments
 (0)