[ads] Add confirmation_tokens and payment_tokens database tables (#35341)
This commit is contained in:
@@ -129,6 +129,8 @@ static_library("internal") {
|
||||
"account/tokens/confirmation_tokens/confirmation_token_info.h",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens.cc",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens.h",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens_database_table.cc",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens_database_table.h",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens_util.cc",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens_util.h",
|
||||
"account/tokens/confirmation_tokens/confirmation_tokens_value_util.cc",
|
||||
@@ -141,6 +143,8 @@ static_library("internal") {
|
||||
"account/tokens/payment_tokens/payment_token_value_util.h",
|
||||
"account/tokens/payment_tokens/payment_tokens.cc",
|
||||
"account/tokens/payment_tokens/payment_tokens.h",
|
||||
"account/tokens/payment_tokens/payment_tokens_database_table.cc",
|
||||
"account/tokens/payment_tokens/payment_tokens_database_table.h",
|
||||
"account/tokens/token_generator.cc",
|
||||
"account/tokens/token_generator.h",
|
||||
"account/tokens/token_generator_interface.h",
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_database_table.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/location.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_token_info.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/public_key.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/unblinded_token.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_column_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_table_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_transaction_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/logging_util.h"
|
||||
#include "brave/components/brave_ads/core/mojom/brave_ads.mojom.h"
|
||||
|
||||
namespace brave_ads::database::table {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kTableName[] = "confirmation_tokens";
|
||||
|
||||
void BindColumnTypes(const mojom::DBActionInfoPtr& mojom_db_action) {
|
||||
CHECK(mojom_db_action);
|
||||
|
||||
mojom_db_action->bind_column_types = {
|
||||
mojom::DBBindColumnType::kString, // unblinded_token
|
||||
mojom::DBBindColumnType::kString, // public_key
|
||||
mojom::DBBindColumnType::kString // signature
|
||||
};
|
||||
}
|
||||
|
||||
size_t BindColumns(const mojom::DBActionInfoPtr& mojom_db_action,
|
||||
const ConfirmationTokenList& confirmation_tokens) {
|
||||
CHECK(mojom_db_action);
|
||||
CHECK(!confirmation_tokens.empty());
|
||||
|
||||
size_t row_count = 0;
|
||||
|
||||
int32_t index = 0;
|
||||
for (const auto& confirmation_token : confirmation_tokens) {
|
||||
BindColumnString(
|
||||
mojom_db_action, index++,
|
||||
confirmation_token.unblinded_token.EncodeBase64().value_or(""));
|
||||
BindColumnString(mojom_db_action, index++,
|
||||
confirmation_token.public_key.EncodeBase64().value_or(""));
|
||||
BindColumnString(mojom_db_action, index++,
|
||||
confirmation_token.signature_base64);
|
||||
|
||||
++row_count;
|
||||
}
|
||||
|
||||
return row_count;
|
||||
}
|
||||
|
||||
ConfirmationTokenInfo FromMojomRow(const mojom::DBRowInfoPtr& mojom_db_row) {
|
||||
CHECK(mojom_db_row);
|
||||
|
||||
ConfirmationTokenInfo confirmation_token;
|
||||
confirmation_token.unblinded_token =
|
||||
cbr::UnblindedToken(ColumnString(mojom_db_row, 0));
|
||||
confirmation_token.public_key = cbr::PublicKey(ColumnString(mojom_db_row, 1));
|
||||
confirmation_token.signature_base64 = ColumnString(mojom_db_row, 2);
|
||||
return confirmation_token;
|
||||
}
|
||||
|
||||
void GetAllCallback(
|
||||
GetConfirmationTokensCallback callback,
|
||||
mojom::DBTransactionResultInfoPtr mojom_db_transaction_result) {
|
||||
if (!IsTransactionSuccessful(mojom_db_transaction_result)) {
|
||||
BLOG(0, "Failed to get confirmation tokens");
|
||||
return std::move(callback).Run(/*success=*/false,
|
||||
/*confirmation_tokens=*/{});
|
||||
}
|
||||
|
||||
CHECK(mojom_db_transaction_result->rows_union);
|
||||
|
||||
ConfirmationTokenList confirmation_tokens;
|
||||
for (auto& mojom_db_row :
|
||||
mojom_db_transaction_result->rows_union->get_rows()) {
|
||||
confirmation_tokens.push_back(FromMojomRow(mojom_db_row));
|
||||
}
|
||||
|
||||
std::move(callback).Run(/*success=*/true, std::move(confirmation_tokens));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ConfirmationTokens::Save(const ConfirmationTokenList& confirmation_tokens,
|
||||
ResultCallback callback) {
|
||||
if (confirmation_tokens.empty()) {
|
||||
return std::move(callback).Run(/*success=*/true);
|
||||
}
|
||||
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
|
||||
Insert(mojom_db_transaction, confirmation_tokens);
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void ConfirmationTokens::Insert(
|
||||
const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
const ConfirmationTokenList& confirmation_tokens) {
|
||||
CHECK(mojom_db_transaction);
|
||||
|
||||
if (confirmation_tokens.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mojom::DBActionInfoPtr mojom_db_action = mojom::DBActionInfo::New();
|
||||
mojom_db_action->type = mojom::DBActionInfo::Type::kExecuteWithBindings;
|
||||
mojom_db_action->sql = BuildInsertSql(mojom_db_action, confirmation_tokens);
|
||||
mojom_db_transaction->actions.push_back(std::move(mojom_db_action));
|
||||
}
|
||||
|
||||
void ConfirmationTokens::Delete(const ConfirmationTokenInfo& confirmation_token,
|
||||
ResultCallback callback) {
|
||||
const std::optional<std::string> unblinded_token_base64 =
|
||||
confirmation_token.unblinded_token.EncodeBase64();
|
||||
if (!unblinded_token_base64) {
|
||||
BLOG(0, "Failed to delete confirmation token");
|
||||
return std::move(callback).Run(/*success=*/false);
|
||||
}
|
||||
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
Execute(mojom_db_transaction, R"(
|
||||
DELETE FROM
|
||||
$1
|
||||
WHERE
|
||||
unblinded_token = '$2')",
|
||||
{kTableName, *unblinded_token_base64});
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void ConfirmationTokens::DeleteAll(ResultCallback callback) {
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
Execute(mojom_db_transaction, R"(
|
||||
DELETE FROM
|
||||
$1)",
|
||||
{kTableName});
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void ConfirmationTokens::GetAll(GetConfirmationTokensCallback callback) const {
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
mojom::DBActionInfoPtr mojom_db_action = mojom::DBActionInfo::New();
|
||||
mojom_db_action->type = mojom::DBActionInfo::Type::kExecuteQueryWithBindings;
|
||||
mojom_db_action->sql = base::ReplaceStringPlaceholders(
|
||||
R"(
|
||||
SELECT
|
||||
unblinded_token,
|
||||
public_key,
|
||||
signature
|
||||
FROM
|
||||
$1)",
|
||||
{kTableName}, nullptr);
|
||||
BindColumnTypes(mojom_db_action);
|
||||
mojom_db_transaction->actions.push_back(std::move(mojom_db_action));
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
base::BindOnce(&GetAllCallback, std::move(callback)));
|
||||
}
|
||||
|
||||
void ConfirmationTokens::Create(
|
||||
const mojom::DBTransactionInfoPtr& mojom_db_transaction) {
|
||||
CHECK(mojom_db_transaction);
|
||||
|
||||
Execute(mojom_db_transaction, R"(
|
||||
CREATE TABLE confirmation_tokens (
|
||||
unblinded_token TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE,
|
||||
public_key TEXT NOT NULL,
|
||||
signature TEXT NOT NULL
|
||||
))");
|
||||
}
|
||||
|
||||
void ConfirmationTokens::Migrate(
|
||||
const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
int to_version) {
|
||||
CHECK(mojom_db_transaction);
|
||||
|
||||
switch (to_version) {
|
||||
case 56: {
|
||||
Create(mojom_db_transaction);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// No migration needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string ConfirmationTokens::BuildInsertSql(
|
||||
const mojom::DBActionInfoPtr& mojom_db_action,
|
||||
const ConfirmationTokenList& confirmation_tokens) const {
|
||||
CHECK(mojom_db_action);
|
||||
CHECK(!confirmation_tokens.empty());
|
||||
|
||||
const size_t row_count = BindColumns(mojom_db_action, confirmation_tokens);
|
||||
|
||||
return base::ReplaceStringPlaceholders(
|
||||
R"(
|
||||
INSERT INTO $1 (
|
||||
unblinded_token,
|
||||
public_key,
|
||||
signature
|
||||
) VALUES $2)",
|
||||
{kTableName, BuildBindColumnPlaceholders(/*column_count=*/3U, row_count)},
|
||||
nullptr);
|
||||
}
|
||||
|
||||
} // namespace brave_ads::database::table
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_TOKENS_CONFIRMATION_TOKENS_CONFIRMATION_TOKENS_DATABASE_TABLE_H_
|
||||
#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_TOKENS_CONFIRMATION_TOKENS_CONFIRMATION_TOKENS_DATABASE_TABLE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_token_info.h"
|
||||
#include "brave/components/brave_ads/core/internal/database/database_table_interface.h"
|
||||
#include "brave/components/brave_ads/core/mojom/brave_ads.mojom-forward.h"
|
||||
#include "brave/components/brave_ads/core/public/ads_callback.h"
|
||||
|
||||
namespace brave_ads::database::table {
|
||||
|
||||
using GetConfirmationTokensCallback =
|
||||
base::OnceCallback<void(bool success,
|
||||
ConfirmationTokenList confirmation_tokens)>;
|
||||
|
||||
// Persists unspent confirmation tokens that are pending assignment to an ad
|
||||
// confirmation. Tokens are loaded from this table on startup to populate the
|
||||
// in-memory cache, and written here on every add or removal.
|
||||
class ConfirmationTokens final : public TableInterface {
|
||||
public:
|
||||
void Save(const ConfirmationTokenList& confirmation_tokens,
|
||||
ResultCallback callback);
|
||||
|
||||
void Insert(const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
const ConfirmationTokenList& confirmation_tokens);
|
||||
|
||||
void Delete(const ConfirmationTokenInfo& confirmation_token,
|
||||
ResultCallback callback);
|
||||
void DeleteAll(ResultCallback callback);
|
||||
|
||||
void GetAll(GetConfirmationTokensCallback callback) const;
|
||||
|
||||
void Create(const mojom::DBTransactionInfoPtr& mojom_db_transaction) override;
|
||||
void Migrate(const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
int to_version) override;
|
||||
|
||||
private:
|
||||
std::string BuildInsertSql(
|
||||
const mojom::DBActionInfoPtr& mojom_db_action,
|
||||
const ConfirmationTokenList& confirmation_tokens) const;
|
||||
};
|
||||
|
||||
} // namespace brave_ads::database::table
|
||||
|
||||
#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_TOKENS_CONFIRMATION_TOKENS_CONFIRMATION_TOKENS_DATABASE_TABLE_H_
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_database_table.h"
|
||||
|
||||
#include "base/test/test_future.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_token_info.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/test/confirmation_tokens_test_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/test/test_base.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BraveAds*
|
||||
|
||||
namespace brave_ads::database::table {
|
||||
|
||||
class BraveAdsConfirmationTokensDatabaseTableTest : public test::TestBase {
|
||||
protected:
|
||||
ConfirmationTokens database_table_;
|
||||
};
|
||||
|
||||
TEST_F(BraveAdsConfirmationTokensDatabaseTableTest,
|
||||
SaveEmptyConfirmationTokens) {
|
||||
// Act
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({}, save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, ConfirmationTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, ConfirmationTokenList>());
|
||||
const auto [success, confirmation_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_THAT(confirmation_tokens, ::testing::IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsConfirmationTokensDatabaseTableTest, SaveConfirmationTokens) {
|
||||
// Act
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save(test::BuildConfirmationTokens(/*count=*/7),
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, ConfirmationTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, ConfirmationTokenList>());
|
||||
const auto [success, confirmation_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ(test::BuildConfirmationTokens(/*count=*/7), confirmation_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsConfirmationTokensDatabaseTableTest,
|
||||
SaveDuplicateConfirmationTokens) {
|
||||
// Arrange
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save(test::BuildConfirmationTokens(/*count=*/1),
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> duplicate_test_future;
|
||||
database_table_.Save(test::BuildConfirmationTokens(/*count=*/1),
|
||||
duplicate_test_future.GetCallback());
|
||||
ASSERT_TRUE(duplicate_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, ConfirmationTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, ConfirmationTokenList>());
|
||||
const auto [success, confirmation_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ(test::BuildConfirmationTokens(/*count=*/1), confirmation_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsConfirmationTokensDatabaseTableTest, DeleteConfirmationToken) {
|
||||
// Arrange
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save(test::BuildConfirmationTokens(/*count=*/2),
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_test_future;
|
||||
database_table_.Delete(test::BuildConfirmationTokens(/*count=*/2).front(),
|
||||
delete_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, ConfirmationTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, ConfirmationTokenList>());
|
||||
const auto [success, confirmation_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ((ConfirmationTokenList{
|
||||
test::BuildConfirmationTokens(/*count=*/2).back()}),
|
||||
confirmation_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsConfirmationTokensDatabaseTableTest,
|
||||
DoNotDeleteMissingConfirmationToken) {
|
||||
// Arrange
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save(test::BuildConfirmationTokens(/*count=*/1),
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_test_future;
|
||||
database_table_.Delete(test::BuildConfirmationTokens(/*count=*/2).back(),
|
||||
delete_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, ConfirmationTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, ConfirmationTokenList>());
|
||||
const auto [success, confirmation_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ(test::BuildConfirmationTokens(/*count=*/1), confirmation_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsConfirmationTokensDatabaseTableTest,
|
||||
DeleteAllConfirmationTokens) {
|
||||
// Arrange
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save(test::BuildConfirmationTokens(/*count=*/7),
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_all_test_future;
|
||||
database_table_.DeleteAll(delete_all_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_all_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, ConfirmationTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, ConfirmationTokenList>());
|
||||
const auto [success, confirmation_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_THAT(confirmation_tokens, ::testing::IsEmpty());
|
||||
}
|
||||
|
||||
} // namespace brave_ads::database::table
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_database_table.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/location.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_info.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/public_key.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/challenge_bypass_ristretto/unblinded_token.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_column_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_table_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_transaction_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/logging_util.h"
|
||||
#include "brave/components/brave_ads/core/mojom/brave_ads.mojom.h"
|
||||
#include "brave/components/brave_ads/core/public/account/confirmations/confirmation_type.h"
|
||||
#include "brave/components/brave_ads/core/public/ad_units/ad_type.h"
|
||||
|
||||
namespace brave_ads::database::table {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kTableName[] = "payment_tokens";
|
||||
|
||||
void BindColumnTypes(const mojom::DBActionInfoPtr& mojom_db_action) {
|
||||
CHECK(mojom_db_action);
|
||||
|
||||
mojom_db_action->bind_column_types = {
|
||||
mojom::DBBindColumnType::kString, // transaction_id
|
||||
mojom::DBBindColumnType::kString, // unblinded_token
|
||||
mojom::DBBindColumnType::kString, // public_key
|
||||
mojom::DBBindColumnType::kString, // confirmation_type
|
||||
mojom::DBBindColumnType::kString // ad_type
|
||||
};
|
||||
}
|
||||
|
||||
size_t BindColumns(const mojom::DBActionInfoPtr& mojom_db_action,
|
||||
const PaymentTokenList& payment_tokens) {
|
||||
CHECK(mojom_db_action);
|
||||
CHECK(!payment_tokens.empty());
|
||||
|
||||
size_t row_count = 0;
|
||||
|
||||
int32_t index = 0;
|
||||
for (const auto& payment_token : payment_tokens) {
|
||||
BindColumnString(mojom_db_action, index++, payment_token.transaction_id);
|
||||
BindColumnString(mojom_db_action, index++,
|
||||
payment_token.unblinded_token.EncodeBase64().value_or(""));
|
||||
BindColumnString(mojom_db_action, index++,
|
||||
payment_token.public_key.EncodeBase64().value_or(""));
|
||||
BindColumnString(mojom_db_action, index++,
|
||||
ToString(payment_token.confirmation_type));
|
||||
BindColumnString(mojom_db_action, index++, ToString(payment_token.ad_type));
|
||||
|
||||
++row_count;
|
||||
}
|
||||
|
||||
return row_count;
|
||||
}
|
||||
|
||||
PaymentTokenInfo FromMojomRow(const mojom::DBRowInfoPtr& mojom_db_row) {
|
||||
CHECK(mojom_db_row);
|
||||
|
||||
PaymentTokenInfo payment_token;
|
||||
payment_token.transaction_id = ColumnString(mojom_db_row, 0);
|
||||
payment_token.unblinded_token =
|
||||
cbr::UnblindedToken(ColumnString(mojom_db_row, 1));
|
||||
payment_token.public_key = cbr::PublicKey(ColumnString(mojom_db_row, 2));
|
||||
payment_token.confirmation_type =
|
||||
ToMojomConfirmationType(ColumnString(mojom_db_row, 3));
|
||||
payment_token.ad_type = ToMojomAdType(ColumnString(mojom_db_row, 4));
|
||||
return payment_token;
|
||||
}
|
||||
|
||||
void GetAllCallback(
|
||||
GetPaymentTokensCallback callback,
|
||||
mojom::DBTransactionResultInfoPtr mojom_db_transaction_result) {
|
||||
if (!IsTransactionSuccessful(mojom_db_transaction_result)) {
|
||||
BLOG(0, "Failed to get payment tokens");
|
||||
return std::move(callback).Run(/*success=*/false, /*payment_tokens=*/{});
|
||||
}
|
||||
|
||||
CHECK(mojom_db_transaction_result->rows_union);
|
||||
|
||||
PaymentTokenList payment_tokens;
|
||||
for (auto& mojom_db_row :
|
||||
mojom_db_transaction_result->rows_union->get_rows()) {
|
||||
payment_tokens.push_back(FromMojomRow(mojom_db_row));
|
||||
}
|
||||
|
||||
std::move(callback).Run(/*success=*/true, std::move(payment_tokens));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void PaymentTokens::Save(const PaymentTokenList& payment_tokens,
|
||||
ResultCallback callback) {
|
||||
if (payment_tokens.empty()) {
|
||||
return std::move(callback).Run(/*success=*/true);
|
||||
}
|
||||
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
|
||||
Insert(mojom_db_transaction, payment_tokens);
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void PaymentTokens::Insert(
|
||||
const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
const PaymentTokenList& payment_tokens) {
|
||||
CHECK(mojom_db_transaction);
|
||||
|
||||
if (payment_tokens.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mojom::DBActionInfoPtr mojom_db_action = mojom::DBActionInfo::New();
|
||||
mojom_db_action->type = mojom::DBActionInfo::Type::kExecuteWithBindings;
|
||||
mojom_db_action->sql = BuildInsertSql(mojom_db_action, payment_tokens);
|
||||
mojom_db_transaction->actions.push_back(std::move(mojom_db_action));
|
||||
}
|
||||
|
||||
void PaymentTokens::Delete(const PaymentTokenInfo& payment_token,
|
||||
ResultCallback callback) {
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
Execute(mojom_db_transaction, R"(
|
||||
DELETE FROM
|
||||
$1
|
||||
WHERE
|
||||
transaction_id = '$2')",
|
||||
{kTableName, payment_token.transaction_id});
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void PaymentTokens::Delete(const PaymentTokenList& payment_tokens,
|
||||
ResultCallback callback) {
|
||||
if (payment_tokens.empty()) {
|
||||
return std::move(callback).Run(/*success=*/true);
|
||||
}
|
||||
|
||||
std::vector<std::string> transaction_ids;
|
||||
transaction_ids.reserve(payment_tokens.size());
|
||||
for (const auto& payment_token : payment_tokens) {
|
||||
transaction_ids.push_back("'" + payment_token.transaction_id + "'");
|
||||
}
|
||||
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
Execute(mojom_db_transaction, R"(
|
||||
DELETE FROM
|
||||
$1
|
||||
WHERE
|
||||
transaction_id IN ($2))",
|
||||
{kTableName, base::JoinString(transaction_ids, ", ")});
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void PaymentTokens::DeleteAll(ResultCallback callback) {
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
Execute(mojom_db_transaction, R"(
|
||||
DELETE FROM
|
||||
$1)",
|
||||
{kTableName});
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void PaymentTokens::GetAll(GetPaymentTokensCallback callback) const {
|
||||
mojom::DBTransactionInfoPtr mojom_db_transaction =
|
||||
mojom::DBTransactionInfo::New();
|
||||
mojom::DBActionInfoPtr mojom_db_action = mojom::DBActionInfo::New();
|
||||
mojom_db_action->type = mojom::DBActionInfo::Type::kExecuteQueryWithBindings;
|
||||
mojom_db_action->sql = base::ReplaceStringPlaceholders(
|
||||
R"(
|
||||
SELECT
|
||||
transaction_id,
|
||||
unblinded_token,
|
||||
public_key,
|
||||
confirmation_type,
|
||||
ad_type
|
||||
FROM
|
||||
$1)",
|
||||
{kTableName}, nullptr);
|
||||
BindColumnTypes(mojom_db_action);
|
||||
mojom_db_transaction->actions.push_back(std::move(mojom_db_action));
|
||||
|
||||
RunTransaction(FROM_HERE, std::move(mojom_db_transaction),
|
||||
base::BindOnce(&GetAllCallback, std::move(callback)));
|
||||
}
|
||||
|
||||
void PaymentTokens::Create(
|
||||
const mojom::DBTransactionInfoPtr& mojom_db_transaction) {
|
||||
CHECK(mojom_db_transaction);
|
||||
|
||||
Execute(mojom_db_transaction, R"(
|
||||
CREATE TABLE payment_tokens (
|
||||
transaction_id TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE,
|
||||
unblinded_token TEXT NOT NULL,
|
||||
public_key TEXT NOT NULL,
|
||||
confirmation_type TEXT NOT NULL,
|
||||
ad_type TEXT NOT NULL
|
||||
))");
|
||||
}
|
||||
|
||||
void PaymentTokens::Migrate(
|
||||
const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
int to_version) {
|
||||
CHECK(mojom_db_transaction);
|
||||
|
||||
switch (to_version) {
|
||||
case 56: {
|
||||
Create(mojom_db_transaction);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// No migration needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string PaymentTokens::BuildInsertSql(
|
||||
const mojom::DBActionInfoPtr& mojom_db_action,
|
||||
const PaymentTokenList& payment_tokens) const {
|
||||
CHECK(mojom_db_action);
|
||||
CHECK(!payment_tokens.empty());
|
||||
|
||||
const size_t row_count = BindColumns(mojom_db_action, payment_tokens);
|
||||
|
||||
return base::ReplaceStringPlaceholders(
|
||||
R"(
|
||||
INSERT INTO $1 (
|
||||
transaction_id,
|
||||
unblinded_token,
|
||||
public_key,
|
||||
confirmation_type,
|
||||
ad_type
|
||||
) VALUES $2)",
|
||||
{kTableName, BuildBindColumnPlaceholders(/*column_count=*/5U, row_count)},
|
||||
nullptr);
|
||||
}
|
||||
|
||||
} // namespace brave_ads::database::table
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_TOKENS_PAYMENT_TOKENS_PAYMENT_TOKENS_DATABASE_TABLE_H_
|
||||
#define BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_TOKENS_PAYMENT_TOKENS_PAYMENT_TOKENS_DATABASE_TABLE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_info.h"
|
||||
#include "brave/components/brave_ads/core/internal/database/database_table_interface.h"
|
||||
#include "brave/components/brave_ads/core/mojom/brave_ads.mojom-forward.h"
|
||||
#include "brave/components/brave_ads/core/public/ads_callback.h"
|
||||
|
||||
namespace brave_ads::database::table {
|
||||
|
||||
using GetPaymentTokensCallback =
|
||||
base::OnceCallback<void(bool success, PaymentTokenList payment_tokens)>;
|
||||
|
||||
// Persists unspent payment tokens that have been earned via ad confirmations
|
||||
// and are awaiting redemption. Tokens are loaded from this table on startup to
|
||||
// populate the in-memory cache, and written here on every add or removal.
|
||||
class PaymentTokens final : public TableInterface {
|
||||
public:
|
||||
void Save(const PaymentTokenList& payment_tokens, ResultCallback callback);
|
||||
|
||||
void Insert(const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
const PaymentTokenList& payment_tokens);
|
||||
|
||||
void Delete(const PaymentTokenInfo& payment_token, ResultCallback callback);
|
||||
void Delete(const PaymentTokenList& payment_tokens, ResultCallback callback);
|
||||
void DeleteAll(ResultCallback callback);
|
||||
|
||||
void GetAll(GetPaymentTokensCallback callback) const;
|
||||
|
||||
void Create(const mojom::DBTransactionInfoPtr& mojom_db_transaction) override;
|
||||
void Migrate(const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
int to_version) override;
|
||||
|
||||
private:
|
||||
std::string BuildInsertSql(const mojom::DBActionInfoPtr& mojom_db_action,
|
||||
const PaymentTokenList& payment_tokens) const;
|
||||
};
|
||||
|
||||
} // namespace brave_ads::database::table
|
||||
|
||||
#endif // BRAVE_COMPONENTS_BRAVE_ADS_CORE_INTERNAL_ACCOUNT_TOKENS_PAYMENT_TOKENS_PAYMENT_TOKENS_DATABASE_TABLE_H_
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_database_table.h"
|
||||
|
||||
#include "base/test/test_future.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_info.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/test/payment_tokens_test_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/test/test_base.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BraveAds*
|
||||
|
||||
namespace brave_ads::database::table {
|
||||
|
||||
class BraveAdsPaymentTokensDatabaseTableTest : public test::TestBase {
|
||||
protected:
|
||||
PaymentTokens database_table_;
|
||||
};
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, SaveEmptyPaymentTokens) {
|
||||
// Act
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({}, save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_THAT(payment_tokens, ::testing::IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, SavePaymentTokens) {
|
||||
// Arrange
|
||||
PaymentTokenInfo payment_token_1 = test::BuildPaymentToken();
|
||||
payment_token_1.transaction_id = "foo";
|
||||
PaymentTokenInfo payment_token_2 = test::BuildPaymentToken();
|
||||
payment_token_2.transaction_id = "bar";
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({payment_token_1, payment_token_2},
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ((PaymentTokenList{payment_token_1, payment_token_2}),
|
||||
payment_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, SaveDuplicatePaymentTokens) {
|
||||
// Arrange
|
||||
const PaymentTokenInfo payment_token = test::BuildPaymentToken();
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({payment_token}, save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> duplicate_test_future;
|
||||
database_table_.Save({payment_token}, duplicate_test_future.GetCallback());
|
||||
ASSERT_TRUE(duplicate_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_THAT(payment_tokens, ::testing::SizeIs(1U));
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, DeletePaymentToken) {
|
||||
// Arrange
|
||||
PaymentTokenInfo payment_token_1 = test::BuildPaymentToken();
|
||||
payment_token_1.transaction_id = "foo";
|
||||
PaymentTokenInfo payment_token_2 = test::BuildPaymentToken();
|
||||
payment_token_2.transaction_id = "bar";
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({payment_token_1, payment_token_2},
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_test_future;
|
||||
database_table_.Delete(payment_token_1, delete_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ((PaymentTokenList{payment_token_2}), payment_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, DeletePaymentTokens) {
|
||||
// Arrange
|
||||
PaymentTokenInfo payment_token_1 = test::BuildPaymentToken();
|
||||
payment_token_1.transaction_id = "foo";
|
||||
PaymentTokenInfo payment_token_2 = test::BuildPaymentToken();
|
||||
payment_token_2.transaction_id = "bar";
|
||||
PaymentTokenInfo payment_token_3 = test::BuildPaymentToken();
|
||||
payment_token_3.transaction_id = "baz";
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({payment_token_1, payment_token_2, payment_token_3},
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_test_future;
|
||||
database_table_.Delete({payment_token_1, payment_token_2},
|
||||
delete_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ((PaymentTokenList{payment_token_3}), payment_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, DeleteEmptyPaymentTokens) {
|
||||
// Act & Assert
|
||||
base::test::TestFuture<bool> delete_test_future;
|
||||
database_table_.Delete(PaymentTokenList{}, delete_test_future.GetCallback());
|
||||
EXPECT_TRUE(delete_test_future.Take());
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, DoNotDeleteMissingPaymentToken) {
|
||||
// Arrange
|
||||
PaymentTokenInfo payment_token = test::BuildPaymentToken();
|
||||
payment_token.transaction_id = "foo";
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({payment_token}, save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
PaymentTokenInfo missing_payment_token = test::BuildPaymentToken();
|
||||
missing_payment_token.transaction_id = "bar";
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_test_future;
|
||||
database_table_.Delete(missing_payment_token,
|
||||
delete_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_EQ((PaymentTokenList{payment_token}), payment_tokens);
|
||||
}
|
||||
|
||||
TEST_F(BraveAdsPaymentTokensDatabaseTableTest, DeleteAllPaymentTokens) {
|
||||
// Arrange
|
||||
PaymentTokenInfo payment_token_1 = test::BuildPaymentToken();
|
||||
payment_token_1.transaction_id = "foo";
|
||||
PaymentTokenInfo payment_token_2 = test::BuildPaymentToken();
|
||||
payment_token_2.transaction_id = "bar";
|
||||
base::test::TestFuture<bool> save_test_future;
|
||||
database_table_.Save({payment_token_1, payment_token_2},
|
||||
save_test_future.GetCallback());
|
||||
ASSERT_TRUE(save_test_future.Take());
|
||||
|
||||
// Act
|
||||
base::test::TestFuture<bool> delete_all_test_future;
|
||||
database_table_.DeleteAll(delete_all_test_future.GetCallback());
|
||||
ASSERT_TRUE(delete_all_test_future.Take());
|
||||
|
||||
// Assert
|
||||
base::test::TestFuture<bool, PaymentTokenList> get_all_test_future;
|
||||
database_table_.GetAll(
|
||||
get_all_test_future.GetCallback<bool, PaymentTokenList>());
|
||||
const auto [success, payment_tokens] = get_all_test_future.Take();
|
||||
EXPECT_TRUE(success);
|
||||
EXPECT_THAT(payment_tokens, ::testing::IsEmpty());
|
||||
}
|
||||
|
||||
} // namespace brave_ads::database::table
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/check.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/debug/crash_logging.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/task/task_traits.h"
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
namespace brave_ads::database {
|
||||
|
||||
inline constexpr int kVersionNumber = 55;
|
||||
inline constexpr int kCompatibleVersionNumber = 55;
|
||||
inline constexpr int kVersionNumber = 56;
|
||||
inline constexpr int kCompatibleVersionNumber = 56;
|
||||
|
||||
// If the database version number is less than or equal to this value, the
|
||||
// database will be razed and recreated during migration. This should be updated
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "base/location.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/confirmations/queue/confirmation_queue_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/deposits/deposits_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/transactions/transactions_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_transaction_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/creatives/campaigns_database_table.h"
|
||||
@@ -37,6 +39,12 @@ void Create(const mojom::DBTransactionInfoPtr& mojom_db_transaction) {
|
||||
table::ConfirmationQueue confirmation_queue_database_table;
|
||||
confirmation_queue_database_table.Create(mojom_db_transaction);
|
||||
|
||||
table::ConfirmationTokens confirmation_tokens_database_table;
|
||||
confirmation_tokens_database_table.Create(mojom_db_transaction);
|
||||
|
||||
table::PaymentTokens payment_tokens_database_table;
|
||||
payment_tokens_database_table.Create(mojom_db_transaction);
|
||||
|
||||
table::AdEvents ad_events_database_table;
|
||||
ad_events_database_table.Create(mojom_db_transaction);
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "base/location.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/confirmations/queue/confirmation_queue_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/deposits/deposits_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/account/transactions/transactions_database_table.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_table_util.h"
|
||||
#include "brave/components/brave_ads/core/internal/common/database/database_transaction_util.h"
|
||||
@@ -114,6 +116,12 @@ void MigrateToVersion(const mojom::DBTransactionInfoPtr& mojom_db_transaction,
|
||||
table::ConfirmationQueue confirmation_queue_database_table;
|
||||
confirmation_queue_database_table.Migrate(mojom_db_transaction, to_version);
|
||||
|
||||
table::ConfirmationTokens confirmation_tokens_database_table;
|
||||
confirmation_tokens_database_table.Migrate(mojom_db_transaction, to_version);
|
||||
|
||||
table::PaymentTokens payment_tokens_database_table;
|
||||
payment_tokens_database_table.Migrate(mojom_db_transaction, to_version);
|
||||
|
||||
table::AdEvents ad_events_database_table;
|
||||
ad_events_database_table.Migrate(mojom_db_transaction, to_version);
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ source_set("brave_ads_unit_tests") {
|
||||
"//brave/components/brave_ads/core/internal/account/statement/statement_util_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/test/account_observer_mock.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/test/account_observer_mock.h",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_database_table_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_util_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/confirmation_tokens_value_util_unittest.cc",
|
||||
@@ -80,6 +81,7 @@ source_set("brave_ads_unit_tests") {
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/confirmation_tokens/test/confirmation_tokens_test_util.h",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_util_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_token_value_util_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_database_table_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/payment_tokens/payment_tokens_unittest.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/payment_tokens/test/payment_tokens_test_util.cc",
|
||||
"//brave/components/brave_ads/core/internal/account/tokens/payment_tokens/test/payment_tokens_test_util.h",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -23,6 +23,37 @@ EXPECTED_ROW_COUNT = 4
|
||||
# TODO(https://github.com/brave/brave-browser/issues/40017): Add foreign key
|
||||
# support.
|
||||
|
||||
# Valid values for columns that have a constrained set of values parsed via
|
||||
# strict enum converters (i.e. those that trigger NOTREACHED on unknown input).
|
||||
# Keys are (table_name, column_name); use None as the table_name to match the
|
||||
# column in any table.
|
||||
COLUMN_VALID_VALUES = {
|
||||
# ConfirmationType: parsed via ToMojomConfirmationType which NOTREACHes on
|
||||
# unknown values.
|
||||
(None, 'confirmation_type'): [
|
||||
'click', 'dismiss', 'view', 'served', 'landed', 'bookmark', 'flag',
|
||||
'upvote', 'downvote', 'conversion', 'interaction', 'media_play',
|
||||
'media_25', 'media_100'
|
||||
],
|
||||
# confirmation_queue.type is a ConfirmationType despite the generic name.
|
||||
('confirmation_queue', 'type'): [
|
||||
'click', 'dismiss', 'view', 'served', 'landed', 'bookmark', 'flag',
|
||||
'upvote', 'downvote', 'conversion', 'interaction', 'media_play',
|
||||
'media_25', 'media_100'
|
||||
],
|
||||
# AdType: parsed via ToMojomAdType which NOTREACHes on unknown values.
|
||||
(None, 'ad_type'): [
|
||||
'ad_notification', 'new_tab_page_ad', 'search_result_ad'
|
||||
],
|
||||
# ad_events.type and ad_history.type are AdType despite the generic name.
|
||||
('ad_events', 'type'): [
|
||||
'ad_notification', 'new_tab_page_ad', 'search_result_ad'
|
||||
],
|
||||
('ad_history', 'type'): [
|
||||
'ad_notification', 'new_tab_page_ad', 'search_result_ad'
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def generate_mock_string(length):
|
||||
characters = string.ascii_letters + string.digits
|
||||
@@ -52,8 +83,19 @@ def generate_mock_chrome_webkit_timestamp():
|
||||
return chrome_webkit_delta_in_seconds * MILLISECONDS_IN_SECOND
|
||||
|
||||
|
||||
def get_column_valid_values(table_name, column_name):
|
||||
# Check for a table-specific override first, then fall back to a
|
||||
# column-name-only match (None key).
|
||||
return (COLUMN_VALID_VALUES.get((table_name, column_name))
|
||||
or COLUMN_VALID_VALUES.get((None, column_name)))
|
||||
|
||||
|
||||
def generate_mock_column_with_random_test_data(connection, table_name,
|
||||
column_name, column_type):
|
||||
valid_values = get_column_valid_values(table_name, column_name)
|
||||
if valid_values:
|
||||
return secrets.choice(valid_values)
|
||||
|
||||
if column_type in ('INTEGER', 'INT', 'NUMERIC'):
|
||||
mock_column = secrets.randbelow(100)
|
||||
elif column_type == 'TEXT':
|
||||
|
||||
Reference in New Issue
Block a user