Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/couchbase
73 changes: 59 additions & 14 deletions ext/rcb_backend.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ cb_Backend_allocate(VALUE klass)
}

auto
construct_cluster_options(VALUE credentials, bool tls_enabled) -> couchbase::cluster_options
construct_authenticator(VALUE credentials)
-> std::variant<couchbase::password_authenticator, couchbase::certificate_authenticator>
{
cb_check_type(credentials, T_HASH);

Expand All @@ -198,11 +199,30 @@ construct_cluster_options(VALUE credentials, bool tls_enabled) -> couchbase::clu
cb_check_type(username, T_STRING);
cb_check_type(password, T_STRING);

return cluster_options{
password_authenticator{
cb_string_new(username),
cb_string_new(password),
},
return couchbase::password_authenticator{
cb_string_new(username),
cb_string_new(password),
};
}

cb_check_type(certificate_path, T_STRING);
cb_check_type(key_path, T_STRING);

return couchbase::certificate_authenticator{
cb_string_new(certificate_path),
cb_string_new(key_path),
};
}

auto
construct_cluster_options(VALUE credentials, bool tls_enabled) -> couchbase::cluster_options
{
std::variant<couchbase::password_authenticator, couchbase::certificate_authenticator>
authenticator = construct_authenticator(credentials);

if (std::holds_alternative<couchbase::password_authenticator>(authenticator)) {
return couchbase::cluster_options{
std::get<couchbase::password_authenticator>(std::move(authenticator)),
};
}

Expand All @@ -212,14 +232,8 @@ construct_cluster_options(VALUE credentials, bool tls_enabled) -> couchbase::clu
"Certificate authenticator requires TLS connection, check the connection string");
}

cb_check_type(certificate_path, T_STRING);
cb_check_type(key_path, T_STRING);

return cluster_options{
certificate_authenticator{
cb_string_new(certificate_path),
cb_string_new(key_path),
},
return couchbase::cluster_options{
std::get<couchbase::certificate_authenticator>(std::move(authenticator)),
};
}

Expand Down Expand Up @@ -610,6 +624,36 @@ cb_Backend_open_bucket(VALUE self, VALUE bucket, VALUE wait_until_ready)
return Qnil;
}

VALUE
cb_Backend_update_credentials(VALUE self, VALUE credentials)
{
auto cluster = cb_backend_to_public_api_cluster(self);

try {
std::variant<couchbase::password_authenticator, couchbase::certificate_authenticator>
authenticator = construct_authenticator(credentials);

couchbase::error err{};
if (std::holds_alternative<couchbase::password_authenticator>(authenticator)) {
err = cluster.set_authenticator(
std::get<couchbase::password_authenticator>(std::move(authenticator)));
} else {
err = cluster.set_authenticator(
std::get<couchbase::certificate_authenticator>(std::move(authenticator)));
}
if (err) {
cb_throw_error(err, "failed to update authenticator");
}
} catch (const std::system_error& se) {
rb_exc_raise(cb_map_error_code(
se.code(), fmt::format("failed to update authenticator {}: {}", __func__, se.what()), false));
} catch (const ruby_exception& e) {
rb_exc_raise(e.exception_object());
}

return Qnil;
}

} // namespace

VALUE
Expand All @@ -620,6 +664,7 @@ init_backend(VALUE mCouchbase)
rb_define_method(cBackend, "open", cb_Backend_open, 3);
rb_define_method(cBackend, "open_bucket", cb_Backend_open_bucket, 2);
rb_define_method(cBackend, "close", cb_Backend_close, 0);
rb_define_method(cBackend, "update_credentials", cb_Backend_update_credentials, 1);

rb_define_singleton_method(cBackend, "notify_fork", cb_Backend_notify_fork, 1);
return cBackend;
Expand Down
39 changes: 32 additions & 7 deletions lib/couchbase/cluster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,31 @@ def bucket(name)
Bucket.new(@backend, name)
end

def update_authenticator(authenticator)
credentials = {}

case authenticator
when PasswordAuthenticator
credentials[:username] = authenticator.username
raise ArgumentError, "missing username" unless credentials[:username]

credentials[:password] = authenticator.password
raise ArgumentError, "missing password" unless credentials[:password]

when CertificateAuthenticator
credentials[:certificate_path] = authenticator.certificate_path
raise ArgumentError, "missing certificate path" unless credentials[:certificate_path]

credentials[:key_path] = authenticator.key_path
raise ArgumentError, "missing key path" unless credentials[:key_path]

else
raise ArgumentError, "argument must be an authenticator"
end

@backend.update_credentials(credentials)
end

# Performs a query against the query (N1QL) services
#
# @param [String] statement the N1QL query statement
Expand Down Expand Up @@ -332,22 +357,22 @@ def initialize(connection_string, *args)
raise ArgumentError, "missing username" unless credentials[:username]
raise ArgumentError, "missing password" unless credentials[:password]
when Options::Cluster
open_options = options&.to_backend || {}
authenticator = options&.authenticator
open_options = options.to_backend || {}
authenticator = options.authenticator
case authenticator
when PasswordAuthenticator
credentials[:username] = authenticator&.username
credentials[:username] = authenticator.username
raise ArgumentError, "missing username" unless credentials[:username]

credentials[:password] = authenticator&.password
credentials[:password] = authenticator.password
raise ArgumentError, "missing password" unless credentials[:password]

open_options[:allowed_sasl_mechanisms] = authenticator&.allowed_sasl_mechanisms
open_options[:allowed_sasl_mechanisms] = authenticator.allowed_sasl_mechanisms
when CertificateAuthenticator
credentials[:certificate_path] = authenticator&.certificate_path
credentials[:certificate_path] = authenticator.certificate_path
raise ArgumentError, "missing certificate path" unless credentials[:certificate_path]

credentials[:key_path] = authenticator&.key_path
credentials[:key_path] = authenticator.key_path
raise ArgumentError, "missing key path" unless credentials[:key_path]

else
Expand Down
Loading