#include <bluetooth-api.h>
#include <bluetooth_internal.h>
-#include <vist/policy/sdk/policy-model.hpp>
-#include <vist/policy/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
#include <memory>
#include <arpa/inet.h>
#include <wifi-manager.h>
-#include <vist/policy/sdk/policy-model.hpp>
-#include <vist/policy/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
#include <klay/dbus/connection.h>
ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(notification)
ADD_SUBDIRECTORY(policy)
+ADD_SUBDIRECTORY(sdk)
ADD_SUBDIRECTORY(service)
ADD_LIBRARY(${TARGET_VIST_LIB} STATIC ${${TARGET_VIST_LIB}_SRCS})
PKG_CHECK_MODULES(VIST_POLICY_DEPS REQUIRED klay dlog)
-INCLUDE_DIRECTORIES(SYSTEM . common ${VIST_POLICY_DEPS_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(SYSTEM . ${VIST_POLICY_DEPS_INCLUDE_DIRS})
-ADD_VIST_POLICY_LIBRARY(vist_policy_core core/api.cpp
- core/policy-manager.cpp
- core/policy-loader.cpp
- core/policy-storage.cpp)
+ADD_VIST_POLICY_LIBRARY(vist_policy_core api.cpp
+ policy-manager.cpp
+ policy-loader.cpp
+ policy-storage.cpp)
-FILE(GLOB POLICY_CORE_TESTS "core/tests/*.cpp")
+FILE(GLOB POLICY_CORE_TESTS "tests/*.cpp")
ADD_VIST_TEST(${POLICY_CORE_TESTS})
-FILE(GLOB POLICY_SDK_TESTS "sdk/tests/*.cpp")
-ADD_VIST_TEST(${POLICY_SDK_TESTS})
-
ADD_LIBRARY(${TARGET_VIST_POLICY_LIB} STATIC ${${TARGET_VIST_POLICY_LIB}_SRCS})
TARGET_LINK_LIBRARIES(${TARGET_VIST_POLICY_LIB} ${VIST_POLICY_DEPS_LIBRARIES}
pthread
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include <vist/policy/api.hpp>
+
+#include "policy-manager.hpp"
+
+namespace vist {
+namespace policy {
+
+PolicyValue API::Get(const std::string& policy)
+{
+ return PolicyManager::Instance().get(policy);
+}
+
+std::unordered_map<std::string, PolicyValue> API::GetAll()
+{
+ return PolicyManager::Instance().getAll();
+}
+
+void API::Admin::Set(const std::string& policy, const PolicyValue& value)
+{
+ // TODO(Sangwan): Get admin name from peer PID
+ PolicyManager::Instance().set(policy, value, "admin");
+}
+
+void API::Admin::Enroll(const std::string& admin)
+{
+ PolicyManager::Instance().enroll(admin);
+}
+
+void API::Admin::Disenroll(const std::string& admin)
+{
+ PolicyManager::Instance().disenroll(admin);
+}
+
+std::vector<std::string> API::Admin::GetAll()
+{
+ return PolicyManager::Instance().getAdmins();
+}
+
+} // namespace policy
+} // namespace vist
#pragma once
-#include <vist/policy/sdk/policy-value.hpp>
+#include <vist/sdk/policy-value.hpp>
#include <string>
#include <unordered_map>
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include <vist/policy/api.hpp>
-
-#include "policy-manager.hpp"
-
-namespace vist {
-namespace policy {
-
-PolicyValue API::Get(const std::string& policy)
-{
- return PolicyManager::Instance().get(policy);
-}
-
-std::unordered_map<std::string, PolicyValue> API::GetAll()
-{
- return PolicyManager::Instance().getAll();
-}
-
-void API::Admin::Set(const std::string& policy, const PolicyValue& value)
-{
- // TODO(Sangwan): Get admin name from peer PID
- PolicyManager::Instance().set(policy, value, "admin");
-}
-
-void API::Admin::Enroll(const std::string& admin)
-{
- PolicyManager::Instance().enroll(admin);
-}
-
-void API::Admin::Disenroll(const std::string& admin)
-{
- PolicyManager::Instance().disenroll(admin);
-}
-
-std::vector<std::string> API::Admin::GetAll()
-{
- return PolicyManager::Instance().getAdmins();
-}
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-#include <string>
-
-namespace vist {
-namespace policy {
-namespace schema {
-
-struct Admin {
- std::string name;
-};
-
-struct PolicyActivated {
- std::string admin;
- std::string policy;
- int value = -1;
-};
-
-struct PolicyDefinition {
- std::string name;
- int ivalue = -1;
-};
-
-} // namespace schema
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include "policy-loader.hpp"
-
-namespace vist {
-namespace policy {
-
-PolicyProvider* PolicyLoader::load(const std::string& path)
-{
- PluginLoader loader(path);
- PolicyProvider::FactoryType factory = nullptr;
- loader.load(PolicyProvider::getFactoryName(), factory);
- if (factory == nullptr)
- std::runtime_error("Failed to load symbol. " + PolicyProvider::getFactoryName());
-
- auto provider = (*factory)();
- if (provider == nullptr)
- std::runtime_error("Failed to make provider. " + PolicyProvider::getFactoryName());
-
- return provider;
-}
-
-PluginLoader::PluginLoader(const std::string& path, int flag)
- : handle(::dlopen(path.c_str(), flag), [](void*)->int{return 0;})
-// Cleaning object after dlclose() makes SEGFAULT.
-// TODO: Sync dynamic loading's life-cycle with program.(PluginManager)
-// : handle(::dlopen(path.c_str(), flag), ::dlclose)
-{
- if (handle == nullptr)
- throw std::invalid_argument("Failed to open: " + path);
-}
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-provider.hpp>
-
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-#include <dlfcn.h>
-
-namespace vist {
-namespace policy {
-
-struct PolicyLoader final {
- static PolicyProvider* load(const std::string& path);
-};
-
-class PluginLoader final {
-public:
- explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY);
-
- template<typename T>
- void load(const std::string& name, T& symbol);
-
-private:
- using Handle = std::unique_ptr<void, int(*)(void*)>;
- Handle handle;
-};
-
-template<typename T>
-void PluginLoader::load(const std::string& name, T& symbol)
-{
- symbol = reinterpret_cast<T>(::dlsym(handle.get(), name.c_str()));
- if (symbol == nullptr)
- throw std::runtime_error("Failed to load: " + name);
-}
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include "policy-manager.hpp"
-#include "policy-loader.hpp"
-
-#include <vist/logger.hpp>
-
-#include <klay/filesystem.h>
-
-namespace vist {
-namespace policy {
-
-PolicyManager::PolicyManager() : storage(DB_PATH)
-{
- loadProviders(PLUGIN_INSTALL_DIR);
- int cnt = loadPolicies();
- INFO(VIST) << std::to_string(cnt) << "-policies loaded";
-}
-
-std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
-{
- INFO(VIST) << "Load policies from :" << path;
- klay::File dir(path);
- if (!dir.exists() || !dir.isDirectory())
- throw std::invalid_argument("Plugin directory is wrong.: " + path);
-
- int passed = 0, failed = 0;
- klay::DirectoryIterator end;
- for (klay::DirectoryIterator iter(path); iter != end; ++iter) {
- if (!iter->isFile())
- continue;
-
- try {
- auto provider = PolicyLoader::load(iter->getPath());
- DEBUG(VIST) << "Loaded provider: " << provider->getName();
-
- bool exist = false;
- for (const auto& p : this->providers) {
- if (p->getName() == provider->getName()) {
- exist = true;
- break;
- }
- }
-
- if (!exist)
- this->providers.emplace_back(std::move(provider));
- } catch (const std::exception& e) {
- ++failed;
- ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what();
- continue;
- }
-
- ++passed;
- }
-
- INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed;
- return std::make_pair(passed, failed);
-}
-
-int PolicyManager::loadPolicies()
-{
- bool changed = false;
-
- /// Make policy-provider map for performance
- for (const auto& provider : providers) {
- for (const auto& pair : provider->policies) {
- policies[pair.first] = provider->getName();
-
- /// Check the policy is defined on policy-storage
- if (!storage.exists(pair.first)) {
- INFO(VIST) << "Define policy: " << pair.first;
- storage.define(pair.first, pair.second->getInitial().value);
- changed = true;
- }
- }
- }
-
- if (changed)
- storage.syncPolicyDefinition();
-
- return policies.size();
-}
-
-void PolicyManager::enroll(const std::string& admin)
-{
- this->storage.enroll(admin);
-}
-
-void PolicyManager::disenroll(const std::string& admin)
-{
- this->storage.disenroll(admin);
-}
-
-void PolicyManager::set(const std::string& policy,
- const PolicyValue& value,
- const std::string& admin)
-{
- if (this->policies.find(policy) == this->policies.end())
- std::runtime_error("Not exist policy: " + policy);
-
- storage.update(admin, policy, value);
-
- for (auto& p : providers) {
- if (p->getName() != this->policies[policy])
- continue;
-
- if (p->policies.find(policy) != p->policies.end()) {
- p->policies[policy]->set(value);
- return;
- }
- }
-}
-
-PolicyValue PolicyManager::get(const std::string& policy)
-{
- return storage.strictest(policy);
-}
-
-std::unordered_map<std::string, PolicyValue> PolicyManager::getAll()
-{
- return storage.strictest();
-}
-
-std::vector<std::string> PolicyManager::getAdmins()
-{
- return storage.getAdmins();
-}
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-provider.hpp>
-#include <vist/policy/sdk/policy-value.hpp>
-
-#include "policy-storage.hpp"
-
-#include <exception>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <gtest/gtest_prod.h>
-
-namespace vist {
-namespace policy {
-
-class PolicyManager final {
-public:
- PolicyManager(const PolicyManager&) = delete;
- PolicyManager& operator=(const PolicyManager&) = delete;
-
- PolicyManager(PolicyManager&&) = delete;
- PolicyManager& operator=(PolicyManager&&) = delete;
-
- static PolicyManager& Instance()
- {
- static PolicyManager manager;
- return manager;
- }
-
- void enroll(const std::string& admin);
- void disenroll(const std::string& admin);
-
- void set(const std::string& policy,
- const PolicyValue& value,
- const std::string& admin);
- PolicyValue get(const std::string& policy);
- std::unordered_map<std::string, PolicyValue> getAll();
-
- std::vector<std::string> getAdmins();
-
-private:
- explicit PolicyManager();
- ~PolicyManager() = default;
-
- std::pair<int, int> loadProviders(const std::string& path);
- int loadPolicies();
-
- PolicyStorage storage;
- std::vector<std::unique_ptr<PolicyProvider>> providers;
-
- /// Policy-Provider
- std::unordered_map<std::string, std::string> policies;
-
- FRIEND_TEST(PolicyCoreTests, policy_loader);
-};
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include "policy-storage.hpp"
-
-#include <vist/logger.hpp>
-#include <vist/query-builder.hpp>
-
-#include <klay/db/column.h>
-#include <klay/db/statement.h>
-#include <klay/exception.h>
-
-#include <algorithm>
-#include <fstream>
-
-using namespace vist::tsqb;
-using namespace vist::policy::schema;
-
-namespace {
-
-auto adminTable = make_table("ADMIN", make_column("name", &Admin::name));
-
-auto polActivatedTable = make_table("POLICY_ACTIVATED",
- make_column("admin", &PolicyActivated::admin),
- make_column("policy", &PolicyActivated::policy),
- make_column("value", &PolicyActivated::value));
-
-auto polDefinitionTable = make_table("POLICY_DEFINITION",
- make_column("name", &PolicyDefinition::name),
- make_column("ivalue", &PolicyDefinition::ivalue));
-
-const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR;
-const std::string SCRIPT_CREATE_SCHEMA = "create-schema";
-
-} // anonymous namespace
-
-namespace vist {
-namespace policy {
-
-PolicyStorage::PolicyStorage(const std::string& path) :
- database(std::make_shared<database::Connection>(path,
- database::Connection::ReadWrite |
- database::Connection::Create))
-{
- database->exec("PRAGMA foreign_keys = ON;");
- database->exec(getScript(SCRIPT_CREATE_SCHEMA));
-
- sync();
-}
-
-void PolicyStorage::sync()
-{
- DEBUG(VIST) << "Sync policy storage to cache object.";
- syncAdmin();
- syncPolicyActivated();
- syncPolicyDefinition();
-}
-
-void PolicyStorage::syncPolicyDefinition()
-{
- this->definitions.clear();
- std::string query = polDefinitionTable.selectAll();
- database::Statement stmt(*database, query);
-
- while (stmt.step()) {
- PolicyDefinition pd;
- pd.name = std::string(stmt.getColumn(0));
- pd.ivalue = stmt.getColumn(1);
- DEBUG(VIST) << "Defined policy:" << pd.name;
- this->definitions.emplace(pd.name, std::move(pd));
- }
-
- DEBUG(VIST) << definitions.size() << "- policies synced.";
-}
-
-void PolicyStorage::syncAdmin()
-{
- this->admins.clear();
- std::string query = adminTable.selectAll();
- database::Statement stmt(*database, query);
-
- while (stmt.step())
- this->admins.emplace_back(std::string(stmt.getColumn(0)));
-
- DEBUG(VIST) << admins.size() << "-admins synced.";
-}
-
-void PolicyStorage::syncPolicyActivated()
-{
- this->activatedPolicies.clear();
- std::string query = polActivatedTable.selectAll();
- database::Statement stmt(*database, query);
-
- while (stmt.step()) {
- PolicyActivated pa;
- pa.admin = std::string(stmt.getColumn(0));
- pa.policy = std::string(stmt.getColumn(1));
- pa.value = stmt.getColumn(2);
- this->activatedPolicies.emplace(pa.policy, std::move(pa));
- }
-
- DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced.";
-}
-
-std::string PolicyStorage::getScript(const std::string& name)
-{
- std::string path = SCRIPT_BASE + "/" + name + ".sql";
- std::ifstream is(path);
- if (is.fail())
- throw std::invalid_argument("Failed to open script: " + path);
-
- std::istreambuf_iterator<char> begin(is), end;
- auto content = std::string(begin, end);
- if (content.empty())
- throw std::runtime_error("Failed to read script: " + path);
-
- return content;
-}
-
-void PolicyStorage::define(const std::string& policy, int ivalue)
-{
- if (definitions.find(policy) != definitions.end()) {
- INFO(VIST) << "Policy is already defined: " << policy;
- return;
- }
-
- PolicyDefinition pd;
- pd.name = policy;
- pd.ivalue = ivalue;
-
- std::string query = polDefinitionTable.insert(&PolicyDefinition::name,
- &PolicyDefinition::ivalue);
- database::Statement stmt(*database, query);
- stmt.bind(1, pd.name);
- stmt.bind(2, pd.ivalue);
- if (!stmt.exec())
- throw std::runtime_error("Failed to define policy: " + pd.name);
-}
-
-void PolicyStorage::enroll(const std::string& name)
-{
- INFO(VIST) << "Enroll admin: " << name;
- if (std::find(admins.begin(), admins.end(), name) != admins.end()) {
- ERROR(VIST) << "Admin is aleady enrolled.: " << name;
- return;
- }
-
- std::string query = adminTable.insert(&Admin::name);
- DEBUG(VIST) << "Enroll admin query statement: " << query;
- database::Statement stmt(*database, query);
- stmt.bind(1, name);
- if (!stmt.exec())
- throw std::runtime_error("Failed to enroll admin: " + name);
-
- admins.push_back(name);
- /// PolicyActivated is triggered by enrolling admin.
- syncPolicyActivated();
-
- int count = activatedPolicies.size() / admins.size();
- INFO(VIST) << "Admin[" << name << "] manages "
- << std::to_string(count) << "-policies.";
-}
-
-void PolicyStorage::disenroll(const std::string& name)
-{
- INFO(VIST) << "Disenroll admin: " << name;
- auto iter = std::find(admins.begin(), admins.end(), name);
- if (iter == admins.end()) {
- ERROR(VIST) << "Not exist admin: " << name;
- return;
- } else {
- admins.erase(iter);
- }
-
- std::string query = adminTable.remove().where(expr(&Admin::name) == name);
- database::Statement stmt(*database, query);
- stmt.bind(1, name);
- if (!stmt.exec())
- throw std::runtime_error("Failed to disenroll admin: " + name);
-}
-
-void PolicyStorage::update(const std::string& admin,
- const std::string& policy,
- const PolicyValue& value)
-{
- DEBUG(VIST) << "Policy-update is called by admin: " << admin
- << ", about: " << policy << ", value: " << std::to_string(value);
-
- if (std::find(admins.begin(), admins.end(), admin) == admins.end())
- throw std::runtime_error("Not exist admin: " + admin);
-
- if (definitions.find(policy) == definitions.end())
- throw std::runtime_error("Not exist policy: " + policy);
-
- int policyValue = value;
- std::string query = polActivatedTable.update(&PolicyActivated::value)
- .where(expr(&PolicyActivated::admin) == admin &&
- expr(&PolicyActivated::policy) == policy);
- database::Statement stmt(*database, query);
- stmt.bind(1, policyValue);
- stmt.bind(2, admin);
- stmt.bind(3, policy);
- if (!stmt.exec())
- throw runtime::Exception("Failed to update policy:" + policy);
-
- syncPolicyActivated();
-}
-
-PolicyValue PolicyStorage::strictest(const std::string& policy)
-{
- if (definitions.find(policy) == definitions.end())
- throw std::runtime_error("Not exist policy: " + policy);
-
- // There is no enrolled admins.
- if (activatedPolicies.size() == 0)
- return PolicyValue(definitions[policy].ivalue);
-
- std::shared_ptr<PolicyValue> strictestPtr = nullptr;
- auto range = activatedPolicies.equal_range(policy);
- for (auto iter = range.first; iter != range.second; iter++) {
- int value = iter->second.value;
- if (strictestPtr == nullptr)
- strictestPtr = std::make_shared<PolicyValue>(value);
- else
- strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value;
-
- DEBUG(VIST) << "The strictest of policy[" << policy
- << "] : " + std::to_string(strictestPtr->value);
- }
-
- if (strictestPtr == nullptr)
- throw std::runtime_error("Not exist managed policy: " + policy);
-
- return std::move(*strictestPtr);
-}
-
-std::unordered_map<std::string, PolicyValue> PolicyStorage::strictest()
-{
- std::unordered_map<std::string, PolicyValue> policies;
- for (const auto& pair : definitions) {
- std::string name = pair.first;
- auto value = this->strictest(name);
-
- policies.emplace(std::move(name), std::move(value));
- }
-
- return policies;
-}
-
-const std::vector<std::string>& PolicyStorage::getAdmins() const noexcept
-{
- return admins;
-}
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * ttp://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-value.hpp>
-
-#include "db-schema.hpp"
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include <klay/db/connection.h>
-
-namespace vist {
-namespace policy {
-
-using namespace schema;
-
-class PolicyStorage final {
-public:
- explicit PolicyStorage(const std::string& path);
-
- /// TODO(Sangwan): Consider to support lazy sync
- void sync();
-
- void syncAdmin();
- void syncPolicyActivated();
- void syncPolicyDefinition();
-
- inline bool exists(const std::string& policy) const noexcept
- {
- return definitions.find(policy) != definitions.end();
- }
-
- inline bool isActivated() const noexcept
- {
- return admins.size() > 0 && activatedPolicies.size() > 0;
- }
-
- void enroll(const std::string& admin);
- void disenroll(const std::string& admin);
-
- void define(const std::string& policy, int ivalue);
- void update(const std::string& admin,
- const std::string& policy,
- const PolicyValue& value);
-
- PolicyValue strictest(const std::string& policy);
- /// Return all strictest policy values
- std::unordered_map<std::string, PolicyValue> strictest();
-
- const std::vector<std::string>& getAdmins() const noexcept;
-
-private:
- std::string getScript(const std::string& name);
-
- std::shared_ptr<klay::database::Connection> database;
-
- /// DB Cache objects
- /// TODO(Sangwan): add locking mechanism
- std::vector<std::string> admins;
- std::unordered_map<std::string, PolicyActivated> activatedPolicies;
- std::unordered_map<std::string, PolicyDefinition> definitions;
-};
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include <gtest/gtest.h>
-
-#include <vist/policy/core/policy-manager.hpp>
-
-namespace vist {
-namespace policy {
-
-class PolicyCoreTests : public testing::Test {};
-
-TEST_F(PolicyCoreTests, policy_loader) {
- auto& manager = PolicyManager::Instance();
-
- EXPECT_TRUE(manager.providers.size() > 0);
- EXPECT_TRUE(manager.policies.size() > 0);
-}
-
-TEST_F(PolicyCoreTests, policy_set_get) {
- auto& manager = PolicyManager::Instance();
- manager.enroll("testAdmin");
- manager.set("bluetooth", PolicyValue(5), "testAdmin");
-
- auto policy = manager.get("bluetooth");
- EXPECT_EQ(policy.value, 5);
-
- manager.enroll("testAdmin1");
- manager.set("bluetooth", PolicyValue(10), "testAdmin1");
-
- /// Manager should return the strongest policy.
- policy = manager.get("bluetooth");
- EXPECT_EQ(policy.value, 5);
-
- manager.disenroll("testAdmin");
- manager.disenroll("testAdmin1");
-}
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include <gtest/gtest.h>
-
-#include <memory>
-
-#include <vist/policy/core/policy-storage.hpp>
-
-using namespace vist::policy;
-
-class PolicyStorageTests : public testing::Test {
-public:
- void SetUp() override
- {
- this->storage = std::make_shared<PolicyStorage>(DB_PATH);
- }
-
- std::shared_ptr<PolicyStorage> getStorage()
- {
- return this->storage;
- }
-
-private:
- std::shared_ptr<PolicyStorage> storage = nullptr;
-};
-
-TEST_F(PolicyStorageTests, initialize)
-{
- bool isRaised = false;
-
- try {
- // DB is maden at run-time
- PolicyStorage storage("/tmp/dummy");
- } catch (const std::exception&) {
- isRaised = true;
- }
-
- EXPECT_FALSE(isRaised);
-}
-
-TEST_F(PolicyStorageTests, enrollment)
-{
- auto storage = getStorage();
- EXPECT_FALSE(storage->isActivated());
-
- storage->enroll("testAdmin0");
- storage->enroll("testAdmin1");
- EXPECT_TRUE(storage->isActivated());
-
- storage->disenroll("testAdmin0");
- EXPECT_TRUE(storage->isActivated());
-
- storage->disenroll("testAdmin1");
- EXPECT_FALSE(storage->isActivated());
-}
-
-TEST_F(PolicyStorageTests, update)
-{
- auto storage = getStorage();
- storage->enroll("testAdmin");
-
- bool isRaised = false;
- try {
- storage->update("fakeAdmin", "bluetooth", PolicyValue(0));
- } catch (const std::exception&) {
- isRaised = true;
- }
-
- isRaised = false;
- try {
- storage->update("testAdmin", "bluetooth", PolicyValue(0));
- } catch (const std::exception&) {
- isRaised = true;
- }
- EXPECT_FALSE(isRaised);
-
- isRaised = false;
- try {
- storage->update("testAdmin", "FakePolicy", PolicyValue(0));
- } catch (const std::exception&) {
- isRaised = true;
- }
- EXPECT_TRUE(isRaised);
-
- storage->disenroll("testAdmin");
-}
-
-TEST_F(PolicyStorageTests, strictest)
-{
- auto storage = getStorage();
- storage->enroll("testAdmin0");
- storage->enroll("testAdmin1");
-
- storage->update("testAdmin0", "bluetooth", PolicyValue(3));
- storage->update("testAdmin1", "bluetooth", PolicyValue(6));
-
- bool isRaised = false;
- try {
- auto value = storage->strictest("FakePolicy");
- } catch (const std::exception&) {
- isRaised = true;
- }
- EXPECT_TRUE(isRaised);
-
- auto policy = storage->strictest("bluetooth");
- EXPECT_EQ(policy.value, 3);
-
- storage->disenroll("testAdmin0");
- storage->disenroll("testAdmin1");
-}
-
-TEST_F(PolicyStorageTests, strictest_all)
-{
- auto storage = getStorage();
- storage->enroll("testAdmin");
-
- auto policies = storage->strictest();
- EXPECT_TRUE(policies.size() > 0);
-
- storage->disenroll("testAdmin");
-}
-
-TEST_F(PolicyStorageTests, admin_list)
-{
- auto storage = getStorage();
-
- auto admins = storage->getAdmins();
- EXPECT_EQ(admins.size(), 0);
-
- storage->enroll("testAdmin1");
- admins = storage->getAdmins();
- EXPECT_EQ(admins.size(), 1);
-
- storage->enroll("testAdmin2");
- admins = storage->getAdmins();
- EXPECT_EQ(admins.size(), 2);
-
- storage->disenroll("testAdmin2");
- admins = storage->getAdmins();
- EXPECT_EQ(admins.size(), 1);
-
- storage->disenroll("testAdmin1");
- admins = storage->getAdmins();
- EXPECT_EQ(admins.size(), 0);
-}
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+#include <string>
+
+namespace vist {
+namespace policy {
+namespace schema {
+
+struct Admin {
+ std::string name;
+};
+
+struct PolicyActivated {
+ std::string admin;
+ std::string policy;
+ int value = -1;
+};
+
+struct PolicyDefinition {
+ std::string name;
+ int ivalue = -1;
+};
+
+} // namespace schema
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include "policy-loader.hpp"
+
+namespace vist {
+namespace policy {
+
+PolicyProvider* PolicyLoader::load(const std::string& path)
+{
+ PluginLoader loader(path);
+ PolicyProvider::FactoryType factory = nullptr;
+ loader.load(PolicyProvider::getFactoryName(), factory);
+ if (factory == nullptr)
+ std::runtime_error("Failed to load symbol. " + PolicyProvider::getFactoryName());
+
+ auto provider = (*factory)();
+ if (provider == nullptr)
+ std::runtime_error("Failed to make provider. " + PolicyProvider::getFactoryName());
+
+ return provider;
+}
+
+PluginLoader::PluginLoader(const std::string& path, int flag)
+ : handle(::dlopen(path.c_str(), flag), [](void*)->int{return 0;})
+// Cleaning object after dlclose() makes SEGFAULT.
+// TODO: Sync dynamic loading's life-cycle with program.(PluginManager)
+// : handle(::dlopen(path.c_str(), flag), ::dlclose)
+{
+ if (handle == nullptr)
+ throw std::invalid_argument("Failed to open: " + path);
+}
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-provider.hpp>
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <dlfcn.h>
+
+namespace vist {
+namespace policy {
+
+struct PolicyLoader final {
+ static PolicyProvider* load(const std::string& path);
+};
+
+class PluginLoader final {
+public:
+ explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY);
+
+ template<typename T>
+ void load(const std::string& name, T& symbol);
+
+private:
+ using Handle = std::unique_ptr<void, int(*)(void*)>;
+ Handle handle;
+};
+
+template<typename T>
+void PluginLoader::load(const std::string& name, T& symbol)
+{
+ symbol = reinterpret_cast<T>(::dlsym(handle.get(), name.c_str()));
+ if (symbol == nullptr)
+ throw std::runtime_error("Failed to load: " + name);
+}
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include "policy-manager.hpp"
+#include "policy-loader.hpp"
+
+#include <vist/logger.hpp>
+
+#include <klay/filesystem.h>
+
+namespace vist {
+namespace policy {
+
+PolicyManager::PolicyManager() : storage(DB_PATH)
+{
+ loadProviders(PLUGIN_INSTALL_DIR);
+ int cnt = loadPolicies();
+ INFO(VIST) << std::to_string(cnt) << "-policies loaded";
+}
+
+std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
+{
+ INFO(VIST) << "Load policies from :" << path;
+ klay::File dir(path);
+ if (!dir.exists() || !dir.isDirectory())
+ throw std::invalid_argument("Plugin directory is wrong.: " + path);
+
+ int passed = 0, failed = 0;
+ klay::DirectoryIterator end;
+ for (klay::DirectoryIterator iter(path); iter != end; ++iter) {
+ if (!iter->isFile())
+ continue;
+
+ try {
+ auto provider = PolicyLoader::load(iter->getPath());
+ DEBUG(VIST) << "Loaded provider: " << provider->getName();
+
+ bool exist = false;
+ for (const auto& p : this->providers) {
+ if (p->getName() == provider->getName()) {
+ exist = true;
+ break;
+ }
+ }
+
+ if (!exist)
+ this->providers.emplace_back(std::move(provider));
+ } catch (const std::exception& e) {
+ ++failed;
+ ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what();
+ continue;
+ }
+
+ ++passed;
+ }
+
+ INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed;
+ return std::make_pair(passed, failed);
+}
+
+int PolicyManager::loadPolicies()
+{
+ bool changed = false;
+
+ /// Make policy-provider map for performance
+ for (const auto& provider : providers) {
+ for (const auto& pair : provider->policies) {
+ policies[pair.first] = provider->getName();
+
+ /// Check the policy is defined on policy-storage
+ if (!storage.exists(pair.first)) {
+ INFO(VIST) << "Define policy: " << pair.first;
+ storage.define(pair.first, pair.second->getInitial().value);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed)
+ storage.syncPolicyDefinition();
+
+ return policies.size();
+}
+
+void PolicyManager::enroll(const std::string& admin)
+{
+ this->storage.enroll(admin);
+}
+
+void PolicyManager::disenroll(const std::string& admin)
+{
+ this->storage.disenroll(admin);
+}
+
+void PolicyManager::set(const std::string& policy,
+ const PolicyValue& value,
+ const std::string& admin)
+{
+ if (this->policies.find(policy) == this->policies.end())
+ std::runtime_error("Not exist policy: " + policy);
+
+ storage.update(admin, policy, value);
+
+ for (auto& p : providers) {
+ if (p->getName() != this->policies[policy])
+ continue;
+
+ if (p->policies.find(policy) != p->policies.end()) {
+ p->policies[policy]->set(value);
+ return;
+ }
+ }
+}
+
+PolicyValue PolicyManager::get(const std::string& policy)
+{
+ return storage.strictest(policy);
+}
+
+std::unordered_map<std::string, PolicyValue> PolicyManager::getAll()
+{
+ return storage.strictest();
+}
+
+std::vector<std::string> PolicyManager::getAdmins()
+{
+ return storage.getAdmins();
+}
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-provider.hpp>
+#include <vist/sdk/policy-value.hpp>
+
+#include "policy-storage.hpp"
+
+#include <exception>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <gtest/gtest_prod.h>
+
+namespace vist {
+namespace policy {
+
+class PolicyManager final {
+public:
+ PolicyManager(const PolicyManager&) = delete;
+ PolicyManager& operator=(const PolicyManager&) = delete;
+
+ PolicyManager(PolicyManager&&) = delete;
+ PolicyManager& operator=(PolicyManager&&) = delete;
+
+ static PolicyManager& Instance()
+ {
+ static PolicyManager manager;
+ return manager;
+ }
+
+ void enroll(const std::string& admin);
+ void disenroll(const std::string& admin);
+
+ void set(const std::string& policy,
+ const PolicyValue& value,
+ const std::string& admin);
+ PolicyValue get(const std::string& policy);
+ std::unordered_map<std::string, PolicyValue> getAll();
+
+ std::vector<std::string> getAdmins();
+
+private:
+ explicit PolicyManager();
+ ~PolicyManager() = default;
+
+ std::pair<int, int> loadProviders(const std::string& path);
+ int loadPolicies();
+
+ PolicyStorage storage;
+ std::vector<std::unique_ptr<PolicyProvider>> providers;
+
+ /// Policy-Provider
+ std::unordered_map<std::string, std::string> policies;
+
+ FRIEND_TEST(PolicyCoreTests, policy_loader);
+};
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include "policy-storage.hpp"
+
+#include <vist/logger.hpp>
+#include <vist/query-builder.hpp>
+
+#include <klay/db/column.h>
+#include <klay/db/statement.h>
+#include <klay/exception.h>
+
+#include <algorithm>
+#include <fstream>
+
+using namespace vist::tsqb;
+using namespace vist::policy::schema;
+
+namespace {
+
+auto adminTable = make_table("ADMIN", make_column("name", &Admin::name));
+
+auto polActivatedTable = make_table("POLICY_ACTIVATED",
+ make_column("admin", &PolicyActivated::admin),
+ make_column("policy", &PolicyActivated::policy),
+ make_column("value", &PolicyActivated::value));
+
+auto polDefinitionTable = make_table("POLICY_DEFINITION",
+ make_column("name", &PolicyDefinition::name),
+ make_column("ivalue", &PolicyDefinition::ivalue));
+
+const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR;
+const std::string SCRIPT_CREATE_SCHEMA = "create-schema";
+
+} // anonymous namespace
+
+namespace vist {
+namespace policy {
+
+PolicyStorage::PolicyStorage(const std::string& path) :
+ database(std::make_shared<database::Connection>(path,
+ database::Connection::ReadWrite |
+ database::Connection::Create))
+{
+ database->exec("PRAGMA foreign_keys = ON;");
+ database->exec(getScript(SCRIPT_CREATE_SCHEMA));
+
+ sync();
+}
+
+void PolicyStorage::sync()
+{
+ DEBUG(VIST) << "Sync policy storage to cache object.";
+ syncAdmin();
+ syncPolicyActivated();
+ syncPolicyDefinition();
+}
+
+void PolicyStorage::syncPolicyDefinition()
+{
+ this->definitions.clear();
+ std::string query = polDefinitionTable.selectAll();
+ database::Statement stmt(*database, query);
+
+ while (stmt.step()) {
+ PolicyDefinition pd;
+ pd.name = std::string(stmt.getColumn(0));
+ pd.ivalue = stmt.getColumn(1);
+ DEBUG(VIST) << "Defined policy:" << pd.name;
+ this->definitions.emplace(pd.name, std::move(pd));
+ }
+
+ DEBUG(VIST) << definitions.size() << "- policies synced.";
+}
+
+void PolicyStorage::syncAdmin()
+{
+ this->admins.clear();
+ std::string query = adminTable.selectAll();
+ database::Statement stmt(*database, query);
+
+ while (stmt.step())
+ this->admins.emplace_back(std::string(stmt.getColumn(0)));
+
+ DEBUG(VIST) << admins.size() << "-admins synced.";
+}
+
+void PolicyStorage::syncPolicyActivated()
+{
+ this->activatedPolicies.clear();
+ std::string query = polActivatedTable.selectAll();
+ database::Statement stmt(*database, query);
+
+ while (stmt.step()) {
+ PolicyActivated pa;
+ pa.admin = std::string(stmt.getColumn(0));
+ pa.policy = std::string(stmt.getColumn(1));
+ pa.value = stmt.getColumn(2);
+ this->activatedPolicies.emplace(pa.policy, std::move(pa));
+ }
+
+ DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced.";
+}
+
+std::string PolicyStorage::getScript(const std::string& name)
+{
+ std::string path = SCRIPT_BASE + "/" + name + ".sql";
+ std::ifstream is(path);
+ if (is.fail())
+ throw std::invalid_argument("Failed to open script: " + path);
+
+ std::istreambuf_iterator<char> begin(is), end;
+ auto content = std::string(begin, end);
+ if (content.empty())
+ throw std::runtime_error("Failed to read script: " + path);
+
+ return content;
+}
+
+void PolicyStorage::define(const std::string& policy, int ivalue)
+{
+ if (definitions.find(policy) != definitions.end()) {
+ INFO(VIST) << "Policy is already defined: " << policy;
+ return;
+ }
+
+ PolicyDefinition pd;
+ pd.name = policy;
+ pd.ivalue = ivalue;
+
+ std::string query = polDefinitionTable.insert(&PolicyDefinition::name,
+ &PolicyDefinition::ivalue);
+ database::Statement stmt(*database, query);
+ stmt.bind(1, pd.name);
+ stmt.bind(2, pd.ivalue);
+ if (!stmt.exec())
+ throw std::runtime_error("Failed to define policy: " + pd.name);
+}
+
+void PolicyStorage::enroll(const std::string& name)
+{
+ INFO(VIST) << "Enroll admin: " << name;
+ if (std::find(admins.begin(), admins.end(), name) != admins.end()) {
+ ERROR(VIST) << "Admin is aleady enrolled.: " << name;
+ return;
+ }
+
+ std::string query = adminTable.insert(&Admin::name);
+ DEBUG(VIST) << "Enroll admin query statement: " << query;
+ database::Statement stmt(*database, query);
+ stmt.bind(1, name);
+ if (!stmt.exec())
+ throw std::runtime_error("Failed to enroll admin: " + name);
+
+ admins.push_back(name);
+ /// PolicyActivated is triggered by enrolling admin.
+ syncPolicyActivated();
+
+ int count = activatedPolicies.size() / admins.size();
+ INFO(VIST) << "Admin[" << name << "] manages "
+ << std::to_string(count) << "-policies.";
+}
+
+void PolicyStorage::disenroll(const std::string& name)
+{
+ INFO(VIST) << "Disenroll admin: " << name;
+ auto iter = std::find(admins.begin(), admins.end(), name);
+ if (iter == admins.end()) {
+ ERROR(VIST) << "Not exist admin: " << name;
+ return;
+ } else {
+ admins.erase(iter);
+ }
+
+ std::string query = adminTable.remove().where(expr(&Admin::name) == name);
+ database::Statement stmt(*database, query);
+ stmt.bind(1, name);
+ if (!stmt.exec())
+ throw std::runtime_error("Failed to disenroll admin: " + name);
+}
+
+void PolicyStorage::update(const std::string& admin,
+ const std::string& policy,
+ const PolicyValue& value)
+{
+ DEBUG(VIST) << "Policy-update is called by admin: " << admin
+ << ", about: " << policy << ", value: " << std::to_string(value);
+
+ if (std::find(admins.begin(), admins.end(), admin) == admins.end())
+ throw std::runtime_error("Not exist admin: " + admin);
+
+ if (definitions.find(policy) == definitions.end())
+ throw std::runtime_error("Not exist policy: " + policy);
+
+ int policyValue = value;
+ std::string query = polActivatedTable.update(&PolicyActivated::value)
+ .where(expr(&PolicyActivated::admin) == admin &&
+ expr(&PolicyActivated::policy) == policy);
+ database::Statement stmt(*database, query);
+ stmt.bind(1, policyValue);
+ stmt.bind(2, admin);
+ stmt.bind(3, policy);
+ if (!stmt.exec())
+ throw runtime::Exception("Failed to update policy:" + policy);
+
+ syncPolicyActivated();
+}
+
+PolicyValue PolicyStorage::strictest(const std::string& policy)
+{
+ if (definitions.find(policy) == definitions.end())
+ throw std::runtime_error("Not exist policy: " + policy);
+
+ // There is no enrolled admins.
+ if (activatedPolicies.size() == 0)
+ return PolicyValue(definitions[policy].ivalue);
+
+ std::shared_ptr<PolicyValue> strictestPtr = nullptr;
+ auto range = activatedPolicies.equal_range(policy);
+ for (auto iter = range.first; iter != range.second; iter++) {
+ int value = iter->second.value;
+ if (strictestPtr == nullptr)
+ strictestPtr = std::make_shared<PolicyValue>(value);
+ else
+ strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value;
+
+ DEBUG(VIST) << "The strictest of policy[" << policy
+ << "] : " + std::to_string(strictestPtr->value);
+ }
+
+ if (strictestPtr == nullptr)
+ throw std::runtime_error("Not exist managed policy: " + policy);
+
+ return std::move(*strictestPtr);
+}
+
+std::unordered_map<std::string, PolicyValue> PolicyStorage::strictest()
+{
+ std::unordered_map<std::string, PolicyValue> policies;
+ for (const auto& pair : definitions) {
+ std::string name = pair.first;
+ auto value = this->strictest(name);
+
+ policies.emplace(std::move(name), std::move(value));
+ }
+
+ return policies;
+}
+
+const std::vector<std::string>& PolicyStorage::getAdmins() const noexcept
+{
+ return admins;
+}
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * ttp://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-value.hpp>
+
+#include "db-schema.hpp"
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include <klay/db/connection.h>
+
+namespace vist {
+namespace policy {
+
+using namespace schema;
+
+class PolicyStorage final {
+public:
+ explicit PolicyStorage(const std::string& path);
+
+ /// TODO(Sangwan): Consider to support lazy sync
+ void sync();
+
+ void syncAdmin();
+ void syncPolicyActivated();
+ void syncPolicyDefinition();
+
+ inline bool exists(const std::string& policy) const noexcept
+ {
+ return definitions.find(policy) != definitions.end();
+ }
+
+ inline bool isActivated() const noexcept
+ {
+ return admins.size() > 0 && activatedPolicies.size() > 0;
+ }
+
+ void enroll(const std::string& admin);
+ void disenroll(const std::string& admin);
+
+ void define(const std::string& policy, int ivalue);
+ void update(const std::string& admin,
+ const std::string& policy,
+ const PolicyValue& value);
+
+ PolicyValue strictest(const std::string& policy);
+ /// Return all strictest policy values
+ std::unordered_map<std::string, PolicyValue> strictest();
+
+ const std::vector<std::string>& getAdmins() const noexcept;
+
+private:
+ std::string getScript(const std::string& name);
+
+ std::shared_ptr<klay::database::Connection> database;
+
+ /// DB Cache objects
+ /// TODO(Sangwan): add locking mechanism
+ std::vector<std::string> admins;
+ std::unordered_map<std::string, PolicyActivated> activatedPolicies;
+ std::unordered_map<std::string, PolicyDefinition> definitions;
+};
+
+} // namespace policy
+} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-value.hpp>
-
-#include <string>
-#include <stdexcept>
-
-namespace vist {
-namespace policy {
-
-class PolicyModel {
-public:
- explicit PolicyModel(std::string name, PolicyValue initial) noexcept :
- name(std::move(name)), initial(std::move(initial)) {}
- virtual ~PolicyModel() = default;
-
- PolicyModel(const PolicyModel&) = delete;
- PolicyModel& operator=(const PolicyModel&) = delete;
-
- PolicyModel(PolicyModel&&) = default;
- PolicyModel& operator=(PolicyModel&&) = default;
-
- inline void set(const PolicyValue& value)
- {
- auto rollback = current;
- current = value;
- ready = true;
-
- try {
- this->onChanged(value);
- } catch (const std::exception& e) {
- current = rollback;
- ready = false;
- std::rethrow_exception(std::current_exception());
- }
- }
-
- inline const PolicyValue& get() const
- {
- if (!ready)
- throw std::runtime_error("Policy value should be set once before use.");
-
- return current;
- }
-
- virtual void onChanged(const PolicyValue& value) = 0;
-
- const std::string& getName() const noexcept { return name; }
- const PolicyValue& getInitial() const noexcept { return initial; }
-
-protected:
- std::string name;
- PolicyValue initial;
- PolicyValue current;
- bool ready = false;
-};
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-#include <vist/policy/sdk/policy-model.hpp>
-
-#include <cstddef>
-#include <memory>
-#include <unordered_map>
-
-namespace vist {
-namespace policy {
-
-class PolicyProvider {
-public:
- using FactoryType = PolicyProvider* (*)();
-
- explicit PolicyProvider(std::string name) noexcept : name(std::move(name)) {}
- virtual ~PolicyProvider() = default;
-
- inline void add(const std::shared_ptr<PolicyModel>& policy)
- {
- policies[policy->getName()] = policy;
- }
-
- inline const std::string& getName() const noexcept { return name; }
- static const std::string& getFactoryName() noexcept
- {
- static std::string name = "PolicyFactory";
- return name;
- }
-
- inline std::size_t size() const noexcept { return policies.size(); }
-
-private:
- std::string name;
- std::unordered_map<std::string, std::shared_ptr<PolicyModel>> policies;
-
- friend class PolicyManager;
-};
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#pragma once
-
-namespace vist {
-namespace policy {
-
-// TODO: Support various value type
-struct PolicyValue final {
- explicit PolicyValue(int value) noexcept : value(value) {}
- explicit PolicyValue() noexcept = default;
- ~PolicyValue() = default;
-
- PolicyValue(const PolicyValue&) noexcept = default;
- PolicyValue& operator=(const PolicyValue&) noexcept = default;
-
- PolicyValue(PolicyValue&&) noexcept = default;
- PolicyValue& operator=(PolicyValue&&) noexcept = default;
-
- PolicyValue& operator=(int val) {
- value = val;
- return *this;
- }
-
- operator int() const { return value; }
- bool operator==(const PolicyValue& rhs) const { return value == rhs.value; }
- bool operator!=(const PolicyValue& rhs) const { return value != rhs.value; }
- bool operator<(const PolicyValue& rhs) const { return value < rhs.value; }
-
- int value = -1;
-};
-
-} // namespace policy
-} // namespace vist
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include <gtest/gtest.h>
-
-#include <vist/policy/sdk/policy-model.hpp>
-#include <vist/policy/sdk/policy-provider.hpp>
-
-#include <exception>
-
-namespace {
- int g_value = -1;
-} // anonymous namespace
-
-using namespace vist::policy;
-
-class PolicySDKTests : public testing::Test {};
-
-class TestPolicyModel : public PolicyModel {
-public:
- TestPolicyModel() : PolicyModel("test_policy", PolicyValue(1)) {}
-
- virtual void onChanged(const PolicyValue& value)
- {
- g_value = value;
- }
-};
-
-class TestPolicyModelFailed : public PolicyModel {
-public:
- TestPolicyModelFailed() : PolicyModel("test_policy_failed", PolicyValue(1)) {}
-
- virtual void onChanged(const PolicyValue& value)
- {
- throw std::runtime_error("Intended exception for test.");
- }
-};
-
-TEST_F(PolicySDKTests, policy_model)
-{
- TestPolicyModel policy;
-
- EXPECT_EQ(policy.getName(), "test_policy");
- EXPECT_EQ(policy.getInitial(), 1);
-
- // Policy value should be set once before use
- bool isRaised = false;
- try {
- auto value = policy.get();
- } catch (const std::exception&) {
- isRaised = true;
- }
-
- EXPECT_TRUE(isRaised);
-
- policy.set(PolicyValue(3));
- EXPECT_EQ(3, g_value);
- EXPECT_EQ(3, policy.get());
-}
-
-TEST_F(PolicySDKTests, policy_model_failed)
-{
- TestPolicyModelFailed policy;
-
- EXPECT_EQ(policy.getName(), "test_policy_failed");
- EXPECT_EQ(policy.getInitial(), 1);
-
- bool isRaised = true;
- try {
- policy.set(PolicyValue(3));
- } catch (const std::exception&) {
- isRaised = true;
- }
-
- EXPECT_TRUE(isRaised);
-}
-
-TEST_F(PolicySDKTests, policy_provider)
-{
- PolicyProvider provider("testProvider");
- provider.add(std::make_shared<TestPolicyModel>());
- provider.add(std::make_shared<TestPolicyModelFailed>());
-
- EXPECT_EQ(2, provider.size());
-}
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include <gtest/gtest.h>
+
+#include <vist/policy/policy-manager.hpp>
+
+namespace vist {
+namespace policy {
+
+class PolicyCoreTests : public testing::Test {};
+
+TEST_F(PolicyCoreTests, policy_loader) {
+ auto& manager = PolicyManager::Instance();
+
+ EXPECT_TRUE(manager.providers.size() > 0);
+ EXPECT_TRUE(manager.policies.size() > 0);
+}
+
+TEST_F(PolicyCoreTests, policy_set_get) {
+ auto& manager = PolicyManager::Instance();
+ manager.enroll("testAdmin");
+ manager.set("bluetooth", PolicyValue(5), "testAdmin");
+
+ auto policy = manager.get("bluetooth");
+ EXPECT_EQ(policy.value, 5);
+
+ manager.enroll("testAdmin1");
+ manager.set("bluetooth", PolicyValue(10), "testAdmin1");
+
+ /// Manager should return the strongest policy.
+ policy = manager.get("bluetooth");
+ EXPECT_EQ(policy.value, 5);
+
+ manager.disenroll("testAdmin");
+ manager.disenroll("testAdmin1");
+}
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+#include <vist/policy/policy-storage.hpp>
+
+using namespace vist::policy;
+
+class PolicyStorageTests : public testing::Test {
+public:
+ void SetUp() override
+ {
+ this->storage = std::make_shared<PolicyStorage>(DB_PATH);
+ }
+
+ std::shared_ptr<PolicyStorage> getStorage()
+ {
+ return this->storage;
+ }
+
+private:
+ std::shared_ptr<PolicyStorage> storage = nullptr;
+};
+
+TEST_F(PolicyStorageTests, initialize)
+{
+ bool isRaised = false;
+
+ try {
+ // DB is maden at run-time
+ PolicyStorage storage("/tmp/dummy");
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+
+ EXPECT_FALSE(isRaised);
+}
+
+TEST_F(PolicyStorageTests, enrollment)
+{
+ auto storage = getStorage();
+ EXPECT_FALSE(storage->isActivated());
+
+ storage->enroll("testAdmin0");
+ storage->enroll("testAdmin1");
+ EXPECT_TRUE(storage->isActivated());
+
+ storage->disenroll("testAdmin0");
+ EXPECT_TRUE(storage->isActivated());
+
+ storage->disenroll("testAdmin1");
+ EXPECT_FALSE(storage->isActivated());
+}
+
+TEST_F(PolicyStorageTests, update)
+{
+ auto storage = getStorage();
+ storage->enroll("testAdmin");
+
+ bool isRaised = false;
+ try {
+ storage->update("fakeAdmin", "bluetooth", PolicyValue(0));
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+
+ isRaised = false;
+ try {
+ storage->update("testAdmin", "bluetooth", PolicyValue(0));
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+ EXPECT_FALSE(isRaised);
+
+ isRaised = false;
+ try {
+ storage->update("testAdmin", "FakePolicy", PolicyValue(0));
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+ EXPECT_TRUE(isRaised);
+
+ storage->disenroll("testAdmin");
+}
+
+TEST_F(PolicyStorageTests, strictest)
+{
+ auto storage = getStorage();
+ storage->enroll("testAdmin0");
+ storage->enroll("testAdmin1");
+
+ storage->update("testAdmin0", "bluetooth", PolicyValue(3));
+ storage->update("testAdmin1", "bluetooth", PolicyValue(6));
+
+ bool isRaised = false;
+ try {
+ auto value = storage->strictest("FakePolicy");
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+ EXPECT_TRUE(isRaised);
+
+ auto policy = storage->strictest("bluetooth");
+ EXPECT_EQ(policy.value, 3);
+
+ storage->disenroll("testAdmin0");
+ storage->disenroll("testAdmin1");
+}
+
+TEST_F(PolicyStorageTests, strictest_all)
+{
+ auto storage = getStorage();
+ storage->enroll("testAdmin");
+
+ auto policies = storage->strictest();
+ EXPECT_TRUE(policies.size() > 0);
+
+ storage->disenroll("testAdmin");
+}
+
+TEST_F(PolicyStorageTests, admin_list)
+{
+ auto storage = getStorage();
+
+ auto admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 0);
+
+ storage->enroll("testAdmin1");
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 1);
+
+ storage->enroll("testAdmin2");
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 2);
+
+ storage->disenroll("testAdmin2");
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 1);
+
+ storage->disenroll("testAdmin1");
+ admins = storage->getAdmins();
+ EXPECT_EQ(admins.size(), 0);
+}
--- /dev/null
+# Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+FILE(GLOB POLICY_SDK_TESTS "tests/*.cpp")
+ADD_VIST_TEST(${POLICY_SDK_TESTS})
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-value.hpp>
+
+#include <string>
+#include <stdexcept>
+
+namespace vist {
+namespace policy {
+
+class PolicyModel {
+public:
+ explicit PolicyModel(std::string name, PolicyValue initial) noexcept :
+ name(std::move(name)), initial(std::move(initial)) {}
+ virtual ~PolicyModel() = default;
+
+ PolicyModel(const PolicyModel&) = delete;
+ PolicyModel& operator=(const PolicyModel&) = delete;
+
+ PolicyModel(PolicyModel&&) = default;
+ PolicyModel& operator=(PolicyModel&&) = default;
+
+ inline void set(const PolicyValue& value)
+ {
+ auto rollback = current;
+ current = value;
+ ready = true;
+
+ try {
+ this->onChanged(value);
+ } catch (const std::exception& e) {
+ current = rollback;
+ ready = false;
+ std::rethrow_exception(std::current_exception());
+ }
+ }
+
+ inline const PolicyValue& get() const
+ {
+ if (!ready)
+ throw std::runtime_error("Policy value should be set once before use.");
+
+ return current;
+ }
+
+ virtual void onChanged(const PolicyValue& value) = 0;
+
+ const std::string& getName() const noexcept { return name; }
+ const PolicyValue& getInitial() const noexcept { return initial; }
+
+protected:
+ std::string name;
+ PolicyValue initial;
+ PolicyValue current;
+ bool ready = false;
+};
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+#include <vist/sdk/policy-model.hpp>
+
+#include <cstddef>
+#include <memory>
+#include <unordered_map>
+
+namespace vist {
+namespace policy {
+
+class PolicyProvider {
+public:
+ using FactoryType = PolicyProvider* (*)();
+
+ explicit PolicyProvider(std::string name) noexcept : name(std::move(name)) {}
+ virtual ~PolicyProvider() = default;
+
+ inline void add(const std::shared_ptr<PolicyModel>& policy)
+ {
+ policies[policy->getName()] = policy;
+ }
+
+ inline const std::string& getName() const noexcept { return name; }
+ static const std::string& getFactoryName() noexcept
+ {
+ static std::string name = "PolicyFactory";
+ return name;
+ }
+
+ inline std::size_t size() const noexcept { return policies.size(); }
+
+private:
+ std::string name;
+ std::unordered_map<std::string, std::shared_ptr<PolicyModel>> policies;
+
+ friend class PolicyManager;
+};
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#pragma once
+
+namespace vist {
+namespace policy {
+
+// TODO: Support various value type
+struct PolicyValue final {
+ explicit PolicyValue(int value) noexcept : value(value) {}
+ explicit PolicyValue() noexcept = default;
+ ~PolicyValue() = default;
+
+ PolicyValue(const PolicyValue&) noexcept = default;
+ PolicyValue& operator=(const PolicyValue&) noexcept = default;
+
+ PolicyValue(PolicyValue&&) noexcept = default;
+ PolicyValue& operator=(PolicyValue&&) noexcept = default;
+
+ PolicyValue& operator=(int val) {
+ value = val;
+ return *this;
+ }
+
+ operator int() const { return value; }
+ bool operator==(const PolicyValue& rhs) const { return value == rhs.value; }
+ bool operator!=(const PolicyValue& rhs) const { return value != rhs.value; }
+ bool operator<(const PolicyValue& rhs) const { return value < rhs.value; }
+
+ int value = -1;
+};
+
+} // namespace policy
+} // namespace vist
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include <gtest/gtest.h>
+
+#include <vist/sdk/policy-model.hpp>
+#include <vist/sdk/policy-provider.hpp>
+
+#include <exception>
+
+namespace {
+ int g_value = -1;
+} // anonymous namespace
+
+using namespace vist::policy;
+
+class PolicySDKTests : public testing::Test {};
+
+class TestPolicyModel : public PolicyModel {
+public:
+ TestPolicyModel() : PolicyModel("test_policy", PolicyValue(1)) {}
+
+ virtual void onChanged(const PolicyValue& value)
+ {
+ g_value = value;
+ }
+};
+
+class TestPolicyModelFailed : public PolicyModel {
+public:
+ TestPolicyModelFailed() : PolicyModel("test_policy_failed", PolicyValue(1)) {}
+
+ virtual void onChanged(const PolicyValue& value)
+ {
+ throw std::runtime_error("Intended exception for test.");
+ }
+};
+
+TEST_F(PolicySDKTests, policy_model)
+{
+ TestPolicyModel policy;
+
+ EXPECT_EQ(policy.getName(), "test_policy");
+ EXPECT_EQ(policy.getInitial(), 1);
+
+ // Policy value should be set once before use
+ bool isRaised = false;
+ try {
+ auto value = policy.get();
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+
+ EXPECT_TRUE(isRaised);
+
+ policy.set(PolicyValue(3));
+ EXPECT_EQ(3, g_value);
+ EXPECT_EQ(3, policy.get());
+}
+
+TEST_F(PolicySDKTests, policy_model_failed)
+{
+ TestPolicyModelFailed policy;
+
+ EXPECT_EQ(policy.getName(), "test_policy_failed");
+ EXPECT_EQ(policy.getInitial(), 1);
+
+ bool isRaised = true;
+ try {
+ policy.set(PolicyValue(3));
+ } catch (const std::exception&) {
+ isRaised = true;
+ }
+
+ EXPECT_TRUE(isRaised);
+}
+
+TEST_F(PolicySDKTests, policy_provider)
+{
+ PolicyProvider provider("testProvider");
+ provider.add(std::make_shared<TestPolicyModel>());
+ provider.add(std::make_shared<TestPolicyModelFailed>());
+
+ EXPECT_EQ(2, provider.size());
+}
#include <gtest/gtest.h>
#include <vist/service/vist.hpp>
-#include <vist/policy/core/policy-manager.hpp>
+#include <vist/policy/api.hpp>
#include <iostream>
#include <chrono>
TEST_F(CoreTests, query_update)
{
- auto& manager = policy::PolicyManager::Instance();
- manager.enroll("admin");
+ policy::API::Admin::Enroll("admin");
std::string statement = "SELECT * FROM policy WHERE name = 'bluetooth'";
auto rows = Vist::Query(statement);
rows = Vist::Query(statement);
EXPECT_EQ(rows[0]["value"], std::to_string(3));
- manager.disenroll("admin");
+ policy::API::Admin::Disenroll("admin");
}