require 'spec_helper'

module VCAP::CloudController
  module Repositories
    RSpec.describe ServiceEventRepository do
      let(:user) { VCAP::CloudController::User.make }
      let(:email) { 'email@example.com' }
      let(:user_name) { 'arthur' }
      let(:logger) { double(:logger, error: nil) }
      let(:repository) { ServiceEventRepository.new(UserAuditInfo.new(user_guid: user.guid, user_name: user_name, user_email: email)) }

      before do
        allow(Steno).to receive(:logger).with('cc.event_repository').and_return(logger)
      end

      describe 'record_service_plan_visibility_event' do
        let(:service_plan_visibility) { VCAP::CloudController::ServicePlanVisibility.make }

        it 'creates the event' do
          params = {
            'organization_guid' => service_plan_visibility.organization.guid,
            'service_plan_guid' => service_plan_visibility.service_plan.guid
          }
          repository.record_service_plan_visibility_event(:create, service_plan_visibility, params)

          event = Event.find(type: 'audit.service_plan_visibility.create')
          expect(event.actor_type).to eq('user')
          expect(event.timestamp).to be
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.actee).to eq(service_plan_visibility.guid)
          expect(event.actee_type).to eq('service_plan_visibility')
          expect(event.actee_name).to eq('')
          expect(event.space_guid).to be_empty
          expect(event.organization_guid).to eq(service_plan_visibility.organization.guid)
          expect(event.metadata).to eq({ 'request' => params })
        end
      end

      describe 'record_service_plan_update_visibility_event' do
        let(:service_plan) { VCAP::CloudController::ServicePlan.make }

        it 'creates the event' do
          params = {
            type: 'organization',
            organizations: [
              { guid: '9c246656-830f-4c47-968f-f92c2d659560' },
              { guid: 'c01fdfc3-ffe4-4ec1-a294-e5a84ef425f1' }
            ]
          }
          repository.record_service_plan_update_visibility_event(service_plan, params)

          event = Event.find(type: 'audit.service_plan_visibility.update')
          expect(event.actor_type).to eq('user')
          expect(event.timestamp).to be
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.actee).to eq(service_plan.guid)
          expect(event.actee_type).to eq('service_plan_visibility')
          expect(event.actee_name).to eq('')
          expect(event.metadata).to eq({ 'request' => params.with_indifferent_access })
        end
      end

      describe 'record_service_plan_delete_visibility_event' do
        let(:service_plan) { VCAP::CloudController::ServicePlan.make }
        let(:org) { VCAP::CloudController::Organization.make }

        it 'creates the event' do
          repository.record_service_plan_delete_visibility_event(service_plan, org)

          event = Event.find(type: 'audit.service_plan_visibility.delete')
          expect(event.actor_type).to eq('user')
          expect(event.timestamp).to be
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.actee).to eq(service_plan.guid)
          expect(event.actee_type).to eq('service_plan_visibility')
          expect(event.actee_name).to eq('')
          expect(event.metadata).to eq({ 'request' => {} })
          expect(event.organization_guid).to eq(org.guid)
        end
      end

      describe '#record_broker_event' do
        let(:service_broker) { VCAP::CloudController::ServiceBroker.make }
        let(:params) do
          {
            name: service_broker.name,
            broker_url: service_broker.broker_url,
            auth_username: service_broker.auth_username,
            auth_password: service_broker.auth_password
          }
        end

        it 'creates an event' do
          repository.record_broker_event(:create, service_broker, params)

          event = Event.find(type: 'audit.service_broker.create')
          expect(event.actor_type).to eq('user')
          expect(event.timestamp).to be
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.actee).to eq(service_broker.guid)
          expect(event.actee_type).to eq('service_broker')
          expect(event.actee_name).to eq(service_broker.name)
          expect(event.space_guid).to be_empty
          expect(event.organization_guid).to be_empty
        end

        describe 'the metadata field' do
          it 'only includes param keys that have values' do
            repository.record_broker_event(:create, service_broker, { name: 'new-name' })
            metadata = Event.first.metadata
            expect(metadata['request']).to include('name' => 'new-name')
            expect(metadata['request']).not_to have_key('broker_url')
            expect(metadata['request']).not_to have_key('auth_username')
            expect(metadata['request']).not_to have_key('auth_password')
          end

          it 'redacts the auth_password field' do
            repository.record_broker_event(:create, service_broker, { auth_password: 'new-passord' })

            metadata = Event.first.metadata
            expect(metadata['request']).to include('auth_password' => '[REDACTED]')
          end

          context 'when no params are passed in' do
            it 'saves an empty request' do
              repository.record_broker_event(:create, service_broker, {})

              expect(Event.first.metadata).to eq({ 'request' => {} })
            end
          end
        end
      end

      describe '#record_broker_event_with_request' do
        let(:service_broker) { VCAP::CloudController::ServiceBroker.make }
        let(:request) do
          {
            fake: 'request'
          }
        end

        it 'creates an event with the request' do
          repository.record_broker_event_with_request(:create, service_broker, request)

          event = Event.find(type: 'audit.service_broker.create')
          expect(event.actor_type).to eq('user')
          expect(event.timestamp).to be
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.actee).to eq(service_broker.guid)
          expect(event.actee_type).to eq('service_broker')
          expect(event.actee_name).to eq(service_broker.name)
          expect(event.space_guid).to be_empty
          expect(event.organization_guid).to be_empty

          expect(event.metadata['request']).to include('fake' => 'request')
        end
      end

      describe '#with_service_event' do
        let(:broker) { VCAP::CloudController::ServiceBroker.make }

        context 'when the service is new' do
          let(:service) do
            VCAP::CloudController::Service.new(
              service_broker: broker,
              label: 'name',
              description: 'some description',
              bindable: true,
              active: false,
              plan_updateable: false,
              unique_id: 'broker-provided-id'
            )
          end

          it 'records a create event' do
            repository.with_service_event(service) do
              service.save
            end

            event = VCAP::CloudController::Event.first(type: 'audit.service.create')
            expect(event.type).to eq('audit.service.create')
            expect(event.actor_type).to eq('service_broker')
            expect(event.actor).to eq(broker.guid)
            expect(event.actor_name).to eq(broker.name)
            expect(event.actor_username).to eq('')
            expect(event.timestamp).to be
            expect(event.actee).to eq(service.guid)
            expect(event.actee_type).to eq('service')
            expect(event.actee_name).to eq(service.label)
            expect(event.space_guid).to eq('')
            expect(event.organization_guid).to eq('')
          end

          it 'records every field of the service in the metadata of the event' do
            repository.with_service_event(service) do
              service.save
            end

            event = Event.first(type: 'audit.service.create')
            expect(event.metadata).to include({
                                                'service_broker_guid' => service.service_broker.guid,
                                                'unique_id' => service.broker_provided_id,
                                                'provider' => service.provider,
                                                'url' => service.url,
                                                'version' => service.version,
                                                'info_url' => service.info_url,
                                                'bindable' => service.bindable,
                                                'long_description' => service.long_description,
                                                'documentation_url' => service.documentation_url,
                                                'label' => service.label,
                                                'description' => service.description,
                                                'tags' => service.tags,
                                                'extra' => service.extra,
                                                'active' => service.active,
                                                'requires' => service.requires,
                                                'plan_updateable' => service.plan_updateable
                                              })
          end
        end

        context 'when the service already exists' do
          let!(:service) { Service.make(service_broker: broker, description: 'description') }

          before do
            service.plan_updateable = true
            service.extra = { 'extra' => 'data' }.to_json
            service.description = 'description' # field is updated but not changed
          end

          it 'creates an update event' do
            repository.with_service_event(service) do
              service.save
            end

            event = VCAP::CloudController::Event.first(type: 'audit.service.update')
            expect(event.type).to eq('audit.service.update')
            expect(event.actor_type).to eq('service_broker')
            expect(event.actor).to eq(broker.guid)
            expect(event.actor_name).to eq(broker.name)
            expect(event.actor_username).to eq('')
            expect(event.timestamp).to be
            expect(event.actee).to eq(service.guid)
            expect(event.actee_type).to eq('service')
            expect(event.actee_name).to eq(service.label)
            expect(event.space_guid).to eq('')
            expect(event.organization_guid).to eq('')
          end

          it 'records in the metadata only those fields which were changed' do
            repository.with_service_event(service) do
              service.save
            end

            metadata = VCAP::CloudController::Event.first(type: 'audit.service.update').metadata
            expect(metadata.keys.length).to eq 2
            expect(metadata['plan_updateable']).to be true
            expect(metadata['extra']).to eq({ 'extra' => 'data' }.to_json)
          end
        end
      end

      describe '#with_service_plan_event' do
        let(:broker) { VCAP::CloudController::ServiceBroker.make }
        let(:service) { VCAP::CloudController::Service.make(service_broker: broker) }

        context 'when the service is new' do
          let(:plan) do
            VCAP::CloudController::ServicePlan.new(
              service: service,
              name: 'myPlan',
              description: 'description',
              free: true,
              unique_id: 'broker-provided-id',
              active: false,
              public: false
            )
          end

          it 'records a create event' do
            repository.with_service_plan_event(plan) do
              plan.save
            end

            event = VCAP::CloudController::Event.first(type: 'audit.service_plan.create')
            expect(event.type).to eq('audit.service_plan.create')
            expect(event.actor_type).to eq('service_broker')
            expect(event.actor).to eq(broker.guid)
            expect(event.actor_name).to eq(broker.name)
            expect(event.actor_username).to eq('')
            expect(event.timestamp).to be
            expect(event.actee).to eq(plan.guid)
            expect(event.actee_type).to eq('service_plan')
            expect(event.actee_name).to eq(plan.name)
            expect(event.space_guid).to eq('')
            expect(event.organization_guid).to eq('')
          end

          it 'records every field of the service plan in the metadata of the event' do
            repository.with_service_plan_event(plan) do
              plan.save
            end

            event = Event.first(type: 'audit.service_plan.create')
            expect(event.metadata).to include({
                                                'name' => plan.name,
                                                'description' => plan.description,
                                                'free' => plan.free,
                                                'active' => plan.active,
                                                'extra' => plan.extra,
                                                'unique_id' => plan.broker_provided_id,
                                                'public' => plan.public,
                                                'service_guid' => service.guid
                                              })
          end
        end

        context 'when the service plan already exists' do
          let!(:plan) { ServicePlan.make(service: service, description: 'description') }

          before do
            plan.extra = { 'extra' => 'data' }.to_json
            plan.description = 'description'
          end

          it 'creates an update event' do
            repository.with_service_plan_event(plan) do
              plan.save
            end

            event = VCAP::CloudController::Event.first(type: 'audit.service_plan.update')
            expect(event.type).to eq('audit.service_plan.update')
            expect(event.actor_type).to eq('service_broker')
            expect(event.actor).to eq(broker.guid)
            expect(event.actor_name).to eq(broker.name)
            expect(event.actor_username).to eq('')
            expect(event.timestamp).to be
            expect(event.actee).to eq(plan.guid)
            expect(event.actee_type).to eq('service_plan')
            expect(event.actee_name).to eq(plan.name)
            expect(event.space_guid).to eq('')
            expect(event.organization_guid).to eq('')
          end

          it 'records in the metadata only those fields which were changed' do
            repository.with_service_plan_event(plan) do
              plan.save
            end

            metadata = VCAP::CloudController::Event.first(type: 'audit.service_plan.update').metadata
            expect(metadata.keys.length).to eq 1
            expect(metadata['extra']).to eq({ 'extra' => 'data' }.to_json)
          end
        end
      end

      describe '#record_service_event' do
        let(:broker) { VCAP::CloudController::ServiceBroker.make }
        let(:service) { VCAP::CloudController::Service.make(service_broker: broker) }

        it 'creates an event with empty metadata because it is only used for delete events' do
          repository.record_service_event(:delete, service)

          event = Event.first
          expect(event.type).to eq('audit.service.delete')
          expect(event.actor_type).to eq('service_broker')
          expect(event.actor).to eq(broker.guid)
          expect(event.actor_name).to eq(broker.name)
          expect(event.actor_username).to eq('')
          expect(event.timestamp).to be
          expect(event.actee).to eq(service.guid)
          expect(event.actee_type).to eq('service')
          expect(event.actee_name).to eq(service.label)
          expect(event.space_guid).to eq('')
          expect(event.organization_guid).to eq('')
          expect(event.metadata).to eq({})
        end
      end

      describe '#record_service_plan_event' do
        let(:broker) { VCAP::CloudController::ServiceBroker.make }
        let(:service) { VCAP::CloudController::Service.make(service_broker: broker) }
        let(:plan) { VCAP::CloudController::ServicePlan.make(service:) }

        it 'creates an event with empty metadata because it is only used for delete events' do
          repository.record_service_plan_event(:delete, plan)

          event = Event.first
          expect(event.type).to eq('audit.service_plan.delete')
          expect(event.actor_type).to eq('service_broker')
          expect(event.actor).to eq(broker.guid)
          expect(event.actor_name).to eq(broker.name)
          expect(event.actor_username).to eq('')
          expect(event.timestamp).to be
          expect(event.actee).to eq(plan.guid)
          expect(event.actee_type).to eq('service_plan')
          expect(event.actee_name).to eq(plan.name)
          expect(event.space_guid).to eq('')
          expect(event.organization_guid).to eq('')
          expect(event.metadata).to eq({})
        end
      end

      describe '#record_service_plan_delete_event' do
        let(:plan) { VCAP::CloudController::ServicePlan.make }

        it 'creates an event with empty metadata' do
          repository.record_service_plan_delete_event(plan)

          event = Event.first
          expect(event.type).to eq('audit.service_plan.delete')
          expect(event.actor_type).to eq('user')
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.timestamp).to be
          expect(event.actee).to eq(plan.guid)
          expect(event.actee_type).to eq('service_plan')
          expect(event.actee_name).to eq(plan.name)
          expect(event.space_guid).to eq('')
          expect(event.organization_guid).to eq('')
          expect(event.metadata).to eq({ 'request' => {} })
        end
      end

      describe '#record_service_dashboard_client_event' do
        let(:broker) { VCAP::CloudController::ServiceBroker.make }
        let(:client_attrs) do
          {
            'id' => 'client-id',
            'secret' => 'super-secret',
            'redirect_uri' => 'redirect-here.com/thing'
          }
        end

        it 'creates an event' do
          repository.record_service_dashboard_client_event(:create, client_attrs, broker)

          event = VCAP::CloudController::Event.first(type: 'audit.service_dashboard_client.create', actee_name: client_attrs['id'])
          expect(event.actor_type).to eq('service_broker')
          expect(event.actor).to eq(broker.guid)
          expect(event.actor_name).to eq(broker.name)
          expect(event.actor_username).to eq('')
          expect(event.timestamp).to be
          expect(event.actee).to eq(client_attrs['id'])
          expect(event.actee_type).to eq('service_dashboard_client')
          expect(event.actee_name).to eq(client_attrs['id'])
          expect(event.space_guid).to eq('')
          expect(event.organization_guid).to eq('')
          expect(event.metadata['redirect_uri']).to eq client_attrs['redirect_uri']
        end

        it 'redacts the client secret' do
          repository.record_service_dashboard_client_event(:create, client_attrs, broker)

          event = VCAP::CloudController::Event.first(type: 'audit.service_dashboard_client.create', actee_name: client_attrs['id'])
          expect(event.metadata['secret']).to eq '[REDACTED]'
        end

        context 'when the redirect_uri is not updated' do
          let(:client_attrs) do
            {
              'id' => 'client-id',
              'secret' => 'super-secret'
            }
          end

          it 'does not include client information in metadata field' do
            repository.record_service_dashboard_client_event(:create, client_attrs, broker)

            event = VCAP::CloudController::Event.first(type: 'audit.service_dashboard_client.create', actee_name: client_attrs['id'])
            expect(event.metadata).to be_empty
          end
        end
      end

      describe '#record_service_instance_event' do
        let(:instance) { VCAP::CloudController::ServiceInstance.make }
        let(:params) do
          {
            'service_plan_guid' => 'plan-guid',
            'space-guid' => 'space-guid',
            'name' => 'instance-name'
          }
        end

        it 'records an event' do
          repository.record_service_instance_event(:create, instance, params)

          event = VCAP::CloudController::Event.first(type: 'audit.service_instance.create')
          expect(event.type).to eq('audit.service_instance.create')
          expect(event.actor_type).to eq('user')
          expect(event.actor).to eq(user.guid)
          expect(event.actor_name).to eq(email)
          expect(event.actor_username).to eq(user_name)
          expect(event.timestamp).to be
          expect(event.actee).to eq(instance.guid)
          expect(event.actee_type).to eq('service_instance')
          expect(event.actee_name).to eq(instance.name)
          expect(event.space_guid).to eq(instance.space.guid)
          expect(event.organization_guid).to eq(instance.space.organization.guid)
        end

        it 'places the params in the metadata' do
          repository.record_service_instance_event(:create, instance, params)

          event = VCAP::CloudController::Event.first(type: 'audit.service_instance.create')

          expect(event.metadata.keys).to eq(['request'])
          expect(event.metadata['request'].except('parameters')).to eq(params)
        end

        it 'allows no params' do
          repository.record_service_instance_event(:create, instance)

          event = VCAP::CloudController::Event.first(type: 'audit.service_instance.create')

          expect(event.metadata.keys).to eq(['request'])
          expect(event.metadata['request']).to be_nil
        end

        it 'allows parameters to not be hashy' do
          expect do
            repository.record_service_instance_event(:create, instance, 5)
          end.not_to raise_error
        end

        context 'when there are params' do
          it 'redacts the arbitrary user parameters' do
            repository.record_service_instance_event(:create, instance, {
                                                       'parameters' => {
                                                         'favorite_dog' => 'chihuahua',
                                                         'username' => 'my-secret-username',
                                                         'password' => 'my-secret-password'
                                                       }
                                                     })

            event = VCAP::CloudController::Event.first(type: 'audit.service_instance.create')
            expect(event.metadata['request']['parameters']).to eq('[PRIVATE DATA HIDDEN]')
          end
        end

        context 'when there are no params' do
          it 'does not redact anything' do
            repository.record_service_instance_event(:create, instance, {})

            event = VCAP::CloudController::Event.first(type: 'audit.service_instance.create')
            expect(event.metadata['request']).not_to have_key('parameters')
          end
        end
      end

      describe '#record_user_provided_service_instance_event' do
        let(:instance) { VCAP::CloudController::UserProvidedServiceInstance.make }
        let(:params) do
          {
            'name' => 'my-upsi',
            'space_guid' => instance.space.guid,
            'syslog_drain_url' => ''
          }
        end

        it 'records an event' do
          repository.record_user_provided_service_instance_event(:create, instance, params)
          event = Event.first(type: 'audit.user_provided_service_instance.create')

          expect(event.actor).to eq user.guid
          expect(event.actor_type).to eq 'user'
          expect(event.actor_name).to eq email
          expect(event.actor_username).to eq user_name
          expect(event.actee).to eq instance.guid
          expect(event.actee_type).to eq 'user_provided_service_instance'
          expect(event.actee_name).to eq instance.name
          expect(event.space_guid).to eq instance.space.guid
          expect(event.metadata).to eq('request' => params)
        end

        it 'allows no params' do
          repository.record_user_provided_service_instance_event(:create, instance)

          event = VCAP::CloudController::Event.first(type: 'audit.user_provided_service_instance.create')

          expect(event.metadata.keys).to eq(['request'])
          expect(event.metadata['request']).to be_nil
        end

        context 'when the params contain credentials' do
          let(:params) do
            {
              'name' => 'my-upsi',
              'credentials' => {
                'url' => 'user:password@url.com'
              },
              'space_guid' => instance.space.guid,
              'syslog_drain_url' => ''
            }
          end

          it 'redacts the credentials' do
            repository.record_user_provided_service_instance_event(:create, instance, params)
            event = Event.first(type: 'audit.user_provided_service_instance.create')
            expect(event.metadata).to eq('request' => {
                                           'name' => params['name'],
                                           'credentials' => '[REDACTED]',
                                           'space_guid' => params['space_guid'],
                                           'syslog_drain_url' => params['syslog_drain_url']
                                         })
          end
        end
      end

      describe '#record_service_key_event' do
        let(:service_key) { VCAP::CloudController::ServiceKey.make }

        def check_event_data(event_type, metadata)
          event = Event.first(type: event_type)
          expect(event.actor).to eq user.guid
          expect(event.actor_type).to eq 'user'
          expect(event.actor_name).to eq email
          expect(event.actor_username).to eq user_name
          expect(event.actee).to eq service_key.guid
          expect(event.actee_type).to eq 'service_key'
          expect(event.actee_name).to eq service_key.name
          expect(event.space_guid).to eq service_key.space.guid
          expect(event.metadata).to eq(metadata)
        end

        it 'records an event for create action' do
          repository.record_service_key_event(:create, service_key)
          metadata = {
            'request' => {
              'service_instance_guid' => service_key.service_instance.guid,
              'name' => service_key.name
            }
          }

          check_event_data 'audit.service_key.create', metadata
        end

        it 'records an event for delete action' do
          repository.record_service_key_event(:delete, service_key)
          metadata = { 'request' => {} }
          check_event_data 'audit.service_key.delete', metadata
        end
      end

      describe '#record_service_purge_event' do
        let(:service) { VCAP::CloudController::Service.make }

        it 'records an event' do
          repository.record_service_purge_event(service)
          event = Event.first(type: 'audit.service.delete')
          metadata = {
            'request' => {
              'purge' => true
            }
          }

          expect(event.actor).to eq user.guid
          expect(event.actor_type).to eq 'user'
          expect(event.actor_name).to eq email
          expect(event.actor_username).to eq user_name
          expect(event.actee).to eq service.guid
          expect(event.actee_type).to eq 'service'
          expect(event.actee_name).to eq service.label
          expect(event.space_guid).to eq ''
          expect(event.organization_guid).to eq ''
          expect(event.metadata).to eq(metadata)
        end
      end

      describe '#record_service_delete_event' do
        let(:service) { VCAP::CloudController::Service.make }

        it 'records an event' do
          repository.record_service_delete_event(service)
          event = Event.first(type: 'audit.service.delete')
          metadata = { 'request' => {} }

          expect(event.actor).to eq user.guid
          expect(event.actor_type).to eq 'user'
          expect(event.actor_name).to eq email
          expect(event.actor_username).to eq user_name
          expect(event.actee).to eq service.guid
          expect(event.actee_type).to eq 'service'
          expect(event.actee_name).to eq service.label
          expect(event.space_guid).to eq ''
          expect(event.organization_guid).to eq ''
          expect(event.metadata).to eq(metadata)
        end
      end

      describe 'when creating the event fails' do
        before do
          allow(Event).to receive(:create).and_raise
        end

        specify 'record_service_plan_visibility_event logs an error but does not propagate errors' do
          service_plan_visibility = VCAP::CloudController::ServicePlanVisibility.make
          repository.record_service_plan_visibility_event(:create, service_plan_visibility, {})
          expect(logger).to have_received(:error)
        end

        specify 'record_broker_event logs an error but does not propagate errors' do
          broker = VCAP::CloudController::ServiceBroker.make
          repository.record_broker_event(:create, broker, {})
          expect(logger).to have_received(:error)
        end

        specify 'record_service_event logs an error but does not propagate errors' do
          broker = VCAP::CloudController::ServiceBroker.make
          service = VCAP::CloudController::Service.make(service_broker: broker)
          repository.record_service_event(:create, service)
          expect(logger).to have_received(:error)
        end

        specify 'record_service_plan_event logs an error but does not propagate errors' do
          broker = VCAP::CloudController::ServiceBroker.make
          service = VCAP::CloudController::Service.make(service_broker: broker)
          service_plan = VCAP::CloudController::ServicePlan.make(service:)
          repository.record_service_plan_event(:create, service_plan)
          expect(logger).to have_received(:error)
        end

        specify 'record_service_dashboard_client_event logs an error but does not propagate errors' do
          broker = VCAP::CloudController::ServiceBroker.make
          repository.record_service_dashboard_client_event(:create, {}, broker)
          expect(logger).to have_received(:error)
        end

        specify 'record_service_instance_event logs an error but does not propagate errors' do
          service_instance = VCAP::CloudController::ServiceInstance.make
          repository.record_service_instance_event(:create, service_instance, {})
          expect(logger).to have_received(:error)
        end

        specify 'record_user_provided_service_instance_event logs an error but does not propagate errors' do
          service_instance = VCAP::CloudController::UserProvidedServiceInstance.make
          repository.record_user_provided_service_instance_event(:create, service_instance, {})
          expect(logger).to have_received(:error)
        end

        specify 'record_service_purge_event logs an error but does not propagate errors' do
          service = VCAP::CloudController::Service.make
          repository.record_service_purge_event(service)
          expect(logger).to have_received(:error)
        end

        specify 'with_service_event logs an error but does not propagate errors' do
          broker = VCAP::CloudController::ServiceBroker.make
          service = VCAP::CloudController::Service.make(service_broker: broker)

          plan = VCAP::CloudController::ServicePlan.new(
            service: service,
            name: 'myPlan',
            description: 'description',
            free: true,
            unique_id: 'broker-provided-id',
            active: false,
            public: false
          )
          repository.with_service_plan_event(plan) { plan.save }
          expect(logger).to have_received(:error)
        end

        specify 'with_service_plan_event logs an error but does not propagate errors' do
          broker = VCAP::CloudController::ServiceBroker.make
          service = VCAP::CloudController::Service.new(
            service_broker: broker,
            label: 'name',
            description: 'some description',
            bindable: true,
            active: false,
            plan_updateable: false,
            unique_id: 'broker-provided-id'
          )
          repository.with_service_event(service) { service.save }
          expect(logger).to have_received(:error)
        end
      end
    end
  end
end
