Skip to content

Commit

Permalink
Moves promotions to new endpoint structure
Browse files Browse the repository at this point in the history
  • Loading branch information
NejcZdovc committed Aug 13, 2020
1 parent 91dd812 commit 4486914
Show file tree
Hide file tree
Showing 16 changed files with 794 additions and 237 deletions.
2 changes: 2 additions & 0 deletions components/brave_rewards/test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ source_set("brave_rewards_unit_tests") {
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/publisher/publisher_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/endpoint/api/api_util_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/endpoint/api/get_parameters/get_parameters_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/endpoint/promotion/promotions_util_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/endpoint/promotion/get_available/get_available_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/uphold/uphold_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/uphold/uphold_util_unittest.cc",
"//brave/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet_util_unittest.cc",
Expand Down
6 changes: 6 additions & 0 deletions vendor/bat-native-ledger/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,12 @@ source_set("ledger") {
"src/bat/ledger/internal/endpoint/api/api_util.h",
"src/bat/ledger/internal/endpoint/api/get_parameters/get_parameters.cc",
"src/bat/ledger/internal/endpoint/api/get_parameters/get_parameters.h",
"src/bat/ledger/internal/endpoint/promotion/promotion_server.cc",
"src/bat/ledger/internal/endpoint/promotion/promotion_server.h",
"src/bat/ledger/internal/endpoint/promotion/promotions_util.cc",
"src/bat/ledger/internal/endpoint/promotion/promotions_util.h",
"src/bat/ledger/internal/endpoint/promotion/get_available/get_available.cc",
"src/bat/ledger/internal/endpoint/promotion/get_available/get_available.h",
"src/bat/ledger/internal/sku/sku.h",
"src/bat/ledger/internal/sku/sku_brave.cc",
"src/bat/ledger/internal/sku/sku_brave.h",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */

#include <utility>

#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "bat/ledger/internal/endpoint/promotion/get_available/get_available.h"
#include "bat/ledger/internal/endpoint/promotion/promotions_util.h"
#include "bat/ledger/internal/ledger_impl.h"
#include "bat/ledger/internal/promotion/promotion_util.h"
#include "net/http/http_status_code.h"

using std::placeholders::_1;

// GET /v1/promotions?migrate=true&paymentId={payment_id}&platform={platform}
//
// Success:
// HTTP_OK (200)
//
// Error codes:
// HTTP_BAD_REQUEST (400)
// HTTP_NOT_FOUND (404)
// HTTP_INTERNAL_SERVER_ERROR (500)
//
// Response body:
// {
// "promotions": [
// {
// "id": "83b3b77b-e7c3-455b-adda-e476fa0656d2",
// "createdAt": "2020-06-08T15:04:45.352584Z",
// "expiresAt": "2020-10-08T15:04:45.352584Z",
// "version": 5,
// "suggestionsPerGrant": 120,
// "approximateValue": "30",
// "type": "ugp",
// "available": true,
// "platform": "desktop",
// "publicKeys": [
// "dvpysTSiJdZUPihius7pvGOfngRWfDiIbrowykgMi1I="
// ],
// "legacyClaimed": false
// }
// ]
// }

namespace ledger {
namespace endpoint {
namespace promotion {

GetAvailable::GetAvailable(bat_ledger::LedgerImpl* ledger):
ledger_(ledger) {
DCHECK(ledger_);
}

GetAvailable::~GetAvailable() = default;

std::string GetAvailable::GetUrl(const std::string& platform) {
const std::string payment_id = ledger_->state()->GetPaymentId();
const std::string& arguments = base::StringPrintf(
"migrate=true&paymentId=%s&platform=%s",
payment_id.c_str(),
platform.c_str());

const std::string& path = base::StringPrintf(
"/v1/promotions?%s",
arguments.c_str());

return GetServerUrl(path);
}

ledger::Result GetAvailable::CheckStatusCode(const int status_code) {
if (status_code == net::HTTP_BAD_REQUEST) {
BLOG(0, "Invalid paymentId or platform in request");
return ledger::Result::LEDGER_ERROR;
}

if (status_code == net::HTTP_NOT_FOUND) {
BLOG(0, "Unrecognized paymentId/promotion combination");
return ledger::Result::NOT_FOUND;
}

if (status_code == net::HTTP_INTERNAL_SERVER_ERROR) {
BLOG(0, "Internal server error");
return ledger::Result::LEDGER_ERROR;
}

if (status_code != net::HTTP_OK) {
return ledger::Result::LEDGER_ERROR;
}

return ledger::Result::LEDGER_OK;
}

ledger::Result GetAvailable::ParseBody(
const std::string& body,
ledger::PromotionList* list,
std::vector<std::string>* corrupted_promotions) {

DCHECK(list && corrupted_promotions);

base::Optional<base::Value> value = base::JSONReader::Read(body);
if (!value || !value->is_dict()) {
BLOG(0, "Invalid JSON");
return ledger::Result::LEDGER_ERROR;
}

base::DictionaryValue* dictionary = nullptr;
if (!value->GetAsDictionary(&dictionary)) {
BLOG(0, "Invalid JSON");
return ledger::Result::LEDGER_ERROR;
}

auto* promotions = dictionary->FindListKey("promotions");
if (!promotions) {
return ledger::Result::LEDGER_OK;
}

const auto promotion_size = promotions->GetList().size();
for (auto& item : promotions->GetList()) {
ledger::PromotionPtr promotion = ledger::Promotion::New();

const auto* id = item.FindStringKey("id");
if (!id) {
continue;
}
promotion->id = *id;

const auto version = item.FindIntKey("version");
if (!version) {
corrupted_promotions->push_back(promotion->id);
continue;
}
promotion->version = *version;

const auto* type = item.FindStringKey("type");
if (!type) {
corrupted_promotions->push_back(promotion->id);
continue;
}
promotion->type =
braveledger_promotion::ConvertStringToPromotionType(*type);

const auto suggestions = item.FindIntKey("suggestionsPerGrant");
if (!suggestions) {
corrupted_promotions->push_back(promotion->id);
continue;
}
promotion->suggestions = *suggestions;

const auto* approximate_value = item.FindStringKey("approximateValue");
if (!approximate_value) {
corrupted_promotions->push_back(promotion->id);
continue;
}

const bool success_conversion =
base::StringToDouble(*approximate_value, &promotion->approximate_value);
if (!success_conversion) {
promotion->approximate_value = 0.0;
}

const auto available = item.FindBoolKey("available");
if (!available) {
corrupted_promotions->push_back(promotion->id);
continue;
}

if (*available) {
promotion->status = ledger::PromotionStatus::ACTIVE;
} else {
promotion->status = ledger::PromotionStatus::OVER;
}

auto* expires_at = item.FindStringKey("expiresAt");
if (!expires_at) {
corrupted_promotions->push_back(promotion->id);
continue;
}

base::Time time;
bool success = base::Time::FromUTCString((*expires_at).c_str(), &time);
if (success) {
promotion->expires_at = time.ToDoubleT();
}

auto* public_keys = item.FindListKey("publicKeys");
if (!public_keys || public_keys->GetList().empty()) {
corrupted_promotions->push_back(promotion->id);
continue;
}

std::string keys_json;
base::JSONWriter::Write(*public_keys, &keys_json);
promotion->public_keys = keys_json;

auto legacy_claimed = item.FindBoolKey("legacyClaimed");
promotion->legacy_claimed = legacy_claimed.value_or(false);

list->push_back(std::move(promotion));
}

if (promotion_size != list->size()) {
return ledger::Result::CORRUPTED_DATA;
}

return ledger::Result::LEDGER_OK;
}

void GetAvailable::Request(
const std::string& platform,
GetAvailableCallback callback) {
auto url_callback = std::bind(&GetAvailable::OnRequest,
this,
_1,
callback);
ledger_->LoadURL(
GetUrl(platform),
{},
"",
"",
ledger::UrlMethod::GET,
url_callback);
}

void GetAvailable::OnRequest(
const ledger::UrlResponse& response,
GetAvailableCallback callback) {
ledger::LogUrlResponse(__func__, response);

ledger::PromotionList list;
std::vector<std::string> corrupted_promotions;
ledger::Result result = CheckStatusCode(response.status_code);

if (result != ledger::Result::LEDGER_OK) {
callback(result, std::move(list), corrupted_promotions);
return;
}

result = ParseBody(response.body, &list, &corrupted_promotions);
callback(result, std::move(list), corrupted_promotions);
}

} // namespace promotion
} // namespace endpoint
} // namespace ledger
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */

#ifndef BRAVELEDGER_ENDPOINT_PROMOTION_GET_AVAILABLE_GET_AVAILABLE_H_
#define BRAVELEDGER_ENDPOINT_PROMOTION_GET_AVAILABLE_GET_AVAILABLE_H_

#include <string>
#include <vector>

#include "bat/ledger/ledger.h"

namespace bat_ledger {
class LedgerImpl;
}

namespace ledger {
namespace endpoint {
namespace promotion {

using GetAvailableCallback = std::function<void(
const ledger::Result result,
ledger::PromotionList list,
const std::vector<std::string>& corrupted_promotions)>;

class GetAvailable {
public:
explicit GetAvailable(bat_ledger::LedgerImpl* ledger);
~GetAvailable();

void Request(
const std::string& platform,
GetAvailableCallback callback);

private:
std::string GetUrl(const std::string& platform);

ledger::Result CheckStatusCode(const int status_code);

ledger::Result ParseBody(
const std::string& body,
ledger::PromotionList* list,
std::vector<std::string>* corrupted_promotions);

void OnRequest(
const ledger::UrlResponse& response,
GetAvailableCallback callback);

bat_ledger::LedgerImpl* ledger_; // NOT OWNED
};

} // namespace promotion
} // namespace endpoint
} // namespace ledger

#endif // BRAVELEDGER_ENDPOINT_PROMOTION_GET_AVAILABLE_GET_AVAILABLE_H_
Loading

0 comments on commit 4486914

Please sign in to comment.