1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "database_helper.h"
17 
18 #include <array>
19 
20 #include "config_define.h"
21 #include "rdb_event_store_callback.h"
22 #include "security_guard_define.h"
23 #include "security_guard_log.h"
24 
25 namespace OHOS::Security::SecurityGuard {
DatabaseHelper(std::string dbTable)26 DatabaseHelper::DatabaseHelper(std::string dbTable)
27 {
28     dbTable_ = dbTable;
29 }
30 
Init()31 int DatabaseHelper::Init()
32 {
33     return SUCCESS;
34 }
35 
Release()36 void DatabaseHelper::Release()
37 {
38 }
39 
InsertEvent(const SecEvent & event)40 int DatabaseHelper::InsertEvent(const SecEvent& event)
41 {
42     NativeRdb::ValuesBucket values;
43     SetValuesBucket(event, values);
44     int64_t rowId;
45     int ret = Insert(rowId, dbTable_, values);
46     if (ret != NativeRdb::E_OK) {
47         SGLOGI("failed to add event, eventId=%{public}" PRId64 ", ret=%{public}d", event.eventId, ret);
48         return DB_OPT_ERR;
49     }
50     return SUCCESS;
51 }
52 
QueryAllEvent(std::vector<SecEvent> & events)53 int DatabaseHelper::QueryAllEvent(std::vector<SecEvent> &events)
54 {
55     NativeRdb::RdbPredicates predicates(dbTable_);
56     return QueryEventBase(predicates, events);
57 }
58 
QueryRecentEventByEventId(int64_t eventId,SecEvent & event)59 int DatabaseHelper::QueryRecentEventByEventId(int64_t eventId, SecEvent &event)
60 {
61     std::vector<std::string> columns { EVENT_ID, VERSION, DATE, CONTENT };
62     NativeRdb::RdbPredicates predicates(dbTable_);
63     predicates.EqualTo(EVENT_ID, std::to_string(eventId));
64     predicates.OrderByDesc(ID);
65     predicates.Limit(1);
66     std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(predicates, columns);
67     if (resultSet == nullptr) {
68         SGLOGI("failed to get event");
69         return DB_OPT_ERR;
70     }
71     SecEventTableInfo table;
72     int32_t ret = GetResultSetTableInfo(resultSet, table);
73     if (ret != SUCCESS) {
74         return ret;
75     }
76     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
77         resultSet->GetLong(table.eventIdIndex, event.eventId);
78         resultSet->GetString(table.versionIndex, event.version);
79         resultSet->GetString(table.dateIndex, event.date);
80         resultSet->GetString(table.contentIndex, event.content);
81     }
82     resultSet->Close();
83     return SUCCESS;
84 }
85 
QueryRecentEventByEventId(const std::vector<int64_t> & eventIds,std::vector<SecEvent> & events)86 int DatabaseHelper::QueryRecentEventByEventId(const std::vector<int64_t> &eventIds, std::vector<SecEvent> &events)
87 {
88     int size = static_cast<int>(eventIds.size());
89     if (size == 0) {
90         return BAD_PARAM;
91     }
92     for (int i = 0; i < size; i++) {
93         SGLOGI("eventId=%{public}" PRId64 "", eventIds[i]);
94         NativeRdb::RdbPredicates predicates(dbTable_);
95         predicates.EqualTo(EVENT_ID, std::to_string(eventIds[i]));
96         predicates.OrderByDesc(ID);
97         predicates.Limit(1);
98         int ret = QueryEventBase(predicates, events);
99         if (ret != SUCCESS) {
100             return ret;
101         }
102     }
103     return SUCCESS;
104 }
105 
QueryEventByEventId(int64_t eventId,std::vector<SecEvent> & events)106 int DatabaseHelper::QueryEventByEventId(int64_t eventId, std::vector<SecEvent> &events)
107 {
108     NativeRdb::RdbPredicates predicates(dbTable_);
109     predicates.EqualTo(EVENT_ID, std::to_string(eventId));
110     return QueryEventBase(predicates, events);
111 }
112 
QueryEventByEventId(std::vector<int64_t> & eventIds,std::vector<SecEvent> & events)113 int DatabaseHelper::QueryEventByEventId(std::vector<int64_t> &eventIds, std::vector<SecEvent> &events)
114 {
115     int size = static_cast<int>(eventIds.size());
116     if (size == 0) {
117         return BAD_PARAM;
118     }
119     NativeRdb::RdbPredicates predicates(dbTable_);
120     for (int i = 0; i < size; i++) {
121         if (i > 0) {
122             predicates.Or();
123         }
124         predicates.EqualTo(EVENT_ID, std::to_string(eventIds[i]));
125     }
126     return QueryEventBase(predicates, events);
127 }
128 
QueryEventByEventIdAndDate(std::vector<int64_t> & eventIds,std::vector<SecEvent> & events,std::string beginTime,std::string endTime)129 int DatabaseHelper::QueryEventByEventIdAndDate(std::vector<int64_t> &eventIds, std::vector<SecEvent> &events,
130     std::string beginTime, std::string endTime)
131 {
132     int size = static_cast<int>(eventIds.size());
133     if (size == 0) {
134         return BAD_PARAM;
135     }
136     NativeRdb::RdbPredicates predicates(dbTable_);
137     predicates.BeginWrap();
138     for (int i = 0; i < size; i++) {
139         if (i > 0) {
140             predicates.Or();
141         }
142         predicates.EqualTo(EVENT_ID, std::to_string(eventIds[i]));
143     }
144     predicates.EndWrap();
145     if (!beginTime.empty()) {
146         predicates.And();
147         predicates.GreaterThanOrEqualTo(DATE, beginTime);
148     }
149     if (!endTime.empty()) {
150         predicates.And();
151         predicates.LessThan(DATE, endTime);
152     }
153     return QueryEventBase(predicates, events);
154 }
155 
QueryEventByEventType(int32_t eventType,std::vector<SecEvent> & events)156 int DatabaseHelper::QueryEventByEventType(int32_t eventType, std::vector<SecEvent> &events)
157 {
158     NativeRdb::RdbPredicates predicates(dbTable_);
159     predicates.EqualTo(EVENT_TYPE, std::to_string(eventType));
160     return QueryEventBase(predicates, events);
161 }
162 
QueryEventByLevel(int32_t level,std::vector<SecEvent> & events)163 int DatabaseHelper::QueryEventByLevel(int32_t level, std::vector<SecEvent> &events)
164 {
165     NativeRdb::RdbPredicates predicates(dbTable_);
166     predicates.EqualTo(DATA_SENSITIVITY_LEVEL, std::to_string(level));
167     return QueryEventBase(predicates, events);
168 }
169 
QueryEventByOwner(std::string owner,std::vector<SecEvent> & events)170 int DatabaseHelper::QueryEventByOwner(std::string owner, std::vector<SecEvent> &events)
171 {
172     NativeRdb::RdbPredicates predicates(dbTable_);
173     predicates.Contains(OWNER, owner);
174     return QueryEventBase(predicates, events);
175 }
176 
CountAllEvent()177 int64_t DatabaseHelper::CountAllEvent()
178 {
179     int64_t count;
180     NativeRdb::RdbPredicates predicates(dbTable_);
181     int ret = Count(count, predicates);
182     if (ret != NativeRdb::E_OK) {
183         SGLOGE("failed to count event, ret=%{public}d", ret);
184     }
185     return count;
186 }
187 
CountEventByEventId(int64_t eventId)188 int64_t DatabaseHelper::CountEventByEventId(int64_t eventId)
189 {
190     int64_t count;
191     NativeRdb::RdbPredicates predicates(dbTable_);
192     predicates.EqualTo(EVENT_ID, std::to_string(eventId));
193     int ret = Count(count, predicates);
194     if (ret != NativeRdb::E_OK) {
195         SGLOGE("failed to count event, eventId=%{public}" PRId64 ", ret=%{public}d", eventId, ret);
196     }
197     return count;
198 }
199 
DeleteOldEventByEventId(int64_t eventId,int64_t count)200 int DatabaseHelper::DeleteOldEventByEventId(int64_t eventId, int64_t count)
201 {
202     NativeRdb::RdbPredicates queryPredicates(dbTable_);
203     queryPredicates.EqualTo(EVENT_ID, std::to_string(eventId));
204     queryPredicates.OrderByAsc(ID);
205     queryPredicates.Limit(count);
206     std::vector<std::string> columns { ID };
207     std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(queryPredicates, columns);
208     if (resultSet == nullptr) {
209         SGLOGI("failed to get event, eventId=%{public}" PRId64 "", eventId);
210         return DB_OPT_ERR;
211     }
212     int64_t primaryKey = -1;
213     std::vector<std::string> primaryKeyVec;
214     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
215         resultSet->GetLong(0, primaryKey);
216         primaryKeyVec.emplace_back(std::to_string(primaryKey));
217     }
218     resultSet->Close();
219     int rowId;
220     NativeRdb::RdbPredicates deletePredicates(dbTable_);
221     deletePredicates.In(ID, primaryKeyVec);
222     deletePredicates.EqualTo(EVENT_ID, std::to_string(eventId));
223     int ret = Delete(rowId, deletePredicates);
224     if (ret != NativeRdb::E_OK) {
225         SGLOGE("failed to delete event, eventId=%{public}" PRId64 ", ret=%{public}d", eventId, ret);
226         return DB_OPT_ERR;
227     }
228     return SUCCESS;
229 }
230 
DeleteAllEventByEventId(int64_t eventId)231 int DatabaseHelper::DeleteAllEventByEventId(int64_t eventId)
232 {
233     int rowId;
234     NativeRdb::RdbPredicates predicates(dbTable_);
235     predicates.EqualTo(EVENT_ID, std::to_string(eventId));
236     int ret = Delete(rowId, predicates);
237     if (ret != NativeRdb::E_OK) {
238         SGLOGI("failed to delete event, eventId=%{public}" PRId64 ", ret=%{public}d", eventId, ret);
239         return DB_OPT_ERR;
240     }
241     return SUCCESS;
242 }
243 
FlushAllEvent()244 int DatabaseHelper::FlushAllEvent()
245 {
246     return SUCCESS;
247 }
248 
QueryEventBase(const NativeRdb::RdbPredicates & predicates,std::vector<SecEvent> & events)249 int DatabaseHelper::QueryEventBase(const NativeRdb::RdbPredicates &predicates, std::vector<SecEvent> &events)
250 {
251     std::vector<std::string> columns { EVENT_ID, VERSION, DATE, CONTENT, USER_ID, DEVICE_ID };
252     std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(predicates, columns);
253     if (resultSet == nullptr) {
254         SGLOGI("failed to get event");
255         return DB_OPT_ERR;
256     }
257     SecEventTableInfo table;
258     table.userIdIndex = INVALID_INDEX;
259     table.deviceIdIndex = INVALID_INDEX;
260     int32_t ret = GetResultSetTableInfo(resultSet, table);
261     if (ret != SUCCESS) {
262         return ret;
263     }
264     SecEvent event;
265     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
266         resultSet->GetLong(table.eventIdIndex, event.eventId);
267         resultSet->GetString(table.versionIndex, event.version);
268         resultSet->GetString(table.dateIndex, event.date);
269         resultSet->GetString(table.contentIndex, event.content);
270         if (table.deviceIdIndex != INVALID_INDEX) {
271             resultSet->GetString(table.deviceIdIndex, event.deviceId);
272         }
273         if (table.userIdIndex != INVALID_INDEX) {
274             resultSet->GetInt(table.userIdIndex, event.userId);
275         }
276         events.emplace_back(event);
277     }
278     resultSet->Close();
279     return SUCCESS;
280 }
281 
GetResultSetTableInfo(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,SecEventTableInfo & table)282 int32_t DatabaseHelper::GetResultSetTableInfo(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
283     SecEventTableInfo &table)
284 {
285     int32_t rowCount = 0;
286     int32_t columnCount = 0;
287     std::vector<std::string> columnNames;
288     if (resultSet->GetRowCount(rowCount) != NativeRdb::E_OK ||
289         resultSet->GetColumnCount(columnCount) != NativeRdb::E_OK ||
290         resultSet->GetAllColumnNames(columnNames) != NativeRdb::E_OK) {
291         SGLOGE("get table info failed");
292         return DB_LOAD_ERR;
293     }
294     int32_t columnNamesCount = static_cast<int32_t>(columnNames.size());
295     for (int32_t i = 0; i < columnNamesCount; i++) {
296         std::string columnName = columnNames.at(i);
297         if (columnName == ID) {
298             table.primaryKeyIndex = i;
299         }
300         if (columnName == EVENT_ID) {
301             table.eventIdIndex = i;
302         }
303         if (columnName == VERSION) {
304             table.versionIndex = i;
305         }
306         if (columnName == DATE) {
307             table.dateIndex = i;
308         }
309         if (columnName == CONTENT) {
310             table.contentIndex = i;
311         }
312         if (columnName == USER_ID) {
313             table.userIdIndex = i;
314         }
315         if (columnName == DEVICE_ID) {
316             table.deviceIdIndex = i;
317         }
318     }
319     table.rowCount = rowCount;
320     table.columnCount = columnCount;
321     SGLOGD("info: row=%{public}d col=%{public}d eventIdIdx=%{public}d versionIdx=%{public}d "
322         "dateIdx=%{public}d contentIdx=%{public}d", rowCount, columnCount,
323         table.eventIdIndex, table.versionIndex, table.dateIndex, table.contentIndex);
324     return SUCCESS;
325 }
326 
SetValuesBucket(const SecEvent & event,NativeRdb::ValuesBucket & values)327 void DatabaseHelper::SetValuesBucket(const SecEvent &event, NativeRdb::ValuesBucket &values)
328 {
329     values.PutLong(EVENT_ID, event.eventId);
330     values.PutString(VERSION, event.version);
331     values.PutString(DATE, event.date);
332     values.PutString(CONTENT, event.content);
333     values.PutInt(EVENT_TYPE, event.eventType);
334     values.PutInt(DATA_SENSITIVITY_LEVEL, event.dataSensitivityLevel);
335     values.PutString(OWNER, event.owner);
336     values.PutInt(USER_ID, event.userId);
337     values.PutString(DEVICE_ID, event.deviceId);
338 }
339 
CreateTable()340 std::string DatabaseHelper::CreateTable()
341 {
342     std::string table;
343     table.append("CREATE TABLE IF NOT EXISTS ").append(dbTable_);
344     table.append("(").append(ID).append(" INTEGER PRIMARY KEY AUTOINCREMENT, ");
345     table.append(EVENT_ID).append(" INTEGER NOT NULL, ");
346     table.append(VERSION).append(" TEXT NOT NULL, ");
347     table.append(DATE).append(" TEXT NOT NULL, ");
348     table.append(CONTENT).append(" TEXT NOT NULL, ");
349     table.append(EVENT_TYPE).append(" INTEGER NOT NULL, ");
350     table.append(DATA_SENSITIVITY_LEVEL).append(" INTEGER NOT NULL, ");
351     table.append(OWNER).append(" TEXT NOT NULL, ");
352     table.append(USER_ID).append(" INTEGER NOT NULL, ");
353     table.append(DEVICE_ID).append(" TEXT NOT NULL)");
354     return table;
355 }
356 } // namespace OHOS::Security::SecurityGuard