Merge remote-tracking branch 'weave/master' into 'weave/aosp-master'
37994f4 Fix some of compiler warnings.
ebde3c1 Rename *BlackList* into *Revocation*
efbd66b Remove unused constants
5a1990f Implement revocation list check when validating auth token
51dcfad Add revocationTimestamp parameter into revocation entry
4846c44 Remove AccessBlackListManager::Unblock
958a359 Revert "debian: add debian packaging files"
7f2a5dc daemon: register device after component init
89b3495 Removing legacy API from libweave
1054d3e Move minimalRole constants from schema_constants.h to a local .cc file
9e9023e daemon/light: fix light trait def
6da60ad Fix use-after-free detected by ASAN
c23ea22 Replace expirationTimeoutSec with expirationTime
7c0ea69 Rename _accessControlBlackList into _accessRevocationList
012cd98 Move mock_component_manager.h into test/ dir
c6d99bb Move MockAccessBlackListManager into separate file
b612e3c Reset access token secret on new black list entry
d1d52e7 Add AccessBlackListManager::AddEntryAddedCallback
7fc5434 debian: add debian packaging files
634c408 Remove property from json added by mistake
Change-Id: I69380e60cf9888999224fdf11a5bc35f0bc7bda2
diff --git a/Makefile b/Makefile
index 9810dd0..70f7ee7 100644
--- a/Makefile
+++ b/Makefile
@@ -28,13 +28,8 @@
-Wextra \
-Wformat=2 \
-Wl,--exclude-libs,ALL \
- -Wno-char-subscripts \
-Wno-missing-field-initializers \
- -Wno-unused-local-typedefs \
-Wno-unused-parameter \
- -Wpacked \
- -Wpointer-arith \
- -Wwrite-strings
CFLAGS_Debug := \
-O0 \
@@ -56,7 +51,6 @@
CFLAGS := $(filter-out -Wl$(comma)--exclude-libs$(comma)ALL,$(CFLAGS))
CFLAGS += \
-fno-omit-frame-pointer \
- -Wno-deprecated-register \
-Wno-inconsistent-missing-override
ifeq (Debug, $(BUILD_MODE))
CFLAGS += \
diff --git a/examples/daemon/common/daemon.h b/examples/daemon/common/daemon.h
index 0b3c25a..22591a2 100644
--- a/examples/daemon/common/daemon.h
+++ b/examples/daemon/common/daemon.h
@@ -92,16 +92,18 @@
http_client_.get(), network_.get(),
dns_sd_.get(), http_server_.get(),
wifi_.get(), bluetooth_.get());
-
if (!opts.registration_ticket.empty()) {
- weave::RegistrationData data;
- data.ticket_id = opts.registration_ticket;
- data.service_url = opts.service_url;
- device_->Register(data, base::Bind(&OnRegisterDeviceDone, device_.get()));
+ registration_data_.ticket_id = opts.registration_ticket;
+ registration_data_.service_url = opts.service_url;
}
}
- void Run() { task_runner_->Run(); }
+ void Run() {
+ if (!registration_data_.ticket_id.empty()) {
+ device_->Register(registration_data_, base::Bind(&OnRegisterDeviceDone, device_.get()));
+ }
+ task_runner_->Run();
+ }
weave::Device* GetDevice() const { return device_.get(); }
@@ -127,4 +129,5 @@
std::unique_ptr<weave::examples::HttpServerImpl> http_server_;
std::unique_ptr<weave::examples::WifiImpl> wifi_;
std::unique_ptr<weave::Device> device_;
+ weave::RegistrationData registration_data_;
};
diff --git a/examples/daemon/light/light.cc b/examples/daemon/light/light.cc
index 4cbf9b4..07c0231 100644
--- a/examples/daemon/light/light.cc
+++ b/examples/daemon/light/light.cc
@@ -19,7 +19,7 @@
"parameters": {
"state": {
"type": "string",
- "enum": [ "on", "standby" ]
+ "enum": [ "on", "off" ]
}
}
}
@@ -27,7 +27,7 @@
"state": {
"state": {
"type": "string",
- "enum": [ "on", "standby" ],
+ "enum": [ "on", "off" ],
"isRequired": true
}
}
@@ -38,23 +38,23 @@
"minimalRole": "user",
"parameters": {
"brightness": {
- "type": "integer",
- "minimum": 0,
- "maximum": 100
+ "type": "number",
+ "minimum": 0.0,
+ "maximum": 1.0
}
}
}
},
"state": {
"brightness": {
- "type": "integer",
+ "type": "number",
"isRequired": true,
- "minimum": 0,
- "maximum": 100
+ "minimum": 0.0,
+ "maximum": 1.0
}
}
},
- "colorXY": {
+ "colorXy": {
"commands": {
"setConfig": {
"minimalRole": "user",
@@ -157,7 +157,7 @@
})";
const char kDefaultState[] = R"({
- "colorXY": {
+ "colorXy": {
"colorSetting": {"colorX": 0, "colorY": 0},
"colorCapRed": {"colorX": 0.674, "colorY": 0.322},
"colorCapGreen":{"colorX": 0.408, "colorY": 0.517},
@@ -178,7 +178,7 @@
device_ = device;
device->AddTraitDefinitionsFromJson(kTraits);
- CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
+ CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXy"},
nullptr));
CHECK(
device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
@@ -190,7 +190,7 @@
device->AddCommandHandler(kComponent, "brightness.setConfig",
base::Bind(&LightHandler::OnBrightnessSetConfig,
weak_ptr_factory_.GetWeakPtr()));
- device->AddCommandHandler(kComponent, "colorXY.setConfig",
+ device->AddCommandHandler(kComponent, "colorXy.setConfig",
base::Bind(&LightHandler::OnColorXYSetConfig,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -252,17 +252,17 @@
return;
LOG(INFO) << "received command: " << cmd->GetName();
const auto& params = cmd->GetParameters();
- const base::DictionaryValue* colorXY = nullptr;
- if (params.GetDictionary("colorSetting", &colorXY)) {
+ const base::DictionaryValue* colorXy = nullptr;
+ if (params.GetDictionary("colorSetting", &colorXy)) {
bool updateState = false;
double X = 0.0;
double Y = 0.0;
- if (colorXY->GetDouble("colorX", &X)) {
+ if (colorXy->GetDouble("colorX", &X)) {
color_X_ = X;
updateState = true;
}
- if (colorXY->GetDouble("colorY", &Y)) {
+ if (colorXy->GetDouble("colorY", &Y)) {
color_Y_ = Y;
updateState = true;
}
@@ -282,13 +282,13 @@
void UpdateLightState() {
base::DictionaryValue state;
- state.SetString("onOff.state", light_status_ ? "on" : "standby");
+ state.SetString("onOff.state", light_status_ ? "on" : "off");
state.SetInteger("brightness.brightness", brightness_state_);
- std::unique_ptr<base::DictionaryValue> colorXY(new base::DictionaryValue());
- colorXY->SetDouble("colorX", color_X_);
- colorXY->SetDouble("colorY", color_Y_);
- state.Set("colorXY.colorSetting", colorXY.release());
+ std::unique_ptr<base::DictionaryValue> colorXy(new base::DictionaryValue());
+ colorXy->SetDouble("colorX", color_X_);
+ colorXy->SetDouble("colorY", color_Y_);
+ state.Set("colorXy.colorSetting", colorXy.release());
device_->SetStateProperties(kComponent, state, nullptr);
}
diff --git a/examples/provider/wifi_manager.cc b/examples/provider/wifi_manager.cc
index 7597e47..9337d23 100644
--- a/examples/provider/wifi_manager.cc
+++ b/examples/provider/wifi_manager.cc
@@ -46,20 +46,21 @@
return status;
}
+struct DirCloser {
+ void operator()(DIR* dir) { closedir(dir); }
+};
+
std::string FindWirelessInterface() {
std::string sysfs_net{"/sys/class/net"};
- DIR* net_dir = opendir(sysfs_net.c_str());
+ std::unique_ptr<DIR, DirCloser> net_dir{opendir(sysfs_net.c_str())};
+ CHECK(net_dir);
dirent* iface;
- while ((iface = readdir(net_dir))) {
+ while ((iface = readdir(net_dir.get()))) {
auto path = sysfs_net + "/" + iface->d_name + "/wireless";
- DIR* wireless_dir = opendir(path.c_str());
- if (wireless_dir != nullptr) {
- closedir(net_dir);
- closedir(wireless_dir);
+ std::unique_ptr<DIR, DirCloser> wireless_dir{opendir(path.c_str())};
+ if (wireless_dir)
return iface->d_name;
- }
}
- closedir(net_dir);
return "";
}
diff --git a/file_lists.mk b/file_lists.mk
index 9a015e2..e13553f 100644
--- a/file_lists.mk
+++ b/file_lists.mk
@@ -4,7 +4,7 @@
WEAVE_SRC_FILES := \
src/access_api_handler.cc \
- src/access_black_list_manager_impl.cc \
+ src/access_revocation_manager_impl.cc \
src/backoff_entry.cc \
src/base_api_handler.cc \
src/commands/cloud_command_proxy.cc \
@@ -51,7 +51,7 @@
WEAVE_UNITTEST_SRC_FILES := \
src/access_api_handler_unittest.cc \
- src/access_black_list_manager_impl_unittest.cc \
+ src/access_revocation_manager_impl_unittest.cc \
src/backoff_entry_unittest.cc \
src/base_api_handler_unittest.cc \
src/commands/cloud_command_proxy_unittest.cc \
diff --git a/include/weave/device.h b/include/weave/device.h
index 9a29574..b79e6a3 100644
--- a/include/weave/device.h
+++ b/include/weave/device.h
@@ -193,68 +193,6 @@
provider::HttpServer* http_server,
provider::Wifi* wifi,
provider::Bluetooth* bluetooth_provider);
-
- //========================== Deprecated APIs =========================
-
- // Adds provided commands definitions. Can be called multiple times with
- // condition that definitions do not conflict.
- // Invalid value is fatal.
- // DO NOT USE IN YOUR CODE: use AddTraitDefinitions() instead.
- LIBWEAVE_DEPRECATED virtual void AddCommandDefinitionsFromJson(
- const std::string& json) = 0;
- LIBWEAVE_DEPRECATED virtual void AddCommandDefinitions(
- const base::DictionaryValue& dict) = 0;
-
- // Sets handler for new commands added to the queue.
- // |command_name| is the full command name of the command to handle. e.g.
- // "base.reboot". Each command can have no more than one handler.
- // Empty |command_name| sets default handler for all unhanded commands.
- // No new command handlers can be set after default handler was set.
- // DO NOT USE IN YOUR CODE: use AddCommandHandler() with component parameter.
- LIBWEAVE_DEPRECATED virtual void AddCommandHandler(
- const std::string& command_name,
- const CommandHandlerCallback& callback) = 0;
-
- // Adds provided state definitions. Can be called multiple times with
- // condition that definitions do not conflict.
- // Invalid value is fatal.
- // DO NOT USE IN YOUR CODE: use AddTraitDefinitions() instead.
- LIBWEAVE_DEPRECATED virtual void AddStateDefinitionsFromJson(
- const std::string& json) = 0;
- LIBWEAVE_DEPRECATED virtual void AddStateDefinitions(
- const base::DictionaryValue& dict) = 0;
-
- // Sets value of multiple properties of the state.
- // It's recommended to call this to initialize state defined by
- // AddStateDefinitions.
- // Example:
- // device->SetStatePropertiesFromJson("{'base':{'firmwareVersion':'123'}}")
- // Method completely replaces properties included |json| or |dict|.
- // Properties of the state not included |json| or |dict| will stay unchanged.
- // DO NOT USE IN YOUR CODE: use SetStateProperties() with component parameter.
- LIBWEAVE_DEPRECATED virtual bool SetStatePropertiesFromJson(
- const std::string& json,
- ErrorPtr* error) = 0;
- LIBWEAVE_DEPRECATED virtual bool SetStateProperties(
- const base::DictionaryValue& dict,
- ErrorPtr* error) = 0;
-
- // Returns value of the single property.
- // |name| is full property name, including package name. e.g. "base.network".
- // DO NOT USE IN YOUR CODE: use GetStateProperty() with component parameter.
- LIBWEAVE_DEPRECATED virtual const base::Value* GetStateProperty(
- const std::string& name) const = 0;
-
- // Sets value of the single property.
- // |name| is full property name, including package name. e.g. "base.network".
- // DO NOT USE IN YOUR CODE: use SetStateProperty() with component parameter.
- LIBWEAVE_DEPRECATED virtual bool SetStateProperty(const std::string& name,
- const base::Value& value,
- ErrorPtr* error) = 0;
-
- // Returns aggregated state properties across all registered packages.
- // DO NOT USE IN YOUR CODE: use GetComponents() instead.
- LIBWEAVE_DEPRECATED virtual const base::DictionaryValue& GetState() const = 0;
};
} // namespace weave
diff --git a/src/access_api_handler.cc b/src/access_api_handler.cc
index 7c39b20..dcfae45 100644
--- a/src/access_api_handler.cc
+++ b/src/access_api_handler.cc
@@ -7,23 +7,24 @@
#include <base/bind.h>
#include <weave/device.h>
-#include "src/access_black_list_manager.h"
+#include "src/access_revocation_manager.h"
#include "src/commands/schema_constants.h"
#include "src/data_encoding.h"
#include "src/json_error_codes.h"
+#include "src/utils.h"
namespace weave {
namespace {
const char kComponent[] = "accessControl";
-const char kTrait[] = "_accessControlBlackList";
-const char kStateSize[] = "_accessControlBlackList.size";
-const char kStateCapacity[] = "_accessControlBlackList.capacity";
+const char kTrait[] = "_accessRevocationList";
+const char kStateCapacity[] = "_accessRevocationList.capacity";
const char kUserId[] = "userId";
const char kApplicationId[] = "applicationId";
-const char kExpirationTimeout[] = "expirationTimeoutSec";
-const char kBlackList[] = "blackList";
+const char kExpirationTime[] = "expirationTime";
+const char kRevocationTimestamp[] = "revocationTimestamp";
+const char kRevocationList[] = "revocationListEntries";
bool GetIds(const base::DictionaryValue& parameters,
std::vector<uint8_t>* user_id_decoded,
@@ -51,12 +52,12 @@
} // namespace
AccessApiHandler::AccessApiHandler(Device* device,
- AccessBlackListManager* manager)
+ AccessRevocationManager* manager)
: device_{device}, manager_{manager} {
device_->AddTraitDefinitionsFromJson(R"({
- "_accessControlBlackList": {
+ "_accessRevocationList": {
"commands": {
- "block": {
+ "revoke": {
"minimalRole": "owner",
"parameters": {
"userId": {
@@ -65,19 +66,11 @@
"applicationId": {
"type": "string"
},
- "expirationTimeoutSec": {
+ "revocationTimestamp": {
"type": "integer"
- }
- }
- },
- "unblock": {
- "minimalRole": "owner",
- "parameters": {
- "userId": {
- "type": "string"
},
- "applicationId": {
- "type": "string"
+ "expirationTime": {
+ "type": "integer"
}
}
},
@@ -85,7 +78,7 @@
"minimalRole": "owner",
"parameters": {},
"results": {
- "blackList": {
+ "revocationEntriesList": {
"type": "array",
"items": {
"type": "object",
@@ -95,6 +88,12 @@
},
"applicationId": {
"type": "string"
+ },
+ "revocationTimestamp": {
+ "type": "integer"
+ },
+ "expirationTime": {
+ "type": "integer"
}
},
"additionalProperties": false
@@ -104,10 +103,6 @@
}
},
"state": {
- "size": {
- "type": "integer",
- "isRequired": true
- },
"capacity": {
"type": "integer",
"isRequired": true
@@ -119,13 +114,10 @@
UpdateState();
device_->AddCommandHandler(
- kComponent, "_accessControlBlackList.block",
+ kComponent, "_accessRevocationList.revoke",
base::Bind(&AccessApiHandler::Block, weak_ptr_factory_.GetWeakPtr()));
device_->AddCommandHandler(
- kComponent, "_accessControlBlackList.unblock",
- base::Bind(&AccessApiHandler::Unblock, weak_ptr_factory_.GetWeakPtr()));
- device_->AddCommandHandler(
- kComponent, "_accessControlBlackList.list",
+ kComponent, "_accessRevocationList.list",
base::Bind(&AccessApiHandler::List, weak_ptr_factory_.GetWeakPtr()));
}
@@ -147,38 +139,27 @@
return;
}
- int timeout_sec = 0;
- parameters.GetInteger(kExpirationTimeout, &timeout_sec);
-
- base::Time expiration =
- base::Time::Now() + base::TimeDelta::FromSeconds(timeout_sec);
-
- manager_->Block(user_id, app_id, expiration,
- base::Bind(&AccessApiHandler::OnCommandDone,
- weak_ptr_factory_.GetWeakPtr(), cmd));
-}
-
-void AccessApiHandler::Unblock(const std::weak_ptr<Command>& cmd) {
- auto command = cmd.lock();
- if (!command)
- return;
-
- CHECK(command->GetState() == Command::State::kQueued)
- << EnumToString(command->GetState());
- command->SetProgress(base::DictionaryValue{}, nullptr);
-
- const auto& parameters = command->GetParameters();
- std::vector<uint8_t> user_id;
- std::vector<uint8_t> app_id;
- ErrorPtr error;
- if (!GetIds(parameters, &user_id, &app_id, &error)) {
+ int expiration_j2k = 0;
+ if (!parameters.GetInteger(kExpirationTime, &expiration_j2k)) {
+ Error::AddToPrintf(&error, FROM_HERE, errors::commands::kInvalidPropValue,
+ "Expiration time is missing");
command->Abort(error.get(), nullptr);
return;
}
- manager_->Unblock(user_id, app_id,
- base::Bind(&AccessApiHandler::OnCommandDone,
- weak_ptr_factory_.GetWeakPtr(), cmd));
+ int revocation_j2k = 0;
+ if (!parameters.GetInteger(kRevocationTimestamp, &revocation_j2k)) {
+ Error::AddToPrintf(&error, FROM_HERE, errors::commands::kInvalidPropValue,
+ "Revocation timestamp is missing");
+ command->Abort(error.get(), nullptr);
+ return;
+ }
+
+ manager_->Block(AccessRevocationManager::Entry{user_id, app_id,
+ FromJ2000Time(revocation_j2k),
+ FromJ2000Time(expiration_j2k)},
+ base::Bind(&AccessApiHandler::OnCommandDone,
+ weak_ptr_factory_.GetWeakPtr(), cmd));
}
void AccessApiHandler::List(const std::weak_ptr<Command>& cmd) {
@@ -199,7 +180,7 @@
}
base::DictionaryValue result;
- result.Set(kBlackList, entries.release());
+ result.Set(kRevocationList, entries.release());
command->Complete(result, nullptr);
}
@@ -219,7 +200,6 @@
void AccessApiHandler::UpdateState() {
base::DictionaryValue state;
- state.SetInteger(kStateSize, manager_->GetSize());
state.SetInteger(kStateCapacity, manager_->GetCapacity());
device_->SetStateProperties(kComponent, state, nullptr);
}
diff --git a/src/access_api_handler.h b/src/access_api_handler.h
index 821ce02..16eaa6f 100644
--- a/src/access_api_handler.h
+++ b/src/access_api_handler.h
@@ -12,31 +12,29 @@
namespace weave {
-class AccessBlackListManager;
+class AccessRevocationManager;
class Command;
class Device;
-// Handles commands for 'accessControlBlackList' trait.
+// Handles commands for '_accessRevocationList' trait.
// Objects of the class subscribe for notification from CommandManager and
// execute incoming commands.
// Handled commands:
-// accessControlBlackList.block
-// accessControlBlackList.unblock
-// accessControlBlackList.list
+// _accessRevocationList.revoke
+// _accessRevocationList.list
class AccessApiHandler final {
public:
- AccessApiHandler(Device* device, AccessBlackListManager* manager);
+ AccessApiHandler(Device* device, AccessRevocationManager* manager);
private:
void Block(const std::weak_ptr<Command>& command);
- void Unblock(const std::weak_ptr<Command>& command);
void List(const std::weak_ptr<Command>& command);
void UpdateState();
void OnCommandDone(const std::weak_ptr<Command>& command, ErrorPtr error);
Device* device_{nullptr};
- AccessBlackListManager* manager_{nullptr};
+ AccessRevocationManager* manager_{nullptr};
base::WeakPtrFactory<AccessApiHandler> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AccessApiHandler);
diff --git a/src/access_api_handler_unittest.cc b/src/access_api_handler_unittest.cc
index 3e7f5d7..fda0748 100644
--- a/src/access_api_handler_unittest.cc
+++ b/src/access_api_handler_unittest.cc
@@ -9,9 +9,10 @@
#include <weave/test/mock_device.h>
#include <weave/test/unittest_utils.h>
+#include "src/access_revocation_manager.h"
#include "src/component_manager_impl.h"
-#include "src/access_black_list_manager.h"
#include "src/data_encoding.h"
+#include "src/test/mock_access_revocation_manager.h"
using testing::_;
using testing::AnyOf;
@@ -22,25 +23,6 @@
namespace weave {
-class MockAccessBlackListManager : public AccessBlackListManager {
- public:
- MOCK_METHOD4(Block,
- void(const std::vector<uint8_t>&,
- const std::vector<uint8_t>&,
- const base::Time&,
- const DoneCallback&));
- MOCK_METHOD3(Unblock,
- void(const std::vector<uint8_t>&,
- const std::vector<uint8_t>&,
- const DoneCallback&));
- MOCK_CONST_METHOD2(IsBlocked,
- bool(const std::vector<uint8_t>&,
- const std::vector<uint8_t>&));
- MOCK_CONST_METHOD0(GetEntries, std::vector<Entry>());
- MOCK_CONST_METHOD0(GetSize, size_t());
- MOCK_CONST_METHOD0(GetCapacity, size_t());
-};
-
class AccessApiHandlerTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -62,9 +44,8 @@
}));
EXPECT_CALL(device_,
- AddCommandHandler(_, AnyOf("_accessControlBlackList.block",
- "_accessControlBlackList.unblock",
- "_accessControlBlackList.list"),
+ AddCommandHandler(_, AnyOf("_accessRevocationList.revoke",
+ "_accessRevocationList.list"),
_))
.WillRepeatedly(
Invoke(&component_manager_, &ComponentManager::AddCommandHandler));
@@ -90,31 +71,31 @@
std::unique_ptr<base::DictionaryValue> GetState() {
std::string path =
- component_manager_.FindComponentWithTrait("_accessControlBlackList");
+ component_manager_.FindComponentWithTrait("_accessRevocationList");
EXPECT_FALSE(path.empty());
const auto* component = component_manager_.FindComponent(path, nullptr);
EXPECT_TRUE(component);
const base::DictionaryValue* state = nullptr;
EXPECT_TRUE(
- component->GetDictionary("state._accessControlBlackList", &state));
+ component->GetDictionary("state._accessRevocationList", &state));
return std::unique_ptr<base::DictionaryValue>{state->DeepCopy()};
}
StrictMock<provider::test::FakeTaskRunner> task_runner_;
ComponentManagerImpl component_manager_{&task_runner_};
StrictMock<test::MockDevice> device_;
- StrictMock<MockAccessBlackListManager> access_manager_;
+ StrictMock<test::MockAccessRevocationManager> access_manager_;
std::unique_ptr<AccessApiHandler> handler_;
};
TEST_F(AccessApiHandlerTest, Initialization) {
const base::DictionaryValue* trait = nullptr;
ASSERT_TRUE(component_manager_.GetTraits().GetDictionary(
- "_accessControlBlackList", &trait));
+ "_accessRevocationList", &trait));
auto expected = R"({
"commands": {
- "block": {
+ "revoke": {
"minimalRole": "owner",
"parameters": {
"userId": {
@@ -123,19 +104,11 @@
"applicationId": {
"type": "string"
},
- "expirationTimeoutSec": {
+ "revocationTimestamp": {
"type": "integer"
- }
- }
- },
- "unblock": {
- "minimalRole": "owner",
- "parameters": {
- "userId": {
- "type": "string"
},
- "applicationId": {
- "type": "string"
+ "expirationTime": {
+ "type": "integer"
}
}
},
@@ -143,7 +116,7 @@
"minimalRole": "owner",
"parameters": {},
"results": {
- "blackList": {
+ "revocationEntriesList": {
"type": "array",
"items": {
"type": "object",
@@ -153,6 +126,12 @@
},
"applicationId": {
"type": "string"
+ },
+ "revocationTimestamp": {
+ "type": "integer"
+ },
+ "expirationTime": {
+ "type": "integer"
}
},
"additionalProperties": false
@@ -162,10 +141,6 @@
}
},
"state": {
- "size": {
- "type": "integer",
- "isRequired": true
- },
"capacity": {
"type": "integer",
"isRequired": true
@@ -175,70 +150,56 @@
EXPECT_JSON_EQ(expected, *trait);
expected = R"({
- "capacity": 10,
- "size": 0
+ "capacity": 10
})";
EXPECT_JSON_EQ(expected, *GetState());
}
-TEST_F(AccessApiHandlerTest, Block) {
- EXPECT_CALL(access_manager_, Block(std::vector<uint8_t>{1, 2, 3},
- std::vector<uint8_t>{3, 4, 5}, _, _))
- .WillOnce(WithArgs<3>(
+TEST_F(AccessApiHandlerTest, Revoke) {
+ EXPECT_CALL(
+ access_manager_,
+ Block(AccessRevocationManager::Entry{std::vector<uint8_t>{1, 2, 3},
+ std::vector<uint8_t>{3, 4, 5},
+ base::Time::FromTimeT(946686034),
+ base::Time::FromTimeT(946692690)},
+ _))
+ .WillOnce(WithArgs<1>(
Invoke([](const DoneCallback& callback) { callback.Run(nullptr); })));
EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(1));
AddCommand(R"({
- 'name' : '_accessControlBlackList.block',
+ 'name' : '_accessRevocationList.revoke',
'component': 'accessControl',
'parameters': {
'userId': 'AQID',
'applicationId': 'AwQF',
- 'expirationTimeoutSec': 1234
+ 'expirationTime': 7890,
+ 'revocationTimestamp': 1234
}
})");
auto expected = R"({
- "capacity": 10,
- "size": 1
- })";
- EXPECT_JSON_EQ(expected, *GetState());
-}
-
-TEST_F(AccessApiHandlerTest, Unblock) {
- EXPECT_CALL(access_manager_, Unblock(std::vector<uint8_t>{1, 2, 3},
- std::vector<uint8_t>{3, 4, 5}, _))
- .WillOnce(WithArgs<2>(
- Invoke([](const DoneCallback& callback) { callback.Run(nullptr); })));
- EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(4));
-
- AddCommand(R"({
- 'name' : '_accessControlBlackList.unblock',
- 'component': 'accessControl',
- 'parameters': {
- 'userId': 'AQID',
- 'applicationId': 'AwQF',
- 'expirationTimeoutSec': 1234
- }
- })");
-
- auto expected = R"({
- "capacity": 10,
- "size": 4
+ "capacity": 10
})";
EXPECT_JSON_EQ(expected, *GetState());
}
TEST_F(AccessApiHandlerTest, List) {
- std::vector<AccessBlackListManager::Entry> entries{
- {{11, 12, 13}, {21, 22, 23}, base::Time::FromTimeT(1410000000)},
- {{31, 32, 33}, {41, 42, 43}, base::Time::FromTimeT(1420000000)},
+ std::vector<AccessRevocationManager::Entry> entries{
+ {{11, 12, 13},
+ {21, 22, 23},
+ base::Time::FromTimeT(1310000000),
+ base::Time::FromTimeT(1410000000)},
+ {{31, 32, 33},
+ {41, 42, 43},
+ base::Time::FromTimeT(1300000000),
+ base::Time::FromTimeT(1420000000)},
};
EXPECT_CALL(access_manager_, GetEntries()).WillOnce(Return(entries));
EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(4));
auto expected = R"({
- "blackList": [ {
+ "revocationListEntries": [ {
"applicationId": "FRYX",
"userId": "CwwN"
}, {
@@ -248,7 +209,7 @@
})";
const auto& results = AddCommand(R"({
- 'name' : '_accessControlBlackList.list',
+ 'name' : '_accessRevocationList.list',
'component': 'accessControl',
'parameters': {
}
diff --git a/src/access_black_list_manager.h b/src/access_black_list_manager.h
deleted file mode 100644
index b56226a..0000000
--- a/src/access_black_list_manager.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_ACCESS_BLACK_LIST_H_
-#define LIBWEAVE_SRC_ACCESS_BLACK_LIST_H_
-
-#include <vector>
-
-#include <base/time/time.h>
-
-namespace weave {
-
-class AccessBlackListManager {
- public:
- struct Entry {
- // user_id is empty, app_id is empty: block everything.
- // user_id is not empty, app_id is empty: block if user_id matches.
- // user_id is empty, app_id is not empty: block if app_id matches.
- // user_id is not empty, app_id is not empty: block if both match.
- std::vector<uint8_t> user_id;
- std::vector<uint8_t> app_id;
-
- // Time after which to discard the rule.
- base::Time expiration;
- };
- virtual ~AccessBlackListManager() = default;
-
- virtual void Block(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id,
- const base::Time& expiration,
- const DoneCallback& callback) = 0;
- virtual void Unblock(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id,
- const DoneCallback& callback) = 0;
- virtual bool IsBlocked(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id) const = 0;
- virtual std::vector<Entry> GetEntries() const = 0;
- virtual size_t GetSize() const = 0;
- virtual size_t GetCapacity() const = 0;
-};
-
-inline bool operator==(const AccessBlackListManager::Entry& l,
- const AccessBlackListManager::Entry& r) {
- return l.user_id == r.user_id && l.app_id == r.app_id &&
- l.expiration == r.expiration;
-}
-
-inline bool operator!=(const AccessBlackListManager::Entry& l,
- const AccessBlackListManager::Entry& r) {
- return !(l == r);
-}
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_ACCESS_BLACK_LIST_H_
diff --git a/src/access_black_list_manager_impl.cc b/src/access_black_list_manager_impl.cc
deleted file mode 100644
index 992a680..0000000
--- a/src/access_black_list_manager_impl.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2016 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/access_black_list_manager_impl.h"
-
-#include <base/json/json_reader.h>
-#include <base/json/json_writer.h>
-#include <base/values.h>
-
-#include "src/commands/schema_constants.h"
-#include "src/data_encoding.h"
-
-namespace weave {
-
-namespace {
-const char kConfigFileName[] = "black_list";
-
-const char kUser[] = "user";
-const char kApp[] = "app";
-const char kExpiration[] = "expiration";
-}
-
-AccessBlackListManagerImpl::AccessBlackListManagerImpl(
- provider::ConfigStore* store,
- size_t capacity,
- base::Clock* clock)
- : capacity_{capacity}, clock_{clock}, store_{store} {
- Load();
-}
-
-void AccessBlackListManagerImpl::Load() {
- if (!store_)
- return;
- if (auto list = base::ListValue::From(
- base::JSONReader::Read(store_->LoadSettings(kConfigFileName)))) {
- for (const auto& e : *list) {
- const base::DictionaryValue* entry{nullptr};
- std::string user;
- std::string app;
- decltype(entries_)::key_type key;
- int expiration;
- if (e->GetAsDictionary(&entry) && entry->GetString(kUser, &user) &&
- Base64Decode(user, &key.first) && entry->GetString(kApp, &app) &&
- Base64Decode(app, &key.second) &&
- entry->GetInteger(kExpiration, &expiration)) {
- base::Time expiration_time = base::Time::FromTimeT(expiration);
- if (expiration_time > clock_->Now())
- entries_[key] = expiration_time;
- }
- }
- if (entries_.size() < list->GetSize()) {
- // Save some storage space by saving without expired entries.
- Save({});
- }
- }
-}
-
-void AccessBlackListManagerImpl::Save(const DoneCallback& callback) {
- if (!store_) {
- if (!callback.is_null())
- callback.Run(nullptr);
- return;
- }
-
- base::ListValue list;
- for (const auto& e : entries_) {
- scoped_ptr<base::DictionaryValue> entry{new base::DictionaryValue};
- entry->SetString(kUser, Base64Encode(e.first.first));
- entry->SetString(kApp, Base64Encode(e.first.second));
- entry->SetInteger(kExpiration, e.second.ToTimeT());
- list.Append(std::move(entry));
- }
-
- std::string json;
- base::JSONWriter::Write(list, &json);
- store_->SaveSettings(kConfigFileName, json, callback);
-}
-
-void AccessBlackListManagerImpl::RemoveExpired() {
- for (auto i = begin(entries_); i != end(entries_);) {
- if (i->second <= clock_->Now())
- i = entries_.erase(i);
- else
- ++i;
- }
-}
-
-void AccessBlackListManagerImpl::Block(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id,
- const base::Time& expiration,
- const DoneCallback& callback) {
- // Iterating is OK as Save below is more expensive.
- RemoveExpired();
- if (expiration <= clock_->Now()) {
- if (!callback.is_null()) {
- ErrorPtr error;
- Error::AddTo(&error, FROM_HERE, "aleady_expired",
- "Entry already expired");
- callback.Run(std::move(error));
- }
- return;
- }
- if (entries_.size() >= capacity_) {
- if (!callback.is_null()) {
- ErrorPtr error;
- Error::AddTo(&error, FROM_HERE, "blacklist_is_full",
- "Unable to store more entries");
- callback.Run(std::move(error));
- }
- return;
- }
- auto& value = entries_[std::make_pair(user_id, app_id)];
- value = std::max(value, expiration);
- Save(callback);
-}
-
-void AccessBlackListManagerImpl::Unblock(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id,
- const DoneCallback& callback) {
- if (!entries_.erase(std::make_pair(user_id, app_id))) {
- if (!callback.is_null()) {
- ErrorPtr error;
- Error::AddTo(&error, FROM_HERE, "entry_not_found", "Unknown entry");
- callback.Run(std::move(error));
- }
- return;
- }
- // Iterating is OK as Save below is more expensive.
- RemoveExpired();
- Save(callback);
-}
-
-bool AccessBlackListManagerImpl::IsBlocked(
- const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id) const {
- for (const auto& user : {{}, user_id}) {
- for (const auto& app : {{}, app_id}) {
- auto both = entries_.find(std::make_pair(user, app));
- if (both != end(entries_) && both->second > clock_->Now())
- return true;
- }
- }
- return false;
-}
-
-std::vector<AccessBlackListManager::Entry>
-AccessBlackListManagerImpl::GetEntries() const {
- std::vector<Entry> result;
- for (const auto& e : entries_)
- result.push_back({e.first.first, e.first.second, e.second});
- return result;
-}
-
-size_t AccessBlackListManagerImpl::GetSize() const {
- return entries_.size();
-}
-
-size_t AccessBlackListManagerImpl::GetCapacity() const {
- return capacity_;
-}
-
-} // namespace weave
diff --git a/src/access_black_list_manager_impl.h b/src/access_black_list_manager_impl.h
deleted file mode 100644
index 1c175db..0000000
--- a/src/access_black_list_manager_impl.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2016 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_ACCESS_BLACK_LIST_IMPL_H_
-#define LIBWEAVE_SRC_ACCESS_BLACK_LIST_IMPL_H_
-
-#include <map>
-#include <utility>
-
-#include <base/time/default_clock.h>
-#include <base/time/time.h>
-#include <weave/error.h>
-#include <weave/provider/config_store.h>
-
-#include "src/access_black_list_manager.h"
-
-namespace weave {
-
-class AccessBlackListManagerImpl : public AccessBlackListManager {
- public:
- explicit AccessBlackListManagerImpl(provider::ConfigStore* store,
- size_t capacity = 1024,
- base::Clock* clock = nullptr);
-
- // AccessBlackListManager implementation.
- void Block(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id,
- const base::Time& expiration,
- const DoneCallback& callback) override;
- void Unblock(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id,
- const DoneCallback& callback) override;
- bool IsBlocked(const std::vector<uint8_t>& user_id,
- const std::vector<uint8_t>& app_id) const override;
- std::vector<Entry> GetEntries() const override;
- size_t GetSize() const override;
- size_t GetCapacity() const override;
-
- private:
- void Load();
- void Save(const DoneCallback& callback);
- void RemoveExpired();
-
- const size_t capacity_{0};
- base::DefaultClock default_clock_;
- base::Clock* clock_{&default_clock_};
-
- provider::ConfigStore* store_{nullptr};
- std::map<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>, base::Time>
- entries_;
-
- DISALLOW_COPY_AND_ASSIGN(AccessBlackListManagerImpl);
-};
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_ACCESS_BLACK_LIST_IMPL_H_
diff --git a/src/access_black_list_manager_impl_unittest.cc b/src/access_black_list_manager_impl_unittest.cc
deleted file mode 100644
index fd9f226..0000000
--- a/src/access_black_list_manager_impl_unittest.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2016 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/access_black_list_manager_impl.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <weave/provider/test/mock_config_store.h>
-#include <weave/test/unittest_utils.h>
-
-#include "src/test/mock_clock.h"
-#include "src/bind_lambda.h"
-
-using testing::_;
-using testing::Return;
-using testing::StrictMock;
-
-namespace weave {
-
-class AccessBlackListManagerImplTest : public testing::Test {
- protected:
- void SetUp() {
- std::string to_load = R"([{
- "user": "BQID",
- "app": "BwQF",
- "expiration": 1410000000
- }, {
- "user": "AQID",
- "app": "AwQF",
- "expiration": 1419999999
- }])";
-
- EXPECT_CALL(config_store_, LoadSettings("black_list"))
- .WillOnce(Return(to_load));
-
- EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
- .WillOnce(testing::WithArgs<1, 2>(testing::Invoke(
- [](const std::string& json, const DoneCallback& callback) {
- std::string to_save = R"([{
- "user": "AQID",
- "app": "AwQF",
- "expiration": 1419999999
- }])";
- EXPECT_JSON_EQ(to_save, *test::CreateValue(json));
- if (!callback.is_null())
- callback.Run(nullptr);
- })));
-
- EXPECT_CALL(clock_, Now())
- .WillRepeatedly(Return(base::Time::FromTimeT(1412121212)));
- manager_.reset(new AccessBlackListManagerImpl{&config_store_, 10, &clock_});
- }
- StrictMock<test::MockClock> clock_;
- StrictMock<provider::test::MockConfigStore> config_store_{false};
- std::unique_ptr<AccessBlackListManagerImpl> manager_;
-};
-
-TEST_F(AccessBlackListManagerImplTest, Init) {
- EXPECT_EQ(1u, manager_->GetSize());
- EXPECT_EQ(10u, manager_->GetCapacity());
- EXPECT_EQ((std::vector<AccessBlackListManagerImpl::Entry>{{
- {1, 2, 3}, {3, 4, 5}, base::Time::FromTimeT(1419999999),
- }}),
- manager_->GetEntries());
-}
-
-TEST_F(AccessBlackListManagerImplTest, Block) {
- EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
- .WillOnce(testing::WithArgs<1, 2>(testing::Invoke(
- [](const std::string& json, const DoneCallback& callback) {
- std::string to_save = R"([{
- "user": "AQID",
- "app": "AwQF",
- "expiration": 1419999999
- }, {
- "app": "CAgI",
- "user": "BwcH",
- "expiration": 1419990000
- }])";
- EXPECT_JSON_EQ(to_save, *test::CreateValue(json));
- if (!callback.is_null())
- callback.Run(nullptr);
- })));
- manager_->Block({7, 7, 7}, {8, 8, 8}, base::Time::FromTimeT(1419990000), {});
-}
-
-TEST_F(AccessBlackListManagerImplTest, BlockExpired) {
- manager_->Block({}, {}, base::Time::FromTimeT(1400000000),
- base::Bind([](ErrorPtr error) {
- EXPECT_TRUE(error->HasError("aleady_expired"));
- }));
-}
-
-TEST_F(AccessBlackListManagerImplTest, BlockListIsFull) {
- EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
- .WillRepeatedly(testing::WithArgs<1, 2>(testing::Invoke(
- [](const std::string& json, const DoneCallback& callback) {
- if (!callback.is_null())
- callback.Run(nullptr);
- })));
- for (size_t i = manager_->GetSize(); i < manager_->GetCapacity(); ++i) {
- manager_->Block(
- {99, static_cast<uint8_t>(i / 256), static_cast<uint8_t>(i % 256)},
- {8, 8, 8}, base::Time::FromTimeT(1419990000), {});
- EXPECT_EQ(i + 1, manager_->GetSize());
- }
- manager_->Block({99}, {8, 8, 8}, base::Time::FromTimeT(1419990000),
- base::Bind([](ErrorPtr error) {
- EXPECT_TRUE(error->HasError("blacklist_is_full"));
- }));
-}
-
-TEST_F(AccessBlackListManagerImplTest, Unblock) {
- EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
- .WillOnce(testing::WithArgs<1, 2>(testing::Invoke(
- [](const std::string& json, const DoneCallback& callback) {
- EXPECT_JSON_EQ("[]", *test::CreateValue(json));
- if (!callback.is_null())
- callback.Run(nullptr);
- })));
- manager_->Unblock({1, 2, 3}, {3, 4, 5}, {});
-}
-
-TEST_F(AccessBlackListManagerImplTest, UnblockNotFound) {
- manager_->Unblock({5, 2, 3}, {5, 4, 5}, base::Bind([](ErrorPtr error) {
- EXPECT_TRUE(error->HasError("entry_not_found"));
- }));
-}
-
-TEST_F(AccessBlackListManagerImplTest, IsBlockedFalse) {
- EXPECT_FALSE(manager_->IsBlocked({7, 7, 7}, {8, 8, 8}));
-}
-
-class AccessBlackListManagerImplIsBlockedTest
- : public AccessBlackListManagerImplTest,
- public testing::WithParamInterface<
- std::tuple<std::vector<uint8_t>, std::vector<uint8_t>>> {
- public:
- void SetUp() override {
- AccessBlackListManagerImplTest::SetUp();
- EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
- .WillOnce(testing::WithArgs<2>(
- testing::Invoke([](const DoneCallback& callback) {
- if (!callback.is_null())
- callback.Run(nullptr);
- })));
- manager_->Block(std::get<0>(GetParam()), std::get<1>(GetParam()),
- base::Time::FromTimeT(1419990000), {});
- }
-};
-
-TEST_P(AccessBlackListManagerImplIsBlockedTest, IsBlocked) {
- EXPECT_TRUE(manager_->IsBlocked({7, 7, 7}, {8, 8, 8}));
-}
-
-INSTANTIATE_TEST_CASE_P(
- Filters,
- AccessBlackListManagerImplIsBlockedTest,
- testing::Combine(testing::Values(std::vector<uint8_t>{},
- std::vector<uint8_t>{7, 7, 7}),
- testing::Values(std::vector<uint8_t>{},
- std::vector<uint8_t>{8, 8, 8})));
-
-} // namespace weave
diff --git a/src/access_revocation_manager.h b/src/access_revocation_manager.h
new file mode 100644
index 0000000..6d5bf7b
--- /dev/null
+++ b/src/access_revocation_manager.h
@@ -0,0 +1,66 @@
+// Copyright 2016 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBWEAVE_SRC_ACCESS_REVOCATION_MANAGER_H_
+#define LIBWEAVE_SRC_ACCESS_REVOCATION_MANAGER_H_
+
+#include <vector>
+
+#include <base/time/time.h>
+
+namespace weave {
+
+class AccessRevocationManager {
+ public:
+ struct Entry {
+ Entry() = default;
+
+ Entry(const std::vector<uint8_t>& user,
+ const std::vector<uint8_t>& app,
+ base::Time revocation_ts,
+ base::Time expiration_ts)
+ : user_id{user},
+ app_id{app},
+ revocation{revocation_ts},
+ expiration{expiration_ts} {}
+ // user_id is empty, app_id is empty: block everything.
+ // user_id is not empty, app_id is empty: block if user_id matches.
+ // user_id is empty, app_id is not empty: block if app_id matches.
+ // user_id is not empty, app_id is not empty: block if both match.
+ std::vector<uint8_t> user_id;
+ std::vector<uint8_t> app_id;
+
+ // Revoke matching entries if |revocation| is not less than
+ // delegation timestamp.
+ base::Time revocation;
+
+ // Time after which to discard the rule.
+ base::Time expiration;
+ };
+ virtual ~AccessRevocationManager() = default;
+
+ virtual void AddEntryAddedCallback(const base::Closure& callback) = 0;
+ virtual void Block(const Entry& entry, const DoneCallback& callback) = 0;
+ virtual bool IsBlocked(const std::vector<uint8_t>& user_id,
+ const std::vector<uint8_t>& app_id,
+ base::Time timestamp) const = 0;
+ virtual std::vector<Entry> GetEntries() const = 0;
+ virtual size_t GetSize() const = 0;
+ virtual size_t GetCapacity() const = 0;
+};
+
+inline bool operator==(const AccessRevocationManager::Entry& l,
+ const AccessRevocationManager::Entry& r) {
+ return l.revocation == r.revocation && l.expiration == r.expiration &&
+ l.user_id == r.user_id && l.app_id == r.app_id;
+}
+
+inline bool operator!=(const AccessRevocationManager::Entry& l,
+ const AccessRevocationManager::Entry& r) {
+ return !(l == r);
+}
+
+} // namespace weave
+
+#endif // LIBWEAVE_SRC_ACCESS_REVOCATION_MANAGER_H_
diff --git a/src/access_revocation_manager_impl.cc b/src/access_revocation_manager_impl.cc
new file mode 100644
index 0000000..f039114
--- /dev/null
+++ b/src/access_revocation_manager_impl.cc
@@ -0,0 +1,171 @@
+// Copyright 2016 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/access_revocation_manager_impl.h"
+
+#include <base/json/json_reader.h>
+#include <base/json/json_writer.h>
+#include <base/values.h>
+
+#include "src/commands/schema_constants.h"
+#include "src/data_encoding.h"
+#include "src/utils.h"
+
+namespace weave {
+
+namespace {
+const char kConfigFileName[] = "black_list";
+
+const char kUser[] = "user";
+const char kApp[] = "app";
+const char kExpiration[] = "expiration";
+const char kRevocation[] = "revocation";
+}
+
+AccessRevocationManagerImpl::AccessRevocationManagerImpl(
+ provider::ConfigStore* store,
+ size_t capacity,
+ base::Clock* clock)
+ : capacity_{capacity}, clock_{clock}, store_{store} {
+ Load();
+}
+
+void AccessRevocationManagerImpl::Load() {
+ if (!store_)
+ return;
+ if (auto list = base::ListValue::From(
+ base::JSONReader::Read(store_->LoadSettings(kConfigFileName)))) {
+ for (const auto& value : *list) {
+ const base::DictionaryValue* entry{nullptr};
+ std::string user;
+ std::string app;
+ Entry e;
+ int revocation = 0;
+ int expiration = 0;
+ if (value->GetAsDictionary(&entry) && entry->GetString(kUser, &user) &&
+ Base64Decode(user, &e.user_id) && entry->GetString(kApp, &app) &&
+ Base64Decode(app, &e.app_id) &&
+ entry->GetInteger(kRevocation, &revocation) &&
+ entry->GetInteger(kExpiration, &expiration)) {
+ e.revocation = FromJ2000Time(revocation);
+ e.expiration = FromJ2000Time(expiration);
+ if (e.expiration > clock_->Now())
+ entries_.insert(e);
+ }
+ }
+ if (entries_.size() < list->GetSize()) {
+ // Save some storage space by saving without expired entries.
+ Save({});
+ }
+ }
+}
+
+void AccessRevocationManagerImpl::Save(const DoneCallback& callback) {
+ if (!store_) {
+ if (!callback.is_null())
+ callback.Run(nullptr);
+ return;
+ }
+
+ base::ListValue list;
+ for (const auto& e : entries_) {
+ scoped_ptr<base::DictionaryValue> entry{new base::DictionaryValue};
+ entry->SetString(kUser, Base64Encode(e.user_id));
+ entry->SetString(kApp, Base64Encode(e.app_id));
+ entry->SetInteger(kRevocation, ToJ2000Time(e.revocation));
+ entry->SetInteger(kExpiration, ToJ2000Time(e.expiration));
+ list.Append(std::move(entry));
+ }
+
+ std::string json;
+ base::JSONWriter::Write(list, &json);
+ store_->SaveSettings(kConfigFileName, json, callback);
+}
+
+void AccessRevocationManagerImpl::RemoveExpired() {
+ for (auto i = begin(entries_); i != end(entries_);) {
+ if (i->expiration <= clock_->Now())
+ i = entries_.erase(i);
+ else
+ ++i;
+ }
+}
+
+void AccessRevocationManagerImpl::AddEntryAddedCallback(
+ const base::Closure& callback) {
+ on_entry_added_callbacks_.push_back(callback);
+}
+
+void AccessRevocationManagerImpl::Block(const Entry& entry,
+ const DoneCallback& callback) {
+ // Iterating is OK as Save below is more expensive.
+ RemoveExpired();
+ if (entry.expiration <= clock_->Now()) {
+ if (!callback.is_null()) {
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "aleady_expired",
+ "Entry already expired");
+ callback.Run(std::move(error));
+ }
+ return;
+ }
+ if (entries_.size() >= capacity_) {
+ if (!callback.is_null()) {
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, "blacklist_is_full",
+ "Unable to store more entries");
+ callback.Run(std::move(error));
+ }
+ return;
+ }
+
+ auto existing = entries_.find(entry);
+ if (existing != entries_.end()) {
+ Entry new_entry = entry;
+ new_entry.expiration = std::max(entry.expiration, existing->expiration);
+ new_entry.revocation = std::max(entry.revocation, existing->revocation);
+ entries_.erase(existing);
+ entries_.insert(new_entry);
+ } else {
+ entries_.insert(entry);
+ }
+
+ for (const auto& cb : on_entry_added_callbacks_)
+ cb.Run();
+
+ Save(callback);
+}
+
+bool AccessRevocationManagerImpl::IsBlocked(const std::vector<uint8_t>& user_id,
+ const std::vector<uint8_t>& app_id,
+ base::Time timestamp) const {
+ Entry entry_to_find;
+ for (const auto& user : {{}, user_id}) {
+ for (const auto& app : {{}, app_id}) {
+ entry_to_find.user_id = user;
+ entry_to_find.app_id = app;
+ auto match = entries_.find(entry_to_find);
+ if (match != end(entries_) && match->expiration > clock_->Now() &&
+ match->revocation >= timestamp) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+std::vector<AccessRevocationManager::Entry>
+AccessRevocationManagerImpl::GetEntries() const {
+ return {begin(entries_), end(entries_)};
+}
+
+size_t AccessRevocationManagerImpl::GetSize() const {
+ return entries_.size();
+}
+
+size_t AccessRevocationManagerImpl::GetCapacity() const {
+ return capacity_;
+}
+
+} // namespace weave
diff --git a/src/access_revocation_manager_impl.h b/src/access_revocation_manager_impl.h
new file mode 100644
index 0000000..a911128
--- /dev/null
+++ b/src/access_revocation_manager_impl.h
@@ -0,0 +1,64 @@
+// Copyright 2016 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBWEAVE_SRC_ACCESS_REVOCATION_MANAGER_IMPL_H_
+#define LIBWEAVE_SRC_ACCESS_REVOCATION_MANAGER_IMPL_H_
+
+#include <set>
+#include <utility>
+
+#include <base/time/default_clock.h>
+#include <base/time/time.h>
+#include <weave/error.h>
+#include <weave/provider/config_store.h>
+
+#include "src/access_revocation_manager.h"
+
+namespace weave {
+
+class AccessRevocationManagerImpl : public AccessRevocationManager {
+ public:
+ explicit AccessRevocationManagerImpl(provider::ConfigStore* store,
+ size_t capacity = 1024,
+ base::Clock* clock = nullptr);
+
+ // AccessRevocationManager implementation.
+ void AddEntryAddedCallback(const base::Closure& callback) override;
+ void Block(const Entry& entry, const DoneCallback& callback) override;
+ bool IsBlocked(const std::vector<uint8_t>& user_id,
+ const std::vector<uint8_t>& app_id,
+ base::Time timestamp) const override;
+ std::vector<Entry> GetEntries() const override;
+ size_t GetSize() const override;
+ size_t GetCapacity() const override;
+
+ private:
+ void Load();
+ void Save(const DoneCallback& callback);
+ void RemoveExpired();
+
+ struct EntryIdsLess {
+ bool operator()(const Entry& l, const Entry& r) const {
+ if (l.user_id < r.user_id)
+ return true;
+ if (l.user_id > r.user_id)
+ return false;
+ return l.app_id < r.app_id;
+ }
+ };
+
+ const size_t capacity_{0};
+ base::DefaultClock default_clock_;
+ base::Clock* clock_{&default_clock_};
+
+ provider::ConfigStore* store_{nullptr};
+ std::set<Entry, EntryIdsLess> entries_;
+ std::vector<base::Closure> on_entry_added_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessRevocationManagerImpl);
+};
+
+} // namespace weave
+
+#endif // LIBWEAVE_SRC_ACCESS_REVOCATION_MANAGER_IMPL_H_
diff --git a/src/access_revocation_manager_impl_unittest.cc b/src/access_revocation_manager_impl_unittest.cc
new file mode 100644
index 0000000..b0b774b
--- /dev/null
+++ b/src/access_revocation_manager_impl_unittest.cc
@@ -0,0 +1,183 @@
+// Copyright 2016 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/access_revocation_manager_impl.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <weave/provider/test/mock_config_store.h>
+#include <weave/test/unittest_utils.h>
+
+#include "src/test/mock_clock.h"
+#include "src/bind_lambda.h"
+
+using testing::_;
+using testing::Return;
+using testing::StrictMock;
+
+namespace weave {
+
+class AccessRevocationManagerImplTest : public testing::Test {
+ protected:
+ void SetUp() {
+ std::string to_load = R"([{
+ "user": "BQID",
+ "app": "BwQF",
+ "expiration": 463315200,
+ "revocation": 463314200
+ }, {
+ "user": "AQID",
+ "app": "AwQF",
+ "expiration": 473315199,
+ "revocation": 473313199
+ }])";
+
+ EXPECT_CALL(config_store_, LoadSettings("black_list"))
+ .WillOnce(Return(to_load));
+
+ EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
+ .WillOnce(testing::WithArgs<1, 2>(testing::Invoke(
+ [](const std::string& json, const DoneCallback& callback) {
+ std::string to_save = R"([{
+ "user": "AQID",
+ "app": "AwQF",
+ "expiration": 473315199,
+ "revocation": 473313199
+ }])";
+ EXPECT_JSON_EQ(to_save, *test::CreateValue(json));
+ if (!callback.is_null())
+ callback.Run(nullptr);
+ })));
+
+ EXPECT_CALL(clock_, Now())
+ .WillRepeatedly(Return(base::Time::FromTimeT(1412121212)));
+ manager_.reset(
+ new AccessRevocationManagerImpl{&config_store_, 10, &clock_});
+ }
+ StrictMock<test::MockClock> clock_;
+ StrictMock<provider::test::MockConfigStore> config_store_{false};
+ std::unique_ptr<AccessRevocationManagerImpl> manager_;
+};
+
+TEST_F(AccessRevocationManagerImplTest, Init) {
+ EXPECT_EQ(1u, manager_->GetSize());
+ EXPECT_EQ(10u, manager_->GetCapacity());
+ EXPECT_EQ((std::vector<AccessRevocationManagerImpl::Entry>{{
+ {1, 2, 3},
+ {3, 4, 5},
+ base::Time::FromTimeT(1419997999),
+ base::Time::FromTimeT(1419999999),
+ }}),
+ manager_->GetEntries());
+}
+
+TEST_F(AccessRevocationManagerImplTest, Block) {
+ bool callback_called = false;
+ manager_->AddEntryAddedCallback(
+ base::Bind([&callback_called]() { callback_called = true; }));
+ EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
+ .WillOnce(testing::WithArgs<1, 2>(testing::Invoke(
+ [](const std::string& json, const DoneCallback& callback) {
+ std::string to_save = R"([{
+ "user": "AQID",
+ "app": "AwQF",
+ "expiration": 473315199,
+ "revocation": 473313199
+ }, {
+ "app": "CAgI",
+ "user": "BwcH",
+ "expiration": 473305200,
+ "revocation": 473295200
+ }])";
+ EXPECT_JSON_EQ(to_save, *test::CreateValue(json));
+ if (!callback.is_null())
+ callback.Run(nullptr);
+ })));
+ manager_->Block({{7, 7, 7},
+ {8, 8, 8},
+ base::Time::FromTimeT(1419980000),
+ base::Time::FromTimeT(1419990000)},
+ {});
+ EXPECT_TRUE(callback_called);
+}
+
+TEST_F(AccessRevocationManagerImplTest, BlockExpired) {
+ manager_->Block({{},
+ {},
+ base::Time::FromTimeT(1300000000),
+ base::Time::FromTimeT(1400000000)},
+ base::Bind([](ErrorPtr error) {
+ EXPECT_TRUE(error->HasError("aleady_expired"));
+ }));
+}
+
+TEST_F(AccessRevocationManagerImplTest, BlockListIsFull) {
+ EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
+ .WillRepeatedly(testing::WithArgs<1, 2>(testing::Invoke(
+ [](const std::string& json, const DoneCallback& callback) {
+ if (!callback.is_null())
+ callback.Run(nullptr);
+ })));
+ for (size_t i = manager_->GetSize(); i < manager_->GetCapacity(); ++i) {
+ manager_->Block(
+ {{99, static_cast<uint8_t>(i / 256), static_cast<uint8_t>(i % 256)},
+ {8, 8, 8},
+ base::Time::FromTimeT(1419970000),
+ base::Time::FromTimeT(1419990000)},
+ {});
+ EXPECT_EQ(i + 1, manager_->GetSize());
+ }
+ manager_->Block({{99},
+ {8, 8, 8},
+ base::Time::FromTimeT(1419970000),
+ base::Time::FromTimeT(1419990000)},
+ base::Bind([](ErrorPtr error) {
+ EXPECT_TRUE(error->HasError("blacklist_is_full"));
+ }));
+}
+
+TEST_F(AccessRevocationManagerImplTest, IsBlockedIdsNotMacth) {
+ EXPECT_FALSE(manager_->IsBlocked({7, 7, 7}, {8, 8, 8}, {}));
+}
+
+TEST_F(AccessRevocationManagerImplTest, IsBlockedRevocationIsOld) {
+ // Ids match but delegation time is newer than revocation time.
+ EXPECT_FALSE(manager_->IsBlocked({1, 2, 3}, {3, 4, 5},
+ base::Time::FromTimeT(1429997999)));
+}
+
+class AccessRevocationManagerImplIsBlockedTest
+ : public AccessRevocationManagerImplTest,
+ public testing::WithParamInterface<
+ std::tuple<std::vector<uint8_t>, std::vector<uint8_t>>> {
+ public:
+ void SetUp() override {
+ AccessRevocationManagerImplTest::SetUp();
+ EXPECT_CALL(config_store_, SaveSettings("black_list", _, _))
+ .WillOnce(testing::WithArgs<2>(
+ testing::Invoke([](const DoneCallback& callback) {
+ if (!callback.is_null())
+ callback.Run(nullptr);
+ })));
+ manager_->Block({std::get<0>(GetParam()),
+ std::get<1>(GetParam()),
+ {},
+ base::Time::FromTimeT(1419990000)},
+ {});
+ }
+};
+
+TEST_P(AccessRevocationManagerImplIsBlockedTest, IsBlocked) {
+ EXPECT_TRUE(manager_->IsBlocked({7, 7, 7}, {8, 8, 8}, {}));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ Filters,
+ AccessRevocationManagerImplIsBlockedTest,
+ testing::Combine(testing::Values(std::vector<uint8_t>{},
+ std::vector<uint8_t>{7, 7, 7}),
+ testing::Values(std::vector<uint8_t>{},
+ std::vector<uint8_t>{8, 8, 8})));
+
+} // namespace weave
diff --git a/src/commands/cloud_command_proxy_unittest.cc b/src/commands/cloud_command_proxy_unittest.cc
index 0de67fe..e0bd4fc 100644
--- a/src/commands/cloud_command_proxy_unittest.cc
+++ b/src/commands/cloud_command_proxy_unittest.cc
@@ -14,7 +14,7 @@
#include <weave/test/unittest_utils.h>
#include "src/commands/command_instance.h"
-#include "src/mock_component_manager.h"
+#include "src/test/mock_component_manager.h"
using testing::_;
using testing::AnyNumber;
@@ -141,7 +141,7 @@
ComponentManager::UpdateID current_state_update_id_{0};
base::CallbackList<void(ComponentManager::UpdateID)> callbacks_;
testing::StrictMock<MockCloudCommandUpdateInterface> cloud_updater_;
- testing::StrictMock<MockComponentManager> component_manager_;
+ testing::StrictMock<test::MockComponentManager> component_manager_;
testing::StrictMock<provider::test::FakeTaskRunner> task_runner_;
std::queue<base::Closure> task_queue_;
std::unique_ptr<CommandInstance> command_instance_;
diff --git a/src/commands/schema_constants.cc b/src/commands/schema_constants.cc
index 732cf44..37bee4c 100644
--- a/src/commands/schema_constants.cc
+++ b/src/commands/schema_constants.cc
@@ -32,12 +32,6 @@
const char kCommand_State[] = "state";
const char kCommand_Error[] = "error";
-const char kCommand_Role[] = "minimalRole";
-const char kCommand_Role_Manager[] = "manager";
-const char kCommand_Role_Owner[] = "owner";
-const char kCommand_Role_User[] = "user";
-const char kCommand_Role_Viewer[] = "viewer";
-
} // namespace attributes
} // namespace commands
diff --git a/src/commands/schema_constants.h b/src/commands/schema_constants.h
index 360079a..623fec3 100644
--- a/src/commands/schema_constants.h
+++ b/src/commands/schema_constants.h
@@ -34,12 +34,6 @@
extern const char kCommand_State[];
extern const char kCommand_Error[];
-extern const char kCommand_Role[];
-extern const char kCommand_Role_Manager[];
-extern const char kCommand_Role_Owner[];
-extern const char kCommand_Role_User[];
-extern const char kCommand_Role_Viewer[];
-
} // namespace attributes
} // namespace commands
diff --git a/src/component_manager.h b/src/component_manager.h
index 832b274..cea5569 100644
--- a/src/component_manager.h
+++ b/src/component_manager.h
@@ -209,17 +209,6 @@
virtual std::string FindComponentWithTrait(
const std::string& trait) const = 0;
- // Support for legacy APIs. Setting command and state definitions.
- // This translates into modifying a trait definition.
- virtual bool AddLegacyCommandDefinitions(const base::DictionaryValue& dict,
- ErrorPtr* error) = 0;
- virtual bool AddLegacyStateDefinitions(const base::DictionaryValue& dict,
- ErrorPtr* error) = 0;
- // Returns device state for legacy APIs.
- virtual const base::DictionaryValue& GetLegacyState() const = 0;
- // Returns command definitions for legacy APIs.
- virtual const base::DictionaryValue& GetLegacyCommandDefinitions() const = 0;
-
DISALLOW_COPY_AND_ASSIGN(ComponentManager);
};
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index dec4a48..3ea1f46 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -19,11 +19,13 @@
// Max of 100 state update events should be enough in the queue.
const size_t kMaxStateChangeQueueSize = 100;
+const char kMinimalRole[] = "minimalRole";
+
const EnumToStringMap<UserRole>::Map kMap[] = {
- {UserRole::kViewer, commands::attributes::kCommand_Role_Viewer},
- {UserRole::kUser, commands::attributes::kCommand_Role_User},
- {UserRole::kOwner, commands::attributes::kCommand_Role_Owner},
- {UserRole::kManager, commands::attributes::kCommand_Role_Manager},
+ {UserRole::kViewer, "viewer"},
+ {UserRole::kUser, "user"},
+ {UserRole::kOwner, "owner"},
+ {UserRole::kManager, "manager"},
};
} // anonymous namespace
@@ -356,7 +358,7 @@
std::string value;
// The JSON definition has been pre-validated already in LoadCommands, so
// just using CHECKs here.
- CHECK(command->GetString(commands::attributes::kCommand_Role, &value));
+ CHECK(command->GetString(kMinimalRole, &value));
CHECK(StringToEnum(value, minimal_role));
return true;
}
@@ -504,140 +506,6 @@
return std::string{};
}
-bool ComponentManagerImpl::AddLegacyCommandDefinitions(
- const base::DictionaryValue& dict,
- ErrorPtr* error) {
- bool result = true;
- bool modified = false;
- for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
- const base::DictionaryValue* command_dict = nullptr;
- if (!it.value().GetAsDictionary(&command_dict)) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
- "Package '%s' must be an object", it.key().c_str());
- result = false;
- continue;
- }
- AddTraitToLegacyComponent(it.key());
- for (base::DictionaryValue::Iterator it_def(*command_dict);
- !it_def.IsAtEnd(); it_def.Advance()) {
- std::string key = base::StringPrintf("%s.commands.%s", it.key().c_str(),
- it_def.key().c_str());
- if (traits_.GetDictionary(key, nullptr)) {
- Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kInvalidPropValue,
- "Redefining command '%s.%s'", it.key().c_str(),
- it_def.key().c_str());
- result = false;
- continue;
- }
- traits_.Set(key, it_def.value().DeepCopy());
- modified = true;
- }
- }
-
- if (modified) {
- for (const auto& cb : on_trait_changed_)
- cb.Run();
- }
- return result;
-}
-
-bool ComponentManagerImpl::AddLegacyStateDefinitions(
- const base::DictionaryValue& dict,
- ErrorPtr* error) {
- bool result = true;
- bool modified = false;
- for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
- const base::DictionaryValue* state_dict = nullptr;
- if (!it.value().GetAsDictionary(&state_dict)) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
- "Package '%s' must be an object", it.key().c_str());
- result = false;
- continue;
- }
- AddTraitToLegacyComponent(it.key());
- for (base::DictionaryValue::Iterator it_def(*state_dict); !it_def.IsAtEnd();
- it_def.Advance()) {
- std::string key = base::StringPrintf("%s.state.%s", it.key().c_str(),
- it_def.key().c_str());
- if (traits_.GetDictionary(key, nullptr)) {
- Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kInvalidPropValue,
- "Redefining state property '%s.%s'",
- it.key().c_str(), it_def.key().c_str());
- result = false;
- continue;
- }
- traits_.Set(key, it_def.value().DeepCopy());
- modified = true;
- }
- }
-
- if (modified) {
- for (const auto& cb : on_trait_changed_)
- cb.Run();
- }
- return result;
-}
-
-const base::DictionaryValue& ComponentManagerImpl::GetLegacyState() const {
- legacy_state_.Clear();
- // Build state from components.
- for (base::DictionaryValue::Iterator it(components_); !it.IsAtEnd();
- it.Advance()) {
- const base::DictionaryValue* component_dict = nullptr;
- const base::DictionaryValue* component_state = nullptr;
- if (it.value().GetAsDictionary(&component_dict) &&
- component_dict->GetDictionary("state", &component_state)) {
- legacy_state_.MergeDictionary(component_state);
- }
- }
- return legacy_state_;
-}
-
-const base::DictionaryValue& ComponentManagerImpl::GetLegacyCommandDefinitions()
- const {
- legacy_command_defs_.Clear();
- // Build commandDefs from traits.
- for (base::DictionaryValue::Iterator it(traits_); !it.IsAtEnd();
- it.Advance()) {
- const base::DictionaryValue* trait_dict = nullptr;
- const base::DictionaryValue* trait_commands = nullptr;
- if (it.value().GetAsDictionary(&trait_dict) &&
- trait_dict->GetDictionary("commands", &trait_commands)) {
- base::DictionaryValue dict;
- dict.Set(it.key(), trait_commands->DeepCopy());
- legacy_command_defs_.MergeDictionary(&dict);
- }
- }
- return legacy_command_defs_;
-}
-
-void ComponentManagerImpl::AddTraitToLegacyComponent(const std::string& trait) {
- // First check if we already have a component supporting this trait.
- if (!FindComponentWithTrait(trait).empty())
- return;
-
- // If not, add this trait to the first component available.
- base::DictionaryValue* component = nullptr;
- base::DictionaryValue::Iterator it(components_);
- if (it.IsAtEnd()) {
- // No components at all. Create a new one with dummy name.
- // This normally wouldn't happen since libweave creates its own component
- // at startup.
- component = new base::DictionaryValue;
- components_.Set("__weave__", component);
- } else {
- CHECK(components_.GetDictionary(it.key(), &component));
- }
- base::ListValue* traits = nullptr;
- if (!component->GetList("traits", &traits)) {
- traits = new base::ListValue;
- component->Set("traits", traits);
- }
- traits->AppendString(trait);
-}
-
base::DictionaryValue* ComponentManagerImpl::FindComponentGraftNode(
const std::string& path,
ErrorPtr* error) {
diff --git a/src/component_manager_impl.h b/src/component_manager_impl.h
index f3c5451..5b8201a 100644
--- a/src/component_manager_impl.h
+++ b/src/component_manager_impl.h
@@ -174,17 +174,6 @@
// tree. No sub-components are searched.
std::string FindComponentWithTrait(const std::string& trait) const override;
- // Support for legacy APIs. Setting command and state definitions.
- // This translates into modifying a trait definition.
- bool AddLegacyCommandDefinitions(const base::DictionaryValue& dict,
- ErrorPtr* error) override;
- bool AddLegacyStateDefinitions(const base::DictionaryValue& dict,
- ErrorPtr* error) override;
- // Returns device state for legacy APIs.
- const base::DictionaryValue& GetLegacyState() const override;
- // Returns command definitions for legacy APIs.
- const base::DictionaryValue& GetLegacyCommandDefinitions() const override;
-
private:
// A helper method to find a JSON element of component at |path| to add new
// sub-components to.
@@ -193,12 +182,6 @@
base::DictionaryValue* FindMutableComponent(const std::string& path,
ErrorPtr* error);
- // Legacy API support: Helper function to support state/command definitions.
- // Adds the given trait to at least one component.
- // Searches for available components and if none of them already supports this
- // trait, it adds it to the first available component.
- void AddTraitToLegacyComponent(const std::string& trait);
-
// Helper method to find a sub-component given a root node and a relative path
// from the root to the target component.
static const base::DictionaryValue* FindComponentAt(
@@ -225,10 +208,6 @@
uint32_t next_command_id_{0};
std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
- // Legacy API support.
- mutable base::DictionaryValue legacy_state_; // Device state.
- mutable base::DictionaryValue legacy_command_defs_; // Command definitions.
-
DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl);
};
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc
index 97dc00d..291ace8 100644
--- a/src/component_manager_unittest.cc
+++ b/src/component_manager_unittest.cc
@@ -12,7 +12,7 @@
#include "src/bind_lambda.h"
#include "src/commands/schema_constants.h"
-#include "src/mock_component_manager.h"
+#include "src/test/mock_component_manager.h"
#include "src/test/mock_clock.h"
namespace weave {
@@ -1262,226 +1262,9 @@
EXPECT_EQ("", manager_.FindComponentWithTrait("trait4"));
}
-TEST_F(ComponentManagerTest, AddLegacyCommandAndStateDefinitions) {
- const char kCommandDefs1[] = R"({
- "package1": {
- "command1": {
- "minimalRole": "user",
- "parameters": {"height": {"type": "integer"}}
- },
- "command2": {
- "minimalRole": "owner",
- "parameters": {}
- }
- },
- "package2": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" }
- }
- })";
- auto json = CreateDictionaryValue(kCommandDefs1);
- EXPECT_TRUE(manager_.AddLegacyCommandDefinitions(*json, nullptr));
- const char kExpected1[] = R"({
- "package1": {
- "commands": {
- "command1": {
- "minimalRole": "user",
- "parameters": {"height": {"type": "integer"}}
- },
- "command2": {
- "minimalRole": "owner",
- "parameters": {}
- }
- }
- },
- "package2": {
- "commands": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" }
- }
- }
- })";
- EXPECT_JSON_EQ(kExpected1, manager_.GetTraits());
- const char kExpectedComponents1[] = R"({
- "__weave__": { "traits": ["package1", "package2"] }
- })";
- EXPECT_JSON_EQ(kExpectedComponents1, manager_.GetComponents());
-
- const char kCommandDefs2[] = R"({
- "package2": {
- "command3": { "minimalRole": "user" }
- },
- "package3": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" }
- }
- })";
- json = CreateDictionaryValue(kCommandDefs2);
- EXPECT_TRUE(manager_.AddLegacyCommandDefinitions(*json, nullptr));
- const char kExpected2[] = R"({
- "package1": {
- "commands": {
- "command1": {
- "minimalRole": "user",
- "parameters": {"height": {"type": "integer"}}
- },
- "command2": {
- "minimalRole": "owner",
- "parameters": {}
- }
- }
- },
- "package2": {
- "commands": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" },
- "command3": { "minimalRole": "user" }
- }
- },
- "package3": {
- "commands": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" }
- }
- }
- })";
- EXPECT_JSON_EQ(kExpected2, manager_.GetTraits());
- const char kExpectedComponents2[] = R"({
- "__weave__": { "traits": ["package1", "package2", "package3"] }
- })";
- EXPECT_JSON_EQ(kExpectedComponents2, manager_.GetComponents());
-
- // Redefining existing commands.
- EXPECT_FALSE(manager_.AddLegacyCommandDefinitions(*json, nullptr));
-
- const char kStateDefs1[] = R"({
- "package1": {
- "prop1": { "type": "string" },
- "prop2": { "type": "string" }
- },
- "package4": {
- "prop3": { "type": "string" },
- "prop4": { "type": "string" }
- }
- })";
- json = CreateDictionaryValue(kStateDefs1);
- EXPECT_TRUE(manager_.AddLegacyStateDefinitions(*json, nullptr));
- const char kExpectedComponents3[] = R"({
- "__weave__": { "traits": ["package1", "package2", "package3", "package4"] }
- })";
- EXPECT_JSON_EQ(kExpectedComponents3, manager_.GetComponents());
-
- const char kExpected3[] = R"({
- "package1": {
- "commands": {
- "command1": {
- "minimalRole": "user",
- "parameters": {"height": {"type": "integer"}}
- },
- "command2": {
- "minimalRole": "owner",
- "parameters": {}
- }
- },
- "state": {
- "prop1": { "type": "string" },
- "prop2": { "type": "string" }
- }
- },
- "package2": {
- "commands": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" },
- "command3": { "minimalRole": "user" }
- }
- },
- "package3": {
- "commands": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" }
- }
- },
- "package4": {
- "state": {
- "prop3": { "type": "string" },
- "prop4": { "type": "string" }
- }
- }
- })";
- EXPECT_JSON_EQ(kExpected3, manager_.GetTraits());
- const char kExpectedComponents4[] = R"({
- "__weave__": { "traits": ["package1", "package2", "package3", "package4"] }
- })";
- EXPECT_JSON_EQ(kExpectedComponents4, manager_.GetComponents());
-
- // Redefining existing commands.
- EXPECT_FALSE(manager_.AddLegacyStateDefinitions(*json, nullptr));
-
- const char kExpected4[] = R"({
- "package1": {
- "command1": {
- "minimalRole": "user",
- "parameters": {"height": {"type": "integer"}}
- },
- "command2": {
- "minimalRole": "owner",
- "parameters": {}
- }
- },
- "package2": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" },
- "command3": { "minimalRole": "user" }
- },
- "package3": {
- "command1": { "minimalRole": "user" },
- "command2": { "minimalRole": "owner" }
- }
- })";
- EXPECT_JSON_EQ(kExpected4, manager_.GetLegacyCommandDefinitions());
-}
-
-TEST_F(ComponentManagerTest, GetLegacyState) {
- const char kTraits[] = R"({
- "trait1": {
- "state": {
- "prop1": { "type": "string" },
- "prop2": { "type": "string" }
- }
- },
- "trait2": {
- "state": {
- "prop3": { "type": "string" },
- "prop4": { "type": "string" }
- }
- }
- })";
- auto traits = CreateDictionaryValue(kTraits);
- ASSERT_TRUE(manager_.LoadTraits(*traits, nullptr));
- ASSERT_TRUE(manager_.AddComponent("", "comp1", {"trait1"}, nullptr));
- ASSERT_TRUE(manager_.AddComponent("", "comp2", {"trait2"}, nullptr));
-
- ASSERT_TRUE(manager_.SetStatePropertiesFromJson(
- "comp1", R"({"trait1": {"prop1": "foo", "prop2": "bar"}})", nullptr));
- ASSERT_TRUE(manager_.SetStatePropertiesFromJson(
- "comp2", R"({"trait2": {"prop3": "baz", "prop4": "quux"}})", nullptr));
-
- const char kExpected[] = R"({
- "trait1": {
- "prop1": "foo",
- "prop2": "bar"
- },
- "trait2": {
- "prop3": "baz",
- "prop4": "quux"
- }
- })";
- EXPECT_JSON_EQ(kExpected, manager_.GetLegacyState());
-}
-
TEST_F(ComponentManagerTest, TestMockComponentManager) {
// Check that all the virtual methods are mocked out.
- MockComponentManager mock;
+ test::MockComponentManager mock;
}
} // namespace weave
diff --git a/src/device_manager.cc b/src/device_manager.cc
index 4c0d3ee..b6b91a9 100644
--- a/src/device_manager.cc
+++ b/src/device_manager.cc
@@ -9,7 +9,7 @@
#include <base/bind.h>
#include "src/access_api_handler.h"
-#include "src/access_black_list_manager_impl.h"
+#include "src/access_revocation_manager_impl.h"
#include "src/base_api_handler.h"
#include "src/commands/schema_constants.h"
#include "src/component_manager_impl.h"
@@ -33,8 +33,13 @@
: config_{new Config{config_store}},
component_manager_{new ComponentManagerImpl{task_runner}} {
if (http_server) {
- auth_manager_.reset(new privet::AuthManager(
- config_.get(), http_server->GetHttpsCertificateFingerprint()));
+ access_revocation_manager_.reset(
+ new AccessRevocationManagerImpl{config_store});
+ auth_manager_.reset(
+ new privet::AuthManager(config_.get(), access_revocation_manager_.get(),
+ http_server->GetHttpsCertificateFingerprint()));
+ access_api_handler_.reset(
+ new AccessApiHandler{this, access_revocation_manager_.get()});
}
device_info_.reset(new DeviceRegistrationInfo(
@@ -42,10 +47,6 @@
network, auth_manager_.get()));
base_api_handler_.reset(new BaseApiHandler{device_info_.get(), this});
- black_list_manager_.reset(new AccessBlackListManagerImpl{config_store});
- access_api_handler_.reset(
- new AccessApiHandler{this, black_list_manager_.get()});
-
device_info_->Start();
if (http_server) {
@@ -156,16 +157,6 @@
component_manager_->AddCommandHandler(component, command_name, callback);
}
-void DeviceManager::AddCommandDefinitionsFromJson(const std::string& json) {
- auto dict = LoadJsonDict(json, nullptr);
- CHECK(dict);
- AddCommandDefinitions(*dict);
-}
-
-void DeviceManager::AddCommandDefinitions(const base::DictionaryValue& dict) {
- CHECK(component_manager_->AddLegacyCommandDefinitions(dict, nullptr));
-}
-
bool DeviceManager::AddCommand(const base::DictionaryValue& command,
std::string* id,
ErrorPtr* error) {
@@ -181,87 +172,10 @@
return component_manager_->FindCommand(id);
}
-void DeviceManager::AddCommandHandler(const std::string& command_name,
- const CommandHandlerCallback& callback) {
- if (command_name.empty())
- return component_manager_->AddCommandHandler("", "", callback);
-
- auto trait = SplitAtFirst(command_name, ".", true).first;
- std::string component = component_manager_->FindComponentWithTrait(trait);
- CHECK(!component.empty());
- component_manager_->AddCommandHandler(component, command_name, callback);
-}
-
void DeviceManager::AddStateChangedCallback(const base::Closure& callback) {
component_manager_->AddStateChangedCallback(callback);
}
-void DeviceManager::AddStateDefinitionsFromJson(const std::string& json) {
- auto dict = LoadJsonDict(json, nullptr);
- CHECK(dict);
- AddStateDefinitions(*dict);
-}
-
-void DeviceManager::AddStateDefinitions(const base::DictionaryValue& dict) {
- CHECK(component_manager_->AddLegacyStateDefinitions(dict, nullptr));
-}
-
-bool DeviceManager::SetStatePropertiesFromJson(const std::string& json,
- ErrorPtr* error) {
- auto dict = LoadJsonDict(json, error);
- return dict && SetStateProperties(*dict, error);
-}
-
-bool DeviceManager::SetStateProperties(const base::DictionaryValue& dict,
- ErrorPtr* error) {
- for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
- std::string component =
- component_manager_->FindComponentWithTrait(it.key());
- if (component.empty()) {
- Error::AddToPrintf(error, FROM_HERE, "unrouted_state",
- "Unable to set property value because there is no "
- "component supporting "
- "trait '%s'",
- it.key().c_str());
- return false;
- }
- base::DictionaryValue trait_state;
- trait_state.Set(it.key(), it.value().DeepCopy());
- if (!component_manager_->SetStateProperties(component, trait_state, error))
- return false;
- }
- return true;
-}
-
-const base::Value* DeviceManager::GetStateProperty(
- const std::string& name) const {
- auto trait = SplitAtFirst(name, ".", true).first;
- std::string component = component_manager_->FindComponentWithTrait(trait);
- if (component.empty())
- return nullptr;
- return component_manager_->GetStateProperty(component, name, nullptr);
-}
-
-bool DeviceManager::SetStateProperty(const std::string& name,
- const base::Value& value,
- ErrorPtr* error) {
- auto trait = SplitAtFirst(name, ".", true).first;
- std::string component = component_manager_->FindComponentWithTrait(trait);
- if (component.empty()) {
- Error::AddToPrintf(
- error, FROM_HERE, "unrouted_state",
- "Unable set value of state property '%s' because there is no component "
- "supporting trait '%s'",
- name.c_str(), trait.c_str());
- return false;
- }
- return component_manager_->SetStateProperty(component, name, value, error);
-}
-
-const base::DictionaryValue& DeviceManager::GetState() const {
- return component_manager_->GetLegacyState();
-}
-
void DeviceManager::Register(const RegistrationData& registration_data,
const DoneCallback& callback) {
device_info_->RegisterDevice(registration_data, callback);
diff --git a/src/device_manager.h b/src/device_manager.h
index f0ad464..545f293 100644
--- a/src/device_manager.h
+++ b/src/device_manager.h
@@ -11,7 +11,7 @@
namespace weave {
class AccessApiHandler;
-class AccessBlackListManager;
+class AccessRevocationManager;
class BaseApiHandler;
class Config;
class ComponentManager;
@@ -78,22 +78,6 @@
const PairingBeginCallback& begin_callback,
const PairingEndCallback& end_callback) override;
- void AddCommandDefinitionsFromJson(const std::string& json) override;
- void AddCommandDefinitions(const base::DictionaryValue& dict) override;
- void AddCommandHandler(const std::string& command_name,
- const CommandHandlerCallback& callback) override;
- void AddStateDefinitionsFromJson(const std::string& json) override;
- void AddStateDefinitions(const base::DictionaryValue& dict) override;
- bool SetStatePropertiesFromJson(const std::string& json,
- ErrorPtr* error) override;
- bool SetStateProperties(const base::DictionaryValue& dict,
- ErrorPtr* error) override;
- const base::Value* GetStateProperty(const std::string& name) const override;
- bool SetStateProperty(const std::string& name,
- const base::Value& value,
- ErrorPtr* error) override;
- const base::DictionaryValue& GetState() const override;
-
Config* GetConfig();
private:
@@ -109,7 +93,7 @@
std::unique_ptr<ComponentManager> component_manager_;
std::unique_ptr<DeviceRegistrationInfo> device_info_;
std::unique_ptr<BaseApiHandler> base_api_handler_;
- std::unique_ptr<AccessBlackListManager> black_list_manager_;
+ std::unique_ptr<AccessRevocationManager> access_revocation_manager_;
std::unique_ptr<AccessApiHandler> access_api_handler_;
std::unique_ptr<privet::Manager> privet_;
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc
index 027ad5a..d905a45 100644
--- a/src/privet/auth_manager.cc
+++ b/src/privet/auth_manager.cc
@@ -6,15 +6,18 @@
#include <algorithm>
+#include <base/bind.h>
#include <base/guid.h>
#include <base/rand_util.h>
#include <base/strings/string_number_conversions.h>
+#include "src/access_revocation_manager.h"
#include "src/config.h"
#include "src/data_encoding.h"
#include "src/privet/constants.h"
#include "src/privet/openssl_utils.h"
#include "src/string_utils.h"
+#include "src/utils.h"
extern "C" {
#include "third_party/libuweave/src/macaroon.h"
@@ -26,20 +29,11 @@
namespace {
-const time_t kJ2000ToTimeT = 946684800;
const size_t kMaxMacaroonSize = 1024;
const size_t kMaxPendingClaims = 10;
const char kInvalidTokenError[] = "invalid_token";
const int kSessionIdTtlMinutes = 1;
-uint32_t ToJ2000Time(const base::Time& time) {
- return std::max(time.ToTimeT(), kJ2000ToTimeT) - kJ2000ToTimeT;
-}
-
-base::Time FromJ2000Time(uint32_t time) {
- return base::Time::FromTimeT(time + kJ2000ToTimeT);
-}
-
template <class T>
void AppendToArray(T value, std::vector<uint8_t>* array) {
auto begin = reinterpret_cast<const uint8_t*>(&value);
@@ -275,10 +269,16 @@
} // namespace
AuthManager::AuthManager(Config* config,
+ AccessRevocationManager* black_list,
const std::vector<uint8_t>& certificate_fingerprint)
: config_{config},
+ black_list_{black_list},
certificate_fingerprint_{certificate_fingerprint},
access_secret_{CreateSecret()} {
+ if (black_list_) {
+ black_list_->AddEntryAddedCallback(base::Bind(
+ &AuthManager::ResetAccessSecret, weak_ptr_factory_.GetWeakPtr()));
+ }
if (config_) {
SetAuthSecret(config_->GetSettings().secret,
config_->GetSettings().root_client_token_owner);
@@ -290,8 +290,9 @@
AuthManager::AuthManager(const std::vector<uint8_t>& auth_secret,
const std::vector<uint8_t>& certificate_fingerprint,
const std::vector<uint8_t>& access_secret,
- base::Clock* clock)
- : AuthManager(nullptr, certificate_fingerprint) {
+ base::Clock* clock,
+ AccessRevocationManager* black_list)
+ : AuthManager(nullptr, black_list, certificate_fingerprint) {
access_secret_ = access_secret.size() == kSha256OutputSize ? access_secret
: CreateSecret();
SetAuthSecret(auth_secret, RootClientTokenOwner::kNone);
@@ -401,7 +402,8 @@
};
pending_claims_.push_back(std::make_pair(
- std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}}, owner));
+ std::unique_ptr<AuthManager>{new AuthManager{nullptr, nullptr, {}}},
+ owner));
if (pending_claims_.size() > kMaxPendingClaims)
pending_claims_.pop_front();
return pending_claims_.back().first->GetRootClientAuthToken(owner);
@@ -511,6 +513,28 @@
"Invalid session id");
}
+ if (black_list_) {
+ std::vector<uint8_t> user_id;
+ std::vector<uint8_t> app_id;
+ for (size_t i = 0; i < result.num_delegatees; ++i) {
+ if (result.delegatees[i].type == kUwMacaroonDelegateeTypeUser) {
+ user_id.assign(result.delegatees[i].id,
+ result.delegatees[i].id + result.delegatees[i].id_len);
+ } else if (result.delegatees[i].type == kUwMacaroonDelegateeTypeApp) {
+ app_id.assign(result.delegatees[i].id,
+ result.delegatees[i].id + result.delegatees[i].id_len);
+ } else {
+ // Do not block by other types of delegatees.
+ continue;
+ }
+ if (black_list_->IsBlocked(
+ user_id, app_id, FromJ2000Time(result.delegatees[i].timestamp))) {
+ return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
+ "Auth token is revoked");
+ }
+ }
+ }
+
CHECK_GE(FromJ2000Time(result.expiration_time), now);
if (!access_token)
@@ -547,6 +571,12 @@
ssid_time <= Now();
}
+void AuthManager::ResetAccessSecret() {
+ auto new_secret = CreateSecret();
+ CHECK(new_secret != access_secret_);
+ access_secret_.swap(new_secret);
+}
+
std::vector<uint8_t> AuthManager::DelegateToUser(
const std::vector<uint8_t>& token,
base::TimeDelta ttl,
diff --git a/src/privet/auth_manager.h b/src/privet/auth_manager.h
index f0a5761..d8174f6 100644
--- a/src/privet/auth_manager.h
+++ b/src/privet/auth_manager.h
@@ -10,6 +10,7 @@
#include <vector>
#include <base/gtest_prod_util.h>
+#include <base/memory/weak_ptr.h>
#include <base/time/default_clock.h>
#include <base/time/time.h>
#include <weave/error.h>
@@ -18,6 +19,7 @@
namespace weave {
+class AccessRevocationManager;
class Config;
enum class RootClientTokenOwner;
@@ -26,13 +28,15 @@
class AuthManager {
public:
AuthManager(Config* config,
+ AccessRevocationManager* black_list,
const std::vector<uint8_t>& certificate_fingerprint);
// Constructor for tests.
AuthManager(const std::vector<uint8_t>& auth_secret,
const std::vector<uint8_t>& certificate_fingerprint,
const std::vector<uint8_t>& access_secret,
- base::Clock* clock = nullptr);
+ base::Clock* clock = nullptr,
+ AccessRevocationManager* black_list = nullptr);
~AuthManager();
std::vector<uint8_t> CreateAccessToken(const UserInfo& user_info,
@@ -74,12 +78,15 @@
private:
friend class AuthManagerTest;
+ void ResetAccessSecret();
+
// Test helpers. Device does not need to implement delegation.
std::vector<uint8_t> DelegateToUser(const std::vector<uint8_t>& token,
base::TimeDelta ttl,
const UserInfo& user_info) const;
Config* config_{nullptr}; // Can be nullptr for tests.
+ AccessRevocationManager* black_list_{nullptr};
base::DefaultClock default_clock_;
base::Clock* clock_{&default_clock_};
mutable uint32_t session_counter_{0};
@@ -91,6 +98,7 @@
std::deque<std::pair<std::unique_ptr<AuthManager>, RootClientTokenOwner>>
pending_claims_;
+ base::WeakPtrFactory<AuthManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AuthManager);
};
diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc
index 3e5aeab..648027d 100644
--- a/src/privet/auth_manager_unittest.cc
+++ b/src/privet/auth_manager_unittest.cc
@@ -11,13 +11,28 @@
#include "src/config.h"
#include "src/data_encoding.h"
#include "src/privet/mock_delegates.h"
+#include "src/test/mock_access_revocation_manager.h"
#include "src/test/mock_clock.h"
+using testing::_;
using testing::Return;
+using testing::SaveArg;
+using testing::StrictMock;
namespace weave {
namespace privet {
+class MockAccessRevocationManager : public test::MockAccessRevocationManager {
+ public:
+ MockAccessRevocationManager() {
+ EXPECT_CALL(*this, AddEntryAddedCallback(_))
+ .WillOnce(SaveArg<0>(&changed_callback_));
+ EXPECT_CALL(*this, IsBlocked(_, _, _)).WillRepeatedly(Return(false));
+ }
+
+ base::Closure changed_callback_;
+};
+
class AuthManagerTest : public testing::Test {
public:
void SetUp() override {
@@ -46,7 +61,8 @@
60, 62, 10, 18, 82, 35, 88, 100, 30, 45, 7, 46, 67, 84, 58, 85};
test::MockClock clock_;
- AuthManager auth_{kSecret1, kFingerprint, kSecret2, &clock_};
+ StrictMock<MockAccessRevocationManager> black_list_;
+ AuthManager auth_{kSecret1, kFingerprint, kSecret2, &clock_, &black_list_};
};
TEST_F(AuthManagerTest, RandomSecret) {
@@ -152,8 +168,9 @@
TEST_F(AuthManagerTest, CreateTokenDifferentInstance) {
EXPECT_NE(auth_.CreateAccessToken(
UserInfo{AuthScope::kUser, TestUserId{"123"}}, {}),
- AuthManager({}, {}).CreateAccessToken(
- UserInfo{AuthScope::kUser, TestUserId{"123"}}, {}));
+ AuthManager({}, nullptr, {})
+ .CreateAccessToken(
+ UserInfo{AuthScope::kUser, TestUserId{"123"}}, {}));
}
TEST_F(AuthManagerTest, ParseAccessToken) {
@@ -189,6 +206,22 @@
}
}
+TEST_F(AuthManagerTest, AccessTokenAfterReset) {
+ UserInfo user_info;
+ auto token1 = auth_.CreateAccessToken(
+ UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {});
+ EXPECT_TRUE(auth_.ParseAccessToken(token1, &user_info, nullptr));
+
+ black_list_.changed_callback_.Run();
+
+ auto token2 = auth_.CreateAccessToken(
+ UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {});
+
+ EXPECT_NE(token1, token2);
+ EXPECT_FALSE(auth_.ParseAccessToken(token1, &user_info, nullptr));
+ EXPECT_TRUE(auth_.ParseAccessToken(token2, &user_info, nullptr));
+}
+
TEST_F(AuthManagerTest, GetRootClientAuthToken) {
EXPECT_EQ("WCCDQxkgAUYIGhudoQBCDABQX3fPR5zsPnrs9aOSvS7/eQ==",
Base64Encode(
@@ -319,6 +352,21 @@
EXPECT_TRUE(error->HasError("invalidAuthCode"));
}
+TEST_F(AuthManagerTest, CreateAccessTokenFromAuthRevoked) {
+ TestUserId user{"234"};
+ EXPECT_CALL(black_list_, IsBlocked(user.user, _, clock_.Now()))
+ .WillOnce(Return(true));
+ std::vector<uint8_t> access_token;
+ auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kCloud);
+ auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000),
+ UserInfo{AuthScope::kUser, user});
+ ErrorPtr error;
+ EXPECT_FALSE(
+ auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1),
+ nullptr, nullptr, nullptr, &error));
+ EXPECT_TRUE(error->HasError("invalidAuthCode"));
+}
+
class AuthManagerClaimTest : public testing::Test {
public:
void SetUp() override { EXPECT_EQ(auth_.GetAuthSecret().size(), 32u); }
@@ -332,7 +380,7 @@
protected:
Config config_{nullptr};
- AuthManager auth_{&config_, {}};
+ AuthManager auth_{&config_, nullptr, {}};
};
TEST_F(AuthManagerClaimTest, WithPreviosOwner) {
diff --git a/src/privet/cloud_delegate.cc b/src/privet/cloud_delegate.cc
index 0b4400f..f565687 100644
--- a/src/privet/cloud_delegate.cc
+++ b/src/privet/cloud_delegate.cc
@@ -151,14 +151,6 @@
return device_->GetSettings().xmpp_endpoint;
}
- const base::DictionaryValue& GetLegacyCommandDef() const override {
- return component_manager_->GetLegacyCommandDefinitions();
- }
-
- const base::DictionaryValue& GetLegacyState() const override {
- return component_manager_->GetLegacyState();
- }
-
const base::DictionaryValue& GetComponents() const override {
return component_manager_->GetComponents();
}
diff --git a/src/privet/cloud_delegate.h b/src/privet/cloud_delegate.h
index 37ed723..43b8904 100644
--- a/src/privet/cloud_delegate.h
+++ b/src/privet/cloud_delegate.h
@@ -100,12 +100,6 @@
virtual std::string GetServiceUrl() const = 0;
virtual std::string GetXmppEndpoint() const = 0;
- // Returns dictionary with device state (for legacy APIs).
- virtual const base::DictionaryValue& GetLegacyState() const = 0;
-
- // Returns dictionary with commands definitions (for legacy APIs).
- virtual const base::DictionaryValue& GetLegacyCommandDef() const = 0;
-
// Returns dictionary with component tree.
virtual const base::DictionaryValue& GetComponents() const = 0;
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h
index 108e450..f04fb37 100644
--- a/src/privet/mock_delegates.h
+++ b/src/privet/mock_delegates.h
@@ -188,8 +188,6 @@
MOCK_CONST_METHOD0(GetOAuthUrl, std::string());
MOCK_CONST_METHOD0(GetServiceUrl, std::string());
MOCK_CONST_METHOD0(GetXmppEndpoint, std::string());
- MOCK_CONST_METHOD0(GetLegacyState, const base::DictionaryValue&());
- MOCK_CONST_METHOD0(GetLegacyCommandDef, const base::DictionaryValue&());
MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
MOCK_CONST_METHOD2(FindComponent,
const base::DictionaryValue*(const std::string& path,
@@ -229,9 +227,6 @@
EXPECT_CALL(*this, GetSetupState()).WillRepeatedly(ReturnRef(setup_state_));
EXPECT_CALL(*this, GetCloudId()).WillRepeatedly(Return("TestCloudId"));
test_dict_.Set("test", new base::DictionaryValue);
- EXPECT_CALL(*this, GetLegacyState()).WillRepeatedly(ReturnRef(test_dict_));
- EXPECT_CALL(*this, GetLegacyCommandDef())
- .WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, GetTraits()).WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, GetComponents()).WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, FindComponent(_, _)).Times(0);
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index 05b6e0a..83d5ef3 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -114,8 +114,6 @@
std::string xmpp_endpoint;
const char kFingerprintKey[] = "fingerprint";
-const char kStateKey[] = "state";
-const char kCommandsKey[] = "commands";
const char kTraitsKey[] = "traits";
const char kComponentsKey[] = "components";
const char kCommandsIdKey[] = "id";
@@ -421,10 +419,6 @@
AuthScope::kManager);
AddSecureHandler("/privet/v3/setup/status", &PrivetHandler::HandleSetupStatus,
AuthScope::kManager);
- AddSecureHandler("/privet/v3/state", &PrivetHandler::HandleState,
- AuthScope::kViewer);
- AddSecureHandler("/privet/v3/commandDefs", &PrivetHandler::HandleCommandDefs,
- AuthScope::kViewer);
AddSecureHandler("/privet/v3/commands/execute",
&PrivetHandler::HandleCommandsExecute, AuthScope::kViewer);
AddSecureHandler("/privet/v3/commands/status",
@@ -875,16 +869,6 @@
callback.Run(http::kOk, output);
}
-void PrivetHandler::HandleState(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- base::DictionaryValue output;
- output.Set(kStateKey, cloud_->GetLegacyState().DeepCopy());
- output.SetString(kFingerprintKey, std::to_string(state_fingerprint_));
-
- callback.Run(http::kOk, output);
-}
-
void PrivetHandler::HandleTraits(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback) {
@@ -931,18 +915,6 @@
callback.Run(http::kOk, output);
}
-void PrivetHandler::HandleCommandDefs(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- base::DictionaryValue output;
- output.Set(kCommandsKey, cloud_->GetLegacyCommandDef().DeepCopy());
- // Use traits fingerprint since right now we treat traits and command defs
- // as being equivalent.
- output.SetString(kFingerprintKey, std::to_string(traits_fingerprint_));
-
- callback.Run(http::kOk, output);
-}
-
void PrivetHandler::HandleCommandsExecute(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback) {
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index 3c72242..ecf4797 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -674,7 +674,6 @@
"client_secret": "test_client_secret",
"oauth_url": "https://oauths/",
"service_url": "https://service/",
- "status": "success",
"xmpp_endpoint": "xmpp:678",
"ticketId": "testTicket",
"user": "testUser"
@@ -728,26 +727,6 @@
R"({"clientToken": "DerivedClientAuthToken"})"));
}
-TEST_F(PrivetHandlerTestWithAuth, State) {
- EXPECT_JSON_EQ(R"({"state": {"test": {}}, "fingerprint": "1"})",
- HandleRequest("/privet/v3/state", "{}"));
-
- cloud_.NotifyOnStateChanged();
-
- EXPECT_JSON_EQ(R"({"state": {"test": {}}, "fingerprint": "2"})",
- HandleRequest("/privet/v3/state", "{}"));
-}
-
-TEST_F(PrivetHandlerTestWithAuth, CommandsDefs) {
- EXPECT_JSON_EQ(R"({"commands": {"test":{}}, "fingerprint": "1"})",
- HandleRequest("/privet/v3/commandDefs", "{}"));
-
- cloud_.NotifyOnTraitDefsChanged();
-
- EXPECT_JSON_EQ(R"({"commands": {"test":{}}, "fingerprint": "2"})",
- HandleRequest("/privet/v3/commandDefs", "{}"));
-}
-
TEST_F(PrivetHandlerTestWithAuth, Traits) {
EXPECT_JSON_EQ(R"({"traits": {"test": {}}, "fingerprint": "1"})",
HandleRequest("/privet/v3/traits", "{}"));
diff --git a/src/test/mock_access_revocation_manager.h b/src/test/mock_access_revocation_manager.h
new file mode 100644
index 0000000..29e3721
--- /dev/null
+++ b/src/test/mock_access_revocation_manager.h
@@ -0,0 +1,33 @@
+// Copyright 2016 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBWEAVE_SRC_MOCK_ACCESS_REVOCATION_MANAGER_H_
+#define LIBWEAVE_SRC_MOCK_ACCESS_REVOCATION_MANAGER_H_
+
+#include <gmock/gmock.h>
+
+#include "src/access_revocation_manager.h"
+
+namespace weave {
+
+namespace test {
+
+class MockAccessRevocationManager : public AccessRevocationManager {
+ public:
+ MOCK_METHOD1(AddEntryAddedCallback, void(const base::Closure&));
+ MOCK_METHOD2(Block, void(const Entry&, const DoneCallback&));
+ MOCK_CONST_METHOD3(IsBlocked,
+ bool(const std::vector<uint8_t>&,
+ const std::vector<uint8_t>&,
+ base::Time));
+ MOCK_CONST_METHOD0(GetEntries, std::vector<Entry>());
+ MOCK_CONST_METHOD0(GetSize, size_t());
+ MOCK_CONST_METHOD0(GetCapacity, size_t());
+};
+
+} // namespace test
+
+} // namespace weave
+
+#endif // LIBWEAVE_SRC_MOCK_ACCESS_REVOCATION_MANAGER_H_
diff --git a/src/mock_component_manager.h b/src/test/mock_component_manager.h
similarity index 92%
rename from src/mock_component_manager.h
rename to src/test/mock_component_manager.h
index addd6f0..2c1d695 100644
--- a/src/mock_component_manager.h
+++ b/src/test/mock_component_manager.h
@@ -11,6 +11,8 @@
namespace weave {
+namespace test {
+
class MockComponentManager : public ComponentManager {
public:
~MockComponentManager() override {}
@@ -95,13 +97,6 @@
const base::Callback<void(UpdateID)>& callback));
MOCK_CONST_METHOD1(FindComponentWithTrait,
std::string(const std::string& trait));
- MOCK_METHOD2(AddLegacyCommandDefinitions,
- bool(const base::DictionaryValue& dict, ErrorPtr* error));
- MOCK_METHOD2(AddLegacyStateDefinitions,
- bool(const base::DictionaryValue& dict, ErrorPtr* error));
- MOCK_CONST_METHOD0(GetLegacyState, const base::DictionaryValue&());
- MOCK_CONST_METHOD0(GetLegacyCommandDefinitions,
- const base::DictionaryValue&());
private:
void AddCommand(std::unique_ptr<CommandInstance> command_instance) override {
@@ -125,6 +120,8 @@
}
};
+} // namespace test
+
} // namespace weave
#endif // LIBWEAVE_SRC_COMPONENT_MANAGER_H_
diff --git a/src/utils.cc b/src/utils.cc
index 28828d7..5d1c3e3 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -26,6 +26,8 @@
const char kErrorCodeKey[] = "code";
const char kErrorMessageKey[] = "message";
+const time_t kJ2000ToTimeT = 946684800;
+
} // anonymous namespace
namespace errors {
@@ -69,4 +71,12 @@
return output;
}
+uint32_t ToJ2000Time(const base::Time& time) {
+ return std::max(time.ToTimeT(), kJ2000ToTimeT) - kJ2000ToTimeT;
+}
+
+base::Time FromJ2000Time(uint32_t time) {
+ return base::Time::FromTimeT(time + kJ2000ToTimeT);
+}
+
} // namespace weave
diff --git a/src/utils.h b/src/utils.h
index 99d7bda..40c76b4 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include <base/time/time.h>
#include <base/values.h>
#include <weave/error.h>
@@ -31,6 +32,9 @@
std::unique_ptr<base::DictionaryValue> ErrorInfoToJson(const Error& error);
+uint32_t ToJ2000Time(const base::Time& time);
+base::Time FromJ2000Time(uint32_t time);
+
} // namespace weave
#endif // LIBWEAVE_SRC_UTILS_H_
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc
index 452ac78..3b28001 100644
--- a/src/weave_unittest.cc
+++ b/src/weave_unittest.cc
@@ -294,7 +294,6 @@
"/privet/v3/accessControl/confirm",
"/privet/v3/auth",
"/privet/v3/checkForUpdates",
- "/privet/v3/commandDefs",
"/privet/v3/commands/cancel",
"/privet/v3/commands/execute",
"/privet/v3/commands/list",
@@ -305,7 +304,6 @@
"/privet/v3/pairing/start",
"/privet/v3/setup/start",
"/privet/v3/setup/status",
- "/privet/v3/state",
"/privet/v3/traits",
// clang-format on
}),
diff --git a/third_party/chromium/base/third_party/dmg_fp/dtoa.cc b/third_party/chromium/base/third_party/dmg_fp/dtoa.cc
index 502c16c..c06219c 100644
--- a/third_party/chromium/base/third_party/dmg_fp/dtoa.cc
+++ b/third_party/chromium/base/third_party/dmg_fp/dtoa.cc
@@ -59,6 +59,7 @@
* 4. Because of 3., we don't need a large table of powers of 10
* for ten-to-e (just some small tables, e.g. of 10^k
* for 0 <= k <= 22).
+ * 5. Fixed -Wchar-subscripts warning in "if (!hexdig['0'])"
*/
/*
@@ -1572,7 +1573,7 @@
CONST char *s;
int c1, havedig, udx0, xshift;
- if (!hexdig['0'])
+ if (!hexdig[0 + '0'])
hexdig_init();
x[0] = x[1] = 0;
havedig = xshift = 0;
diff --git a/third_party/chromium/base/third_party/dmg_fp/g_fmt.cc b/third_party/chromium/base/third_party/dmg_fp/g_fmt.cc
index bfa358d..67c9f57 100644
--- a/third_party/chromium/base/third_party/dmg_fp/g_fmt.cc
+++ b/third_party/chromium/base/third_party/dmg_fp/g_fmt.cc
@@ -27,10 +27,10 @@
namespace dmg_fp {
char *
-g_fmt(register char *b, double x)
+g_fmt(char *b, double x)
{
- register int i, k;
- register char *s;
+ int i, k;
+ char *s;
int decpt, j, sign;
char *b0, *s0, *se;