Skip to content

Commit

Permalink
setup directory v3 client
Browse files Browse the repository at this point in the history
  • Loading branch information
gimmyxd committed Nov 15, 2023
1 parent 85bd759 commit fbdc97e
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"cSpell.words": [
"creds"
"creds",
"etag"
]
}
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ group :development do
gem "bundler", ">= 1.15.0", "< 3.0"
gem "codecov", "~> 0.6"
gem "grpc_mock", "~> 0.4"
gem "pry-byebug", "~> 3.10"
gem "rspec", "~> 3.0"
gem "rubocop-performance", "~> 1.14"
gem "rubocop-rspec", "~> 2.11"
Expand Down
4 changes: 2 additions & 2 deletions aserto.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ Gem::Specification.new do |spec|
spec.metadata["rubygems_mfa_required"] = "true"

# runtime dependencies
spec.add_runtime_dependency "aserto-authorizer", ">= 0.0.5"
spec.add_runtime_dependency "aserto-directory", ">= 0.0.3"
spec.add_runtime_dependency "aserto-authorizer", ">= 0.20.1"
spec.add_runtime_dependency "aserto-directory", ">= 0.30.1"
spec.add_runtime_dependency "jwt", "~> 2.4"
spec.add_runtime_dependency "rack", "~> 2.0"
end
19 changes: 10 additions & 9 deletions lib/aserto.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
require_relative "aserto/auth_client"
require_relative "aserto/errors"
require_relative "aserto/directory/client"
require_relative "aserto/directory/v3/client"

module Aserto
class << self
Expand Down Expand Up @@ -52,17 +53,17 @@ def with_policy_path_mapper
def with_resource_mapper
Aserto::ResourceMapper.class_eval do |klass|
klass.define_singleton_method(:execute) do |request|
if block_given?
result = yield(request)
unless result.is_a?(Hash)
raise Aserto::InvalidResourceMapping, "block must return a hash, got: #{result.class}"
end
return unless block_given?

require "google/protobuf/well_known_types"

result.transform_keys!(&:to_s)
Google::Protobuf::Struct.from_hash(result)
result = yield(request)
unless result.is_a?(Hash)
raise Aserto::InvalidResourceMapping, "block must return a hash, got: #{result.class}"
end

require "google/protobuf/well_known_types"

result.transform_keys!(&:to_s)
Google::Protobuf::Struct.from_hash(result)
end
end
end
Expand Down
107 changes: 107 additions & 0 deletions lib/aserto/directory/v3/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# frozen_string_literal: true

require "aserto/directory"
require_relative "../interceptors/headers"
require_relative "config"

module Aserto
module Directory
module V3
class Client
attr_reader :reader, :writer, :importer, :exporter, :model

# Creates a new Directory V3 Client
#
# @param config [Aserto::Directory::V3::Config] the service configuration
# Base configuration
# If non-nil, this configuration is used for any client that doesn't have its own configuration.
# If nil, only clients that have their own configuration will be created.
# {
# url: "base_url",
# tenant_id: "base_tenant_id",
# api_key: "base_api_key"
#
# Reader Configuration
# reader: {
# url: "reader_url",
# tenant_id: "reader_tenant_id",
# api_key: "reader_api_key"
# },
#
# Writer Configuration
# writer: {
# url: "writer_url",
# tenant_id: "writer_tenant_id",
# api_key: "writer_api_key"
# },
#
# Importer Configuration
# importer: {
# url: "importer_url",
# tenant_id: "importer_tenant_id",
# api_key: "importer_api_key"
# },
#
# Exporter Configuration
# exporter: {
# url: "exporter_url",
# tenant_id: "exporter_tenant_id",
# api_key: "exporter_api_key"
# },
#
# Model Configuration
# model: {
# url: "model_url",
# tenant_id: "model_tenant_id",
# api_key: "model_api_key"
# }
# }
#
# @return [Aserto::Directory::V3::Client] the new Directory V3 Client
def initialize(config)
base_config = ::Aserto::Directory::V3::Config.new(config)

@reader = create_client(:reader, base_config.reader)
@writer = create_client(:writer, base_config.writer)
@importer = create_client(:importer, base_config.importer)
@exporter = create_client(:exporter, base_config.exporter)
@model = create_client(:model, base_config.model)
end

private

class NullClient
def initialize(name)
@name = name
end

def method_missing(method, *_args)
puts "Cannot call '#{method}': '#{@name.to_s.capitalize}' client is not initialized."
end

def respond_to_missing?(_name, _include_private)
true
end
end

SERVICE_MAP = {
reader: ::Aserto::Directory::Reader::V3::Reader::Stub,
writer: ::Aserto::Directory::Writer::V3::Writer::Stub,
importer: ::Aserto::Directory::Importer::V3::Importer::Stub,
exporter: ::Aserto::Directory::Exporter::V3::Exporter::Stub,
model: ::Aserto::Directory::Model::V3::Model::Stub
}.freeze

def create_client(type, config)
return NullClient.new(type) unless config

SERVICE_MAP[type].new(
config.url,
config.credentials,
interceptors: config.interceptors
)
end
end
end
end
end
53 changes: 53 additions & 0 deletions lib/aserto/directory/v3/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require_relative "../interceptors/headers"

module Aserto
module Directory
module V3
class Config
attr_reader :reader, :writer, :importer, :exporter, :model

class BaseConfig
attr_reader :url, :credentials, :interceptors

def initialize(url, credentials, interceptors)
@url = url
@credentials = credentials
@interceptors = interceptors
end
end

def initialize(config)
@base = {
url: config[:url] || "directory.prod.aserto.com:8443",
api_key: config[:api_key],
tenant_id: config[:tenant_id]
}

@reader = build(**(config[:reader] || {}))
@writer = build(**(config[:writer] || {}))
@importer = build(**(config[:importer] || {}))
@exporter = build(**(config[:exporter] || {}))
@model = build(**(config[:model] || {}))
end

private

def build(url: @base[:url], api_key: @base[:api_key], tenant_id: @base[:tenant_id], cert_path: nil)
return if url.nil? || url.empty? || api_key.nil? || api_key.empty? || tenant_id.nil? || tenant_id.empty?

BaseConfig.new(url, load_creds(cert_path), [Interceptors::Headers.new(api_key, tenant_id)])
end

def load_creds(cert_path)
if cert_path && File.file?(cert_path)
GRPC::Core::ChannelCredentials.new(File.read(cert_path))
else
GRPC::Core::ChannelCredentials.new
end
end
end
end
end
end
40 changes: 40 additions & 0 deletions spec/aserto/directory/v3/client_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

describe Aserto::Directory::V3::Client do
let(:client) { described_class.new(tenant_id: "1234", api_key: "basic test") }

describe ".reader" do
describe ".get_object" do
before do
GrpcMock.stub_request("/aserto.directory.reader.v3.Reader/GetObject").to_return do
Aserto::Directory::Reader::V3::GetObjectResponse.new(
{ result: { id: "id", type: "type", display_name: "display_name" } }
)
end
end

it "returns the correct object" do
expect(client.reader.get_object(
Aserto::Directory::Reader::V3::GetObjectRequest.new(
object_id: "id",
object_type: "type"
)
).to_h).to eq(
{
result: {
created_at: nil,
display_name: "display_name",
etag: "",
id: "id",
properties: nil,
type: "type",
updated_at: nil
},
relations: [],
page: nil
}
)
end
end
end
end

0 comments on commit fbdc97e

Please sign in to comment.