Database access function obtaining apps of a certain user
[platform/core/security/security-manager.git] / src / common / privilege_db.cpp
1 /*
2  * security-manager, database access
3  *
4  * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Rafal Krypa <r.krypa@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /*
23  * @file        privilege_db.cpp
24  * @author      Krzysztof Sasiak <k.sasiak@samsung.com>
25  * @author      Rafal Krypa <r.krypa@samsung.com>
26  * @version     0.1
27  * @brief       This file contains declaration of the API to privileges database.
28  */
29
30 #include <cstdio>
31 #include <list>
32 #include <string>
33 #include <iostream>
34
35 #include <dpl/log/log.h>
36 #include "privilege_db.h"
37
38 namespace SecurityManager {
39
40 /* Common code for handling SqlConnection exceptions */
41 template <typename T>
42 T try_catch(const std::function<T()> &func)
43 {
44     try {
45         return func();
46     } catch (DB::SqlConnection::Exception::SyntaxError &e) {
47         LogError("Syntax error in command: " << e.DumpToString());
48         ThrowMsg(PrivilegeDb::Exception::InternalError,
49             "Syntax error in command: " << e.DumpToString());
50     } catch (DB::SqlConnection::Exception::InternalError &e) {
51         LogError("Mysterious internal error in SqlConnection class" << e.DumpToString());
52         ThrowMsg(PrivilegeDb::Exception::InternalError,
53             "Mysterious internal error in SqlConnection class: " << e.DumpToString());
54     }
55 }
56
57 PrivilegeDb::PrivilegeDb(const std::string &path)
58 {
59     try {
60         mSqlConnection = new DB::SqlConnection(path,
61                 DB::SqlConnection::Flag::None,
62                 DB::SqlConnection::Flag::RW);
63     } catch (DB::SqlConnection::Exception::Base &e) {
64         LogError("Database initialization error: " << e.DumpToString());
65         ThrowMsg(PrivilegeDb::Exception::IOError,
66                 "Database initialization error:" << e.DumpToString());
67
68     };
69 }
70
71 PrivilegeDb::~PrivilegeDb()
72 {
73     delete mSqlConnection;
74 }
75
76 PrivilegeDb &PrivilegeDb::getInstance()
77 {
78     static PrivilegeDb privilegeDb;
79     return privilegeDb;
80 }
81
82 void PrivilegeDb::BeginTransaction(void)
83 {
84     try_catch<void>([&] {
85         mSqlConnection->BeginTransaction();
86     });
87 }
88
89 void PrivilegeDb::CommitTransaction(void)
90 {
91     try_catch<void>([&] {
92         mSqlConnection->CommitTransaction();
93     });
94 }
95
96 void PrivilegeDb::RollbackTransaction(void)
97 {
98     try_catch<void>([&] {
99         mSqlConnection->RollbackTransaction();
100     });
101 }
102
103 bool PrivilegeDb::PkgIdExists(const std::string &pkgId)
104 {
105     return try_catch<bool>([&] {
106         DB::SqlConnection::DataCommandAutoPtr command =
107                 mSqlConnection->PrepareDataCommand(
108                         Queries.at(QueryType::EPkgIdExists));
109         command->BindString(1, pkgId.c_str());
110         if (command->Step()) {
111             // pkgId found in the database
112             command->Reset();
113             return true;
114         };
115
116         // pkgId not found in the database
117         return false;
118     });
119 }
120
121 bool PrivilegeDb::GetAppPkgId(const std::string &appId, std::string &pkgId)
122 {
123     return try_catch<bool>([&] {
124         DB::SqlConnection::DataCommandAutoPtr command =
125             mSqlConnection->PrepareDataCommand(Queries.at(QueryType::EGetPkgId));
126         command->BindString(1, appId.c_str());
127
128         if (!command->Step()) {
129             // No application with such appId
130             return false;
131         }
132
133         // application package found in the database, get it
134         pkgId = command->GetColumnString(0);
135
136         return true;
137     });
138 }
139
140 void PrivilegeDb::AddApplication(const std::string &appId,
141         const std::string &pkgId, uid_t uid, bool &pkgIdIsNew)
142 {
143     pkgIdIsNew = !(this->PkgIdExists(pkgId));
144
145     try_catch<void>([&] {
146         DB::SqlConnection::DataCommandAutoPtr command =
147                 mSqlConnection->PrepareDataCommand(
148                         Queries.at(QueryType::EAddApplication));
149
150         command->BindString(1, appId.c_str());
151         command->BindString(2, pkgId.c_str());
152         command->BindInteger(3, static_cast<unsigned int>(uid));
153
154         if (command->Step()) {
155             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
156                     Queries.at(QueryType::EAddApplication));
157         };
158
159         command->Reset();
160         LogDebug("Added appId: " << appId << ", pkgId: " << pkgId);
161     });
162 }
163
164 void PrivilegeDb::RemoveApplication(const std::string &appId, uid_t uid,
165         bool &pkgIdIsNoMore)
166 {
167     try_catch<void>([&] {
168         std::string pkgId;
169         if (!GetAppPkgId(appId, pkgId)) {
170             pkgIdIsNoMore = false;
171             return;
172         }
173
174         DB::SqlConnection::DataCommandAutoPtr command =
175                 mSqlConnection->PrepareDataCommand(
176                         Queries.at(QueryType::ERemoveApplication));
177
178         command->BindString(1, appId.c_str());
179         command->BindInteger(2, static_cast<unsigned int>(uid));
180
181         if (command->Step()) {
182             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
183                     Queries.at(QueryType::ERemoveApplication));
184         };
185
186         command->Reset();
187         LogDebug("Removed appId: " << appId);
188
189         pkgIdIsNoMore = !(this->PkgIdExists(pkgId));
190     });
191 }
192
193 void PrivilegeDb::GetPkgPrivileges(const std::string &pkgId, uid_t uid,
194         std::vector<std::string> &currentPrivileges)
195 {
196     try_catch<void>([&] {
197         DB::SqlConnection::DataCommandAutoPtr command =
198                 mSqlConnection->PrepareDataCommand(
199                         Queries.at(QueryType::EGetPkgPrivileges));
200         command->BindString(1, pkgId.c_str());
201         command->BindInteger(2, static_cast<unsigned int>(uid));
202
203         while (command->Step()) {
204             std::string privilege = command->GetColumnString(0);
205             LogDebug("Got privilege: " << privilege);
206             currentPrivileges.push_back(privilege);
207         };
208     });
209 }
210
211 void PrivilegeDb::RemoveAppPrivileges(const std::string &appId, uid_t uid)
212 {
213     try_catch<void>([&] {
214         DB::SqlConnection::DataCommandAutoPtr command =
215             mSqlConnection->PrepareDataCommand(Queries.at(QueryType::ERemoveAppPrivileges));
216
217         command->BindString(1, appId.c_str());
218         command->BindInteger(2, static_cast<unsigned int>(uid));
219         if (command->Step()) {
220             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
221                     Queries.at(QueryType::ERemoveAppPrivileges));
222         }
223
224         LogDebug("Removed all privileges for appId: " << appId);
225     });
226 }
227
228 void PrivilegeDb::UpdateAppPrivileges(const std::string &appId, uid_t uid,
229         const std::vector<std::string> &privileges)
230 {
231     try_catch<void>([&] {
232         DB::SqlConnection::DataCommandAutoPtr command =
233             mSqlConnection->PrepareDataCommand(Queries.at(QueryType::EAddAppPrivileges));
234         command->BindString(1, appId.c_str());
235         command->BindInteger(2, static_cast<unsigned int>(uid));
236
237         RemoveAppPrivileges(appId, uid);
238
239         for (const auto &privilege : privileges) {
240             command->BindString(3, privilege.c_str());
241             command->Step();
242             command->Reset();
243             LogDebug("Added privilege: " << privilege << " to appId: " << appId);
244         }
245     });
246 }
247
248 void PrivilegeDb::GetPrivilegeGroups(const std::string &privilege,
249         std::vector<std::string> &groups)
250 {
251    try_catch<void>([&] {
252         DB::SqlConnection::DataCommandAutoPtr command =
253                 mSqlConnection->PrepareDataCommand(
254                         Queries.at(QueryType::EGetPrivilegeGroups));
255         command->BindString(1, privilege.c_str());
256
257         while (command->Step()) {
258             std::string groupName = command->GetColumnString(0);
259             LogDebug("Privilege " << privilege << " gives access to group: " << groupName);
260             groups.push_back(groupName);
261         };
262     });
263 }
264
265 void PrivilegeDb::GetUserApps(uid_t uid, std::vector<std::string> &apps)
266 {
267    try_catch<void>([&] {
268         DB::SqlConnection::DataCommandAutoPtr command =
269                 mSqlConnection->PrepareDataCommand(
270                         Queries.at(QueryType::EGetUserApps));
271         command->BindInteger(1, static_cast<unsigned int>(uid));
272         apps.clear();
273         while (command->Step()) {
274             std::string app = command->GetColumnString(0);
275             LogDebug("User " << uid << " has app " << app << " installed");
276             apps.push_back(app);
277         };
278     });
279 }
280
281
282 } //namespace SecurityManager