Add loading database in Cynara::init
[platform/core/security/cynara.git] / src / service / storage / InMemoryStorageBackend.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        InMemoryStorageBackend.cpp
18  * @author      Aleksander Zdyb <a.zdyb@partner.samsung.com>
19  * @version     1.0
20  * @brief       Implementation of InMemoryStorageBackend
21  */
22
23 #include <fstream>
24 #include <functional>
25
26 #include <log/log.h>
27 #include <exceptions/FileNotFoundException.h>
28 #include <storage/BucketDeserializer.h>
29 #include <storage/StorageDeserializer.h>
30 #include <types/PolicyBucketId.h>
31
32 #include "InMemoryStorageBackend.h"
33
34 namespace Cynara {
35
36 void InMemoryStorageBackend::load(void) {
37     std::string indexFilename = m_dbPath + "buckets";
38
39     try {
40         std::ifstream indexStream;
41         openFileStream(indexStream, indexFilename);
42
43         StorageDeserializer storageDeserializer(indexStream,
44             std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1));
45
46         storageDeserializer.initBuckets(buckets());
47         storageDeserializer.loadBuckets(buckets());
48     } catch (const FileNotFoundException &) {
49         LOGE("Reading cynara database failed.");
50     }
51
52     if(!hasBucket(defaultPolicyBucketId)) {
53             LOGN("Creating defaultBucket.");
54             this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() });
55     }
56 }
57
58 PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) {
59     return searchBucket(defaultPolicyBucketId, key);
60 }
61
62 PolicyBucket InMemoryStorageBackend::searchBucket(const PolicyBucketId &bucketId,
63                                                   const PolicyKey &key) {
64     try {
65         const auto &bucket = this->buckets().at(bucketId);
66         return bucket.filtered(key);
67     } catch (const std::out_of_range &) {
68         throw BucketNotExistsException(bucketId);
69     }
70 }
71
72 void InMemoryStorageBackend::insertPolicy(const PolicyBucketId &bucketId, PolicyPtr policy) {
73     try {
74         auto &bucket = buckets().at(bucketId);
75         auto &policies = bucket.policyCollection();
76         policies.push_back(policy);
77     } catch (const std::out_of_range &) {
78         throw BucketNotExistsException(bucketId);
79     }
80 }
81
82 void InMemoryStorageBackend::createBucket(const PolicyBucketId &bucketId,
83                                           const PolicyResult &defaultPolicy) {
84     PolicyBucket newBucket;
85     newBucket.setDefaultPolicy(defaultPolicy);
86     buckets().insert({ bucketId, newBucket });
87 }
88
89 void InMemoryStorageBackend::updateBucket(const PolicyBucketId &bucketId,
90                                           const PolicyResult &defaultPolicy) {
91     try {
92         auto &bucket = buckets().at(bucketId);
93         bucket.setDefaultPolicy(defaultPolicy);
94     } catch (const std::out_of_range &) {
95         throw BucketNotExistsException(bucketId);
96     }
97 }
98
99 void InMemoryStorageBackend::deleteBucket(const PolicyBucketId &bucketId) {
100     auto bucketErased = buckets().erase(bucketId);
101     if (bucketErased == 0) {
102         throw BucketNotExistsException(bucketId);
103     }
104 }
105
106 bool InMemoryStorageBackend::hasBucket(const PolicyBucketId &bucketId) {
107     return buckets().find(bucketId) != buckets().end();
108 }
109
110 void InMemoryStorageBackend::deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key) {
111     try {
112         // TODO: Move the erase code to PolicyCollection maybe?
113         auto &bucket = buckets().at(bucketId);
114         auto &policies = bucket.policyCollection();
115         policies.erase(remove_if(policies.begin(), policies.end(),
116                 [key](PolicyPtr policy) -> bool {
117                     return policy->key() == key;
118             }), policies.end());
119     } catch(const std::out_of_range &) {
120         throw BucketNotExistsException(bucketId);
121     }
122 }
123
124 void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) {
125     auto bucketIdMatches = [&bucketId] (PolicyPtr policy) -> bool {
126         auto policyResult = policy->result();
127
128         // Check bucket id only if policy is a bucket policy
129         // TODO: Maybe move the test to PolicyResult
130         if (policyResult.policyType() == PredefinedPolicyType::BUCKET) {
131             return policyResult.metadata() == bucketId;
132         }
133         return false;
134     };
135
136     for(auto &bucketIter : buckets()) {
137         // TODO: Move the erase code to PolicyCollection maybe?
138         auto &bucket = bucketIter.second;
139         auto &policies = bucket.policyCollection();
140         policies.erase(remove_if(policies.begin(), policies.end(), bucketIdMatches),
141                 policies.end());
142     }
143 }
144
145 void InMemoryStorageBackend::openFileStream(std::ifstream &stream, const std::string &filename) {
146     // TODO: Consider adding exceptions to streams and handling them:
147     // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
148     stream.open(filename);
149
150     if (!stream.is_open())
151         throw FileNotFoundException(filename);
152 }
153
154 std::shared_ptr<BucketDeserializer> InMemoryStorageBackend::bucketStreamOpener(
155         const PolicyBucketId &bucketId) {
156     std::string bucketFilename = m_dbPath + "_" + bucketId;
157     std::ifstream bucketStream;
158     try {
159         openFileStream(bucketStream, bucketFilename);
160         return std::make_shared<BucketDeserializer>(bucketStream);
161     } catch (const FileNotFoundException &) {
162         return nullptr;
163     }
164 }
165
166 } /* namespace Cynara */