Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit d874405

Browse files
author
Derik Evangelista
authored
v3(service-plan-visibility): add audit events (cloudfoundry#1890)
[#166785822](https://www.pivotaltracker.com/story/show/166785822)
1 parent 258f447 commit d874405

4 files changed

Lines changed: 126 additions & 18 deletions

File tree

app/controllers/v3/service_plan_visibility_controller.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,16 @@ def destroy
4242
resource_not_found!(:service_plan_visibility) unless to_delete.present?
4343

4444
ServicePlanVisibilityDelete.delete(to_delete)
45-
45+
event_repository.record_service_plan_delete_visibility_event(service_plan, org)
4646
head :no_content
4747
end
4848

4949
private
5050

51+
def event_repository
52+
VCAP::CloudController::Repositories::ServiceEventRepository::WithUserActor.new(user_audit_info)
53+
end
54+
5155
def update_visibility(opts={})
5256
service_plan = ServicePlanFetcher.fetch(hashed_params[:guid])
5357
service_plan_not_found! unless service_plan.present? && visible_to_current_user?(plan: service_plan)
@@ -57,6 +61,7 @@ def update_visibility(opts={})
5761
bad_request!(message.errors.full_messages) unless message.valid?
5862

5963
updated_service_plan = V3::ServicePlanVisibilityUpdate.new.update(service_plan, message, opts)
64+
event_repository.record_service_plan_update_visibility_event(service_plan, message.audit_hash)
6065

6166
visible_in_orgs = ServicePlanVisibilityFetcher.new(permission_queryer).fetch_orgs(
6267
service_plan_guids: [service_plan.guid]

app/repositories/service_event_repository.rb

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ def logger
1717

1818
delegate(
1919
:record_service_plan_visibility_event,
20+
:record_service_plan_update_visibility_event,
21+
:record_service_plan_delete_visibility_event,
2022
:record_broker_event,
2123
:record_broker_event_with_request,
2224
:record_service_instance_event,
@@ -78,20 +80,23 @@ def initialize(user_audit_info)
7880
end
7981

8082
def record_service_plan_visibility_event(type, visibility, params)
81-
actee = {
82-
actee: visibility.guid,
83-
actee_type: 'service_plan_visibility',
84-
actee_name: ''
85-
}
86-
87-
metadata = { request: params }
88-
8983
space_data = {
9084
space_guid: '',
9185
organization_guid: visibility.organization_guid
9286
}
87+
record_plan_visibility_event(type, visibility.guid, params, space_data)
88+
end
9389

94-
create_event("audit.service_plan_visibility.#{type}", user_actor, actee, metadata, space_data)
90+
def record_service_plan_update_visibility_event(plan, params)
91+
record_plan_visibility_event(:update, plan.guid, params)
92+
end
93+
94+
def record_service_plan_delete_visibility_event(plan, org)
95+
space_data = {
96+
space_guid: '',
97+
organization_guid: org.guid
98+
}
99+
record_plan_visibility_event(:delete, plan.guid, {}, space_data)
95100
end
96101

97102
def record_broker_event(type, broker, params)
@@ -191,6 +196,18 @@ def record_service_plan_delete_event(plan)
191196

192197
attr_reader :user_audit_info
193198

199+
def record_plan_visibility_event(type, actee_guid, params, space_data=nil)
200+
actee = {
201+
actee: actee_guid,
202+
actee_type: 'service_plan_visibility',
203+
actee_name: ''
204+
}
205+
206+
metadata = { request: params }
207+
208+
create_event("audit.service_plan_visibility.#{type}", user_actor, actee, metadata, space_data)
209+
end
210+
194211
def with_parameters_redacted(request_data)
195212
redact(request_data, for_key: 'parameters', with: Presenters::Censorship::PRIVATE_DATA_HIDDEN)
196213
end

spec/request/service_plan_visibility_spec.rb

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,26 +384,25 @@
384384

385385
describe 'POST /v3/service_plans/:guid/visibility' do
386386
let(:third_org) { VCAP::CloudController::Organization.make }
387+
let(:yet_another_org) { VCAP::CloudController::Organization.make }
387388
let(:api_url) { "/v3/service_plans/#{guid}/visibility" }
388389
let(:api_call) { lambda { |user_headers| post api_url, req_body.to_json, user_headers } }
389390
let(:guid) { service_plan.guid }
390-
391391
let(:service_plan) do
392392
plan = VCAP::CloudController::ServicePlan.make(public: false)
393393
VCAP::CloudController::ServicePlanVisibility.make(organization: org, service_plan: plan)
394394
VCAP::CloudController::ServicePlanVisibility.make(organization: other_org, service_plan: plan)
395395
plan
396396
end
397+
let(:body) { { type: 'organization', organizations: [{ guid: third_org.guid }, { guid: yet_another_org.guid }] } }
397398

398399
context 'when the plan current visibility is "organization"' do
399400
it 'can add new organizations' do
400-
yet_another_org = VCAP::CloudController::Organization.make
401-
body = { type: 'organization', organizations: [{ guid: third_org.guid }, { guid: yet_another_org.guid }] }.to_json
402401
expected_orgs = [org, other_org, third_org, yet_another_org].map do |o|
403402
{ 'guid' => o.guid, 'name' => o.name }
404403
end
405404

406-
post api_url, body, admin_headers
405+
post api_url, body.to_json, admin_headers
407406
expect(last_response).to have_status_code(200)
408407
expect(parsed_response['type']).to eq 'organization'
409408
expect(parsed_response['organizations']).to match_array(expected_orgs)
@@ -413,6 +412,16 @@
413412
expect(parsed_response['organizations']).to match_array(expected_orgs)
414413
end
415414

415+
it 'creates an audit event' do
416+
post api_url, body.to_json, admin_headers
417+
event = VCAP::CloudController::Event.find(type: 'audit.service_plan_visibility.update')
418+
expect(event).to be
419+
expect(event.actee).to eq(service_plan.guid)
420+
expect(event.data).to include({
421+
'request' => body.with_indifferent_access
422+
})
423+
end
424+
416425
it 'ignores organizations that already have visibility' do
417426
body = { type: 'organization', organizations: [{ guid: org.guid }, { guid: third_org.guid }] }.to_json
418427
expected_orgs = [
@@ -442,14 +451,24 @@
442451

443452
context 'when the current visibility type is not organization' do
444453
let(:service_plan) { VCAP::CloudController::ServicePlan.make(public: true) }
454+
let(:body) { { type: 'organization', organizations: [{ guid: org.guid }] } }
445455

446456
it 'updates the visibility type AND add the orgs' do
447-
body = { type: 'organization', organizations: [{ guid: org.guid }] }.to_json
448-
post api_url, body, admin_headers
457+
post api_url, body.to_json, admin_headers
449458

450459
expect(parsed_response['type']).to eq 'organization'
451460
expect(parsed_response['organizations']).to contain_exactly({ 'guid' => org.guid, 'name' => org.name })
452461
end
462+
463+
it 'creates an audit event' do
464+
post api_url, body.to_json, admin_headers
465+
event = VCAP::CloudController::Event.find(type: 'audit.service_plan_visibility.update')
466+
expect(event).to be
467+
expect(event.actee).to eq(service_plan.guid)
468+
expect(event.data).to include({
469+
'request' => body.with_indifferent_access
470+
})
471+
end
453472
end
454473

455474
context 'when an org in the list does not exist' do
@@ -497,16 +516,27 @@
497516
end
498517

499518
context 'when request type is not "organization"' do
519+
let(:body) { { type: 'public' } }
520+
500521
it 'behaves like a PATCH' do
501-
body = { type: 'public' }.to_json
502-
post api_url, body, admin_headers
522+
post api_url, body.to_json, admin_headers
503523
expect(last_response).to have_status_code(200)
504524

505525
get api_url, {}, admin_headers
506526
expect(parsed_response).to eq({ 'type' => 'public' })
507527
visibilities = VCAP::CloudController::ServicePlanVisibility.where(service_plan: service_plan).all
508528
expect(visibilities).to be_empty
509529
end
530+
531+
it 'creates an audit event' do
532+
post api_url, body.to_json, admin_headers
533+
event = VCAP::CloudController::Event.find(type: 'audit.service_plan_visibility.update')
534+
expect(event).to be
535+
expect(event.actee).to eq(service_plan.guid)
536+
expect(event.data).to include({
537+
'request' => body.with_indifferent_access
538+
})
539+
end
510540
end
511541

512542
context 'permissions' do
@@ -607,5 +637,14 @@
607637

608638
it_behaves_like 'permissions for delete endpoint', ALL_PERMISSIONS
609639
end
640+
641+
it 'creates an audit event' do
642+
delete api_url, {}, admin_headers
643+
expect(last_response).to have_status_code(204)
644+
event = VCAP::CloudController::Event.find(type: 'audit.service_plan_visibility.delete')
645+
expect(event).to be
646+
expect(event.actee).to eq(service_plan.guid)
647+
expect(event.organization_guid).to eq(org.guid)
648+
end
610649
end
611650
end

spec/unit/repositories/service_event_repository_spec.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,53 @@ module Repositories
3838
end
3939
end
4040

41+
describe 'record_service_plan_update_visibility_event' do
42+
let(:service_plan) { VCAP::CloudController::ServicePlan.make }
43+
44+
it 'creates the event' do
45+
params = {
46+
type: 'organization',
47+
organizations: [
48+
{ guid: '9c246656-830f-4c47-968f-f92c2d659560' },
49+
{ guid: 'c01fdfc3-ffe4-4ec1-a294-e5a84ef425f1' }
50+
]
51+
}
52+
repository.record_service_plan_update_visibility_event(service_plan, params)
53+
54+
event = Event.find(type: 'audit.service_plan_visibility.update')
55+
expect(event.actor_type).to eq('user')
56+
expect(event.timestamp).to be
57+
expect(event.actor).to eq(user.guid)
58+
expect(event.actor_name).to eq(email)
59+
expect(event.actor_username).to eq(user_name)
60+
expect(event.actee).to eq(service_plan.guid)
61+
expect(event.actee_type).to eq('service_plan_visibility')
62+
expect(event.actee_name).to eq('')
63+
expect(event.metadata).to eq({ 'request' => params.with_indifferent_access })
64+
end
65+
end
66+
67+
describe 'record_service_plan_delete_visibility_event' do
68+
let(:service_plan) { VCAP::CloudController::ServicePlan.make }
69+
let(:org) { VCAP::CloudController::Organization.make }
70+
71+
it 'creates the event' do
72+
repository.record_service_plan_delete_visibility_event(service_plan, org)
73+
74+
event = Event.find(type: 'audit.service_plan_visibility.delete')
75+
expect(event.actor_type).to eq('user')
76+
expect(event.timestamp).to be
77+
expect(event.actor).to eq(user.guid)
78+
expect(event.actor_name).to eq(email)
79+
expect(event.actor_username).to eq(user_name)
80+
expect(event.actee).to eq(service_plan.guid)
81+
expect(event.actee_type).to eq('service_plan_visibility')
82+
expect(event.actee_name).to eq('')
83+
expect(event.metadata).to eq({ 'request' => {} })
84+
expect(event.organization_guid).to eq(org.guid)
85+
end
86+
end
87+
4188
describe '#record_broker_event' do
4289
let(:service_broker) { VCAP::CloudController::ServiceBroker.make }
4390
let(:params) do

0 commit comments

Comments
 (0)