Skip to content

Commit

Permalink
v3(services): Return list of service credential bindings (cloudfoundr…
Browse files Browse the repository at this point in the history
…y#1761)

* v3(services): Return list of service credential bindings

[#173171550](https://www.pivotaltracker.com/story/show/173171550)
  • Loading branch information
Brian Butz authored Jul 29, 2020
1 parent 214fda4 commit 3b6ccfc
Show file tree
Hide file tree
Showing 18 changed files with 429 additions and 116 deletions.
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
--color
--order rand
-I app
56 changes: 36 additions & 20 deletions app/controllers/v3/service_credential_bindings_controller.rb
Original file line number Diff line number Diff line change
@@ -1,49 +1,65 @@
require 'fetchers/service_credential_binding_fetcher'
require 'fetchers/service_credential_binding_list_fetcher'
require 'presenters/v3/service_credential_binding_presenter'

class ServiceCredentialBindingsController < ApplicationController
before_action :ensure_service_credential_binding_exists!
before_action :ensure_user_has_access!
def index
results = list_fetcher.fetch(space_guids: space_guids)

presenter = Presenters::V3::PaginatedListPresenter.new(
presenter: Presenters::V3::ServiceCredentialBindingPresenter,
paginated_result: SequelPaginator.new.get_page(results, pagination_options),
path: '/v3' + service_credential_bindings_path
)

render status: :ok, json: presenter
end

def show
ensure_service_credential_binding_is_accessible!
render status: :ok, json: serialized
end

private

def serialized
{
guid: service_credential_binding.guid,
type: service_credential_binding.type
}
def service_credential_binding
@service_credential_binding ||= fetcher.fetch(hashed_params[:guid], space_guids: space_guids)
end

def ensure_service_credential_binding_exists!
not_found! unless service_credential_binding_exists?
def space_guids
if permission_queryer.can_read_globally?
:all
else
permission_queryer.readable_space_guids
end
end

def ensure_user_has_access!
not_found! unless allowed_to_access_space?
def pagination_options
query_params_with_order_by = query_params.reverse_merge(order_by: :created_at)
ListMessage.from_params(query_params_with_order_by, []).pagination_options
end

def not_found!
resource_not_found!(:service_credential_binding)
def serialized
Presenters::V3::ServiceCredentialBindingPresenter.new(service_credential_binding).to_hash
end

def service_credential_binding
@service_credential_binding ||= fetcher.fetch(hashed_params[:guid])
def ensure_service_credential_binding_is_accessible!
not_found! unless service_credential_binding_exists?
end

def fetcher
@fetcher ||= VCAP::CloudController::ServiceCredentialBindingFetcher.new
def not_found!
resource_not_found!(:service_credential_binding)
end

def service_credential_binding_exists?
!!service_credential_binding
end

def allowed_to_access_space?
space = service_credential_binding.space
def list_fetcher
@list_fetcher ||= VCAP::CloudController::ServiceCredentialBindingListFetcher.new
end

permission_queryer.can_read_from_space?(space.guid, space.organization_guid)
def fetcher
@fetcher ||= VCAP::CloudController::ServiceCredentialBindingFetcher.new
end
end
15 changes: 10 additions & 5 deletions app/fetchers/service_credential_binding_fetcher.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
module VCAP
module CloudController
class ServiceCredentialBindingFetcher
ServiceInstanceCredential = Struct.new(:guid, :type, :space).freeze
ServiceInstanceCredential = Struct.new(:guid, :type).freeze

def fetch(guid)
ServiceCredentialBinding::View.first(guid: guid).try do |db_binding|
def fetch(guid, space_guids:)
list_fetcher.fetch(space_guids: space_guids).first(guid: guid).try do |db_binding|
ServiceInstanceCredential.new(
db_binding.guid,
db_binding.type,
db_binding.space
db_binding.type
)
end
end

private

def list_fetcher
ServiceCredentialBindingListFetcher.new
end
end
end
end
14 changes: 14 additions & 0 deletions app/fetchers/service_credential_binding_list_fetcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module VCAP
module CloudController
class ServiceCredentialBindingListFetcher
def fetch(space_guids:)
case space_guids
when :all
ServiceCredentialBinding::View.dataset
else
ServiceCredentialBinding::View.where { Sequel[:space_guid] =~ space_guids }
end
end
end
end
end
38 changes: 16 additions & 22 deletions app/models/services/service_credential_binding_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,26 @@ module Types
SERVICE_BINDING = 'app'.freeze
end

SERVICE_KEY_VIEW = VCAP::CloudController::ServiceKey.select(
:guid,
SERVICE_KEY_VIEW = Sequel::Model(:service_keys).select(
Sequel.as(:service_keys__guid, :guid),
Sequel.as(Types::SERVICE_KEY, :type),
:service_instance_id,
Sequel.as(nil, :app_guid)
Sequel.as(:spaces__guid, :space_guid),
Sequel.as(:service_keys__created_at, :created_at)
).join(
:service_instances, id: Sequel[:service_keys][:service_instance_id]
).join(
:spaces, id: Sequel[:service_instances][:space_id]
).freeze

SERVICE_BINDING_VIEW = VCAP::CloudController::ServiceBinding.select(
:guid,
SERVICE_BINDING_VIEW = Sequel::Model(:service_bindings).select(
Sequel.as(:service_bindings__guid, :guid),
Sequel.as(Types::SERVICE_BINDING, :type),
Sequel.as(nil, :service_instance_id),
:app_guid
Sequel.as(:spaces__guid, :space_guid),
Sequel.as(:service_bindings__created_at, :created_at)
).join(
:apps, guid: Sequel[:service_bindings][:app_guid]
).join(
:spaces, guid: Sequel[:apps][:space_guid]
).freeze

VIEW = [
Expand All @@ -28,20 +36,6 @@ module Types
end.from_self.freeze

class View < Sequel::Model(VIEW)
many_to_one :service_instance, class: 'VCAP::CloudController::ServiceInstance'
many_to_one :app, class: 'VCAP::CloudController::AppModel', key: :app_guid, primary_key: :guid, without_guid_generation: true

def space
relation =
case type
when Types::SERVICE_BINDING
app
else
service_instance
end

relation.space
end
end
end
end
Expand Down
16 changes: 9 additions & 7 deletions app/presenters/helpers/censorship.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
module VCAP::CloudController
module Presenters
module Censorship
PRIVATE_DATA_HIDDEN = '[PRIVATE DATA HIDDEN]'.freeze
PRIVATE_DATA_HIDDEN_LIST = '[PRIVATE DATA HIDDEN IN LISTS]'.freeze
REDACTED = '[REDACTED]'.freeze
REDACTED_CREDENTIAL = '***'.freeze
module VCAP
module CloudController
module Presenters
module Censorship
PRIVATE_DATA_HIDDEN = '[PRIVATE DATA HIDDEN]'.freeze
PRIVATE_DATA_HIDDEN_LIST = '[PRIVATE DATA HIDDEN IN LISTS]'.freeze
REDACTED = '[REDACTED]'.freeze
REDACTED_CREDENTIAL = '***'.freeze
end
end
end
end
40 changes: 21 additions & 19 deletions app/presenters/v3/base_presenter.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
require 'presenters/helpers/censorship'

module VCAP::CloudController
module Presenters
module V3
class BasePresenter
def initialize(resource, show_secrets: true, censored_message: Censorship::PRIVATE_DATA_HIDDEN, decorators: [])
@resource = resource
@show_secrets = show_secrets
@censored_message = censored_message
@decorators = decorators
end
module VCAP
module CloudController
module Presenters
module V3
class BasePresenter
def initialize(resource, show_secrets: true, censored_message: Censorship::PRIVATE_DATA_HIDDEN, decorators: [])
@resource = resource
@show_secrets = show_secrets
@censored_message = censored_message
@decorators = decorators
end

private
private

def redact(unredacted_value)
@show_secrets ? unredacted_value : @censored_message
end
def redact(unredacted_value)
@show_secrets ? unredacted_value : @censored_message
end

def redact_hash(unredacted_value)
@show_secrets ? unredacted_value : { 'redacted_message' => @censored_message }
end
def redact_hash(unredacted_value)
@show_secrets ? unredacted_value : { 'redacted_message' => @censored_message }
end

def url_builder
@url_builder ||= VCAP::CloudController::Presenters::ApiUrlBuilder
def url_builder
@url_builder ||= VCAP::CloudController::Presenters::ApiUrlBuilder
end
end
end
end
Expand Down
18 changes: 18 additions & 0 deletions app/presenters/v3/service_credential_binding_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require_relative 'base_presenter'

module VCAP
module CloudController
module Presenters
module V3
class ServiceCredentialBindingPresenter < BasePresenter
def to_hash
{
guid: @resource.guid,
type: @resource.type
}
end
end
end
end
end
end
4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@
delete '/service_bindings/:guid', to: 'service_bindings#destroy'

# service_credential_bindings
get '/service_credential_bindings/:guid', to: 'service_credential_bindings#show'
resources :service_credential_bindings,
param: :guid,
only: [:show, :index]

# service_brokers
get '/service_brokers', to: 'service_brokers#index'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<% content_for :single_service_credential_binding_app do %>
{
"guid": "ddd7fb26-c42d-4acf-a035-60fdd094a167",
"type": "app"
}
<% end %>

<% content_for :single_service_credential_binding_key do %>
{
"guid": "ddd7fb26-c42d-4acf-a035-60fdd094a167",
"type": "key"
}
<% end %>

<% content_for :paginated_list_of_service_credential_bindings do |base_url| %>
{
"pagination": {
"total_results": 3,
"total_pages": 2,
"first": {
"href": "https://api.example.org<%= base_url %>?page=1&per_page=2"
},
"last": {
"href": "https://api.example.org<%= base_url %>?page=2&per_page=2"
},
"next": {
"href": "https://api.example.org<%= base_url %>?page=2&per_page=2"
},
"previous": null
},
"resources": [
{
"guid": "dde5ad2a-d8f4-44dc-a56f-0452d744f1c3",
"type": "app"
},
{
"guid": "7aa37bad-6ccb-4ef9-ba48-9ce3a91b2b62",
"type": "key"
}
]
}
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
### Get a service credential binding

```
Example Request
```

```shell
curl "https://api.example.org/v3/service_credential_bindings/[guid]" \
-X GET \
-H "Authorization: bearer [token]"
```

```
Example App Credential Binding Response
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

<%= yield_content :single_service_credential_binding_app %>
```

```
Example Key Credential Binding Response
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

<%= yield_content :single_service_credential_binding_key %>
```


This endpoint retrieves the service credential binding by GUID.

#### Definition
`GET /v3/service_service_credential_bindings/:guid`

#### Permitted roles
|
--- | ---
Admin |
Admin Read-Only |
Global Auditor |
Org Manager |
Space Auditor |
Space Developer |
Space Manager |
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Service Credential Binding (experimental)

An instantiation of a service credential binding.
Loading

0 comments on commit 3b6ccfc

Please sign in to comment.