Add start point in Storage::checkPolicy()
[platform/core/security/cynara.git] / src / service / storage / Storage.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        Storage.cpp
18  * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
19  * @author      Aleksander Zdyb <a.zdyb@partner.samsung.com>
20  * @version     1.0
21  * @brief       This file implements policy rules storage procedures
22  */
23
24 #include <memory>
25 #include <vector>
26
27 #include <exceptions/BucketNotExistsException.h>
28 #include "exceptions/DefaultBucketDeletionException.h"
29 #include <types/pointers.h>
30 #include <types/Policy.h>
31 #include <types/PolicyBucket.h>
32 #include <types/PolicyBucketId.h>
33 #include <types/PolicyCollection.h>
34 #include <types/PolicyResult.h>
35 #include <types/PolicyType.h>
36
37 #include "Storage.h"
38
39 namespace Cynara {
40
41 PolicyResult Storage::checkPolicy(const PolicyKey &key,
42                                   const PolicyBucketId &startBucketId /*= defaultPolicyBucketId*/,
43                                   bool recursive /*= true*/) {
44     auto policies = m_backend.searchBucket(startBucketId, key);
45     return minimalPolicy(policies, key, recursive);
46 };
47
48 PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key,
49                                     bool recursive) {
50     bool hasMinimal = false;
51     PolicyResult minimal = bucket.defaultPolicy();
52
53     auto proposeMinimal = [&minimal, &hasMinimal](const PolicyResult &candidate) {
54         if (hasMinimal == false) {
55             minimal = candidate;
56         } else if (candidate < minimal) {
57             minimal = candidate;
58         }
59         hasMinimal = true;
60     };
61
62     for (const auto policy : bucket) {
63         const auto &policyResult = policy->result();
64
65         switch (policyResult.policyType()) {
66             case PredefinedPolicyType::DENY:
67                 return policyResult; // Do not expect lower value than DENY
68             case PredefinedPolicyType::BUCKET: {
69                     if (recursive == true) {
70                         auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key);
71                         auto minimumOfBucket = minimalPolicy(bucketResults, key, true);
72                         proposeMinimal(minimumOfBucket);
73                     }
74                     continue;
75                 }
76             case PredefinedPolicyType::ALLOW:
77             default:
78                 break;
79         }
80
81         proposeMinimal(policyResult);
82     }
83
84     return minimal;
85 }
86
87 void Storage::insertPolicies(const std::map<PolicyBucketId, std::vector<Policy>> &policiesByBucketId) {
88
89     auto pointedBucketExists = [this] (const Policy &policy) -> void {
90         if (policy.result().policyType() == PredefinedPolicyType::BUCKET) {
91             const auto &bucketId = policy.result().metadata();
92             if (m_backend.hasBucket(bucketId) == false) {
93                 throw BucketNotExistsException(bucketId);
94             }
95         }
96     };
97
98     // TODO: Rewrite, when transactions are supported
99     // Check if all of buckets exist
100     for (const auto &group : policiesByBucketId) {
101         const auto &policies = group.second;
102         std::for_each(policies.cbegin(), policies.cend(), pointedBucketExists);
103     }
104
105     // Then insert policies
106     for (const auto &group : policiesByBucketId) {
107         const PolicyBucketId &bucketId = group.first;
108         const auto &policies = group.second;
109         for (const auto &policy : policies) {
110             m_backend.insertPolicy(bucketId, std::make_shared<Policy>(policy));
111         }
112     }
113 }
114
115 void Storage::addOrUpdateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultBucketPolicy) {
116     if (m_backend.hasBucket(bucketId)) {
117         m_backend.updateBucket(bucketId, defaultBucketPolicy);
118     } else {
119         m_backend.createBucket(bucketId, defaultBucketPolicy);
120     }
121 }
122
123 void Storage::deleteBucket(const PolicyBucketId &bucketId) {
124     // TODO: Check if bucket exists
125
126     if (bucketId == defaultPolicyBucketId) {
127         throw DefaultBucketDeletionException();
128     }
129
130     m_backend.deleteLinking(bucketId);
131     m_backend.deleteBucket(bucketId);
132 }
133
134 void Storage::deletePolicies(const std::map<PolicyBucketId, std::vector<PolicyKey>> &keysByBucketId) {
135     for (const auto &bucket : keysByBucketId) {
136         const PolicyBucketId &bucketId = bucket.first;
137         for (const auto &policyKey : bucket.second) {
138             m_backend.deletePolicy(bucketId, policyKey);
139         }
140     }
141 }
142
143 void Storage::load(void) {
144     m_backend.load();
145 }
146
147 void Storage::save(void) {
148     m_backend.save();
149 }
150
151 } // namespace Cynara