Add cynara_admin_check_batch() to API 59/317559/6
authorKrzysztof Malysa <k.malysa@samsung.com>
Wed, 11 Sep 2024 16:48:46 +0000 (18:48 +0200)
committerKrzysztof Malysa <k.malysa@samsung.com>
Wed, 2 Oct 2024 10:07:27 +0000 (12:07 +0200)
Change-Id: I02b8aace1d195175799b10c83c1f74cf90039998

31 files changed:
src/admin/api/ApiInterface.h
src/admin/api/admin-api.cpp
src/admin/logic/Logic.cpp
src/admin/logic/Logic.h
src/admin/logic/OfflineLogic.cpp
src/admin/logic/OfflineLogic.h
src/admin/logic/OnlineLogic.cpp
src/admin/logic/OnlineLogic.h
src/common/CMakeLists.txt
src/common/protocol/ProtocolAdmin.cpp
src/common/protocol/ProtocolAdmin.h
src/common/protocol/ProtocolOpCode.h
src/common/request/AdminCheckBatchRequest.cpp [new file with mode: 0644]
src/common/request/AdminCheckBatchRequest.h [new file with mode: 0644]
src/common/request/RequestTaker.cpp
src/common/request/RequestTaker.h
src/common/request/pointers.h
src/common/response/AdminCheckBatchResponse.cpp [new file with mode: 0644]
src/common/response/AdminCheckBatchResponse.h [new file with mode: 0644]
src/common/response/ResponseTaker.cpp
src/common/response/ResponseTaker.h
src/common/response/pointers.h
src/common/types/AdminBatchCheck.h [new file with mode: 0644]
src/include/cynara-admin-types.h
src/include/cynara-admin.h
src/service/logic/Logic.cpp
src/service/logic/Logic.h
test/CMakeLists.txt
test/common/protocols/admin/admincheckbatchrequest.cpp [new file with mode: 0644]
test/common/protocols/admin/admincheckbatchresponse.cpp [new file with mode: 0644]
test/common/protocols/admin/iterateallcombinations.h [new file with mode: 0644]

index 025b42ad566fc8403931217e2c1fad8283f291e2..f2a98032680358daf6ed81cd5b383048601898ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -32,6 +32,7 @@
 #include <string>
 #include <vector>
 
+#include <types/AdminBatchCheck.h>
 #include <types/Policy.h>
 #include <types/PolicyBucketId.h>
 #include <types/PolicyDescription.h>
@@ -58,6 +59,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 adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                                std::vector<PolicyResult>& results) = 0;
     virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter,
                              std::vector<Policy> &policies) = 0;
     virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive,
index 9b6488425f0c9b568b13ab0f00939a580829f167..d53dcc9e9d3b9419a9c8bcf5468fdeda93eb3521 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -256,6 +256,63 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin,
     });
 }
 
+CYNARA_API
+int cynara_admin_check_batch(struct cynara_admin *p_cynara_admin,
+                             struct cynara_admin_batch_check* batch_checks,
+                             size_t batch_checks_len) {
+    if (!p_cynara_admin || !p_cynara_admin->impl)
+        return CYNARA_API_INVALID_PARAM;
+    if (!batch_checks)
+        return CYNARA_API_INVALID_PARAM;
+    if (batch_checks_len == 0 || batch_checks_len > CYNARA_MAX_VECTOR_SIZE)
+        return CYNARA_API_INVALID_PARAM;
+
+    for (size_t i = 0; i < batch_checks_len; ++i) {
+        const auto& batch_check = batch_checks[i];
+        if (!isStringValid(batch_check.start_bucket) || !isStringValid(batch_check.client))
+            return CYNARA_API_INVALID_PARAM;
+        if (!isStringValid(batch_check.user) || !isStringValid(batch_check.privilege))
+            return CYNARA_API_INVALID_PARAM;
+    }
+
+    return Cynara::tryCatch([&] {
+        std::vector<Cynara::AdminBatchCheck> checks(batch_checks_len);
+        for (size_t i = 0; i < batch_checks_len; ++i) {
+            checks[i].startBucket = std::string{batch_checks[i].start_bucket};
+            checks[i].recursive = batch_checks[i].recursive != 0;
+            checks[i].key = Cynara::PolicyKey{std::string{batch_checks[i].client},
+                                              std::string{batch_checks[i].user},
+                                              std::string{batch_checks[i].privilege}};
+        }
+
+        std::vector<Cynara::PolicyResult> results;
+        int ret = p_cynara_admin->impl->adminCheckBatch(checks, results);
+        if (ret != CYNARA_API_SUCCESS)
+            return ret;
+        if (results.size() != batch_checks_len)
+            return CYNARA_API_UNKNOWN_ERROR;
+
+        for (size_t i = 0; i < batch_checks_len; ++i) {
+            batch_checks[i].result = static_cast<int>(results[i].policyType());
+
+            const auto& res_metadata = results[i].metadata();
+            if (res_metadata.empty())
+                batch_checks[i].result_extra = nullptr;
+            else {
+                auto str = strdup(res_metadata.c_str());
+                if (!str) {
+                    for (size_t j = 0; j < i; ++j)
+                        free(batch_checks[j].result_extra);
+                    return CYNARA_API_OUT_OF_MEMORY;
+                }
+                batch_checks[i].result_extra = str;
+            }
+        }
+
+        return CYNARA_API_SUCCESS;
+    });
+}
+
 static int copyPolicy(const char *bucket, const Cynara::Policy &from, cynara_admin_policy *&to) {
     to = reinterpret_cast<cynara_admin_policy*>(calloc(1, sizeof(cynara_admin_policy)));
     if (!to)
index 5d4965ce2511f25e801b8b064a2c1155a9fb7f4b..15c750ba317406d8fac47539119402e671693ce9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -71,6 +71,14 @@ int Logic::adminCheck(const PolicyBucketId &startBucket, bool recursive, const P
                            recursive, std::cref(key), std::ref(result)));
 }
 
+int Logic::adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                           std::vector<PolicyResult>& results) {
+    using std::placeholders::_1;
+    return callApiFunction(std::bind(&ApiInterface::adminCheckBatch, _1, std::cref(checks),
+                           std::ref(results)));
+
+}
+
 int Logic::listDescriptions(std::vector<PolicyDescription> &descriptions) {
     using std::placeholders::_1;
     return callApiFunction(std::bind(&ApiInterface::listDescriptions, _1, std::ref(descriptions)));
index 4a047abd1f7c5d00b093c6a6bd378a135443fa3d..805593932277139a084ff7f0e8859f2c953bd9ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -57,6 +57,8 @@ public:
     virtual int removeBucket(const PolicyBucketId &bucket);
     virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive,
                            const PolicyKey &key, PolicyResult &result);
+    virtual int adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                                std::vector<PolicyResult>& results);
     virtual int listDescriptions(std::vector<PolicyDescription> &descriptions);
     virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter,
                              std::vector<Policy> &policies);
index 030e78c799ba0451fc3628351d7e78c20c4296fb..8c9d7f41e12c38bab9d87c4165c65bb8bfc020d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -170,6 +170,24 @@ int OfflineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive,
     return CYNARA_API_SUCCESS;
 }
 
+int OfflineLogic::adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                                  std::vector<PolicyResult>& results) {
+    try {
+        acquireDatabase();
+        results.resize(checks.size());
+        for (size_t i = 0; i < checks.size(); ++i) {
+            results[i] = m_storage->checkPolicy(checks[i].key, checks[i].startBucket,
+                                                checks[i].recursive);
+        }
+    } catch (const BucketNotExistsException &ex) {
+        return CYNARA_API_BUCKET_NOT_FOUND;
+    } catch (const DatabaseCorruptedException &) {
+        return CYNARA_API_DATABASE_CORRUPTED;
+    }
+
+    return CYNARA_API_SUCCESS;
+}
+
 int OfflineLogic::listDescriptions(std::vector<PolicyDescription> &descriptions) {
     acquirePlugins();
     descriptions = m_pluginManager->getPolicyDescriptions();
index 77b2070a8e8ed350a330c972e8897eebe79fff97..4aa4a885bbb64db145cccef85d15556447dfef79 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -54,6 +54,8 @@ public:
     int removeBucket(const PolicyBucketId &bucket);
     int adminCheck(const PolicyBucketId &startBucket, bool recursive,
                    const PolicyKey &key, PolicyResult &result);
+    int adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                        std::vector<PolicyResult>& results);
     int listDescriptions(std::vector<PolicyDescription> &descriptions);
     int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter,
                      std::vector<Policy> &policies);
index b303e9eceafbb162c8ca00532df2a617aa10cc84..28c8124074ccc5c2bc4f49b4a234a30143b7150c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -40,6 +40,7 @@
 #include <log/log.h>
 #include <protocol/Protocol.h>
 #include <protocol/ProtocolAdmin.h>
+#include <request/AdminCheckBatchRequest.h>
 #include <request/AdminCheckRequest.h>
 #include <request/DescriptionListRequest.h>
 #include <request/EraseRequest.h>
@@ -48,6 +49,7 @@
 #include <request/pointers.h>
 #include <request/RemoveBucketRequest.h>
 #include <request/SetPoliciesRequest.h>
+#include <response/AdminCheckBatchResponse.h>
 #include <response/AdminCheckResponse.h>
 #include <response/CodeResponse.h>
 #include <response/DescriptionListResponse.h>
@@ -185,6 +187,40 @@ int OnlineLogic::adminCheck(const PolicyBucketId &startBucket, bool recursive, c
     return CYNARA_API_SUCCESS;
 }
 
+int OnlineLogic::adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                                 std::vector<PolicyResult>& results) {
+
+    AdminCheckBatchResponsePtr adminCheckBatchResponse;
+    int ret = getResponse<AdminCheckBatchRequest>(adminCheckBatchResponse, checks);
+    if (ret != CYNARA_API_SUCCESS) {
+        return ret;
+    }
+
+    if (adminCheckBatchResponse->isDbCorrupted()) {
+        LOGC("Cynara service answered: Database is corrupted.");
+        return CYNARA_API_DATABASE_CORRUPTED;
+    }
+
+    if (!adminCheckBatchResponse->areAllBucketsValid()) {
+        LOGE("Some bucket provided as startBucket in adminCheckBatch does not exist in cynara database");
+        return CYNARA_API_BUCKET_NOT_FOUND;
+    }
+
+    if (adminCheckBatchResponse->results().size() != checks.size()) {
+        LOGE("Cynara service answered with the wrong number of results");
+        return CYNARA_API_UNKNOWN_ERROR;
+    }
+
+    results.resize(checks.size());
+    for (size_t i = 0; i < checks.size(); ++i) {
+        results[i] = adminCheckBatchResponse->results()[i];
+        LOGD("AdminCheckBatchResponse: [%zu] policyType [%" PRIu16 "], metadata <%s>", i,
+            results[i].policyType(), results[i].metadata().c_str());
+    }
+
+    return CYNARA_API_SUCCESS;
+}
+
 int OnlineLogic::listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter,
                         std::vector<Policy> &policies) {
     ListResponsePtr listResponse;
index c6304914843f0a73a775c30c056249ede06ed54c..b4ec4f1e64f6e068f217335fc7fa2aabe0427465 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -53,6 +53,8 @@ public:
     virtual int removeBucket(const PolicyBucketId &bucket);
     virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive,
                            const PolicyKey &key, PolicyResult &result);
+    virtual int adminCheckBatch(const std::vector<AdminBatchCheck>& checks,
+                                std::vector<PolicyResult>& results);
     virtual int listPolicies(const PolicyBucketId &bucket, const PolicyKey &filter,
                              std::vector<Policy> &policies);
     virtual int erasePolicies(const PolicyBucketId &startBucket, bool recursive,
index 80ab2ee624b4e1008a31e5fa85a7c83d3ba375ca..7699508854eaf01928309e44139183432cf80c3d 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
 #
 # This file is licensed under the terms of MIT License or the Apache License
 # Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -49,6 +49,7 @@ SET(COMMON_SOURCES
     ${COMMON_PATH}/protocol/ProtocolMonitorGet.cpp
     ${COMMON_PATH}/protocol/ProtocolSerialization.cpp
     ${COMMON_PATH}/protocol/ProtocolSignal.cpp
+    ${COMMON_PATH}/request/AdminCheckBatchRequest.cpp
     ${COMMON_PATH}/request/AdminCheckRequest.cpp
     ${COMMON_PATH}/request/AgentActionRequest.cpp
     ${COMMON_PATH}/request/AgentRegisterRequest.cpp
@@ -67,6 +68,7 @@ SET(COMMON_SOURCES
     ${COMMON_PATH}/request/SetPoliciesRequest.cpp
     ${COMMON_PATH}/request/SignalRequest.cpp
     ${COMMON_PATH}/request/SimpleCheckRequest.cpp
+    ${COMMON_PATH}/response/AdminCheckBatchResponse.cpp
     ${COMMON_PATH}/response/AdminCheckResponse.cpp
     ${COMMON_PATH}/response/AgentActionResponse.cpp
     ${COMMON_PATH}/response/AgentRegisterResponse.cpp
index 1266ef38213ae6cf60b82492a18eb8d051b43386..7e3ee0ab8c8306ddbf5ce3c78e16f9a605032dc5 100644 (file)
  */
 
 #include <cinttypes>
+#include <cstdint>
 #include <memory>
 
 #include <exceptions/InvalidProtocolException.h>
 #include <log/log.h>
 #include <protocol/ProtocolFrame.h>
 #include <protocol/ProtocolFrameSerializer.h>
+#include <protocol/ProtocolOpCode.h>
+#include <protocol/ProtocolSerialization.h>
+#include <request/AdminCheckBatchRequest.h>
 #include <request/AdminCheckRequest.h>
 #include <request/DescriptionListRequest.h>
 #include <request/EraseRequest.h>
 #include <request/InsertOrUpdateBucketRequest.h>
 #include <request/ListRequest.h>
+#include <request/pointers.h>
 #include <request/RemoveBucketRequest.h>
 #include <request/RequestContext.h>
 #include <request/SetPoliciesRequest.h>
+#include <response/AdminCheckBatchResponse.h>
 #include <response/AdminCheckResponse.h>
 #include <response/CodeResponse.h>
 #include <response/DescriptionListResponse.h>
 #include <response/ListResponse.h>
+#include <types/AdminBatchCheck.h>
 #include <types/PolicyKey.h>
+#include <types/PolicyResult.h>
 
 #include "ProtocolAdmin.h"
 
@@ -80,6 +88,30 @@ RequestPtr ProtocolAdmin::deserializeAdminCheckRequest(void) {
                                                m_frameHeader.sequenceNumber());
 }
 
+RequestPtr ProtocolAdmin::deserializeAdminCheckBatchRequest(void) {
+    uint32_t len;
+    ProtocolDeserialization::deserialize(m_frameHeader, len);
+
+    std::vector<AdminBatchCheck> checks(len);
+    for (auto& check : checks) {
+        ProtocolDeserialization::deserialize(m_frameHeader, check.key);
+        ProtocolDeserialization::deserialize(m_frameHeader, check.startBucket);
+        ProtocolDeserialization::deserialize(m_frameHeader, check.recursive);
+    }
+
+    LOGD("Deserialized AdminCheckBatchRequest: number of checks [%zu]", checks.size());
+    for (size_t i = 0; i < checks.size(); ++i) {
+        LOGD("Deserialized AdminCheckBatchRequest: check[%zu]: client <%s>, user <%s>, "
+             "privilege <%s>, startBucket <%s>, recursive [%d]",
+             i, checks[i].key.client().value().c_str(), checks[i].key.user().value().c_str(),
+             checks[i].key.privilege().value().c_str(), checks[i].startBucket.c_str(),
+             static_cast<int>(checks[i].recursive));
+    }
+
+    return std::make_shared<AdminCheckBatchRequest>(std::move(checks),
+                                                    m_frameHeader.sequenceNumber());
+}
+
 RequestPtr ProtocolAdmin::deserializeDescriptionListRequest(void) {
     LOGD("Deserialized DescriptionListRequest");
     return std::make_shared<DescriptionListRequest>(m_frameHeader.sequenceNumber());
@@ -173,6 +205,8 @@ RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueuePtr bufferQueue) {
         switch (opCode) {
         case OpAdminCheckRequest:
             return deserializeAdminCheckRequest();
+        case OpAdminCheckBatchRequest:
+            return deserializeAdminCheckBatchRequest();
         case OpDescriptionListRequest:
             return deserializeDescriptionListRequest();
         case OpEraseRequest:
@@ -215,6 +249,32 @@ ResponsePtr ProtocolAdmin::deserializeAdminCheckResponse(void) {
                                                 m_frameHeader.sequenceNumber());
 }
 
+ResponsePtr ProtocolAdmin::deserializeAdminCheckBatchResponse(void) {
+    uint32_t len;
+    bool allBucketsValid;
+    bool dbCorrupted;
+
+    ProtocolDeserialization::deserialize(m_frameHeader, len);
+    ProtocolDeserialization::deserialize(m_frameHeader, allBucketsValid);
+    ProtocolDeserialization::deserialize(m_frameHeader, dbCorrupted);
+
+    std::vector<PolicyResult> results(len);
+    for (auto& result : results)
+        ProtocolDeserialization::deserialize(m_frameHeader, result);
+
+    LOGD("Deserialized AdminCheckBatchResponse: sequenceNumber [%" PRIu16 "], "
+         "allBucketsValid [%d], dbCorrupted [%d], length [%zu]",
+         m_frameHeader.sequenceNumber(), static_cast<int>(allBucketsValid),
+         static_cast<int>(dbCorrupted), results.size());
+    for (size_t i = 0; i < results.size(); ++i) {
+        LOGD("Deserialized AdminCheckBatchResponse: result[%zu]: policyType[%" PRIu16 "], "
+             "metadata <%s>", i, results[i].policyType(), results[i].metadata().c_str());
+    }
+
+    return std::make_shared<AdminCheckBatchResponse>(std::move(results), allBucketsValid, dbCorrupted,
+                                                m_frameHeader.sequenceNumber());
+}
+
 ResponsePtr ProtocolAdmin::deserializeCodeResponse(void) {
     ProtocolResponseCode responseCode;
     ProtocolDeserialization::deserialize(m_frameHeader, responseCode);
@@ -270,6 +330,8 @@ ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueuePtr bufferQueue)
         switch (opCode) {
         case OpAdminCheckPolicyResponse:
             return deserializeAdminCheckResponse();
+        case OpAdminCheckBatchResponse:
+            return deserializeAdminCheckBatchResponse();
         case OpCodeResponse:
             return deserializeCodeResponse();
         case OpDescriptionListResponse:
@@ -302,6 +364,31 @@ void ProtocolAdmin::execute(const RequestContext &context, const AdminCheckReque
                                                  *context.responseQueue()->lock());
 }
 
+void ProtocolAdmin::execute(const RequestContext &context, const AdminCheckBatchRequest &request) {
+    LOGD("Serializing AdminCheckBatchRequest: sequenceNumber [%" PRIu16 "], number of checks [%zu]",
+         request.sequenceNumber(), request.checks().size());
+
+    ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request.sequenceNumber());
+
+    ProtocolSerialization::serialize(frame, OpAdminCheckBatchRequest);
+    ProtocolSerialization::serialize(frame, static_cast<uint32_t>(request.checks().size()));
+
+    for (size_t i = 0; i < request.checks().size(); ++i) {
+        const auto& check = request.checks()[i];
+        LOGD("Serializing AdminCheckBatchRequest: check[%zu]: client <%s>, user <%s>, "
+             "privilege <%s>, startBucket <%s>, recursive [%d]",
+             i, check.key.client().value().c_str(), check.key.user().value().c_str(),
+             check.key.privilege().value().c_str(), check.startBucket.c_str(),
+             static_cast<int>(check.recursive));
+
+        ProtocolSerialization::serialize(frame, check.key);
+        ProtocolSerialization::serialize(frame, check.startBucket);
+        ProtocolSerialization::serialize(frame, check.recursive);
+    }
+
+    ProtocolFrameSerializer::finishSerialization(frame, *context.responseQueue()->lock());
+}
+
 void ProtocolAdmin::execute(const RequestContext &context, const DescriptionListRequest &request) {
     LOGD("Serializing DescriptionListRequest");
     ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(request.sequenceNumber());
@@ -412,6 +499,32 @@ void ProtocolAdmin::execute(const RequestContext &context, const AdminCheckRespo
                                                  *context.responseQueue()->lock());
 }
 
+void ProtocolAdmin::execute(const RequestContext &context, const AdminCheckBatchResponse &response) {
+    LOGD("Serializing AdminCheckBatchResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], "
+         "allBucketsValid [%d], dbCorrupted [%d], length [%zu]",
+         OpAdminCheckBatchResponse, response.sequenceNumber(),
+         static_cast<int>(response.areAllBucketsValid()),
+         static_cast<int>(response.isDbCorrupted()), response.results().size());
+
+    ProtocolFrame frame = ProtocolFrameSerializer::startSerialization(
+            response.sequenceNumber());
+
+    ProtocolSerialization::serialize(frame, OpAdminCheckBatchResponse);
+    ProtocolSerialization::serialize(frame, static_cast<uint32_t>(response.results().size()));
+    ProtocolSerialization::serialize(frame, response.areAllBucketsValid());
+    ProtocolSerialization::serialize(frame, response.isDbCorrupted());
+
+    for (size_t i = 0; i < response.results().size(); ++i) {
+        const auto& result = response.results()[i];
+        LOGD("Serializing AdminCheckBatchResponse: result[%zu]: policyType[%" PRIu16 "], "
+             "metadata <%s>", i, result.policyType(), result.metadata().c_str());
+
+        ProtocolSerialization::serialize(frame, result);
+    }
+
+    ProtocolFrameSerializer::finishSerialization(frame, *context.responseQueue()->lock());
+}
+
 void ProtocolAdmin::execute(const RequestContext &context, const CodeResponse &response) {
     LOGD("Serializing CodeResponse: op [%" PRIu8 "], sequenceNumber [%" PRIu16 "], "
          "code [%" PRIu16 "]", OpCodeResponse, response.sequenceNumber(), response.m_code);
index c1ad23ec40d797867315705c00dde5cef7bf3cf4..1470bcbe6da1e7a99cb09b956acc4f493c9f3fc0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -46,6 +46,7 @@ public:
     using Protocol::execute;
 
     virtual void execute(const RequestContext &context, const AdminCheckRequest &request);
+    virtual void execute(const RequestContext &context, const AdminCheckBatchRequest &request);
     virtual void execute(const RequestContext &context, const DescriptionListRequest &request);
     virtual void execute(const RequestContext &context, const EraseRequest &request);
     virtual void execute(const RequestContext &context, const InsertOrUpdateBucketRequest &request);
@@ -54,12 +55,14 @@ public:
     virtual void execute(const RequestContext &context, const SetPoliciesRequest &request);
 
     virtual void execute(const RequestContext &context, const AdminCheckResponse &response);
+    virtual void execute(const RequestContext &context, const AdminCheckBatchResponse &response);
     virtual void execute(const RequestContext &context, const CodeResponse &response);
     virtual void execute(const RequestContext &context, const DescriptionListResponse &response);
     virtual void execute(const RequestContext &context, const ListResponse &response);
 
 private:
     RequestPtr deserializeAdminCheckRequest(void);
+    RequestPtr deserializeAdminCheckBatchRequest(void);
     RequestPtr deserializeDescriptionListRequest(void);
     RequestPtr deserializeEraseRequest(void);
     RequestPtr deserializeInsertOrUpdateBucketRequest(void);
@@ -68,6 +71,7 @@ private:
     RequestPtr deserializeSetPoliciesRequest(void);
 
     ResponsePtr deserializeAdminCheckResponse(void);
+    ResponsePtr deserializeAdminCheckBatchResponse(void);
     ResponsePtr deserializeCodeResponse(void);
     ResponsePtr deserializeDescriptionListResponse(void);
     ResponsePtr deserializeListResponse(void);
index 7a8a0d477553d8f38ef8fe95020bbf1a4569978d..767f98310306ecbca7aa1444df9974e22b974134 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
  *
@@ -61,8 +61,10 @@ enum ProtocolOpCode : uint8_t {
     OpEraseRequest,
     OpDescriptionListRequest,
     OpDescriptionListResponse,
+    OpAdminCheckBatchRequest,
+    OpAdminCheckBatchResponse,
 
-    /** Opcodes 31 - 39 are reserved for future use */
+    /** Opcodes 33 - 39 are reserved for future use */
 
     /** Agent operations */
     OpAgentRegisterRequest = 40,
diff --git a/src/common/request/AdminCheckBatchRequest.cpp b/src/common/request/AdminCheckBatchRequest.cpp
new file mode 100644 (file)
index 0000000..ede927f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/request/AdminCheckBatchRequest.cpp
+ * @author      Krzysztof Malysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       This file implements admin check batch request class
+ */
+
+#include <request/RequestTaker.h>
+
+#include "AdminCheckBatchRequest.h"
+
+namespace Cynara {
+
+void AdminCheckBatchRequest::execute(RequestTaker &taker, const RequestContext &context) const {
+    taker.execute(context, *this);
+}
+
+bool AdminCheckBatchRequest::canBeExecutedReadOnly(const ReadOnlyRequestTaker &taker) const {
+    return taker.canBeExecutedReadOnly(*this);
+}
+
+} // namespace Cynara
diff --git a/src/common/request/AdminCheckBatchRequest.h b/src/common/request/AdminCheckBatchRequest.h
new file mode 100644 (file)
index 0000000..e07b102
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/request/AdminCheckBatchRequest.h
+ * @author      Krzysztof Malysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       This file defines admin check batch request class
+ */
+
+#ifndef SRC_COMMON_REQUEST_ADMINCHECKBATCHREQUEST_H_
+#define SRC_COMMON_REQUEST_ADMINCHECKBATCHREQUEST_H_
+
+#include <vector>
+
+#include <types/AdminBatchCheck.h>
+
+#include <request/pointers.h>
+#include <request/Request.h>
+
+namespace Cynara {
+
+class AdminCheckBatchRequest : public Request {
+public:
+    AdminCheckBatchRequest(std::vector<AdminBatchCheck> checks,
+                           ProtocolFrameSequenceNumber sequenceNumber) :
+        Request(sequenceNumber), m_checks{std::move(checks)} {
+    }
+
+    virtual ~AdminCheckBatchRequest() = default;
+
+    const std::vector<AdminBatchCheck>& checks() const noexcept {
+        return m_checks;
+    }
+
+    void execute(RequestTaker &taker, const RequestContext &context) const override;
+
+    bool canBeExecutedReadOnly(const ReadOnlyRequestTaker& taker) const override;
+
+private:
+    const std::vector<AdminBatchCheck> m_checks;
+};
+
+} // namespace Cynara
+
+#endif /* SRC_COMMON_REQUEST_ADMINCHECKBATCHREQUEST_H_ */
index d550d8d4484ee343154c6fbfaceba937d551cd14..0483cf815f6edbb3af4031ebba59354d94f40074 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -39,6 +39,11 @@ void RequestTaker::execute(const RequestContext &context UNUSED,
     throw NotImplementedException();
 }
 
+void RequestTaker::execute(const RequestContext &context UNUSED,
+                           const AdminCheckBatchRequest &request UNUSED) {
+    throw NotImplementedException();
+}
+
 void RequestTaker::execute(const RequestContext &context UNUSED,
                            const AgentActionRequest &request UNUSED) {
     throw NotImplementedException();
index e3d37a4a9ccea582e8768e34ba47962990d86009..63be0d6d2a1338f3e4295fdc316e51592a74b737 100644 (file)
@@ -39,6 +39,7 @@ public:
     virtual ~RequestTaker() {};
 
     virtual void execute(const RequestContext &context, const AdminCheckRequest &request);
+    virtual void execute(const RequestContext &context, const AdminCheckBatchRequest &request);
     virtual void execute(const RequestContext &context, const AgentActionRequest &request);
     virtual void execute(const RequestContext &context, const AgentRegisterRequest &request);
     virtual void execute(const RequestContext &context, const CancelRequest &request);
@@ -62,6 +63,7 @@ public:
 class ReadOnlyRequestTaker : public RequestTaker {
 public:
     virtual bool canBeExecutedReadOnly(const AdminCheckRequest &request) const = 0;
+    virtual bool canBeExecutedReadOnly(const AdminCheckBatchRequest &request) const = 0;
     virtual bool canBeExecutedReadOnly(const AgentActionRequest &request) const = 0;
     virtual bool canBeExecutedReadOnly(const AgentRegisterRequest &request) const = 0;
     virtual bool canBeExecutedReadOnly(const CancelRequest &request) const = 0;
index 240ce93e07f39558cffaee888a4384565c4b4348..7866567fd607a70ab65138957b39c596ac83546a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -36,6 +36,9 @@ namespace Cynara {
 class AdminCheckRequest;
 typedef std::shared_ptr<AdminCheckRequest> AdminCheckRequestPtr;
 
+class AdminCheckBatchRequest;
+typedef std::shared_ptr<AdminCheckBatchRequest> AdminCheckBatchRequestPtr;
+
 class AgentActionRequest;
 typedef std::shared_ptr<AgentActionRequest> AgentActionRequestPtr;
 
diff --git a/src/common/response/AdminCheckBatchResponse.cpp b/src/common/response/AdminCheckBatchResponse.cpp
new file mode 100644 (file)
index 0000000..09cd46d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/AdminCheckBatchResponse.cpp
+ * @author      Krzysztof Malysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       This file implements admin check batch response class
+ */
+
+#include <response/ResponseTaker.h>
+
+#include "AdminCheckBatchResponse.h"
+
+namespace Cynara {
+
+void AdminCheckBatchResponse::execute(ResponseTaker &taker, const RequestContext &context) const {
+    taker.execute(context, *this);
+}
+
+} // namespace Cynara
diff --git a/src/common/response/AdminCheckBatchResponse.h b/src/common/response/AdminCheckBatchResponse.h
new file mode 100644 (file)
index 0000000..4014594
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/AdminCheckBatchResponse.h
+ * @author      Krzysztof Malysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       This file defines response class for admin check batch request
+ */
+
+#ifndef SRC_COMMON_RESPONSE_ADMINCHECKBATCHRESPONSE_H_
+#define SRC_COMMON_RESPONSE_ADMINCHECKBATCHRESPONSE_H_
+
+#include <vector>
+
+#include <types/PolicyResult.h>
+
+#include <request/pointers.h>
+#include <response/pointers.h>
+#include <response/Response.h>
+
+namespace Cynara {
+
+class AdminCheckBatchResponse : public Response {
+public:
+    AdminCheckBatchResponse(std::vector<PolicyResult> results, bool areAllBucketsValid,
+                            bool isDbCorrupted, ProtocolFrameSequenceNumber sequenceNumber) :
+            Response(sequenceNumber), m_results{std::move(results)},
+            m_areAllBucketsValid{areAllBucketsValid}, m_isDbCorrupted{isDbCorrupted} {
+        }
+
+    virtual ~AdminCheckBatchResponse() = default;
+
+    virtual void execute(ResponseTaker &taker, const RequestContext &context) const;
+
+    const std::vector<PolicyResult>& results() const noexcept {
+        return m_results;
+    }
+
+    bool areAllBucketsValid() const noexcept {
+        return m_areAllBucketsValid;
+    }
+
+    bool isDbCorrupted() const noexcept {
+        return m_isDbCorrupted;
+    }
+
+private:
+    const std::vector<PolicyResult> m_results;
+    const bool m_areAllBucketsValid;
+    const bool m_isDbCorrupted;
+};
+
+} // namespace Cynara
+
+#endif /* SRC_COMMON_RESPONSE_ADMINCHECKBATCHRESPONSE_H_ */
index 34930249587c0a353a9c45acc695dfe930e1c8b4..332daad971e15650b0f32bfdc203ecbb7766cfd3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -39,6 +39,11 @@ void ResponseTaker::execute(const RequestContext &context UNUSED,
     throw NotImplementedException();
 }
 
+void ResponseTaker::execute(const RequestContext &context UNUSED,
+                            const AdminCheckBatchResponse &response UNUSED) {
+    throw NotImplementedException();
+}
+
 void ResponseTaker::execute(const RequestContext &context UNUSED,
                             const AgentActionResponse &response UNUSED) {
     throw NotImplementedException();
index ea9d2dce60aa7874cfccdd7026187b97f286d21a..ca586209bce06d55c596b970ac0647116cb86aac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -40,6 +40,7 @@ public:
     virtual ~ResponseTaker() {};
 
     virtual void execute(const RequestContext &context, const AdminCheckResponse &response);
+    virtual void execute(const RequestContext &context, const AdminCheckBatchResponse &response);
     virtual void execute(const RequestContext &context, const AgentActionResponse &response);
     virtual void execute(const RequestContext &context, const AgentRegisterResponse &response);
     virtual void execute(const RequestContext &context, const CancelResponse &response);
index 25650b6082f434a35df78a8b504a9fd62a74f880..d36ed606b8b021168192665137da1390b34a7dc2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -36,6 +36,9 @@ namespace Cynara {
 class AdminCheckResponse;
 typedef std::shared_ptr<AdminCheckResponse> AdminCheckResponsePtr;
 
+class AdminCheckBatchResponse;
+typedef std::shared_ptr<AdminCheckBatchResponse> AdminCheckBatchResponsePtr;
+
 class AgentActionResponse;
 typedef std::shared_ptr<AgentActionResponse> AgentActionResponsePtr;
 
diff --git a/src/common/types/AdminBatchCheck.h b/src/common/types/AdminBatchCheck.h
new file mode 100644 (file)
index 0000000..362f339
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/types/AdminBatchCheck.h
+ * @author      Krzysztof Malysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       This file defines AdminBatchCheck - struct which defines a single admin batch check
+ */
+
+#ifndef CYNARA_COMMON_TYPES_ADMINBATCHCHECK_H_
+#define CYNARA_COMMON_TYPES_ADMINBATCHCHECK_H_
+
+#include <types/PolicyBucketId.h>
+#include <types/PolicyKey.h>
+
+namespace Cynara {
+
+struct AdminBatchCheck {
+    PolicyBucketId startBucket;
+    bool recursive;
+    PolicyKey key;
+};
+
+} /* namespace Cynara */
+
+
+#endif /* CYNARA_COMMON_TYPES_ADMINBATCHCHECK_H_ */
index 56eb14602fe336ec9fce54e02664c7826c119e78..13e0a3521f9c0eed18d38e8492b2da43c00f8e83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -51,6 +51,23 @@ struct cynara_admin_policy {
                              like e.g. name of bucket in case result == CYNARA_ADMIN_BUCKET */
 };
 
+/**
+ * \struct cynara_admin_batch_check
+ * \brief Defines input and output parameters of a single check for cynara_admin_check_batch()
+ */
+struct cynara_admin_batch_check {
+    const char *start_bucket; /**< name of bucket where the search would start */
+    int recursive;            /**< FALSE (== 0) : single bucket search;
+                                   TRUE  (!= 0) : search does not ignore policies leading to another
+                                                  buckets */
+    const char *client;       /**< application or process identifier */
+    const char *user;         /**< user running client */
+    const char *privilege;    /**< privilege that is a subject of the check */
+    int result;               /**< placeholder for matched policy type */
+    char *result_extra;       /**< placeholder for matched policy additional data (see
+                                   Important Notes! for cynara_admin_check_batch()) */
+};
+
 /**
  * \struct cynara_admin_policy_descr
  * \brief Describes policy of type given with result
index eafbaabe8d2e95e5171b2bab47b524fa5b30cded..38912b63f017424b14b81ed3ef5b4012d22d0244 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2024 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * This file is licensed under the terms of MIT License or the Apache License
  * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -31,6 +31,8 @@
 #ifndef CYNARA_ADMIN_H
 #define CYNARA_ADMIN_H
 
+#include <stddef.h>
+
 #include <cynara-admin-types.h>
 #include <cynara-error.h>
 #include <cynara-limits.h>
@@ -231,7 +233,7 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc
  * This API should be used to check type of matching policy for check request
  *
  * \par Typical use case:
- * Administrator of cynara want to know, what would cynara return to client, if asked about given
+ * Administrator of cynara wants to know, what would cynara return to client, if asked about given
  * access.
  *
  * \par Method of function operation:
@@ -277,6 +279,50 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin,
                        const char *client, const char *user, const char *privilege,
                        int *result, char **result_extra);
 
+/**
+ * \brief Raw batched check client and user access for given privilege without using plugins
+ *        extensions.
+ *
+ * \par Description:
+ * Raw batched check client and user access for given privilege without using plugins extensions.
+ *
+ * \par Purpose:
+ * This API should be used to check type of matching policies for batched check requests
+ *
+ * \par Typical use case:
+ * Administrator of cynara wants to know, what would cynara return to client, if asked about given
+ * accesses.
+ *
+ * \par Method of function operation:
+ * \parblock
+ * Function works the same way as cynara_admin_check(), but allows more than one check to be
+ * performed in one operation.
+ * \endparblock
+ *
+ * \par Sync (or) Async:
+ * This is a synchronous API.
+ *
+ * \par Important notes:
+ * \parblock
+ * batch_checks[i].result will store the result of the check.
+ * batch_checks[i].result_extra may be set to NULL if extra data are not used in matched policy
+ * If batch_checks[i].result_extra is not NULL, it contains a string allocated by cynara admin
+ * library with malloc(3) function and must be released with free(3) function.
+ *
+ * \p batch_checks_len cannot exceed CYNARA_MAX_VECTOR_SIZE or be equal to 0 and string length
+ * cannot exceed CYNARA_MAX_ID_LENGTH, otherwise CYNARA_API_INVALID_PARAM will be returned.
+ * \endparblock
+ *
+ * \param[in] p_cynara_admin cynara admin structure.
+ * \param[in,out] batch_checks cynara_admin_batch_check structure array.
+ * \param[in] batch_checks_len cynara_admin_batch_check structure array length.
+ *
+ * \return CYNARA_API_SUCCESS on success, or error code otherwise.
+ */
+int cynara_admin_check_batch(struct cynara_admin *p_cynara_admin,
+                             struct cynara_admin_batch_check* batch_checks,
+                             size_t batch_checks_len);
+
 /**
  * \brief Lists policies from single bucket in cynara database.
  *
index 8f0febf98e2f3b883e846a79dbe834ec9de3232a..506bd36ae2ef3c4dab9b3913d451658f78035fce 100644 (file)
@@ -47,6 +47,7 @@
 #include <exceptions/PluginNotFoundException.h>
 #include <exceptions/UnexpectedErrorException.h>
 #include <exceptions/UnknownPolicyTypeException.h>
+#include <request/AdminCheckBatchRequest.h>
 #include <request/AdminCheckRequest.h>
 #include <request/AgentActionRequest.h>
 #include <request/AgentRegisterRequest.h>
@@ -65,6 +66,7 @@
 #include <request/SetPoliciesRequest.h>
 #include <request/SignalRequest.h>
 #include <request/SimpleCheckRequest.h>
+#include <response/AdminCheckBatchResponse.h>
 #include <response/AdminCheckResponse.h>
 #include <response/AgentRegisterResponse.h>
 #include <response/CancelResponse.h>
@@ -75,6 +77,7 @@
 #include <response/MonitorGetEntriesResponse.h>
 #include <response/SimpleCheckResponse.h>
 #include <types/Policy.h>
+#include <types/PolicyResult.h>
 
 #include <main/Cynara.h>
 #include <agent/AgentManager.h>
@@ -113,6 +116,12 @@ void Logic::execute(const RequestContext &/*context*/, const AdminCheckRequest &
     throw UnexpectedErrorException{std::move(msg)};
 }
 
+void Logic::execute(const RequestContext &/*context*/, const AdminCheckBatchRequest &/*request*/) {
+    auto msg = std::string("This function (") + __PRETTY_FUNCTION__ + ") should not be called";
+    LOGE(msg.c_str());
+    throw UnexpectedErrorException{std::move(msg)};
+}
+
 void Logic::execute(const RequestContext &context, const AgentActionRequest &request) {
     AgentTalkerPtr talkerPtr = m_agentManager->getTalker(context.responseQueue(),
                                                          request.sequenceNumber());
@@ -568,6 +577,30 @@ void ReadOnlyLogic::execute(const RequestContext &context,
                                               request.sequenceNumber()));
 }
 
+void ReadOnlyLogic::execute(const RequestContext &context,
+                            const AdminCheckBatchRequest &request) {
+    std::vector<PolicyResult> results;
+    bool allBucketsValid = true;
+    if (m_dbCorrupted) {
+        allBucketsValid = false;
+    } else {
+        try {
+            results.resize(request.checks().size());
+            for (size_t i = 0; i < results.size(); ++i) {
+                const auto& check = request.checks()[i];
+                results[i] = m_storageClone->checkPolicy(check.key, check.startBucket,
+                                                         check.recursive);
+            }
+        } catch (const BucketNotExistsException& ex) {
+            allBucketsValid = false;
+            results.clear();
+        }
+    }
+
+    context.returnResponse(AdminCheckBatchResponse(std::move(results), allBucketsValid,
+                                                   m_dbCorrupted, request.sequenceNumber()));
+}
+
 void ReadOnlyLogic::execute(const RequestContext &context, const CheckRequest &request) {
     const auto& key = request.key();
 
@@ -640,6 +673,10 @@ bool ReadOnlyLogic::canBeExecutedReadOnly(const AdminCheckRequest &/*request*/)
     return true;
 }
 
+bool ReadOnlyLogic::canBeExecutedReadOnly(const AdminCheckBatchRequest &/*request*/) const {
+    return true;
+}
+
 bool ReadOnlyLogic::canBeExecutedReadOnly(const AgentActionRequest &/*request*/) const {
     return false;
 }
index f3dd15729d644c27b741c6b0148f001fd9400825..93960c4faa9292409ad363dbd24befeb2d97efd3 100644 (file)
@@ -90,6 +90,7 @@ public:
     }
 
     virtual void execute(const RequestContext &context, const AdminCheckRequest &request);
+    virtual void execute(const RequestContext &context, const AdminCheckBatchRequest &request);
     virtual void execute(const RequestContext &context, const AgentActionRequest &request);
     virtual void execute(const RequestContext &context, const AgentRegisterRequest &request);
     virtual void execute(const RequestContext &context, const CancelRequest &request);
@@ -146,6 +147,7 @@ public:
                   std::unique_ptr<PluginManagerReadOnlyCopy> pluginManagerClone);
 
     void execute(const RequestContext &context, const AdminCheckRequest &request) override;
+    void execute(const RequestContext &context, const AdminCheckBatchRequest &request) override;
     void execute(const RequestContext &context, const CheckRequest &request) override;
     void execute(const RequestContext &context, const DescriptionListRequest &request) override;
     void execute(const RequestContext &context, const ListRequest &request) override;
@@ -154,6 +156,7 @@ public:
     void contextClosed(const RequestContext &context) override;
 
     bool canBeExecutedReadOnly(const AdminCheckRequest &request) const override;
+    bool canBeExecutedReadOnly(const AdminCheckBatchRequest &request) const override;
     bool canBeExecutedReadOnly(const AgentActionRequest &request) const override;
     bool canBeExecutedReadOnly(const AgentRegisterRequest &request) const override;
     bool canBeExecutedReadOnly(const CancelRequest &request) const override;
index 06f4ddbe8eda58964d32a76e78f6337bcc259d56..04a0c059c7be335f5855178f2f205f8e86567ddb 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2014-2024 Samsung Electronics Co., Ltd All Rights Reserved
 #
 # This file is licensed under the terms of MIT License or the Apache License
 # Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -91,6 +91,7 @@ SET(CYNARA_SOURCES_FOR_TESTS
     ${CYNARA_SRC}/common/protocol/ProtocolFrameHeader.cpp
     ${CYNARA_SRC}/common/protocol/ProtocolFrameSerializer.cpp
     ${CYNARA_SRC}/common/protocol/ProtocolMonitorGet.cpp
+    ${CYNARA_SRC}/common/request/AdminCheckBatchRequest.cpp
     ${CYNARA_SRC}/common/request/AdminCheckRequest.cpp
     ${CYNARA_SRC}/common/request/AgentActionRequest.cpp
     ${CYNARA_SRC}/common/request/AgentRegisterRequest.cpp
@@ -109,6 +110,7 @@ SET(CYNARA_SOURCES_FOR_TESTS
     ${CYNARA_SRC}/common/request/SetPoliciesRequest.cpp
     ${CYNARA_SRC}/common/request/SignalRequest.cpp
     ${CYNARA_SRC}/common/request/SimpleCheckRequest.cpp
+    ${CYNARA_SRC}/common/response/AdminCheckBatchResponse.cpp
     ${CYNARA_SRC}/common/response/AdminCheckResponse.cpp
     ${CYNARA_SRC}/common/response/DescriptionListResponse.cpp
     ${CYNARA_SRC}/common/response/AgentActionResponse.cpp
@@ -163,6 +165,8 @@ SET(CYNARA_TESTS_SOURCES
     common/error/safestrerror.cpp
     common/exceptions/bucketrecordcorrupted.cpp
     common/exceptions/trycatch.cpp
+    common/protocols/admin/admincheckbatchrequest.cpp
+    common/protocols/admin/admincheckbatchresponse.cpp
     common/protocols/admin/admincheckrequest.cpp
     common/protocols/admin/admincheckresponse.cpp
     common/protocols/admin/coderesponse.cpp
diff --git a/test/common/protocols/admin/admincheckbatchrequest.cpp b/test/common/protocols/admin/admincheckbatchrequest.cpp
new file mode 100644 (file)
index 0000000..287dd80
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/admincheckbatchrequest.cpp
+ * @author      Krzysztof Małysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       Tests for Cynara::AdminCheckBatchRequest usage in Cynara::ProtocolAdmin
+ */
+
+#include "iterateallcombinations.h"
+
+#include <cstddef>
+#include <gtest/gtest.h>
+#include <memory>
+#include <vector>
+
+#include <protocol/ProtocolAdmin.h>
+#include <request/AdminCheckBatchRequest.h>
+#include <types/AdminBatchCheck.h>
+#include <types/PolicyKey.h>
+
+#include <NegativeTestHelper.h>
+#include <RequestTestHelper.h>
+#include <TestDataCollection.h>
+
+namespace {
+
+template<>
+void compare(const Cynara::AdminCheckBatchRequest &req1, const Cynara::AdminCheckBatchRequest &req2) {
+    ASSERT_EQ(req1.checks().size(), req2.checks().size());
+    for (size_t i = 0; i < req1.checks().size(); ++i) {
+        EXPECT_EQ(req1.checks()[i].startBucket, req2.checks()[i].startBucket);
+        EXPECT_EQ(req1.checks()[i].recursive, req2.checks()[i].recursive);
+        EXPECT_EQ(req1.checks()[i].key, req2.checks()[i].key);
+    }
+}
+
+} /* anonymous namespace */
+
+using namespace Cynara;
+using namespace NegativeTestHelper;
+using namespace RequestTestHelper;
+using namespace TestDataCollection;
+
+template<class Func>
+void testOneAndTwoChecks(Func&& func) {
+    // Single check
+    iterateAllCombinations([&](const auto& key, const auto& bucket, const auto& recursive,
+                               const auto& sequenceNumber) {
+        auto checks = std::vector{AdminBatchCheck{bucket, recursive, key}};
+        func(std::move(checks), sequenceNumber);
+    }, Keys::all, Buckets::all, Admin::Recursive::all, SN::all);
+    // Two checks
+    iterateAllCombinations([&](const auto& key1, const auto& bucket1, const auto& recursive1,
+                               const auto& key2, const auto& bucket2, const auto& recursive2,
+                               const auto& sequenceNumber) {
+        auto checks = std::vector{
+            AdminBatchCheck{bucket1, recursive1, key1},
+            AdminBatchCheck{bucket2, recursive2, key2},
+        };
+        func(std::move(checks), sequenceNumber);
+    }, Keys::all, Buckets::all, Admin::Recursive::all, Keys::all, Buckets::all,
+       Admin::Recursive::all, SN::all);
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchRequestPositive) {
+    testOneAndTwoChecks([](auto&& checks, const auto& sequenceNumber) {
+        auto request = std::make_shared<AdminCheckBatchRequest>(std::move(checks), sequenceNumber);
+        auto protocol = std::make_shared<ProtocolAdmin>();
+        testRequest(request, protocol);
+    });
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchRequestBinaryPositive) {
+    testOneAndTwoChecks([](auto&& checks, const auto& sequenceNumber) {
+        auto request = std::make_shared<AdminCheckBatchRequest>(std::move(checks), sequenceNumber);
+        auto protocol = std::make_shared<ProtocolAdmin>();
+        binaryTestRequest(request, protocol);
+    });
+}
+
+void testInvalidKey(PolicyKey key) {
+    // Single check
+    iterateAllCombinations([&](const auto& bucket, const auto& recursive,
+                               const auto& sequenceNumber) {
+        auto checks = std::vector{AdminBatchCheck{bucket, recursive, key}};
+        testInvalidProtocol<ProtocolAdmin, AdminCheckBatchRequest>(std::move(checks),
+                                                                   sequenceNumber);
+    }, Buckets::all, Admin::Recursive::all, SN::all);
+    // Two checks
+    iterateAllCombinations([&](const auto& other_key, const auto& bucket1, const auto& recursive1,
+                               const auto& bucket2, const auto& recursive2,
+                               const auto& sequenceNumber) {
+        // First key is bad
+        {
+            auto checks = std::vector{
+                AdminBatchCheck{bucket1, recursive1, key},
+                AdminBatchCheck{bucket2, recursive2, other_key},
+            };
+            testInvalidProtocol<ProtocolAdmin, AdminCheckBatchRequest>(std::move(checks),
+                                                                    sequenceNumber);
+        }
+        // Second key is bad
+        {
+            auto checks = std::vector{
+                AdminBatchCheck{bucket1, recursive1, other_key},
+                AdminBatchCheck{bucket2, recursive2, key},
+            };
+            testInvalidProtocol<ProtocolAdmin, AdminCheckBatchRequest>(std::move(checks),
+                                                                    sequenceNumber);
+        }
+    }, Keys::all, Buckets::all, Admin::Recursive::all, Buckets::all, Admin::Recursive::all,
+       SN::all);
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchRequestTooLongClientNegative) {
+    PKF tooLongClient = PKF::create(std::string(CYNARA_MAX_ID_LENGTH + 1, 'c'));
+    testInvalidKey(PolicyKey(tooLongClient, Keys::k_aaa.user(), Keys::k_cww.privilege()));
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchRequestTooLongUserNegative) {
+    PKF tooLongUser = PKF::create(std::string(CYNARA_MAX_ID_LENGTH + 1, 'u'));
+    testInvalidKey(PolicyKey(Keys::k_cup.client(), tooLongUser, Keys::k_nun.privilege()));
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchRequestTooLongPrivilegeNegative) {
+    PKF tooLongPrivilege = PKF::create(std::string(CYNARA_MAX_ID_LENGTH + 1, 'p'));
+    testInvalidKey(PolicyKey(Keys::k_cup2.client(), Keys::k_cuw.user(), tooLongPrivilege));
+}
+
+TEST(ProtocolAdmin, AdminCheckCheckRequestTooLongBucketNegative) {
+    PolicyBucketId bucket(CYNARA_MAX_ID_LENGTH + 1, 'b');
+    // Single check
+    iterateAllCombinations([&](const auto& key, const auto& recursive,
+                               const auto& sequenceNumber) {
+        auto checks = std::vector{AdminBatchCheck{bucket, recursive, key}};
+        testInvalidProtocol<ProtocolAdmin, AdminCheckBatchRequest>(std::move(checks),
+                                                                   sequenceNumber);
+    }, Keys::all, Admin::Recursive::all, SN::all);
+    // Two checks
+    iterateAllCombinations([&](const auto& key1, const auto& other_bucket, const auto& recursive1,
+                               const auto& key2, const auto& recursive2,
+                               const auto& sequenceNumber) {
+        // First bucket is bad
+        {
+            auto checks = std::vector{
+                AdminBatchCheck{bucket, recursive1, key1},
+                AdminBatchCheck{other_bucket, recursive2, key2},
+            };
+            testInvalidProtocol<ProtocolAdmin, AdminCheckBatchRequest>(std::move(checks),
+                                                                    sequenceNumber);
+        }
+        // Second bucket is bad
+        {
+            auto checks = std::vector{
+                AdminBatchCheck{other_bucket, recursive1, key1},
+                AdminBatchCheck{bucket, recursive2, key2},
+            };
+            testInvalidProtocol<ProtocolAdmin, AdminCheckBatchRequest>(std::move(checks),
+                                                                    sequenceNumber);
+        }
+    }, Keys::all, Buckets::all, Admin::Recursive::all, Keys::all, Admin::Recursive::all,
+       SN::all);
+}
diff --git a/test/common/protocols/admin/admincheckbatchresponse.cpp b/test/common/protocols/admin/admincheckbatchresponse.cpp
new file mode 100644 (file)
index 0000000..68500de
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/admincheckbatchresponse.cpp
+ * @author      Krzysztof Malysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       Tests for Cynara::AdminCheckBatchResponse usage in Cynara::ProtocolAdmin
+ */
+
+#include "iterateallcombinations.h"
+
+#include <gtest/gtest.h>
+#include <memory>
+
+#include <cynara-limits.h>
+#include <protocol/ProtocolAdmin.h>
+#include <response/AdminCheckBatchResponse.h>
+
+#include <NegativeTestHelper.h>
+#include <ResponseTestHelper.h>
+#include <TestDataCollection.h>
+
+namespace {
+
+template<>
+void compare(const Cynara::AdminCheckBatchResponse &resp1, const Cynara::AdminCheckBatchResponse &resp2) {
+    EXPECT_EQ(resp1.areAllBucketsValid(), resp2.areAllBucketsValid());
+    EXPECT_EQ(resp1.isDbCorrupted(), resp2.isDbCorrupted());
+    EXPECT_EQ(resp1.results(), resp2.results());
+}
+
+} /* anonymous namespace */
+
+using namespace Cynara;
+using namespace NegativeTestHelper;
+using namespace ResponseTestHelper;
+using namespace TestDataCollection;
+
+template<class Func>
+void testOneAndTwoResponses(Func&& func) {
+    // Single result
+    iterateAllCombinations([&](const auto& result, const auto& bucketStatus, const auto& dbStatus,
+                               const auto& sequenceNumber) {
+        func(std::vector{result}, bucketStatus, dbStatus, sequenceNumber);
+    }, Results::all, Admin::BucketStatus::all, Admin::DBStatus::all, SN::all);
+    // Two results
+    iterateAllCombinations([&](const auto& result1, const auto& result2, const auto& bucketStatus,
+                               const auto& dbStatus, const auto& sequenceNumber) {
+        func(std::vector{result1, result2}, bucketStatus, dbStatus, sequenceNumber);
+    }, Results::all, Results::all, Admin::BucketStatus::all, Admin::DBStatus::all, SN::all);
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchResponsePositive) {
+    testOneAndTwoResponses([&](auto results, auto bucketStatus, auto dbStatus,
+                               auto sequenceNumber) {
+        auto response = std::make_shared<AdminCheckBatchResponse>(std::move(results),
+                                                                  std::move(bucketStatus),
+                                                                  std::move(dbStatus),
+                                                                  std::move(sequenceNumber));
+        auto protocol = std::make_shared<ProtocolAdmin>();
+        testResponse(response, protocol);
+    });
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchResponseBinaryPositive) {
+    testOneAndTwoResponses([&](auto results, auto bucketStatus, auto dbStatus,
+                               auto sequenceNumber) {
+        auto response = std::make_shared<AdminCheckBatchResponse>(std::move(results),
+                                                                  std::move(bucketStatus),
+                                                                  std::move(dbStatus),
+                                                                  std::move(sequenceNumber));
+        auto protocol = std::make_shared<ProtocolAdmin>();
+        binaryTestResponse(response, protocol);
+    });
+}
+
+TEST(ProtocolAdmin, AdminCheckBatchResponseTooLongMetadataNegative) {
+    PolicyResult badResult(Types::plugin_type, std::string(CYNARA_MAX_ID_LENGTH + 1, 'm'));
+    // Single result
+    iterateAllCombinations([&](const auto& bucketStatus, const auto& dbStatus,
+                               const auto& sequenceNumber) {
+        testInvalidProtocol<ProtocolAdmin, AdminCheckBatchResponse>(std::vector{badResult},
+                                                                    bucketStatus, dbStatus,
+                                                                    sequenceNumber);
+    }, Admin::BucketStatus::all, Admin::DBStatus::all, SN::all);
+    // Two results
+    iterateAllCombinations([&](const auto& result, const auto& bucketStatus, const auto& dbStatus,
+                               const auto& sequenceNumber) {
+        // First result is bad
+        testInvalidProtocol<ProtocolAdmin, AdminCheckBatchResponse>(std::vector{badResult, result},
+                                                                    bucketStatus, dbStatus,
+                                                                    sequenceNumber);
+        // Second result is bad
+        testInvalidProtocol<ProtocolAdmin, AdminCheckBatchResponse>(std::vector{result, badResult},
+                                                                    bucketStatus, dbStatus,
+                                                                    sequenceNumber);
+    }, Results::all, Admin::BucketStatus::all, Admin::DBStatus::all, SN::all);
+}
+
diff --git a/test/common/protocols/admin/iterateallcombinations.h b/test/common/protocols/admin/iterateallcombinations.h
new file mode 100644 (file)
index 0000000..bc3c175
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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/iterateallcombinations.cpp
+ * @author      Krzysztof Małysa <k.malysa@samsung.com>
+ * @version     1.0
+ * @brief       Test helper for iterating all combinations of elements from multiple collections
+ */
+
+#include <utility>
+#include <tuple>
+
+template<class... Collections, class Func>
+void iterateAllCombinations(Func&& func, Collections&&... collections) {
+    if constexpr (sizeof...(collections) == 0)
+        return;
+
+    static constexpr auto impl = [](const auto& self, auto& func, auto&& args_tuple,
+                                    const auto& first, const auto&... rest) {
+        for (const auto& elem : first) {
+            auto merged_tuple = std::tuple_cat(args_tuple, std::tuple<decltype(elem)>{elem});
+            if constexpr (sizeof...(rest) == 0)
+                std::apply(func, std::move(merged_tuple));
+            else
+                self(self, func, std::move(merged_tuple), rest...);
+        }
+    };
+    impl(impl, func, std::tuple{}, collections...);
+}