From fab54adac57dd1fcdf1b304603600599b7e1e5f9 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 29 Oct 2014 09:42:33 +0100 Subject: [PATCH 01/16] Add convenient typedefs in admin ApiInterface Change-Id: I9cd8b674a00aba90432609a4cf351e4c8fae3e66 --- src/admin/api/ApiInterface.h | 9 ++++++--- src/admin/logic/Logic.cpp | 4 ++-- src/admin/logic/Logic.h | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/admin/api/ApiInterface.h b/src/admin/api/ApiInterface.h index 62c40e5..4f7eed0 100644 --- a/src/admin/api/ApiInterface.h +++ b/src/admin/api/ApiInterface.h @@ -38,15 +38,18 @@ namespace Cynara { class ApiInterface { public: + + typedef std::map> PoliciesByBucket; + typedef std::map> KeysByBucket; + ApiInterface() = default; virtual ~ApiInterface() {}; - virtual int setPolicies(const std::map> &insertOrUpdate, - const std::map> &remove) = 0; + virtual int setPolicies(const PoliciesByBucket &insertOrUpdate, + const KeysByBucket &remove) = 0; virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult) = 0; virtual int removeBucket(const PolicyBucketId &bucket) = 0; - virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result) = 0; diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 506ecbf..67f7172 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -106,8 +106,8 @@ int Logic::askCynaraAndInterpreteCodeResponse(Args... args) { } } -int Logic::setPolicies(const std::map> &insertOrUpdate, - const std::map> &remove) { +int Logic::setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove) { return askCynaraAndInterpreteCodeResponse(insertOrUpdate, remove); } diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index a8688c2..c0b3999 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -43,8 +43,8 @@ public: Logic(); virtual ~Logic() {}; - virtual int setPolicies(const std::map> &insertOrUpdate, - const std::map> &remove); + virtual int setPolicies(const ApiInterface::PoliciesByBucket &insertOrUpdate, + const ApiInterface::KeysByBucket &remove); virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult); virtual int removeBucket(const PolicyBucketId &bucket); -- 2.7.4 From 6fc739e0eeacb82e9ace84c793f365fdcb529b88 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 26 Nov 2014 09:23:06 +0100 Subject: [PATCH 02/16] Add FileLock class A class creating advisory lock on provided file. The file must exist and be openable by the process. Change-Id: Ia5fa4ef51e1a413beb81efd56f807e1434145691 --- src/common/CMakeLists.txt | 1 + src/common/exceptions/DatabaseBusyException.h | 47 +++++++++++++ src/common/exceptions/FileLockAcquiringException.h | 60 +++++++++++++++++ src/common/lock/FileLock.cpp | 77 ++++++++++++++++++++++ src/common/lock/FileLock.h | 44 +++++++++++++ src/service/main/pointers.h | 3 + 6 files changed, 232 insertions(+) create mode 100644 src/common/exceptions/DatabaseBusyException.h create mode 100644 src/common/exceptions/FileLockAcquiringException.h create mode 100644 src/common/lock/FileLock.cpp create mode 100644 src/common/lock/FileLock.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e8974cb..a8e0632 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -28,6 +28,7 @@ INCLUDE_DIRECTORIES( SET(COMMON_SOURCES ${COMMON_PATH}/config/PathConfig.cpp ${COMMON_PATH}/containers/BinaryQueue.cpp + ${COMMON_PATH}/lock/FileLock.cpp ${COMMON_PATH}/log/log.cpp ${COMMON_PATH}/plugin/PluginManager.cpp ${COMMON_PATH}/protocol/ProtocolAdmin.cpp diff --git a/src/common/exceptions/DatabaseBusyException.h b/src/common/exceptions/DatabaseBusyException.h new file mode 100644 index 0000000..78c90cb --- /dev/null +++ b/src/common/exceptions/DatabaseBusyException.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 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 src/common/exceptions/DatabaseBusyException.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file defines exception thrown when database is busy + */ + +#ifndef SRC_COMMON_EXCEPTIONS_DATABASEBUSYEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_DATABASEBUSYEXCEPTION_H_ + +#include + +#include + +namespace Cynara { + +class DatabaseBusyException : public DatabaseException { +public: + DatabaseBusyException() : m_message("Database busy") {}; + virtual ~DatabaseBusyException() {}; + + const std::string &message(void) const { + return m_message; + } + +private: + std::string m_message; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_DATABASEBUSYEXCEPTION_H_ */ diff --git a/src/common/exceptions/FileLockAcquiringException.h b/src/common/exceptions/FileLockAcquiringException.h new file mode 100644 index 0000000..44bc54a --- /dev/null +++ b/src/common/exceptions/FileLockAcquiringException.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 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 src/common/exceptions/FileLockAcquiringException.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file defines exception thrown when file lock cannot be acquired + */ + +#ifndef SRC_COMMON_EXCEPTIONS_FILELOCKACQUIRINGEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_FILELOCKACQUIRINGEXCEPTION_H_ + +#include +#include + +#include + +namespace Cynara { + +class FileLockAcquiringException { +public: + FileLockAcquiringException(const int errNumber) : m_errno(errNumber) { + m_message = "File lock acquiring error [" + std::to_string(errorNumber()) + "]" + + " <" + errorString() + ">"; + }; + virtual ~FileLockAcquiringException() {}; + + const std::string &message(void) const { + return m_message; + } + + int errorNumber(void) const { + return m_errno; + } + + const std::string errorString(void) const { + return strerror(m_errno); + } + +private: + std::string m_message; + int m_errno; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_FILELOCKACQUIRINGEXCEPTION_H_ */ diff --git a/src/common/lock/FileLock.cpp b/src/common/lock/FileLock.cpp new file mode 100644 index 0000000..b8bd34a --- /dev/null +++ b/src/common/lock/FileLock.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014 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 src/common/lock/FileLock.cpp + * @author Aleksander Zdyb + * @version 1.0 + * @brief A class for acquiring and holding file lock + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "FileLock.h" + +namespace Cynara { + +FileLock::FileLock(const std::string &lockFilename) : m_lockFilename(lockFilename) { + m_fd = ::open(m_lockFilename.c_str(), O_RDONLY); + + if (m_fd < 0) { + LOGE("Could not open lock file <%s>", lockFilename.c_str()); + throw FileLockAcquiringException(errno); + } + + LOGD("File lock file opened"); +} + +FileLock::~FileLock() { + ::close(m_fd); +} + +bool FileLock::tryLock(void) { + int lock = TEMP_FAILURE_RETRY(::flock(m_fd, LOCK_EX | LOCK_NB)); + + if (lock == 0) { + LOGI("File lock acquired"); + return true; + } else if (errno == EWOULDBLOCK) { + LOGI("File lock NOT acquired"); + return false; + } + + throw FileLockAcquiringException(errno); +} + +void FileLock::lock(void) { + int lock = TEMP_FAILURE_RETRY(::flock(m_fd, LOCK_EX)); + + if (lock == -1) + throw FileLockAcquiringException(errno); + + LOGI("File lock acquired"); +} + +} /* namespace Cynara */ diff --git a/src/common/lock/FileLock.h b/src/common/lock/FileLock.h new file mode 100644 index 0000000..53f048f --- /dev/null +++ b/src/common/lock/FileLock.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014 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 src/common/lock/FileLock.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief A class for acquiring and holding file lock + */ + +#ifndef SRC_COMMON_LOCK_FILELOCK_H_ +#define SRC_COMMON_LOCK_FILELOCK_H_ + +#include + +namespace Cynara { + +class FileLock { +public: + explicit FileLock(const std::string &lockFilename); + ~FileLock(); + bool tryLock(void); + void lock(void); + +private: + std::string m_lockFilename; + int m_fd; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_LOCK_FILELOCK_H_ */ diff --git a/src/service/main/pointers.h b/src/service/main/pointers.h index f32c4ab..db734ae 100644 --- a/src/service/main/pointers.h +++ b/src/service/main/pointers.h @@ -45,6 +45,9 @@ typedef std::shared_ptr StoragePtr; class StorageBackend; typedef std::shared_ptr StorageBackendPtr; +class FileLock; +typedef std::unique_ptr FileLockUniquePtr; + } // namespace Cynara #endif /* SRC_SERVICE_MAIN_POINTERS_H_ */ -- 2.7.4 From 957d586061fc56ddcb661a61cb934f78ef502322 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 25 Nov 2014 17:37:59 +0100 Subject: [PATCH 03/16] Introduce cynara_admin_list_policies() admin function Introduce new administrative API function: cynara_admin_list_policies() New function allows listing with filter policies from a single bucket. New admin define CYNARA_ADMIN_ANY is also introduced. It is a wildcard for policy listing and removal. It can be used as client, user or privilege name and matches any policy (even CYNARA_ADMIN_WILDCARD). Change-Id: I9d014ebc8018e3fa6ad897c4de768471e672ac40 --- src/include/cynara-admin-types.h | 11 +++++++ src/include/cynara-admin.h | 63 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/include/cynara-admin-types.h b/src/include/cynara-admin-types.h index 8dd3c66..5978c80 100644 --- a/src/include/cynara-admin-types.h +++ b/src/include/cynara-admin-types.h @@ -63,6 +63,17 @@ struct cynara_admin_policy { */ #define CYNARA_ADMIN_DEFAULT_BUCKET "" +/** + * \name Any + * definition of ANY, that can replace client, user or privilege name. + * ANY matches any string (including WILDCARD) during: + * * policy removal (setPolicies with CYNARA_ADMIN_DELETE) + * * listing policies from a single bucket. + * Using ANY as default policy for bucket or as policy type of inserted policy record + * is forbidden and will cause CYNARA_API_INVALID_PARAM error. + */ +#define CYNARA_ADMIN_ANY "#" + #ifdef __cplusplus } #endif diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index 3b737d8..595ad6a 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -85,7 +85,7 @@ int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin); * This API releases inner library structures and destroys cynara_admin structure. * * \par Sync (or) Async: - * This is a Synchronous API. + * This is a synchronous API. * * \par Important notes: * No invocations of cynara-admin library API functions are allowed after call to @@ -132,7 +132,7 @@ int cynara_admin_finish(struct cynara_admin *p_cynara_admin); * However, considered buckets must exist before referring to them in policies. * * \par Sync (or) Async: - * This is a Synchronous API. + * This is a synchronous API. * * \par Important notes: * When plugin API will be specified, there will be more valid types to pass as result. @@ -171,7 +171,7 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, * CYNARA_ADMIN_DELETE, a bucket is removed with all policies that were kept in it. * * \par Sync (or) Async: - * This is a Synchronous API. + * This is a synchronous API. * * \par Important notes: * When plugin API will be specified, there will be more valid types to pass as operation / default @@ -245,6 +245,63 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin, const char *client, const char *user, const char *privilege, int *result, char **result_extra); +/** + * \par Description: + * Lists filtered cynara policies from single bucket. + * + * \par Purpose: + * This API should be used to list policies from single bucket. + * + * \par Typical use case: + * List all policies matching defined filter. + * + * \par Method of function operation: + * Policies are arranged into buckets. Every bucket contains set of policies. Each of policies are + * identified with tripple {client, user, privilege}. Function lists all policies from single bucket + * with matching client, user and privilege names. + * + * CYNARA_ADMIN_ANY can be used to match any client, user or privilege, e.g. + * + * List with paramaters: {client = CYNARA_ADMIN_ANY, user = "alice", privilege = CYNARA_ADMIN_ANY} + * will match all policies related to "alice", so will match {"app1", "alice", "gps"} and + * {CYNARA_ADMIN_WILDCARD, "alice", "sms"}, but won't match {"app3", CYNARA_ADMIN_WILDCARD, "call"}. + * + * List with paramaters: {client = "calculator", user = CYNARA_ADMIN_WILDCARD, + * privilege = CYNARA_ADMIN_ANY} will match {"calculator", CYNARA_ADMIN_WILDCARD, "sms"} but won't + * match {CYNARA_ADMIN_WILDCARD, CYNARA_ADMIN_WILDCARD, "sms"} nor {"calculator", "bob", "sms"} + * + * Matching policies are returned as NULL terminated array of pointers to cynara_admin_policy + * structures. + * + * If any of: bucket, client, user, privilege, policies is NULL then CYNARA_API_INVALID_PARAM + * is returned. + * If there is no bucket with given name CYNARA_API_BUCKET_NOT_FOUND is returned. + * + * In case of successful call CYNARA_API_SUCCESS is returned and *policies points to newly created + * array of pointers to struct cynara_admin_policy. It is responsibility of caller to release: + * * all non-NULL const char* pointers in all cynara_admin_policy structures; + * * all pointers to cynara_admin_policy structures kept in *policies array; + * * *policies array itself. + * All allocation made by cynara admin library are done with malloc(3) function and must be released + * with free(3) function. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \param[in] p_cynara_admin cynara admin structure. + * \param[in] bucket name. + * \param[in] client filter for client name. + * \param[in] user filter for user name. + * \param[in] privilege filter for privilege. + * \param[out] policies placeholder for NULL terminated array of pointers to policy structures. + * + * \return CYNARA_API_SUCCESS on success, or error code otherwise. + * + * \brief Lists policies from single bucket in cynara database. + */ +int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char *bucket, + const char *client, const char *user, const char *privilege, + struct cynara_admin_policy ***policies); #ifdef __cplusplus } #endif -- 2.7.4 From 6dcb8e5566a250f4c6b2850afb6cf9a2db640bd4 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 25 Nov 2014 18:15:09 +0100 Subject: [PATCH 04/16] Enhance PolicyKey and PolicyKeyFeature by ANY wildcard Enhance PolicyKey and PolicyKeyFeature classes, so they can hold new ANY wildcard as user, client or privilege. New wildcard can be used for listing and removal of many policies. It matches any PolicyKeyFeature. Minor cleanup in class: missing voids added, public section reordered Change-Id: Icad8e06b87a014fc2fbab32e0553ddd76e5bb06d --- src/common/types/PolicyKey.cpp | 11 +++-- src/common/types/PolicyKey.h | 95 +++++++++++++++++++++++++++--------------- test/types/policykey.cpp | 16 ++++--- 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/common/types/PolicyKey.cpp b/src/common/types/PolicyKey.cpp index 14b3bc6..ffb1400 100644 --- a/src/common/types/PolicyKey.cpp +++ b/src/common/types/PolicyKey.cpp @@ -25,15 +25,18 @@ #include +#include + namespace Cynara { -std::string PolicyKeyFeature::m_wildcardValue = "*"; +const std::string PolicyKeyFeature::m_wildcardValue = CYNARA_ADMIN_WILDCARD; +const std::string PolicyKeyFeature::m_anyValue = CYNARA_ADMIN_ANY; -const std::string &PolicyKeyFeature::toString() const { - return isWildcard() ? m_wildcardValue : value(); +const std::string &PolicyKeyFeature::toString(void) const { + return value(); } -std::string PolicyKey::toString() const { +std::string PolicyKey::toString(void) const { std::stringstream ss; ss << client().toString() << "\t" << user().toString() << "\t" diff --git a/src/common/types/PolicyKey.h b/src/common/types/PolicyKey.h index 3f65c58..4fed189 100644 --- a/src/common/types/PolicyKey.h +++ b/src/common/types/PolicyKey.h @@ -22,8 +22,8 @@ policy rule */ -#ifndef CYNARA_COMMON_TYPES_POLICYKEY_H -#define CYNARA_COMMON_TYPES_POLICYKEY_H +#ifndef CYNARA_COMMON_TYPES_POLICYKEY_H_ +#define CYNARA_COMMON_TYPES_POLICYKEY_H_ #include #include @@ -39,32 +39,59 @@ public: PolicyKeyFeature(const PolicyKeyFeature &) = default; PolicyKeyFeature(PolicyKeyFeature &&) = default; + PolicyKeyFeature& operator=(const PolicyKeyFeature &) = default; + PolicyKeyFeature& operator=(PolicyKeyFeature &&) = default; + typedef std::string ValueType; static PolicyKeyFeature create(ValueType value) { return PolicyKeyFeature(value); } - static PolicyKeyFeature createWildcard() { - return PolicyKeyFeature(); + static PolicyKeyFeature createWildcard(void) { + return PolicyKeyFeature(m_wildcardValue); + } + + static PolicyKeyFeature createAny(void) { + return PolicyKeyFeature(m_anyValue); } // TODO: Different features (client, user, privilege) // shouldn't be comparable bool operator==(const PolicyKeyFeature &other) const { - return anyWildcard(*this, other) || valuesMatch(*this, other); + return valuesMatch(*this, other); } bool operator==(const PolicyKeyFeature::ValueType &other) const { - return anyWildcard(*this, other) || valuesMatch(*this, other); + return valuesMatch(*this, PolicyKeyFeature(other)); } - const std::string &toString() const; + const std::string &toString(void) const; + + const ValueType &value(void) const { + return m_value; + } + + bool isWildcard(void) const { + return m_isWildcard; + } + + bool isAny(void) const { + return m_isAny; + } + + bool matchFilter(const PolicyKeyFeature &filter) const { + return filter.isAny() || valuesMatch(*this, filter); + } protected: - PolicyKeyFeature(const ValueType &value) : m_value(value), - m_isWildcard(value == PolicyKeyFeature::m_wildcardValue) {} - PolicyKeyFeature() : m_value(m_wildcardValue), m_isWildcard(true) {} + explicit PolicyKeyFeature(const ValueType &value) : m_value(value), + m_isWildcard(value == PolicyKeyFeature::m_wildcardValue), + m_isAny(value == PolicyKeyFeature::m_anyValue) {} + + static bool anyAny(const PolicyKeyFeature &pkf1, const PolicyKeyFeature &pkf2) { + return pkf1.isAny() || pkf2.isAny(); + } static bool anyWildcard(const PolicyKeyFeature &pkf1, const PolicyKeyFeature &pkf2) { return pkf1.isWildcard() || pkf2.isWildcard(); @@ -77,15 +104,10 @@ protected: private: ValueType m_value; bool m_isWildcard; - static std::string m_wildcardValue; + bool m_isAny; -public: - bool isWildcard() const { - return m_isWildcard; - } - const ValueType& value() const { - return m_value; - } + const static std::string m_wildcardValue; + const static std::string m_anyValue; }; class PolicyKey @@ -93,41 +115,48 @@ class PolicyKey public: PolicyKey(const PolicyKeyFeature &clientId, const PolicyKeyFeature &userId, - const PolicyKeyFeature &privilegeId) + const PolicyKeyFeature &privilegeId) : m_client(clientId), m_user(userId), m_privilege(privilegeId) {}; PolicyKey(const PolicyKeyFeature::ValueType &clientId, - const PolicyKeyFeature::ValueType &userId, - const PolicyKeyFeature::ValueType &privilegeId) + const PolicyKeyFeature::ValueType &userId, + const PolicyKeyFeature::ValueType &privilegeId) : m_client(clientId), m_user(userId), m_privilege(privilegeId) {}; PolicyKey(const PolicyKey &) = default; PolicyKey(PolicyKey &&) = default; + PolicyKey& operator=(const PolicyKey &) = default; + PolicyKey& operator=(PolicyKey &&) = default; + bool operator==(const PolicyKey &other) const { return std::tie(m_client, m_user, m_privilege) - == std::tie(other.m_client, other.m_user, other.m_privilege); + == std::tie(other.m_client, other.m_user, other.m_privilege); } - std::string toString() const; - -private: - PolicyKeyFeature m_client; - PolicyKeyFeature m_user; - PolicyKeyFeature m_privilege; + std::string toString(void) const; -public: - const PolicyKeyFeature &client() const { + const PolicyKeyFeature &client(void) const { return m_client; } - const PolicyKeyFeature &user() const { + const PolicyKeyFeature &user(void) const { return m_user; } - const PolicyKeyFeature &privilege() const { + const PolicyKeyFeature &privilege(void) const { return m_privilege; } + + bool matchFilter(const PolicyKey &filter) const { + return m_client.matchFilter(filter.m_client) && m_user.matchFilter(filter.m_user) + && m_privilege.matchFilter(filter.m_privilege); + } + +private: + PolicyKeyFeature m_client; + PolicyKeyFeature m_user; + PolicyKeyFeature m_privilege; }; bool operator ==(const PolicyKeyFeature::ValueType &pkf1, const PolicyKeyFeature &pkf2); @@ -135,4 +164,4 @@ bool operator ==(const PolicyKeyFeature::ValueType &pkf1, const PolicyKeyFeature } /* namespace Cynara */ -#endif /* CYNARA_COMMON_TYPES_POLICYKEY_H */ +#endif /* CYNARA_COMMON_TYPES_POLICYKEY_H_ */ diff --git a/test/types/policykey.cpp b/test/types/policykey.cpp index 228cb98..5556065 100644 --- a/test/types/policykey.cpp +++ b/test/types/policykey.cpp @@ -20,14 +20,13 @@ * @brief Tests for Cynara::PolicyKey */ - - #include #include #include "../helpers.h" -#include "types/PolicyKey.h" +#include +#include using namespace Cynara; @@ -38,8 +37,15 @@ TEST(PolicyKey, to_string) { ASSERT_EQ("c\tu\tp", pk1.toString()); PolicyKey pk2(PKF::createWildcard(), PKF::createWildcard(), PKF::createWildcard()); - ASSERT_EQ("*\t*\t*", pk2.toString()); + ASSERT_EQ(CYNARA_ADMIN_WILDCARD "\t" CYNARA_ADMIN_WILDCARD "\t" CYNARA_ADMIN_WILDCARD, + pk2.toString()); PolicyKey pk3(PKF::createWildcard(), PKF::create("u"), PKF::createWildcard()); - ASSERT_EQ("*\tu\t*", pk3.toString()); + ASSERT_EQ(CYNARA_ADMIN_WILDCARD "\tu\t" CYNARA_ADMIN_WILDCARD, pk3.toString()); + + PolicyKey pk4(PKF::createAny(), PKF::createAny(), PKF::createAny()); + ASSERT_EQ(CYNARA_ADMIN_ANY "\t" CYNARA_ADMIN_ANY "\t" CYNARA_ADMIN_ANY, pk4.toString()); + + PolicyKey pk5(PKF::createWildcard(), PKF::create("u"), PKF::createAny()); + ASSERT_EQ(CYNARA_ADMIN_WILDCARD "\tu\t" CYNARA_ADMIN_ANY, pk5.toString()); } -- 2.7.4 From b03a7e8501c39019e62de3f198f2b09ea751c405 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 25 Nov 2014 20:39:41 +0100 Subject: [PATCH 05/16] Implement cynara_admin_list_policies in admin-api layer Implementation is complete on admin-api layer. ApiInterface of libcynara-admin is enhanced by listPolicies method. Its implementation in Logic layer of admin library is stubbed. Change-Id: I25f2d4dbc8616717c7e19835c676b218615df9eb --- src/admin/api/ApiInterface.h | 2 + src/admin/api/admin-api.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/admin/logic/Logic.cpp | 6 +++ src/admin/logic/Logic.h | 3 +- 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/admin/api/ApiInterface.h b/src/admin/api/ApiInterface.h index 4f7eed0..6628b2c 100644 --- a/src/admin/api/ApiInterface.h +++ b/src/admin/api/ApiInterface.h @@ -52,6 +52,8 @@ public: virtual int removeBucket(const PolicyBucketId &bucket) = 0; virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result) = 0; + virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, + std::vector &policies) = 0; }; diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 1e73ff7..c2a5212 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -20,7 +20,9 @@ * @brief Implementation of external libcynara-admin API */ +#include #include +#include #include #include #include @@ -219,3 +221,93 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin, return CYNARA_API_SUCCESS; }); } + +static int createPoliciesArray(const char *bucket, + const std::vector &policiesVector, + struct cynara_admin_policy ***policies) { + typedef struct cynara_admin_policy Elem; + size_t elems = policiesVector.size(); + + Elem **tab = reinterpret_cast(calloc(elems + 1U, sizeof(Elem*))); + if (!tab) + return CYNARA_API_OUT_OF_MEMORY; + std::unique_ptr> plumber(tab, + [](Elem **tab) { + Elem *elem = *tab; + while (elem) { + free(elem->bucket); + free(elem->client); + free(elem->user); + free(elem->privilege); + free(elem->result_extra); + free(elem++); + } + free(tab); + }); + + for (size_t i = 0U; i < elems; ++i) { + tab[i] = reinterpret_cast(calloc(1U, sizeof(Elem))); + if (!tab[i]) + return CYNARA_API_OUT_OF_MEMORY; + + tab[i]->bucket = strdup(bucket); + if (!tab[i]->bucket) + return CYNARA_API_OUT_OF_MEMORY; + + tab[i]->client = strdup(policiesVector[i].key().client().value().c_str()); + if (!tab[i]->client) + return CYNARA_API_OUT_OF_MEMORY; + tab[i]->user = strdup(policiesVector[i].key().user().value().c_str()); + if (!tab[i]->user) + return CYNARA_API_OUT_OF_MEMORY; + tab[i]->privilege = strdup(policiesVector[i].key().privilege().value().c_str()); + if (!tab[i]->privilege) + return CYNARA_API_OUT_OF_MEMORY; + + tab[i]->result = static_cast(policiesVector[i].result().policyType()); + if (!policiesVector[i].result().metadata().empty()) { + tab[i]->result_extra = strdup(policiesVector[i].result().metadata().c_str()); + if (!tab[i]->result_extra) + return CYNARA_API_OUT_OF_MEMORY; + } + } + *policies = tab; + plumber.release(); + return CYNARA_API_SUCCESS; +} + +CYNARA_API +int cynara_admin_list_policies(struct cynara_admin *p_cynara_admin, const char *bucket, + const char *client, const char *user, const char *privilege, + struct cynara_admin_policy ***policies) { + if (!p_cynara_admin || !p_cynara_admin->impl) + return CYNARA_API_INVALID_PARAM; + if (!bucket || !client || !user || !privilege) + return CYNARA_API_INVALID_PARAM; + if (!policies) + return CYNARA_API_INVALID_PARAM; + + return Cynara::tryCatch([&]() { + Cynara::PolicyKeyFeature::ValueType clientStr; + Cynara::PolicyKeyFeature::ValueType userStr; + Cynara::PolicyKeyFeature::ValueType privilegeStr; + Cynara::PolicyBucketId bucketId; + try { + clientStr = client; + userStr = user; + privilegeStr = privilege; + bucketId = bucket; + } catch (const std::length_error &e) { + LOGE("%s", e.what()); + return CYNARA_API_INVALID_PARAM; + } + + std::vector policiesVector; + int ret = p_cynara_admin->impl->listPolicies(bucket, Cynara::PolicyKey(clientStr, userStr, + privilegeStr), policiesVector); + if (ret != CYNARA_API_SUCCESS) + return ret; + + return createPoliciesArray(bucket, policiesVector, policies); + }); +} diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 67f7172..1bf8a8a 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -154,4 +154,10 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P return CYNARA_API_SUCCESS; } +int Logic::listPolicies(const PolicyBucketId &bucket UNUSED, const PolicyKey &filter UNUSED, + std::vector &policies UNUSED) { + //stub + return CYNARA_API_SUCCESS; +} + } // namespace Cynara diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index c0b3999..3469593 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -48,9 +48,10 @@ public: virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult); virtual int removeBucket(const PolicyBucketId &bucket); - virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, const PolicyKey &key, PolicyResult &result); + virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, + std::vector &policies); }; } // namespace Cynara -- 2.7.4 From 3b75361a78f41f40d14d81ca9997167e22f2ae8d Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 29 Nov 2014 15:40:09 +0100 Subject: [PATCH 06/16] Add ListRequest - new class for listing policies Introduced class wraps a request for policies list that can be sent by admin of cynara. Request contains name of bucket that should be searched and a policy key filter. Change-Id: Ie12b8e5d3d997655bf5c4b8356d71ac5817dbb7f --- src/common/CMakeLists.txt | 1 + src/common/request/ListRequest.cpp | 35 ++++++++++++++++++++++ src/common/request/ListRequest.h | 60 +++++++++++++++++++++++++++++++++++++ src/common/request/RequestTaker.cpp | 4 +++ src/common/request/RequestTaker.h | 1 + src/common/request/pointers.h | 3 ++ 6 files changed, 104 insertions(+) create mode 100644 src/common/request/ListRequest.cpp create mode 100644 src/common/request/ListRequest.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index a8e0632..893d146 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -45,6 +45,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/request/CancelRequest.cpp ${COMMON_PATH}/request/CheckRequest.cpp ${COMMON_PATH}/request/InsertOrUpdateBucketRequest.cpp + ${COMMON_PATH}/request/ListRequest.cpp ${COMMON_PATH}/request/RemoveBucketRequest.cpp ${COMMON_PATH}/request/RequestTaker.cpp ${COMMON_PATH}/request/SetPoliciesRequest.cpp diff --git a/src/common/request/ListRequest.cpp b/src/common/request/ListRequest.cpp new file mode 100644 index 0000000..f8e261e --- /dev/null +++ b/src/common/request/ListRequest.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 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 src/common/list/ListRequest.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file implements policies list request class + */ + +#include + +#include + +#include "ListRequest.h" + +namespace Cynara { + +void ListRequest::execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/request/ListRequest.h b/src/common/request/ListRequest.h new file mode 100644 index 0000000..069ea4a --- /dev/null +++ b/src/common/request/ListRequest.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 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 src/common/list/ListRequest.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines policies list request class + */ + +#ifndef SRC_COMMON_REQUEST_LISTREQUEST_H_ +#define SRC_COMMON_REQUEST_LISTREQUEST_H_ + +#include +#include + +#include +#include + +namespace Cynara { + +class ListRequest : public Request { +private: + PolicyBucketId m_bucket; + PolicyKey m_filter; + +public: + ListRequest(const PolicyBucketId &bucket, const PolicyKey &filter, + ProtocolFrameSequenceNumber sequenceNumber) : + Request(sequenceNumber), m_bucket(bucket), m_filter(filter) { + } + + virtual ~ListRequest() {}; + + const PolicyBucketId &bucket(void) const { + return m_bucket; + } + + const PolicyKey &filter(void) const { + return m_filter; + } + + virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_REQUEST_LISTREQUEST_H_ */ diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index f46d428..bc6c7a1 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -54,6 +54,10 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, throw NotImplementedException(); } +void RequestTaker::execute(RequestContextPtr context UNUSED, ListRequestPtr request UNUSED) { + throw NotImplementedException(); +} + void RequestTaker::execute(RequestContextPtr context UNUSED, RemoveBucketRequestPtr request UNUSED) { throw NotImplementedException(); diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h index f190e69..c36b5c9 100644 --- a/src/common/request/RequestTaker.h +++ b/src/common/request/RequestTaker.h @@ -37,6 +37,7 @@ public: virtual void execute(RequestContextPtr context, AgentRegisterRequestPtr request); virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); + virtual void execute(RequestContextPtr context, ListRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index 19429a9..d984c99 100644 --- a/src/common/request/pointers.h +++ b/src/common/request/pointers.h @@ -45,6 +45,9 @@ typedef std::shared_ptr CheckRequestPtr; class InsertOrUpdateBucketRequest; typedef std::shared_ptr InsertOrUpdateBucketRequestPtr; +class ListRequest; +typedef std::shared_ptr ListRequestPtr; + class RemoveBucketRequest; typedef std::shared_ptr RemoveBucketRequestPtr; -- 2.7.4 From 55e12b580b4e0c66edcec6765dc8bc809b8d258e Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 29 Nov 2014 16:02:20 +0100 Subject: [PATCH 07/16] Add ListResponse - response class for ListRequest Introduced class wraps a response for policies list that can be sent by admin of cynara. Response contains vector of matched policies and boolean information about bucket validity. If there is no bucket with name that was passed in request - returned vector is empty and bucket validity is false. Change-Id: I208555f7a991e0dc4a531312ebbbef658c95f22b --- src/common/CMakeLists.txt | 1 + src/common/response/ListResponse.cpp | 35 ++++++++++++++++++++ src/common/response/ListResponse.h | 62 +++++++++++++++++++++++++++++++++++ src/common/response/ResponseTaker.cpp | 4 +++ src/common/response/ResponseTaker.h | 1 + src/common/response/pointers.h | 3 ++ 6 files changed, 106 insertions(+) create mode 100644 src/common/response/ListResponse.cpp create mode 100644 src/common/response/ListResponse.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 893d146..f30d335 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -55,6 +55,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/response/CancelResponse.cpp ${COMMON_PATH}/response/CheckResponse.cpp ${COMMON_PATH}/response/CodeResponse.cpp + ${COMMON_PATH}/response/ListResponse.cpp ${COMMON_PATH}/response/ResponseTaker.cpp ${COMMON_PATH}/sockets/Socket.cpp ${COMMON_PATH}/sockets/SocketClient.cpp diff --git a/src/common/response/ListResponse.cpp b/src/common/response/ListResponse.cpp new file mode 100644 index 0000000..8931ee1 --- /dev/null +++ b/src/common/response/ListResponse.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 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 src/common/response/ListResponse.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file implements policies list response class + */ + +#include + +#include "ListResponse.h" +#include "ResponseTaker.h" + +namespace Cynara { + +void ListResponse::execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/response/ListResponse.h b/src/common/response/ListResponse.h new file mode 100644 index 0000000..ec52736 --- /dev/null +++ b/src/common/response/ListResponse.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 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 src/common/response/ListResponse.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines response class for policies list request + */ + +#ifndef SRC_COMMON_RESPONSE_LISTRESPONSE_H_ +#define SRC_COMMON_RESPONSE_LISTRESPONSE_H_ + +#include + +#include + +#include +#include +#include + +namespace Cynara { + +class ListResponse : public Response { +public: + ListResponse(const std::vector &policies, bool bucketValid, + ProtocolFrameSequenceNumber sequenceNumber) : + Response(sequenceNumber), m_policies(policies), m_bucketValid(bucketValid) { + } + + virtual ~ListResponse() {}; + + virtual void execute(ResponsePtr self, ResponseTakerPtr taker, RequestContextPtr context) const; + + bool isBucketValid(void) const { + return m_bucketValid; + } + + const std::vector &policies(void) const { + return m_policies; + } + +private: + std::vector m_policies; + bool m_bucketValid; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_RESPONSE_LISTRESPONSE_H_ */ diff --git a/src/common/response/ResponseTaker.cpp b/src/common/response/ResponseTaker.cpp index cf5ae40..0de4371 100644 --- a/src/common/response/ResponseTaker.cpp +++ b/src/common/response/ResponseTaker.cpp @@ -48,4 +48,8 @@ void ResponseTaker::execute(RequestContextPtr context UNUSED, CodeResponsePtr re throw NotImplementedException(); } +void ResponseTaker::execute(RequestContextPtr context UNUSED, ListResponsePtr response UNUSED) { + throw NotImplementedException(); +} + } // namespace Cynara diff --git a/src/common/response/ResponseTaker.h b/src/common/response/ResponseTaker.h index 6256e73..721dc2a 100644 --- a/src/common/response/ResponseTaker.h +++ b/src/common/response/ResponseTaker.h @@ -38,6 +38,7 @@ public: virtual void execute(RequestContextPtr context, CancelResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); + virtual void execute(RequestContextPtr context, ListResponsePtr response); }; } // namespace Cynara diff --git a/src/common/response/pointers.h b/src/common/response/pointers.h index 378fed4..c5fdb1d 100644 --- a/src/common/response/pointers.h +++ b/src/common/response/pointers.h @@ -42,6 +42,9 @@ typedef std::shared_ptr CheckResponsePtr; class CodeResponse; typedef std::shared_ptr CodeResponsePtr; +class ListResponse; +typedef std::shared_ptr ListResponsePtr; + class Response; typedef std::shared_ptr ResponsePtr; -- 2.7.4 From 9138bd1a8352b8a55ac54505455a409acf09e160 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 29 Nov 2014 16:34:05 +0100 Subject: [PATCH 08/16] Handle ListRequest by AdminProtocol Add serialziation and deserialization of ListRequest to AdminProtocol. Change-Id: Id1fadae22333acba6caec905d82c8e214c2560e9 --- src/common/protocol/ProtocolAdmin.cpp | 37 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAdmin.h | 2 ++ src/common/protocol/ProtocolOpCode.h | 4 +++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 8d792f9..60341bc 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -30,11 +30,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "ProtocolAdmin.h" @@ -87,6 +89,22 @@ RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(void) { PolicyResult(policyType, policyMetaData), m_frameHeader.sequenceNumber()); } +RequestPtr ProtocolAdmin::deserializeListRequest(void) { + PolicyBucketId bucketId; + PolicyKeyFeature::ValueType client, user, privilege; + + ProtocolDeserialization::deserialize(m_frameHeader, bucketId); + ProtocolDeserialization::deserialize(m_frameHeader, client); + ProtocolDeserialization::deserialize(m_frameHeader, user); + ProtocolDeserialization::deserialize(m_frameHeader, privilege); + + LOGD("Deserialized ListRequest: bucketId <%s>, filter client <%s> filter user <%s>, filter " + "privilege <%s>", bucketId.c_str(), client.c_str(), user.c_str(), privilege.c_str()); + + return std::make_shared(bucketId, PolicyKey(client, user, privilege), + m_frameHeader.sequenceNumber()); +} + RequestPtr ProtocolAdmin::deserializeRemoveBucketRequest(void) { PolicyBucketId policyBucketId; @@ -163,6 +181,8 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { return deserializeAdminCheckRequest(); case OpInsertOrUpdateBucket: return deserializeInsertOrUpdateBucketRequest(); + case OpListRequest: + return deserializeListRequest(); case OpRemoveBucket: return deserializeRemoveBucketRequest(); case OpSetPolicies: @@ -258,6 +278,23 @@ void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketReque ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } +void ProtocolAdmin::execute(RequestContextPtr context, ListRequestPtr request) { + LOGD("Serializing ListRequest: sequenceNumber [%" PRIu16 "], bucketId <%s>, " + "filter client <%s> filter user <%s> filter privilege <%s>", request->sequenceNumber(), + request->bucket().c_str(), request->filter().client().value().c_str(), + request->filter().user().value().c_str(), request->filter().privilege().value().c_str()); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpListRequest); + ProtocolSerialization::serialize(frame, request->bucket()); + ProtocolSerialization::serialize(frame, request->filter().client().value()); + ProtocolSerialization::serialize(frame, request->filter().user().value()); + ProtocolSerialization::serialize(frame, request->filter().privilege().value()); + + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); +} + void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr request) { LOGD("Serializing RemoveBucketRequest: sequenceNumber [%" PRIu16 "], bucketId <%s>", request->sequenceNumber(), request->bucketId().c_str()); diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 9d2c6ac..f5b2c96 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -40,6 +40,7 @@ public: virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); + virtual void execute(RequestContextPtr context, ListRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); @@ -49,6 +50,7 @@ public: private: RequestPtr deserializeAdminCheckRequest(void); RequestPtr deserializeInsertOrUpdateBucketRequest(void); + RequestPtr deserializeListRequest(void); RequestPtr deserializeRemoveBucketRequest(void); RequestPtr deserializeSetPoliciesRequest(void); diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 7bd67ae..36670c9 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -18,6 +18,7 @@ /** * @file src/common/protocol/ProtocolOpCode.h * @author Adam Malinowski + * @author Lukasz Wojciechowski * @version 1.0 * @brief Decalaration of protocol frame operation codes. */ @@ -44,8 +45,9 @@ enum ProtocolOpCode : uint8_t { OpSetPolicies, OpCodeResponse, OpAdminCheckRequest, + OpListRequest, - /** Opcodes 25 - 39 are reserved for future use */ + /** Opcodes 26 - 39 are reserved for future use */ /** Agent operations */ OpAgentRegisterRequest = 40, -- 2.7.4 From 3b145f190dde648e4845ab3410a0fbe2fbbb36cf Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 29 Nov 2014 17:22:29 +0100 Subject: [PATCH 09/16] Handle ListResponse by ProtocolAdmin Add serialization and deserialization of ListResponse. Change-Id: I7df388bf105183732d76cc1c37122919ca6d23df --- src/common/protocol/ProtocolAdmin.cpp | 61 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAdmin.h | 2 ++ src/common/protocol/ProtocolOpCode.h | 5 +-- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 60341bc..0d646a4 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "ProtocolAdmin.h" @@ -221,6 +222,38 @@ ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) { m_frameHeader.sequenceNumber()); } +ResponsePtr ProtocolAdmin::deserializeListResponse(void) { + ProtocolFrameFieldsCount policiesCount; + PolicyKeyFeature::ValueType client, user, privilege; + PolicyType policyType; + PolicyResult::PolicyMetadata metadata; + std::vector policies; + + ProtocolDeserialization::deserialize(m_frameHeader, policiesCount); + policies.reserve(policiesCount); + + for (ProtocolFrameFieldsCount p = 0; p < policiesCount; ++p) { + // PolicyKey + ProtocolDeserialization::deserialize(m_frameHeader, client); + ProtocolDeserialization::deserialize(m_frameHeader, user); + ProtocolDeserialization::deserialize(m_frameHeader, privilege); + // PolicyResult + ProtocolDeserialization::deserialize(m_frameHeader, policyType); + ProtocolDeserialization::deserialize(m_frameHeader, metadata); + + policies.push_back(Policy(PolicyKey(client, user, privilege), + PolicyResult(policyType, metadata))); + } + + bool isBucketValid; + ProtocolDeserialization::deserialize(m_frameHeader, isBucketValid); + + LOGD("Deserialized ListResponse: number of policies [%" PRIu16 "], isBucketValid [%d]", + policiesCount, isBucketValid); + + return std::make_shared(policies, isBucketValid, m_frameHeader.sequenceNumber()); +} + ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) { ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); @@ -235,6 +268,8 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) return deserializeCheckResponse(); case OpCodeResponse: return deserializeCodeResponse(); + case OpListResponse: + return deserializeListResponse(); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); break; @@ -380,4 +415,30 @@ void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } +void ProtocolAdmin::execute(RequestContextPtr context, ListResponsePtr response) { + ProtocolFrameFieldsCount policiesSize + = static_cast(response->policies().size()); + + LOGD("Serializing ListResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " + "number of policies [%" PRIu16 "], isBucketValid [%d]", OpListResponse, + response->sequenceNumber(), policiesSize, response->isBucketValid()); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(response->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpListResponse); + ProtocolSerialization::serialize(frame, policiesSize); + for (auto &policy : response->policies()) { + // PolicyKey + ProtocolSerialization::serialize(frame, policy.key().client().value()); + ProtocolSerialization::serialize(frame, policy.key().user().value()); + ProtocolSerialization::serialize(frame, policy.key().privilege().value()); + // PolicyResult + ProtocolSerialization::serialize(frame, policy.result().policyType()); + ProtocolSerialization::serialize(frame, policy.result().metadata()); + } + ProtocolSerialization::serialize(frame, response->isBucketValid()); + + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); +} + } // namespace Cynara diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index f5b2c96..48421be 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -46,6 +46,7 @@ public: virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); + virtual void execute(RequestContextPtr context, ListResponsePtr response); private: RequestPtr deserializeAdminCheckRequest(void); @@ -56,6 +57,7 @@ private: ResponsePtr deserializeCheckResponse(void); ResponsePtr deserializeCodeResponse(void); + ResponsePtr deserializeListResponse(void); }; } // namespace Cynara diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 36670c9..69be21c 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -20,7 +20,7 @@ * @author Adam Malinowski * @author Lukasz Wojciechowski * @version 1.0 - * @brief Decalaration of protocol frame operation codes. + * @brief Declaration of protocol frame operation codes. */ #ifndef SRC_COMMON_TYPES_PROTOCOLOPCODE_H_ @@ -46,8 +46,9 @@ enum ProtocolOpCode : uint8_t { OpCodeResponse, OpAdminCheckRequest, OpListRequest, + OpListResponse, - /** Opcodes 26 - 39 are reserved for future use */ + /** Opcodes 27 - 39 are reserved for future use */ /** Agent operations */ OpAgentRegisterRequest = 40, -- 2.7.4 From bf46f5d43cd8c4c4da76684648d374717c947487 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 29 Nov 2014 23:24:00 +0100 Subject: [PATCH 10/16] Add tests for ListRequest and ListResponse Added tests cover testing serialization and deserialization of ListRequest and ListResponse classes by ProtocolAdmin. Change-Id: I19915d4712be51217a2be17776a21751cff4218d --- test/CMakeLists.txt | 18 ++ test/common/protocols/CommonsTestHelper.h | 39 ++++ test/common/protocols/RequestTestHelper.h | 78 ++++++++ test/common/protocols/ResponseTestHelper.h | 78 ++++++++ test/common/protocols/TestDataCollection.h | 86 +++++++++ test/common/protocols/admin/listrequest.cpp | 131 ++++++++++++++ test/common/protocols/admin/listresponse.cpp | 257 +++++++++++++++++++++++++++ 7 files changed, 687 insertions(+) create mode 100644 test/common/protocols/CommonsTestHelper.h create mode 100644 test/common/protocols/RequestTestHelper.h create mode 100644 test/common/protocols/ResponseTestHelper.h create mode 100644 test/common/protocols/TestDataCollection.h create mode 100644 test/common/protocols/admin/listrequest.cpp create mode 100644 test/common/protocols/admin/listresponse.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 063098f..19b8f13 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -23,6 +23,21 @@ ADD_DEFINITIONS("-DCYNARA_NO_LOGS") SET(CYNARA_SRC ${PROJECT_SOURCE_DIR}/src) SET(CYNARA_SOURCES_FOR_TESTS + ${CYNARA_SRC}/common/containers/BinaryQueue.cpp + ${CYNARA_SRC}/common/protocol/ProtocolAdmin.cpp + ${CYNARA_SRC}/common/protocol/ProtocolFrame.cpp + ${CYNARA_SRC}/common/protocol/ProtocolFrameHeader.cpp + ${CYNARA_SRC}/common/protocol/ProtocolFrameSerializer.cpp + ${CYNARA_SRC}/common/request/AdminCheckRequest.cpp + ${CYNARA_SRC}/common/request/InsertOrUpdateBucketRequest.cpp + ${CYNARA_SRC}/common/request/ListRequest.cpp + ${CYNARA_SRC}/common/request/RemoveBucketRequest.cpp + ${CYNARA_SRC}/common/request/RequestTaker.cpp + ${CYNARA_SRC}/common/request/SetPoliciesRequest.cpp + ${CYNARA_SRC}/common/response/CheckResponse.cpp + ${CYNARA_SRC}/common/response/CodeResponse.cpp + ${CYNARA_SRC}/common/response/ListResponse.cpp + ${CYNARA_SRC}/common/response/ResponseTaker.cpp ${CYNARA_SRC}/common/types/PolicyBucket.cpp ${CYNARA_SRC}/common/types/PolicyKey.cpp ${CYNARA_SRC}/common/types/PolicyKeyHelpers.cpp @@ -41,6 +56,8 @@ SET(CYNARA_SOURCES_FOR_TESTS SET(CYNARA_TESTS_SOURCES TestEventListenerProxy.cpp common/exceptions/bucketrecordcorrupted.cpp + common/protocols/admin/listrequest.cpp + common/protocols/admin/listresponse.cpp common/types/policybucket.cpp credsCommons/parser/Parser.cpp helpers.cpp @@ -66,6 +83,7 @@ INCLUDE_DIRECTORIES( ${CYNARA_SRC}/include ${CYNARA_SRC} credsCommons/parser + common/protocols ) ADD_EXECUTABLE(${TARGET_CYNARA_TESTS} diff --git a/test/common/protocols/CommonsTestHelper.h b/test/common/protocols/CommonsTestHelper.h new file mode 100644 index 0000000..a43e158 --- /dev/null +++ b/test/common/protocols/CommonsTestHelper.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 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 test/common/protocols/CommonsTestHelper.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Common helper functions for tests of serialization by protocols + */ + +#ifndef TEST_COMMON_PROTOCOLS_COMMONSTESTHELPER_H_ +#define TEST_COMMON_PROTOCOLS_COMMONSTESTHELPER_H_ + +#include + +namespace { + +template +void compare(const R &r1, const R &r2) { + (void) r1; + (void) r2; + ASSERT_FALSE("Specialization of compare function must be implemented!"); +} + +} /* namespace anonymous */ + +#endif /* TEST_COMMON_PROTOCOLS_COMMONSTESTHELPER_H_ */ diff --git a/test/common/protocols/RequestTestHelper.h b/test/common/protocols/RequestTestHelper.h new file mode 100644 index 0000000..9274a46 --- /dev/null +++ b/test/common/protocols/RequestTestHelper.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 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 test/common/protocols/RequestTestHelper.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Helper functions for tests of request serialization by protocols + */ + +#ifndef TEST_COMMON_PROTOCOLS_REQUESTTESTHELPER_H_ +#define TEST_COMMON_PROTOCOLS_REQUESTTESTHELPER_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "CommonsTestHelper.h" + +namespace { +namespace RequestTestHelper { + +template +void testRequest(std::shared_ptr request, Cynara::ProtocolPtr protocol) { + auto queue = std::make_shared(); + auto context = std::make_shared(Cynara::ResponseTakerPtr(), queue); + + request->execute(request, protocol, context); + + auto extractedRequest = protocol->extractRequestFromBuffer(queue); + ASSERT_TRUE(bool(extractedRequest)); + ASSERT_EQ(queue->size(), 0); + + compare(*request, dynamic_cast(*extractedRequest)); +} + +void binaryTestRequest(Cynara::RequestPtr request, Cynara::ProtocolPtr protocol) { + auto queue = std::make_shared(); + auto context = std::make_shared(Cynara::ResponseTakerPtr(), queue); + + request->execute(request, protocol, context); + Cynara::RawBuffer data(queue->size()); + queue->flatten(data.data(), queue->size()); + + auto extractedRequest = protocol->extractRequestFromBuffer(queue); + ASSERT_TRUE(bool(extractedRequest)); + ASSERT_EQ(queue->size(), 0); + + extractedRequest->execute(extractedRequest, protocol, context); + Cynara::RawBuffer data2(queue->size()); + queue->flatten(data2.data(), queue->size()); + + ASSERT_EQ(data, data2); +} + +} /* namespace RequestTestHelper */ +} /* namespace anonymous */ + +#endif /* TEST_COMMON_PROTOCOLS_REQUESTTESTHELPER_H_ */ diff --git a/test/common/protocols/ResponseTestHelper.h b/test/common/protocols/ResponseTestHelper.h new file mode 100644 index 0000000..63e658b --- /dev/null +++ b/test/common/protocols/ResponseTestHelper.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 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 test/common/protocols/ResponseTestHelper.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Helper functions for tests of response serialization by protocols + */ + +#ifndef TEST_COMMON_PROTOCOLS_RESPONSETESTHELPER_H_ +#define TEST_COMMON_PROTOCOLS_RESPONSETESTHELPER_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "CommonsTestHelper.h" + +namespace { +namespace ResponseTestHelper { + +template +void testResponse(std::shared_ptr response, Cynara::ProtocolPtr protocol) { + auto queue = std::make_shared(); + auto context = std::make_shared(Cynara::ResponseTakerPtr(), queue); + + response->execute(response, protocol, context); + + auto extractedResponse = protocol->extractResponseFromBuffer(queue); + ASSERT_TRUE(bool(extractedResponse)); + ASSERT_EQ(queue->size(), 0); + + compare(*response, dynamic_cast(*extractedResponse)); +} + +void binaryTestResponse(Cynara::ResponsePtr response, Cynara::ProtocolPtr protocol) { + auto queue = std::make_shared(); + auto context = std::make_shared(Cynara::ResponseTakerPtr(), queue); + + response->execute(response, protocol, context); + Cynara::RawBuffer data(queue->size()); + queue->flatten(data.data(), queue->size()); + + auto extractedResponse = protocol->extractResponseFromBuffer(queue); + ASSERT_TRUE(bool(extractedResponse)); + ASSERT_EQ(queue->size(), 0); + + extractedResponse->execute(extractedResponse, protocol, context); + Cynara::RawBuffer data2(queue->size()); + queue->flatten(data2.data(), queue->size()); + + ASSERT_EQ(data, data2); +} + +} /* namespace ResponseTestHelper */ +} /* namespace anonymous */ + +#endif /* TEST_COMMON_PROTOCOLS_RESPONSETESTHELPER_H_ */ diff --git a/test/common/protocols/TestDataCollection.h b/test/common/protocols/TestDataCollection.h new file mode 100644 index 0000000..cf7c323 --- /dev/null +++ b/test/common/protocols/TestDataCollection.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 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 test/common/protocols/TestDataCollection.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Collection of sample data for protocol tests + */ + +#ifndef TEST_COMMON_PROTOCOLS_TESTDATACOLLECTION_H_ +#define TEST_COMMON_PROTOCOLS_TESTDATACOLLECTION_H_ + +#include + +#include +#include +#include +#include +#include + +namespace { +namespace TestDataCollection { + +typedef Cynara::PolicyKeyFeature PKF; + +namespace Keys { + static const Cynara::PolicyKey k_nun(PKF::create(""), PKF::create("u"), PKF::create("")); + static const Cynara::PolicyKey k_cup(PKF::create("c"), PKF::create("u"), PKF::create("p")); + static const Cynara::PolicyKey k_www(PKF::createWildcard(), PKF::createWildcard(), + PKF::createWildcard()); + static const Cynara::PolicyKey k_wuw(PKF::createWildcard(), PKF::create("u"), + PKF::createWildcard()); + static const Cynara::PolicyKey k_aaa(PKF::createAny(), PKF::createAny(), PKF::createAny()); + static const Cynara::PolicyKey k_wua(PKF::createWildcard(), PKF::create("u"), PKF::createAny()); + static const Cynara::PolicyKey k_nua(PKF::create(""), PKF::create("u"), PKF::createAny()); +} /* namespace Keys */ + +namespace SN { + static const Cynara::ProtocolFrameSequenceNumber min(0); + static const Cynara::ProtocolFrameSequenceNumber min_1(min + 1); + static const Cynara::ProtocolFrameSequenceNumber min_2(min + 2); + static const Cynara::ProtocolFrameSequenceNumber max(UINT16_MAX); + static const Cynara::ProtocolFrameSequenceNumber max_1(max - 1); + static const Cynara::ProtocolFrameSequenceNumber max_2(max - 2); + static const Cynara::ProtocolFrameSequenceNumber mid((min + max) / 2); +} /* namespace SN */ + +namespace Buckets { + static const Cynara::PolicyBucketId empty(""); + static const Cynara::PolicyBucketId not_empty("testBucket_1"); +} /* namespace Buckets */ + +namespace Types { + static const Cynara::PolicyType allow(Cynara::PredefinedPolicyType::ALLOW); + static const Cynara::PolicyType deny(Cynara::PredefinedPolicyType::DENY); + static const Cynara::PolicyType bucket(Cynara::PredefinedPolicyType::BUCKET); + static const Cynara::PolicyType none(Cynara::PredefinedPolicyType::NONE); + static const Cynara::PolicyType plugin_type(100); +} /* namespace Types */ + +namespace Results { + static const Cynara::PolicyResult allow(Types::allow, ""); + static const Cynara::PolicyResult deny(Types::deny, ""); + static const Cynara::PolicyResult bucket_empty(Types::bucket, Buckets::empty); + static const Cynara::PolicyResult bucket_not_empty(Types::bucket, Buckets::not_empty); + static const Cynara::PolicyResult none(Types::none, ""); + static const Cynara::PolicyResult plugin_1(Types::plugin_type, ""); + static const Cynara::PolicyResult plugin_2(Types::plugin_type, "meta_data_2"); +} /* namespace Results */ +} /* namespace TestDataCollection */ +} /* namespace anonymous */ + +#endif /* TEST_COMMON_PROTOCOLS_TESTDATACOLLECTION_H_ */ diff --git a/test/common/protocols/admin/listrequest.cpp b/test/common/protocols/admin/listrequest.cpp new file mode 100644 index 0000000..06f80cb --- /dev/null +++ b/test/common/protocols/admin/listrequest.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014 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 test/common/protocols/admin/listrequest.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Tests for Cynara::ListRequest usage in Cynara::ProtocolAdmin + */ + +#include + +#include +#include + +#include +#include + +namespace { + +template<> +void compare(const Cynara::ListRequest &req1, const Cynara::ListRequest &req2) { + EXPECT_EQ(req1.bucket(), req2.bucket()); + EXPECT_EQ(req1.filter(), req2.filter()); +} + +} /* namespace anonymous */ + +using namespace Cynara; +using namespace RequestTestHelper; +using namespace TestDataCollection; + +/* *** compare by objects test cases *** */ + +TEST(ProtocolAdmin, ListRequest01) { + auto request = std::make_shared(Buckets::empty, Keys::k_nun, SN::min); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequest02) { + auto request = std::make_shared(Buckets::not_empty, Keys::k_cup, SN::min_1); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequest03) { + auto request = std::make_shared(Buckets::empty, Keys::k_www, SN::min_2); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequest04) { + auto request = std::make_shared(Buckets::not_empty, Keys::k_wuw, SN::max); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequest05) { + auto request = std::make_shared(Buckets::empty, Keys::k_aaa, SN::max_1); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequest06) { + auto request = std::make_shared(Buckets::not_empty, Keys::k_wua, SN::max_2); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequest07) { + auto request = std::make_shared(Buckets::empty, Keys::k_nua, SN::mid); + auto protocol = std::make_shared(); + testRequest(request, protocol); +} + +/* *** compare by serialized data test cases *** */ + +TEST(ProtocolAdmin, ListRequestBinary01) { + auto request = std::make_shared(Buckets::empty, Keys::k_nun, SN::min); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequestBinary02) { + auto request = std::make_shared(Buckets::not_empty, Keys::k_cup, SN::min_1); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequestBinary03) { + auto request = std::make_shared(Buckets::empty, Keys::k_www, SN::min_2); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequestBinary04) { + auto request = std::make_shared(Buckets::not_empty, Keys::k_wuw, SN::max); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequestBinary05) { + auto request = std::make_shared(Buckets::empty, Keys::k_aaa, SN::max_1); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequestBinary06) { + auto request = std::make_shared(Buckets::not_empty, Keys::k_wua, SN::max_2); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} + +TEST(ProtocolAdmin, ListRequestBinary07) { + auto request = std::make_shared(Buckets::empty, Keys::k_nua, SN::mid); + auto protocol = std::make_shared(); + binaryTestRequest(request, protocol); +} diff --git a/test/common/protocols/admin/listresponse.cpp b/test/common/protocols/admin/listresponse.cpp new file mode 100644 index 0000000..fddd2ca --- /dev/null +++ b/test/common/protocols/admin/listresponse.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2014 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 test/common/protocols/admin/listresponse.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Tests for Cynara::ListResponse usage in Cynara::ProtocolAdmin + */ + +#include + +#include + +#include +#include +#include + +#include +#include + +namespace { + +template<> +void compare(const Cynara::ListResponse &resp1, const Cynara::ListResponse &resp2) { + EXPECT_EQ(resp1.policies(), resp2.policies()); + EXPECT_EQ(resp1.isBucketValid(), resp2.isBucketValid()); +} + +static const bool VALID_BUCKET = true; +static const bool NO_BUCKET = false; + +} /* namespace anonymous */ + +using namespace Cynara; +using namespace ResponseTestHelper; +using namespace TestDataCollection; + +/* *** compare by objects test cases *** */ + +TEST(ProtocolAdmin, ListResponse01) { + std::vector policies = { + Policy(Keys::k_nun, Results::allow), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponse02) { + std::vector policies = { + Policy(Keys::k_cup, Results::deny), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min_1); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponse03) { + std::vector policies = { + Policy(Keys::k_www, Results::bucket_empty), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min_2); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponse04) { + std::vector policies = { + Policy(Keys::k_wuw, Results::bucket_not_empty), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::max); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponse05) { + std::vector policies = { + Policy(Keys::k_aaa, Results::none), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::max_1); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponse06) { + std::vector policies = { + Policy(Keys::k_wua, Results::plugin_1), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::max_2); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponse07) { + std::vector policies = { + Policy(Keys::k_nua, Results::plugin_2), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::mid); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseMultiplePolicies) { + std::vector policies = { + Policy(Keys::k_nun, Results::allow), + Policy(Keys::k_cup, Results::deny), + Policy(Keys::k_www, Results::bucket_empty), + Policy(Keys::k_wuw, Results::bucket_not_empty), + Policy(Keys::k_aaa, Results::none), + Policy(Keys::k_wua, Results::plugin_1), + Policy(Keys::k_nua, Results::plugin_2), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseEmptyPolicies) { + std::vector policies; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min_1); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseNoBucket) { + std::vector policies; + + auto response = std::make_shared(policies, NO_BUCKET, SN::min_2); + auto protocol = std::make_shared(); + testResponse(response, protocol); +} + +/* *** compare by serialized data test cases *** */ + +TEST(ProtocolAdmin, ListResponseBinary01) { + std::vector policies = { + Policy(Keys::k_nun, Results::allow), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinary02) { + std::vector policies = { + Policy(Keys::k_cup, Results::deny), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min_1); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinary03) { + std::vector policies = { + Policy(Keys::k_www, Results::bucket_empty), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min_2); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinary04) { + std::vector policies = { + Policy(Keys::k_wuw, Results::bucket_not_empty), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::max); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinary05) { + std::vector policies = { + Policy(Keys::k_aaa, Results::none), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::max_1); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinary06) { + std::vector policies = { + Policy(Keys::k_wua, Results::plugin_1), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::max_2); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinary07) { + std::vector policies = { + Policy(Keys::k_nua, Results::plugin_2), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::mid); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinaryMultiplePolicies) { + std::vector policies = { + Policy(Keys::k_nun, Results::allow), + Policy(Keys::k_cup, Results::deny), + Policy(Keys::k_www, Results::bucket_empty), + Policy(Keys::k_wuw, Results::bucket_not_empty), + Policy(Keys::k_aaa, Results::none), + Policy(Keys::k_wua, Results::plugin_1), + Policy(Keys::k_nua, Results::plugin_2), + }; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinaryEmptyPolicies) { + std::vector policies; + + auto response = std::make_shared(policies, VALID_BUCKET, SN::min_1); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} + +TEST(ProtocolAdmin, ListResponseBinaryNoBucket) { + std::vector policies; + + auto response = std::make_shared(policies, NO_BUCKET, SN::min_2); + auto protocol = std::make_shared(); + binaryTestResponse(response, protocol); +} -- 2.7.4 From 2deb5d0f10c156a80c2d453a99b898dcbbcff944 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sun, 30 Nov 2014 00:19:55 +0100 Subject: [PATCH 11/16] Implement listPolicies() in libcynara-admin Logic Implementation sends ListRequest object to cynara service and expects ListResponse. Change-Id: I5602e815a0b5070b79a02538b1823290380d66c8 --- src/admin/logic/Logic.cpp | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 1bf8a8a..6648189 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -33,11 +33,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -154,9 +156,39 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P return CYNARA_API_SUCCESS; } -int Logic::listPolicies(const PolicyBucketId &bucket UNUSED, const PolicyKey &filter UNUSED, - std::vector &policies UNUSED) { - //stub +int Logic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter, + std::vector &policies) { + if (!ensureConnection()) { + LOGE("Cannot connect to cynara. Service not available."); + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } + + ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); + + //Ask cynara service + ListResponsePtr listResponse; + + RequestPtr request = std::make_shared(bucket, filter, sequenceNumber); + ResponsePtr response; + while (!(response = m_socketClient->askCynaraServer(request))) { + if (!m_socketClient->connect()) + return CYNARA_API_SERVICE_NOT_AVAILABLE; + } + + listResponse = std::dynamic_pointer_cast(response); + if (!listResponse) { + LOGC("Casting Response to ListResponse failed."); + return CYNARA_API_UNKNOWN_ERROR; + } + + LOGD("listResponse: number of policies [%zu], bucketValid [%d]", + listResponse->policies().size(), listResponse->isBucketValid()); + + if (!listResponse->isBucketValid()) { + return CYNARA_API_BUCKET_NOT_FOUND; + } + + policies = listResponse->policies(); return CYNARA_API_SUCCESS; } -- 2.7.4 From df9ef16e6f017b9aa5b3ce4952324232b23a5900 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sun, 30 Nov 2014 00:46:28 +0100 Subject: [PATCH 12/16] Implement listing Policies in Storage Implement listPolicies() in Storage and InMemoryStorageBackend. UnitTests for Storage::listPolicies() were added. Change-Id: I113c3c0f9b5c1d1d5cbed44e3d23d5d7e489a227 --- src/common/types/PolicyBucket.cpp | 10 +++++++++ src/common/types/PolicyBucket.h | 3 +++ src/storage/InMemoryStorageBackend.cpp | 10 +++++++++ src/storage/InMemoryStorageBackend.h | 5 +++++ src/storage/Storage.cpp | 5 +++++ src/storage/Storage.h | 3 +++ src/storage/StorageBackend.h | 3 ++- test/storage/storage/fakestoragebackend.h | 4 ++-- test/storage/storage/policies.cpp | 37 +++++++++++++++++++++++++++++++ 9 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/common/types/PolicyBucket.cpp b/src/common/types/PolicyBucket.cpp index 622bc05..052ac35 100644 --- a/src/common/types/PolicyBucket.cpp +++ b/src/common/types/PolicyBucket.cpp @@ -89,6 +89,16 @@ void PolicyBucket::deletePolicy(std::function predicate) { } } +PolicyBucket::Policies PolicyBucket::listPolicies(const PolicyKey &filter) const { + PolicyBucket::Policies policies; + for (auto iter = m_policyCollection.begin(); iter != m_policyCollection.end(); ++iter) { + auto &policyPtr = iter->second; + if (policyPtr->key().matchFilter(filter)) + policies.push_back(*policyPtr); + } + return policies; +} + PolicyMap PolicyBucket::makePolicyMap(const PolicyCollection &policies) { PolicyMap result; for (const auto &policy : policies) { diff --git a/src/common/types/PolicyBucket.h b/src/common/types/PolicyBucket.h index df57d0f..262c7d3 100644 --- a/src/common/types/PolicyBucket.h +++ b/src/common/types/PolicyBucket.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,7 @@ public: typedef PolicyCollection::value_type value_type; typedef const_policy_iterator const_iterator; + typedef std::vector Policies; // TODO: Review usefulness of ctors //delete default constructor in order to prevent creation of buckets with no id @@ -62,6 +64,7 @@ public: PolicyBucket filtered(const PolicyKey &key) const; void insertPolicy(PolicyPtr policy); void deletePolicy(const PolicyKey &key); + Policies listPolicies(const PolicyKey &filter) const; // TODO: Try to change interface, so this method is not needed void deletePolicy(std::function predicate); diff --git a/src/storage/InMemoryStorageBackend.cpp b/src/storage/InMemoryStorageBackend.cpp index a2366e8..bc3d01a 100644 --- a/src/storage/InMemoryStorageBackend.cpp +++ b/src/storage/InMemoryStorageBackend.cpp @@ -201,6 +201,16 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) { } } +PolicyBucket::Policies InMemoryStorageBackend::listPolicies(const PolicyBucketId &bucketId, + const PolicyKey &filter) const { + try { + auto &bucket = buckets().at(bucketId); + return bucket.listPolicies(filter); + } catch (const std::out_of_range &) { + throw BucketNotExistsException(bucketId); + } +} + void InMemoryStorageBackend::openFileStream(std::shared_ptr stream, const std::string &filename) { // TODO: Consider adding exceptions to streams and handling them: diff --git a/src/storage/InMemoryStorageBackend.h b/src/storage/InMemoryStorageBackend.h index d03dd6c..07f7fcd 100644 --- a/src/storage/InMemoryStorageBackend.h +++ b/src/storage/InMemoryStorageBackend.h @@ -58,6 +58,8 @@ public: virtual bool hasBucket(const PolicyBucketId &bucketId); virtual void deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key); virtual void deleteLinking(const PolicyBucketId &bucketId); + virtual PolicyBucket::Policies listPolicies(const PolicyBucketId &bucketId, + const PolicyKey &filter) const; protected: InMemoryStorageBackend() {} @@ -80,6 +82,9 @@ protected: virtual Buckets &buckets(void) { return m_buckets; } + virtual const Buckets &buckets(void) const { + return m_buckets; + } }; } /* namespace Cynara */ diff --git a/src/storage/Storage.cpp b/src/storage/Storage.cpp index aa9bc93..fafb374 100644 --- a/src/storage/Storage.cpp +++ b/src/storage/Storage.cpp @@ -154,6 +154,11 @@ void Storage::deletePolicies(const std::map Date: Sun, 30 Nov 2014 01:48:42 +0100 Subject: [PATCH 13/16] Implement listPolicies() in service Logic layer Implementation lists policies from Storage and returns filled vector of Policies. It catches also BucketNotExistsException that is thrown when invalid bucket is passed in ListRequest. Change-Id: I7b3777b70f654d9a7324c6203e9f25eebb029f1e --- src/service/logic/Logic.cpp | 18 ++++++++++++++++++ src/service/logic/Logic.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 684eac3..679da17 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +52,8 @@ #include #include #include +#include +#include #include
#include @@ -277,6 +281,20 @@ void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr re request->sequenceNumber())); } +void Logic::execute(RequestContextPtr context, ListRequestPtr request) { + bool bucketValid = true; + + std::vector policies; + try { + policies = m_storage->listPolicies(request->bucket(), request->filter()); + } catch (const BucketNotExistsException &ex) { + bucketValid = false; + } + + context->returnResponse(context, std::make_shared(policies, bucketValid, + request->sequenceNumber())); +} + void Logic::execute(RequestContextPtr context, RemoveBucketRequestPtr request) { auto code = CodeResponse::Code::OK; try { diff --git a/src/service/logic/Logic.h b/src/service/logic/Logic.h index 33c5701..d347071 100644 --- a/src/service/logic/Logic.h +++ b/src/service/logic/Logic.h @@ -70,6 +70,7 @@ public: virtual void execute(RequestContextPtr context, CancelRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); + virtual void execute(RequestContextPtr context, ListRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); virtual void execute(RequestContextPtr context, SignalRequestPtr request); -- 2.7.4 From c71c10a540191e8905dc6c1215b5b676dc3819d8 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 5 Dec 2014 22:07:18 +0100 Subject: [PATCH 14/16] Introduce AdminCheckResponse class AdminCheckResponse is class for responses to AdminCheckRequests. It differs from CheckResponse as it contains additional information about existence of start bucket. Start bucket is BucketId provided by AdminCheckRequest from which policy search is started. Change-Id: I9858cfdb8a0acc0016a080eb850bbc65ec081a98 --- src/common/CMakeLists.txt | 1 + src/common/response/AdminCheckResponse.cpp | 34 +++++++++++++++++ src/common/response/AdminCheckResponse.h | 61 ++++++++++++++++++++++++++++++ src/common/response/ResponseTaker.cpp | 11 +++++- src/common/response/ResponseTaker.h | 1 + src/common/response/pointers.h | 3 ++ test/CMakeLists.txt | 1 + 7 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 src/common/response/AdminCheckResponse.cpp create mode 100644 src/common/response/AdminCheckResponse.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index f30d335..e01c325 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -50,6 +50,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/request/RequestTaker.cpp ${COMMON_PATH}/request/SetPoliciesRequest.cpp ${COMMON_PATH}/request/SignalRequest.cpp + ${COMMON_PATH}/response/AdminCheckResponse.cpp ${COMMON_PATH}/response/AgentActionResponse.cpp ${COMMON_PATH}/response/AgentRegisterResponse.cpp ${COMMON_PATH}/response/CancelResponse.cpp diff --git a/src/common/response/AdminCheckResponse.cpp b/src/common/response/AdminCheckResponse.cpp new file mode 100644 index 0000000..85ee425 --- /dev/null +++ b/src/common/response/AdminCheckResponse.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 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 src/common/response/AdminCheckResponse.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file implements admin check response class + */ + +#include + +#include "AdminCheckResponse.h" + +namespace Cynara { + +void AdminCheckResponse::execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/response/AdminCheckResponse.h b/src/common/response/AdminCheckResponse.h new file mode 100644 index 0000000..c2bbf30 --- /dev/null +++ b/src/common/response/AdminCheckResponse.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 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 src/common/response/AdminCheckResponse.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines response class for admin check request + */ + +#ifndef SRC_COMMON_RESPONSE_ADMINCHECKRESPONSE_H_ +#define SRC_COMMON_RESPONSE_ADMINCHECKRESPONSE_H_ + +#include + +#include +#include +#include + +namespace Cynara { + +class AdminCheckResponse : public Response { +public: + AdminCheckResponse(const PolicyResult &result, bool bucketValid, + ProtocolFrameSequenceNumber sequenceNumber) : + Response(sequenceNumber), m_result(result), m_bucketValid(bucketValid) { + } + + virtual ~AdminCheckResponse() {} + + virtual void execute(ResponsePtr self, ResponseTakerPtr taker, + RequestContextPtr context) const; + + const PolicyResult &result(void) const { + return m_result; + } + + bool isBucketValid(void) const { + return m_bucketValid; + } + +private: + const PolicyResult m_result; + bool m_bucketValid; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_RESPONSE_ADMINCHECKRESPONSE_H_ */ diff --git a/src/common/response/ResponseTaker.cpp b/src/common/response/ResponseTaker.cpp index 0de4371..af47659 100644 --- a/src/common/response/ResponseTaker.cpp +++ b/src/common/response/ResponseTaker.cpp @@ -28,11 +28,18 @@ namespace Cynara { -void ResponseTaker::execute(RequestContextPtr context UNUSED, AgentActionResponsePtr response UNUSED) { +void ResponseTaker::execute(RequestContextPtr context UNUSED, + AdminCheckResponsePtr response UNUSED) { throw NotImplementedException(); } -void ResponseTaker::execute(RequestContextPtr context UNUSED, AgentRegisterResponsePtr response UNUSED) { +void ResponseTaker::execute(RequestContextPtr context UNUSED, + AgentActionResponsePtr response UNUSED) { + throw NotImplementedException(); +} + +void ResponseTaker::execute(RequestContextPtr context UNUSED, + AgentRegisterResponsePtr response UNUSED) { throw NotImplementedException(); } diff --git a/src/common/response/ResponseTaker.h b/src/common/response/ResponseTaker.h index 721dc2a..20296af 100644 --- a/src/common/response/ResponseTaker.h +++ b/src/common/response/ResponseTaker.h @@ -33,6 +33,7 @@ public: ResponseTaker() = default; virtual ~ResponseTaker() {}; + virtual void execute(RequestContextPtr context, AdminCheckResponsePtr response); virtual void execute(RequestContextPtr context, AgentActionResponsePtr response); virtual void execute(RequestContextPtr context, AgentRegisterResponsePtr response); virtual void execute(RequestContextPtr context, CancelResponsePtr response); diff --git a/src/common/response/pointers.h b/src/common/response/pointers.h index c5fdb1d..5e26929 100644 --- a/src/common/response/pointers.h +++ b/src/common/response/pointers.h @@ -27,6 +27,9 @@ namespace Cynara { +class AdminCheckResponse; +typedef std::shared_ptr AdminCheckResponsePtr; + class AgentActionResponse; typedef std::shared_ptr AgentActionResponsePtr; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 19b8f13..5bb0a7e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,6 +34,7 @@ SET(CYNARA_SOURCES_FOR_TESTS ${CYNARA_SRC}/common/request/RemoveBucketRequest.cpp ${CYNARA_SRC}/common/request/RequestTaker.cpp ${CYNARA_SRC}/common/request/SetPoliciesRequest.cpp + ${CYNARA_SRC}/common/response/AdminCheckResponse.cpp ${CYNARA_SRC}/common/response/CheckResponse.cpp ${CYNARA_SRC}/common/response/CodeResponse.cpp ${CYNARA_SRC}/common/response/ListResponse.cpp -- 2.7.4 From 700193cd0946aaaf2bcac4b9fbfd8f61206967dd Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 5 Dec 2014 23:54:02 +0100 Subject: [PATCH 15/16] Serialize AdminCheckResponse by ProtocolAdmin Add serialization and deserialization of AdminCheckResponse by ProtocolAdmin. Change-Id: I727c44f5a599537887d75dca724c56a448107368 --- src/common/protocol/ProtocolAdmin.cpp | 38 +++++++++++++++++++++++++++++++++++ src/common/protocol/ProtocolAdmin.h | 2 ++ src/common/protocol/ProtocolOpCode.h | 3 ++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 0d646a4..2c1164e 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,24 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) { return nullptr; } +ResponsePtr ProtocolAdmin::deserializeAdminCheckResponse(void) { + PolicyType result; + PolicyResult::PolicyMetadata additionalInfo; + bool bucketValid; + + ProtocolDeserialization::deserialize(m_frameHeader, result); + ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo); + ProtocolDeserialization::deserialize(m_frameHeader, bucketValid); + + const PolicyResult policyResult(result, additionalInfo); + + LOGD("Deserialized AdminCheckResponse: result [%" PRIu16 "], metadata <%s>, bucketValid [%d]", + policyResult.policyType(), policyResult.metadata().c_str(), static_cast(bucketValid)); + + return std::make_shared(policyResult, bucketValid, + m_frameHeader.sequenceNumber()); +} + ResponsePtr ProtocolAdmin::deserializeCheckResponse(void) { PolicyType result; PolicyResult::PolicyMetadata additionalInfo; @@ -264,6 +283,8 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) ProtocolDeserialization::deserialize(m_frameHeader, opCode); LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { + case OpAdminCheckPolicyResponse: + return deserializeAdminCheckResponse(); case OpCheckPolicyResponse: return deserializeCheckResponse(); case OpCodeResponse: @@ -386,6 +407,23 @@ void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr req ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } +void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckResponsePtr response) { + LOGD("Serializing AdminCheckResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " + "policyType [%" PRIu16 "], metadata <%s>, bucketValid [%d]", OpAdminCheckPolicyResponse, + response->sequenceNumber(), response->result().policyType(), + response->result().metadata().c_str(), static_cast(response->isBucketValid())); + + ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( + response->sequenceNumber()); + + ProtocolSerialization::serialize(frame, OpAdminCheckPolicyResponse); + ProtocolSerialization::serialize(frame, response->result().policyType()); + ProtocolSerialization::serialize(frame, response->result().metadata()); + ProtocolSerialization::serialize(frame, response->isBucketValid()); + + ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); +} + void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response) { LOGD("Serializing CheckResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " "policyType [%" PRIu16 "], metadata <%s>", OpCheckPolicyResponse, diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 48421be..1454be2 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -44,6 +44,7 @@ public: virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); + virtual void execute(RequestContextPtr context, AdminCheckResponsePtr response); virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); virtual void execute(RequestContextPtr context, ListResponsePtr response); @@ -55,6 +56,7 @@ private: RequestPtr deserializeRemoveBucketRequest(void); RequestPtr deserializeSetPoliciesRequest(void); + ResponsePtr deserializeAdminCheckResponse(void); ResponsePtr deserializeCheckResponse(void); ResponsePtr deserializeCodeResponse(void); ResponsePtr deserializeListResponse(void); diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index 69be21c..984ddef 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -47,8 +47,9 @@ enum ProtocolOpCode : uint8_t { OpAdminCheckRequest, OpListRequest, OpListResponse, + OpAdminCheckPolicyResponse, - /** Opcodes 27 - 39 are reserved for future use */ + /** Opcodes 28 - 39 are reserved for future use */ /** Agent operations */ OpAgentRegisterRequest = 40, -- 2.7.4 From 6566b149fe740e5f4347da1df4c579bbfb1979ce Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Sat, 6 Dec 2014 00:37:20 +0100 Subject: [PATCH 16/16] Respond to AdminCheckRequest with AdminCheckResponse Change implementation of both service and admin library Logic layers so they use AdminCheckResponse instead of CheckResponse as a reply for AdminCheckRequest. This change allows passing additional information about existence or vacancy of start bucket given in AdminCheckRequest. In case of vacancy of such bucket in cynara database cynara-admin library returns CYNARA_API_BUCKET_NOT_FOUND from cynara_admin_check() function. This fixes also a bug that was hidden in service Logic. Passing unexisting bucket causes cynara service to stop because of an unhandled exception. Change-Id: Ibf65a69c35ba92ea62bee91a67f43975b97052ca --- src/admin/logic/Logic.cpp | 24 +++++++++++++++--------- src/common/protocol/ProtocolAdmin.cpp | 34 ---------------------------------- src/common/protocol/ProtocolAdmin.h | 2 -- src/service/logic/Logic.cpp | 13 ++++++++++--- 4 files changed, 25 insertions(+), 48 deletions(-) diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 6648189..7fef282 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -132,7 +132,7 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber(); //Ask cynara service - CheckResponsePtr checkResponse; + AdminCheckResponsePtr adminCheckResponse; RequestPtr request = std::make_shared(key, startBucket, recursive, sequenceNumber); @@ -142,17 +142,23 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P return CYNARA_API_SERVICE_NOT_AVAILABLE; } - checkResponse = std::dynamic_pointer_cast(response); - if (!checkResponse) { - LOGC("Casting Response to CheckResponse failed."); + adminCheckResponse = std::dynamic_pointer_cast(response); + if (!adminCheckResponse) { + LOGC("Casting Response to AdminCheckResponse failed."); return CYNARA_API_UNKNOWN_ERROR; } - LOGD("checkResponse: policyType [%" PRIu16 "], metadata <%s>", - checkResponse->m_resultRef.policyType(), - checkResponse->m_resultRef.metadata().c_str()); + LOGD("AdminCheckResponse: policyType [%" PRIu16 "], metadata <%s>, bucketValid [%d]", + adminCheckResponse->result().policyType(), adminCheckResponse->result().metadata().c_str(), + static_cast(adminCheckResponse->isBucketValid())); - result = checkResponse->m_resultRef; + if (!adminCheckResponse->isBucketValid()) { + LOGE("Bucket <%s> provided as startBucket in adminCheck does not exist in cynara database", + startBucket.c_str()); + return CYNARA_API_BUCKET_NOT_FOUND; + } + + result = adminCheckResponse->result(); return CYNARA_API_SUCCESS; } diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index 2c1164e..293db97 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -216,21 +215,6 @@ ResponsePtr ProtocolAdmin::deserializeAdminCheckResponse(void) { m_frameHeader.sequenceNumber()); } -ResponsePtr ProtocolAdmin::deserializeCheckResponse(void) { - PolicyType result; - PolicyResult::PolicyMetadata additionalInfo; - - ProtocolDeserialization::deserialize(m_frameHeader, result); - ProtocolDeserialization::deserialize(m_frameHeader, additionalInfo); - - const PolicyResult policyResult(result, additionalInfo); - - LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>", - policyResult.policyType(), policyResult.metadata().c_str()); - - return std::make_shared(policyResult, m_frameHeader.sequenceNumber()); -} - ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) { ProtocolResponseCode responseCode; ProtocolDeserialization::deserialize(m_frameHeader, responseCode); @@ -285,8 +269,6 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue) switch (opCode) { case OpAdminCheckPolicyResponse: return deserializeAdminCheckResponse(); - case OpCheckPolicyResponse: - return deserializeCheckResponse(); case OpCodeResponse: return deserializeCodeResponse(); case OpListResponse: @@ -424,22 +406,6 @@ void ProtocolAdmin::execute(RequestContextPtr context, AdminCheckResponsePtr res ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); } -void ProtocolAdmin::execute(RequestContextPtr context, CheckResponsePtr response) { - LOGD("Serializing CheckResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " - "policyType [%" PRIu16 "], metadata <%s>", OpCheckPolicyResponse, - response->sequenceNumber(), response->m_resultRef.policyType(), - response->m_resultRef.metadata().c_str()); - - ProtocolFrame frame = ProtocolFrameSerializer::startSerialization( - response->sequenceNumber()); - - ProtocolSerialization::serialize(frame, OpCheckPolicyResponse); - ProtocolSerialization::serialize(frame, response->m_resultRef.policyType()); - ProtocolSerialization::serialize(frame, response->m_resultRef.metadata()); - - ProtocolFrameSerializer::finishSerialization(frame, *(context->responseQueue())); -} - void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) { LOGD("Serializing CodeResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], " "code [%" PRIu16 "]", OpCodeResponse, response->sequenceNumber(), response->m_code); diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index 1454be2..b9c7e17 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -45,7 +45,6 @@ public: virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); virtual void execute(RequestContextPtr context, AdminCheckResponsePtr response); - virtual void execute(RequestContextPtr context, CheckResponsePtr response); virtual void execute(RequestContextPtr context, CodeResponsePtr response); virtual void execute(RequestContextPtr context, ListResponsePtr response); @@ -57,7 +56,6 @@ private: RequestPtr deserializeSetPoliciesRequest(void); ResponsePtr deserializeAdminCheckResponse(void); - ResponsePtr deserializeCheckResponse(void); ResponsePtr deserializeCodeResponse(void); ResponsePtr deserializeListResponse(void); }; diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 679da17..3445984 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -86,10 +87,16 @@ void Logic::execute(RequestContextPtr context UNUSED, SignalRequestPtr request) } void Logic::execute(RequestContextPtr context, AdminCheckRequestPtr request) { - PolicyResult result = m_storage->checkPolicy(request->key(), request->startBucket(), - request->recursive()); + PolicyResult result; + bool bucketValid = true; + try { + result = m_storage->checkPolicy(request->key(), request->startBucket(), + request->recursive()); + } catch (const BucketNotExistsException &ex) { + bucketValid = false; + } - context->returnResponse(context, std::make_shared(result, + context->returnResponse(context, std::make_shared(result, bucketValid, request->sequenceNumber())); } -- 2.7.4