Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion src/mongocxx/include/mongocxx/v1/data_key_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ class data_key_options {
///
/// Return the current "keyMaterial" field.
///
MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional<key_material_type>) key_material();
MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional<key_material_type>) key_material() const;

class internal;
};

} // namespace v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#pragma once

#include <mongocxx/v1/data_key_options-fwd.hpp>

#include <mongocxx/config/prelude.hpp>

namespace mongocxx {
Expand All @@ -29,7 +31,7 @@ class data_key;
namespace mongocxx {
namespace options {

using ::mongocxx::v_noabi::options::data_key;
using v_noabi::options::data_key;

} // namespace options
} // namespace mongocxx
Expand All @@ -40,3 +42,6 @@ using ::mongocxx::v_noabi::options::data_key;
/// @file
/// Declares @ref mongocxx::v_noabi::options::data_key.
///
/// @par Includes
/// - @ref mongocxx/v1/data_key_options-fwd.hpp
///
103 changes: 87 additions & 16 deletions src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/data_key.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,22 @@

#pragma once

#include <mongocxx/options/data_key-fwd.hpp> // IWYU pragma: export

//

#include <bsoncxx/v1/document/value.hpp>

#include <mongocxx/v1/data_key_options.hpp> // IWYU pragma: export

#include <cstdint>
#include <string>
#include <utility>
#include <vector>

#include <mongocxx/client_encryption-fwd.hpp>
#include <mongocxx/options/data_key-fwd.hpp> // IWYU pragma: export
#include <mongocxx/client_encryption-fwd.hpp> // IWYU pragma: keep: backward compatibility, to be removed.

#include <bsoncxx/document/view.hpp>
#include <bsoncxx/document/view_or_value.hpp>
#include <bsoncxx/stdx/optional.hpp>

Expand All @@ -34,6 +44,35 @@ namespace options {
///
class data_key {
public:
///
/// Default initialization.
///
data_key() = default;

///
/// Construct with the @ref mongocxx::v1 equivalent.
///
/* explicit(false) */ MONGOCXX_ABI_EXPORT_CDECL() data_key(v1::data_key_options key);

///
/// Convert to the @ref mongocxx::v1 equivalent.
///
explicit operator v1::data_key_options() const {
v1::data_key_options ret;

if (_master_key) {
ret.master_key(bsoncxx::v1::document::value{bsoncxx::v_noabi::to_v1(_master_key->view())});
}

ret.key_alt_names(_key_alt_names);

if (_key_material) {
ret.key_material(*_key_material);
}

return ret;
}

///
/// Sets a KMS-specific key used to encrypt the new data key.
///
Expand Down Expand Up @@ -99,17 +138,20 @@ class data_key {
/// @see
/// - https://www.mongodb.com/docs/manual/core/security-client-side-encryption-key-management/
///
MONGOCXX_ABI_EXPORT_CDECL(data_key&)
master_key(bsoncxx::v_noabi::document::view_or_value master_key);
data_key& master_key(bsoncxx::v_noabi::document::view_or_value master_key) {
_master_key = std::move(master_key);
return *this;
}

///
/// Gets the master key.
///
/// @return
/// An optional document containing the master key.
///
MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v_noabi::stdx::optional<bsoncxx::v_noabi::document::view_or_value> const&)
master_key() const;
bsoncxx::v_noabi::stdx::optional<bsoncxx::v_noabi::document::view_or_value> const& master_key() const {
return _master_key;
}

///
/// Sets an optional list of string alternate names used to reference the key.
Expand All @@ -125,20 +167,25 @@ class data_key {
/// @see
/// - https://www.mongodb.com/docs/manual/reference/method/getClientEncryption/
///
MONGOCXX_ABI_EXPORT_CDECL(data_key&) key_alt_names(std::vector<std::string> key_alt_names);
data_key& key_alt_names(std::vector<std::string> key_alt_names) {
_key_alt_names = std::move(key_alt_names);
return *this;
}

///
/// Gets the alternate names for the data key.
///
/// @return
/// The alternate names for the data key.
///
MONGOCXX_ABI_EXPORT_CDECL(std::vector<std::string> const&) key_alt_names() const;
std::vector<std::string> const& key_alt_names() const {
return _key_alt_names;
}

///
/// Represents binary data used to represent key material.
///
using key_material_type = std::vector<uint8_t>;
using key_material_type = std::vector<std::uint8_t>;

///
/// Sets the binary data for the key material
Expand All @@ -159,7 +206,10 @@ class data_key {
/// @see
/// - https://www.mongodb.com/docs/v6.0/reference/method/KeyVault.createKey/
///
MONGOCXX_ABI_EXPORT_CDECL(data_key&) key_material(key_material_type key_material);
data_key& key_material(key_material_type key_material) {
_key_material = std::move(key_material);
return *this;
}

///
/// Gets the keyMaterial as binary data
Expand All @@ -170,14 +220,13 @@ class data_key {
/// @see
/// - https://www.mongodb.com/docs/v6.0/reference/method/KeyVault.createKey/
///
MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v_noabi::stdx::optional<key_material_type> const&)
key_material();
bsoncxx::v_noabi::stdx::optional<key_material_type> const& key_material() {
return _key_material;
}

private:
friend ::mongocxx::v_noabi::client_encryption;

void* convert() const;
class internal;

private:
bsoncxx::v_noabi::stdx::optional<bsoncxx::v_noabi::document::view_or_value> _master_key;
std::vector<std::string> _key_alt_names;
bsoncxx::v_noabi::stdx::optional<key_material_type> _key_material;
Expand All @@ -187,9 +236,31 @@ class data_key {
} // namespace v_noabi
} // namespace mongocxx

namespace mongocxx {
namespace v_noabi {

///
/// Convert to the @ref mongocxx::v_noabi equivalent of `v`.
///
inline v_noabi::options::data_key from_v1(v1::data_key_options v) {
return {std::move(v)};
}

/// Convert to the @ref mongocxx::v1 equivalent of `v`.
///
inline v1::data_key_options to_v1(v_noabi::options::data_key v) {
return v1::data_key_options{std::move(v)};
}

} // namespace v_noabi
} // namespace mongocxx

#include <mongocxx/config/postlude.hpp>

///
/// @file
/// Provides @ref mongocxx::v_noabi::options::data_key.
///
/// @par Includes
/// - @ref mongocxx/v1/data_key_options.hpp
///
148 changes: 147 additions & 1 deletion src/mongocxx/lib/mongocxx/v1/data_key_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,150 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <mongocxx/v1/data_key_options.hpp>
#include <mongocxx/v1/data_key_options.hh>

//

#include <bsoncxx/v1/document/value.hpp>
#include <bsoncxx/v1/stdx/optional.hpp>

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include <mongocxx/private/mongoc.hh>
#include <mongocxx/private/scoped_bson.hh>
#include <mongocxx/private/utility.hh>

namespace mongocxx {
namespace v1 {

class data_key_options::impl {
public:
bsoncxx::v1::stdx::optional<bsoncxx::v1::document::value> _master_key;
std::vector<std::string> _key_alt_names;
bsoncxx::v1::stdx::optional<key_material_type> _key_material;

static impl const& with(data_key_options const& self) {
return *static_cast<impl const*>(self._impl);
}

static impl const* with(data_key_options const* self) {
return static_cast<impl const*>(self->_impl);
}

static impl& with(data_key_options& self) {
return *static_cast<impl*>(self._impl);
}

static impl* with(data_key_options* self) {
return static_cast<impl*>(self->_impl);
}

static impl* with(void* ptr) {
return static_cast<impl*>(ptr);
}
};

data_key_options::~data_key_options() {
delete impl::with(this);
}

data_key_options::data_key_options(data_key_options&& other) noexcept : _impl{exchange(other._impl, nullptr)} {}

data_key_options& data_key_options::operator=(data_key_options&& other) noexcept {
if (this != &other) {
delete impl::with(exchange(_impl, exchange(other._impl, nullptr)));
}

return *this;
}

data_key_options::data_key_options(data_key_options const& other) : _impl{new impl{impl::with(other)}} {}

data_key_options& data_key_options::operator=(data_key_options const& other) {
if (this != &other) {
delete impl::with(exchange(_impl, new impl{impl::with(other)}));
}

return *this;
}

data_key_options::data_key_options() : _impl{new impl{}} {}

data_key_options& data_key_options::master_key(bsoncxx::v1::document::value master_key) {
impl::with(this)->_master_key = std::move(master_key);
return *this;
}

bsoncxx::v1::stdx::optional<bsoncxx::v1::document::view> data_key_options::master_key() const {
return impl::with(this)->_master_key;
}

data_key_options& data_key_options::key_alt_names(std::vector<std::string> key_alt_names) {
impl::with(this)->_key_alt_names = std::move(key_alt_names);
return *this;
}

std::vector<std::string> data_key_options::key_alt_names() const {
return impl::with(this)->_key_alt_names;
}

data_key_options& data_key_options::key_material(key_material_type key_material) {
impl::with(this)->_key_material = std::move(key_material);
return *this;
}

bsoncxx::v1::stdx::optional<data_key_options::key_material_type> data_key_options::key_material() const {
return impl::with(this)->_key_material;
}

std::unique_ptr<mongoc_client_encryption_datakey_opts_t, data_key_options::internal::deleter_type>
data_key_options::internal::to_mongoc(data_key_options const& self) {
std::unique_ptr<mongoc_client_encryption_datakey_opts_t, data_key_options::internal::deleter_type> ret{
libmongoc::client_encryption_datakey_opts_new()};

auto const opts = ret.get();
auto& _impl = impl::with(self);

if (auto const& opt = _impl._master_key) {
libmongoc::client_encryption_datakey_opts_set_masterkey(opts, scoped_bson_view{opt->view()}.bson());
}

if (!_impl._key_alt_names.empty()) {
std::vector<char*> names;

names.reserve(_impl._key_alt_names.size());
for (auto const& name : _impl._key_alt_names) {
names.push_back(const_cast<char*>(name.c_str())); // For copy only.
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (auto const& name : _impl._key_alt_names) {
names.push_back(const_cast<char*>(name.c_str())); // For copy only.
}
std::transform(
_impl._key_alt_names.begin(), _impl._key_alt_names.end(), std::back_inserter(names), [](auto const& name) {
return const_cast<char*>(name.c_str()); // For copy only
});

I tend to advocate for algorithm use, but with a single-statement loop like this, I chalk it up to preference.

Also, I am not sure what your intentions are with clang-tidy, but you may want to preemptively add a // NOLINT(cppcoreguidelines-pro-type-const-cast).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to advocate for algorithm use, but with a single-statement loop like this, I chalk it up to preference.

Accepted the suggestion, with the caveat that generic lambdas are C++14 and newer. I've personally preferred to avoid <algorithm> unless dealing with generic code over iterators (e.g. no direct access to the parent container or knowledge of its type, if any), but there is an argument to be made for opting-into the opportunity for stdlib-internal optimizations based on iterator and element type (likely not applicable here, but nevertheless) and/or ease of extending behavior (e.g. C++17 parallel execution: this could be par_unseq). But maybe this too is YAGNI.

I am not sure what your intentions are with clang-tidy

I'm hesitating to insert any clang-tidy-related comments until we've decided on the set of diagnostics to care about in #1496. Feel free to add yourself as a reviewer if interested in providing input.


libmongoc::client_encryption_datakey_opts_set_keyaltnames(
opts, names.data(), static_cast<std::uint32_t>(_impl._key_alt_names.size()));
}

if (auto const& opt = _impl._key_material) {
libmongoc::client_encryption_datakey_opts_set_keymaterial(
opts, opt->data(), static_cast<std::uint32_t>(opt->size()));
}

return ret;
}

bsoncxx::v1::stdx::optional<bsoncxx::v1::document::value>& data_key_options::internal::master_key(
data_key_options& self) {
return impl::with(self)._master_key;
}

std::vector<std::string>& data_key_options::internal::key_alt_names(data_key_options& self) {
return impl::with(self)._key_alt_names;
}

bsoncxx::v1::stdx::optional<data_key_options::key_material_type>& data_key_options::internal::key_material(
data_key_options& self) {
return impl::with(self)._key_material;
}

} // namespace v1
} // namespace mongocxx
Loading