1 /*
2  * Copyright (c) 2022 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 "permission_used_record_db.h"
17 
18 #include <cinttypes>
19 #include <mutex>
20 
21 #include "accesstoken_log.h"
22 #include "active_change_response_info.h"
23 #include "constant.h"
24 #include "permission_used_type.h"
25 #include "privacy_field_const.h"
26 #include "time_util.h"
27 
28 namespace OHOS {
29 namespace Security {
30 namespace AccessToken {
31 namespace {
32 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
33     LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PermissionUsedRecordDb"
34 };
35 constexpr const char* FIELD_COUNT_NUMBER = "count";
36 constexpr const char* INTEGER_STR = " integer not null,";
37 constexpr const char* CREATE_TABLE_STR = "create table if not exists ";
38 constexpr const char* WHERE_1_STR = " where 1 = 1";
39 
40 std::recursive_mutex g_instanceMutex;
41 }
42 
GetInstance()43 PermissionUsedRecordDb& PermissionUsedRecordDb::GetInstance()
44 {
45     static PermissionUsedRecordDb* instance = nullptr;
46     if (instance == nullptr) {
47         std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
48         if (instance == nullptr) {
49             PermissionUsedRecordDb* tmp = new PermissionUsedRecordDb();
50             instance = std::move(tmp);
51         }
52     }
53     return *instance;
54 }
55 
~PermissionUsedRecordDb()56 PermissionUsedRecordDb::~PermissionUsedRecordDb()
57 {
58     Close();
59 }
60 
OnCreate()61 void PermissionUsedRecordDb::OnCreate()
62 {
63     ACCESSTOKEN_LOG_INFO(LABEL, "Entry");
64     CreatePermissionRecordTable();
65     CreatePermissionUsedTypeTable();
66 }
67 
OnUpdate(int32_t version)68 void PermissionUsedRecordDb::OnUpdate(int32_t version)
69 {
70     ACCESSTOKEN_LOG_INFO(LABEL, "Entry");
71     if (version == DataBaseVersion::VERISION_1) {
72         InsertLockScreenStatusColumn();
73         InsertPermissionUsedTypeColumn();
74         CreatePermissionUsedTypeTable();
75         UpdatePermissionRecordTablePrimaryKey();
76     } else if (version == DataBaseVersion::VERISION_2) {
77         InsertPermissionUsedTypeColumn();
78         CreatePermissionUsedTypeTable();
79         UpdatePermissionRecordTablePrimaryKey();
80     } else if (version == DataBaseVersion::VERISION_3) {
81         UpdatePermissionRecordTablePrimaryKey();
82     }
83 }
84 
PermissionUsedRecordDb()85 PermissionUsedRecordDb::PermissionUsedRecordDb() : SqliteHelper(DATABASE_NAME, DATABASE_PATH, DATABASE_VERSION)
86 {
87     SqliteTable permissionRecordTable;
88     permissionRecordTable.tableName_ = PERMISSION_RECORD_TABLE;
89     permissionRecordTable.tableColumnNames_ = {
90         PrivacyFiledConst::FIELD_TOKEN_ID,
91         PrivacyFiledConst::FIELD_OP_CODE,
92         PrivacyFiledConst::FIELD_STATUS,
93         PrivacyFiledConst::FIELD_TIMESTAMP,
94         PrivacyFiledConst::FIELD_ACCESS_DURATION,
95         PrivacyFiledConst::FIELD_ACCESS_COUNT,
96         PrivacyFiledConst::FIELD_REJECT_COUNT,
97         PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS,
98         PrivacyFiledConst::FIELD_USED_TYPE
99     };
100 
101     SqliteTable permissionUsedTypeTable;
102     permissionUsedTypeTable.tableName_ = PERMISSION_USED_TYPE_TABLE;
103     permissionUsedTypeTable.tableColumnNames_ = {
104         PrivacyFiledConst::FIELD_TOKEN_ID,
105         PrivacyFiledConst::FIELD_PERMISSION_CODE,
106         /**
107          * bit operation:
108          * 1 -> 001, NORMAL_TYPE
109          * 2 -> 010, PICKER_TYPE
110          * 3 -> 011, NORMAL_TYPE + PICKER_TYPE
111          * 4 -> 100, SECURITY_COMPONENT_TYPE
112          * 5 -> 101, NORMAL_TYPE + SECURITY_COMPONENT_TYPE
113          * 6 -> 110, PICKER_TYPE + SECURITY_COMPONENT_TYPE
114          * 7 -> 111, NORMAL_TYPE + PICKER_TYPE + SECURITY_COMPONENT_TYPE
115          */
116         PrivacyFiledConst::FIELD_USED_TYPE
117     };
118 
119     dataTypeToSqlTable_ = {
120         {PERMISSION_RECORD, permissionRecordTable},
121         {PERMISSION_USED_TYPE, permissionUsedTypeTable},
122     };
123     Open();
124 }
125 
Add(DataType type,const std::vector<GenericValues> & values)126 int32_t PermissionUsedRecordDb::Add(DataType type, const std::vector<GenericValues>& values)
127 {
128     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
129 
130     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
131     std::string prepareSql = CreateInsertPrepareSqlCmd(type);
132     if (prepareSql.empty()) {
133         ACCESSTOKEN_LOG_ERROR(LABEL, "Type %{public}u invalid", type);
134         return FAILURE;
135     }
136     ACCESSTOKEN_LOG_DEBUG(LABEL, "Add sql is %{public}s.", prepareSql.c_str());
137 
138     auto statement = Prepare(prepareSql);
139     BeginTransaction();
140     bool isAddSuccessfully = true;
141     for (const auto& value : values) {
142         std::vector<std::string> columnNames = value.GetAllKeys();
143         for (const auto& name : columnNames) {
144             statement.Bind(name, value.Get(name));
145         }
146         int32_t ret = statement.Step();
147         if (ret != Statement::State::DONE) {
148             ACCESSTOKEN_LOG_ERROR(LABEL, "Failed, errorMsg: %{public}s", SpitError().c_str());
149             isAddSuccessfully = false;
150         }
151         statement.Reset();
152     }
153     if (!isAddSuccessfully) {
154         ACCESSTOKEN_LOG_ERROR(LABEL, "Rollback transaction.");
155         RollbackTransaction();
156         return FAILURE;
157     }
158     ACCESSTOKEN_LOG_DEBUG(LABEL, "Commit transaction.");
159     CommitTransaction();
160 
161     int64_t endTime = TimeUtil::GetCurrentTimestamp();
162     ACCESSTOKEN_LOG_INFO(LABEL, "Add cost %{public}" PRId64 ".", endTime - beginTime);
163 
164     return SUCCESS;
165 }
166 
Remove(DataType type,const GenericValues & conditions)167 int32_t PermissionUsedRecordDb::Remove(DataType type, const GenericValues& conditions)
168 {
169     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
170 
171     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
172     std::vector<std::string> columnNames = conditions.GetAllKeys();
173     std::string prepareSql = CreateDeletePrepareSqlCmd(type, columnNames);
174     if (prepareSql.empty()) {
175         ACCESSTOKEN_LOG_ERROR(LABEL, "Type %{public}u invalid", type);
176         return FAILURE;
177     }
178     ACCESSTOKEN_LOG_DEBUG(LABEL, "Remove sql is %{public}s.", prepareSql.c_str());
179 
180     auto statement = Prepare(prepareSql);
181     for (const auto& columnName : columnNames) {
182         statement.Bind(columnName, conditions.Get(columnName));
183     }
184     int32_t ret = statement.Step();
185 
186     int64_t endTime = TimeUtil::GetCurrentTimestamp();
187     ACCESSTOKEN_LOG_INFO(LABEL, "Remove cost %{public}" PRId64 ".", endTime - beginTime);
188 
189     return (ret == Statement::State::DONE) ? SUCCESS : FAILURE;
190 }
191 
FindByConditions(DataType type,const std::set<int32_t> & opCodeList,const GenericValues & andConditions,std::vector<GenericValues> & results,int32_t databaseQueryCount)192 int32_t PermissionUsedRecordDb::FindByConditions(DataType type, const std::set<int32_t>& opCodeList,
193     const GenericValues& andConditions, std::vector<GenericValues>& results, int32_t databaseQueryCount)
194 {
195     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
196 
197     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
198     std::vector<std::string> andColumns = andConditions.GetAllKeys();
199     int32_t tokenId = andConditions.GetInt(PrivacyFiledConst::FIELD_TOKEN_ID);
200     std::string prepareSql = CreateSelectByConditionPrepareSqlCmd(tokenId, type, opCodeList, andColumns,
201         databaseQueryCount);
202     if (prepareSql.empty()) {
203         ACCESSTOKEN_LOG_ERROR(LABEL, "Type %{public}u invalid", type);
204         return FAILURE;
205     }
206     ACCESSTOKEN_LOG_DEBUG(LABEL, "FindByConditions sql is %{public}s.", prepareSql.c_str());
207 
208     auto statement = Prepare(prepareSql);
209 
210     for (const auto& columnName : andColumns) {
211         statement.Bind(columnName, andConditions.Get(columnName));
212     }
213 
214     while (statement.Step() == Statement::State::ROW) {
215         int32_t columnCount = statement.GetColumnCount();
216         GenericValues value;
217         for (int32_t i = 0; i < columnCount; i++) {
218             if ((statement.GetColumnName(i) == PrivacyFiledConst::FIELD_TIMESTAMP) ||
219                 (statement.GetColumnName(i) == PrivacyFiledConst::FIELD_ACCESS_DURATION)) {
220                 value.Put(statement.GetColumnName(i), statement.GetValue(i, true));
221             } else {
222                 value.Put(statement.GetColumnName(i), statement.GetValue(i, false));
223             }
224         }
225         results.emplace_back(value);
226     }
227 
228     int64_t endTime = TimeUtil::GetCurrentTimestamp();
229     ACCESSTOKEN_LOG_INFO(LABEL, "FindByConditions cost %{public}" PRId64 ".", endTime - beginTime);
230 
231     return SUCCESS;
232 }
233 
Count(DataType type)234 int32_t PermissionUsedRecordDb::Count(DataType type)
235 {
236     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
237 
238     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
239     GenericValues countValue;
240     std::string countSql = CreateCountPrepareSqlCmd(type);
241     ACCESSTOKEN_LOG_DEBUG(LABEL, "Count sql is %{public}s.", countSql.c_str());
242     auto countStatement = Prepare(countSql);
243     if (countStatement.Step() == Statement::State::ROW) {
244         int32_t column = 0;
245         countValue.Put(FIELD_COUNT_NUMBER, countStatement.GetValue(column, false));
246     }
247 
248     int64_t endTime = TimeUtil::GetCurrentTimestamp();
249     ACCESSTOKEN_LOG_INFO(LABEL, "Count cost %{public}" PRId64 ".", endTime - beginTime);
250 
251     return countValue.GetInt(FIELD_COUNT_NUMBER);
252 }
253 
DeleteExpireRecords(DataType type,const GenericValues & andConditions)254 int32_t PermissionUsedRecordDb::DeleteExpireRecords(DataType type,
255     const GenericValues& andConditions)
256 {
257     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
258 
259     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
260     std::vector<std::string> andColumns = andConditions.GetAllKeys();
261     if (!andColumns.empty()) {
262         std::string deleteExpireSql = CreateDeleteExpireRecordsPrepareSqlCmd(type, andColumns);
263         ACCESSTOKEN_LOG_DEBUG(LABEL, "DeleteExpireRecords sql is %{public}s.", deleteExpireSql.c_str());
264         auto deleteExpireStatement = Prepare(deleteExpireSql);
265         for (const auto& columnName : andColumns) {
266             deleteExpireStatement.Bind(columnName, andConditions.Get(columnName));
267         }
268         if (deleteExpireStatement.Step() != Statement::State::DONE) {
269             return FAILURE;
270         }
271     }
272 
273     int64_t endTime = TimeUtil::GetCurrentTimestamp();
274     ACCESSTOKEN_LOG_INFO(LABEL, "DeleteExpireRecords cost %{public}" PRId64 ".", endTime - beginTime);
275 
276     return SUCCESS;
277 }
278 
DeleteExcessiveRecords(DataType type,uint32_t excessiveSize)279 int32_t PermissionUsedRecordDb::DeleteExcessiveRecords(DataType type, uint32_t excessiveSize)
280 {
281     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
282 
283     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
284     std::string deleteExcessiveSql = CreateDeleteExcessiveRecordsPrepareSqlCmd(type, excessiveSize);
285     ACCESSTOKEN_LOG_DEBUG(LABEL, "DeleteExcessiveRecords sql is %{public}s.", deleteExcessiveSql.c_str());
286     auto deleteExcessiveStatement = Prepare(deleteExcessiveSql);
287     if (deleteExcessiveStatement.Step() != Statement::State::DONE) {
288         return FAILURE;
289     }
290 
291     int64_t endTime = TimeUtil::GetCurrentTimestamp();
292     ACCESSTOKEN_LOG_INFO(LABEL, "DeleteExcessiveRecords cost %{public}" PRId64 ".", endTime - beginTime);
293 
294     return SUCCESS;
295 }
296 
Update(DataType type,const GenericValues & modifyValue,const GenericValues & conditionValue)297 int32_t PermissionUsedRecordDb::Update(DataType type, const GenericValues& modifyValue,
298     const GenericValues& conditionValue)
299 {
300     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
301 
302     std::vector<std::string> modifyNames = modifyValue.GetAllKeys();
303     std::vector<std::string> conditionNames = conditionValue.GetAllKeys();
304 
305     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
306     std::string prepareSql = CreateUpdatePrepareSqlCmd(type, modifyNames, conditionNames);
307     if (prepareSql.empty()) {
308         ACCESSTOKEN_LOG_ERROR(LABEL, "Type %{public}u invalid", type);
309         return FAILURE;
310     }
311     ACCESSTOKEN_LOG_DEBUG(LABEL, "Update sql is %{public}s.", prepareSql.c_str());
312 
313     auto statement = Prepare(prepareSql);
314 
315     for (const auto& modifyName : modifyNames) {
316         statement.Bind(modifyName, modifyValue.Get(modifyName));
317     }
318 
319     for (const auto& conditionName : conditionNames) {
320         statement.Bind(conditionName, conditionValue.Get(conditionName));
321     }
322 
323     int32_t ret = statement.Step();
324     if (ret != Statement::State::DONE) {
325         ACCESSTOKEN_LOG_ERROR(LABEL,
326             "Update table Type %{public}u failed, errCode is %{public}d, errMsg is %{public}s.", type, ret,
327             SpitError().c_str());
328         return FAILURE;
329     }
330 
331     int64_t endTime = TimeUtil::GetCurrentTimestamp();
332     ACCESSTOKEN_LOG_INFO(LABEL, "Update cost %{public}" PRId64 ".", endTime - beginTime);
333 
334     return SUCCESS;
335 }
336 
Query(DataType type,const GenericValues & conditionValue,std::vector<GenericValues> & results)337 int32_t PermissionUsedRecordDb::Query(DataType type, const GenericValues& conditionValue,
338     std::vector<GenericValues>& results)
339 {
340     int64_t beginTime = TimeUtil::GetCurrentTimestamp();
341 
342     std::vector<std::string> conditionColumns = conditionValue.GetAllKeys();
343 
344     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
345     std::string prepareSql = CreateQueryPrepareSqlCmd(type, conditionColumns);
346     if (prepareSql.empty()) {
347         ACCESSTOKEN_LOG_ERROR(LABEL, "Type %{public}u invalid.", type);
348         return FAILURE;
349     }
350     ACCESSTOKEN_LOG_DEBUG(LABEL, "Query sql is %{public}s.", prepareSql.c_str());
351 
352     auto statement = Prepare(prepareSql);
353     for (const auto& conditionColumn : conditionColumns) {
354         statement.Bind(conditionColumn, conditionValue.Get(conditionColumn));
355     }
356 
357     while (statement.Step() == Statement::State::ROW) {
358         int32_t columnCount = statement.GetColumnCount();
359         GenericValues value;
360 
361         for (int32_t i = 0; i < columnCount; i++) {
362             value.Put(statement.GetColumnName(i), statement.GetValue(i, false));
363         }
364 
365         results.emplace_back(value);
366     }
367 
368     int64_t endTime = TimeUtil::GetCurrentTimestamp();
369     ACCESSTOKEN_LOG_INFO(LABEL, "Query cost %{public}" PRId64 ".", endTime - beginTime);
370 
371     return SUCCESS;
372 }
373 
CreateInsertPrepareSqlCmd(DataType type) const374 std::string PermissionUsedRecordDb::CreateInsertPrepareSqlCmd(DataType type) const
375 {
376     auto it = dataTypeToSqlTable_.find(type);
377     if (it == dataTypeToSqlTable_.end()) {
378         return std::string();
379     }
380     std::string sql = "insert into " + it->second.tableName_ + " values(";
381     int32_t i = 1;
382     for (const auto& name : it->second.tableColumnNames_) {
383         sql.append(":" + name);
384         if (i < static_cast<int32_t>(it->second.tableColumnNames_.size())) {
385             sql.append(",");
386         }
387         i += 1;
388     }
389     sql.append(")");
390     return sql;
391 }
392 
CreateQueryPrepareSqlCmd(DataType type,const std::vector<std::string> & conditionColumns) const393 std::string PermissionUsedRecordDb::CreateQueryPrepareSqlCmd(DataType type,
394     const std::vector<std::string>& conditionColumns) const
395 {
396     auto it = dataTypeToSqlTable_.find(type);
397     if (it == dataTypeToSqlTable_.end()) {
398         return std::string();
399     }
400     std::string sql = "select * from " + it->second.tableName_ + WHERE_1_STR;
401 
402     for (const auto& andColumn : conditionColumns) {
403         sql.append(" and ");
404         sql.append(andColumn + "=:" + andColumn);
405     }
406 
407     return sql;
408 }
409 
CreateDeletePrepareSqlCmd(DataType type,const std::vector<std::string> & columnNames) const410 std::string PermissionUsedRecordDb::CreateDeletePrepareSqlCmd(
411     DataType type, const std::vector<std::string>& columnNames) const
412 {
413     auto it = dataTypeToSqlTable_.find(type);
414     if (it == dataTypeToSqlTable_.end()) {
415         return std::string();
416     }
417     std::string sql = "delete from " + it->second.tableName_ + WHERE_1_STR;
418     for (const auto& name : columnNames) {
419         sql.append(" and ");
420         sql.append(name + "=:" + name);
421     }
422     return sql;
423 }
424 
CreateUpdatePrepareSqlCmd(DataType type,const std::vector<std::string> & modifyColumns,const std::vector<std::string> & conditionColumns) const425 std::string PermissionUsedRecordDb::CreateUpdatePrepareSqlCmd(DataType type,
426     const std::vector<std::string>& modifyColumns, const std::vector<std::string>& conditionColumns) const
427 {
428     if (modifyColumns.empty()) {
429         return std::string();
430     }
431 
432     auto it = dataTypeToSqlTable_.find(type);
433     if (it == dataTypeToSqlTable_.end()) {
434         return std::string();
435     }
436 
437     std::string sql = "update " + it->second.tableName_ + " set ";
438     int32_t i = 1;
439     for (const auto& name : modifyColumns) {
440         sql.append(name + "=:" + name);
441         if (i < static_cast<int32_t>(modifyColumns.size())) {
442             sql.append(",");
443         }
444         i += 1;
445     }
446 
447     if (!conditionColumns.empty()) {
448         sql.append(WHERE_1_STR);
449         for (const auto& columnName : conditionColumns) {
450             sql.append(" and ");
451             sql.append(columnName + "=:" + columnName);
452         }
453     }
454     return sql;
455 }
456 
CreateSelectByConditionPrepareSqlCmd(const int32_t tokenId,DataType type,const std::set<int32_t> & opCodeList,const std::vector<std::string> & andColumns,int32_t databaseQueryCount) const457 std::string PermissionUsedRecordDb::CreateSelectByConditionPrepareSqlCmd(const int32_t tokenId, DataType type,
458     const std::set<int32_t>& opCodeList, const std::vector<std::string>& andColumns, int32_t databaseQueryCount) const
459 {
460     auto it = dataTypeToSqlTable_.find(type);
461     if (it == dataTypeToSqlTable_.end()) {
462         return std::string();
463     }
464 
465     std::string sql = "select * from " + it->second.tableName_ + WHERE_1_STR;
466 
467     for (const auto& andColName : andColumns) {
468         if (andColName == PrivacyFiledConst::FIELD_TIMESTAMP_BEGIN) {
469             sql.append(" and ");
470             sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
471             sql.append(" >=:" + andColName);
472         } else if (andColName == PrivacyFiledConst::FIELD_TIMESTAMP_END) {
473             sql.append(" and ");
474             sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
475             sql.append(" <=:" + andColName);
476         } else if (andColName == PrivacyFiledConst::FIELD_TOKEN_ID) {
477             if (tokenId != 0) {
478                 sql.append(" and ");
479                 sql.append(PrivacyFiledConst::FIELD_TOKEN_ID);
480                 sql.append(" =:" + andColName);
481             }
482         } else {
483             sql.append(" and ");
484             sql.append(andColName + "=:" + andColName);
485         }
486     }
487     if (!opCodeList.empty()) {
488         sql.append(" and (");
489         for (const auto& opCode : opCodeList) {
490             if (opCode != Constant::OP_INVALID) {
491                 sql.append(PrivacyFiledConst::FIELD_OP_CODE);
492                 sql.append(+ " = " + std::to_string(opCode));
493                 sql.append(" or ");
494             }
495         }
496         sql.append("0)");
497     }
498     sql.append(" order by timestamp desc");
499     sql.append(" limit " + std::to_string(databaseQueryCount));
500     return sql;
501 }
502 
CreateCountPrepareSqlCmd(DataType type) const503 std::string PermissionUsedRecordDb::CreateCountPrepareSqlCmd(DataType type) const
504 {
505     auto it = dataTypeToSqlTable_.find(type);
506     if (it == dataTypeToSqlTable_.end()) {
507         return std::string();
508     }
509     std::string sql = "select count(*) from " + it->second.tableName_;
510     return sql;
511 }
512 
CreateDeleteExpireRecordsPrepareSqlCmd(DataType type,const std::vector<std::string> & andColumns) const513 std::string PermissionUsedRecordDb::CreateDeleteExpireRecordsPrepareSqlCmd(DataType type,
514     const std::vector<std::string>& andColumns) const
515 {
516     auto it = dataTypeToSqlTable_.find(type);
517     if (it == dataTypeToSqlTable_.end()) {
518         return std::string();
519     }
520     std::string sql = "delete from " + it->second.tableName_ + " where ";
521     sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
522     sql.append(" in (select ");
523     sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
524     sql.append(" from " + it->second.tableName_ + WHERE_1_STR);
525     for (const auto& name : andColumns) {
526         if (name == PrivacyFiledConst::FIELD_TIMESTAMP_BEGIN) {
527             sql.append(" and ");
528             sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
529             sql.append(" >=:" + name);
530         } else if (name == PrivacyFiledConst::FIELD_TIMESTAMP_END) {
531             sql.append(" and ");
532             sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
533             sql.append(" <=:" + name);
534         } else {
535             sql.append(" and ");
536             sql.append(name + "=:" + name);
537         }
538     }
539     sql.append(" )");
540     return sql;
541 }
542 
CreateDeleteExcessiveRecordsPrepareSqlCmd(DataType type,uint32_t excessiveSize) const543 std::string PermissionUsedRecordDb::CreateDeleteExcessiveRecordsPrepareSqlCmd(DataType type,
544     uint32_t excessiveSize) const
545 {
546     auto it = dataTypeToSqlTable_.find(type);
547     if (it == dataTypeToSqlTable_.end()) {
548         return std::string();
549     }
550     std::string sql = "delete from " + it->second.tableName_ + " where ";
551     sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
552     sql.append(" in (select ");
553     sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
554     sql.append(" from " + it->second.tableName_ + " order by ");
555     sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
556     sql.append(" limit ");
557     sql.append(std::to_string(excessiveSize) + " )");
558     return sql;
559 }
560 
CreatePermissionRecordTable() const561 int32_t PermissionUsedRecordDb::CreatePermissionRecordTable() const
562 {
563     auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_RECORD);
564     if (it == dataTypeToSqlTable_.end()) {
565         return FAILURE;
566     }
567     std::string sql = CREATE_TABLE_STR;
568     sql.append(it->second.tableName_ + " (")
569         .append(PrivacyFiledConst::FIELD_TOKEN_ID)
570         .append(INTEGER_STR)
571         .append(PrivacyFiledConst::FIELD_OP_CODE)
572         .append(INTEGER_STR)
573         .append(PrivacyFiledConst::FIELD_STATUS)
574         .append(INTEGER_STR)
575         .append(PrivacyFiledConst::FIELD_TIMESTAMP)
576         .append(INTEGER_STR)
577         .append(PrivacyFiledConst::FIELD_ACCESS_DURATION)
578         .append(INTEGER_STR)
579         .append(PrivacyFiledConst::FIELD_ACCESS_COUNT)
580         .append(INTEGER_STR)
581         .append(PrivacyFiledConst::FIELD_REJECT_COUNT)
582         .append(INTEGER_STR)
583         .append(PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS)
584         .append(INTEGER_STR)
585         .append(PrivacyFiledConst::FIELD_USED_TYPE)
586         .append(INTEGER_STR)
587         .append("primary key(")
588         .append(PrivacyFiledConst::FIELD_TOKEN_ID)
589         .append(",")
590         .append(PrivacyFiledConst::FIELD_OP_CODE)
591         .append(",")
592         .append(PrivacyFiledConst::FIELD_STATUS)
593         .append(",")
594         .append(PrivacyFiledConst::FIELD_TIMESTAMP)
595         .append(",")
596         .append(PrivacyFiledConst::FIELD_USED_TYPE)
597         .append("))");
598     return ExecuteSql(sql);
599 }
600 
CreatePermissionUsedTypeTable() const601 int32_t PermissionUsedRecordDb::CreatePermissionUsedTypeTable() const
602 {
603     auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_USED_TYPE);
604     if (it == dataTypeToSqlTable_.end()) {
605         return FAILURE;
606     }
607     std::string sql = CREATE_TABLE_STR;
608     sql.append(it->second.tableName_ + " (")
609         .append(PrivacyFiledConst::FIELD_TOKEN_ID)
610         .append(INTEGER_STR)
611         .append(PrivacyFiledConst::FIELD_PERMISSION_CODE)
612         .append(INTEGER_STR)
613         .append(PrivacyFiledConst::FIELD_USED_TYPE)
614         .append(INTEGER_STR)
615         .append("primary key(")
616         .append(PrivacyFiledConst::FIELD_TOKEN_ID)
617         .append(",")
618         .append(PrivacyFiledConst::FIELD_PERMISSION_CODE)
619         .append("))");
620     return ExecuteSql(sql);
621 }
622 
InsertLockScreenStatusColumn() const623 int32_t PermissionUsedRecordDb::InsertLockScreenStatusColumn() const
624 {
625     auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_RECORD);
626     if (it == dataTypeToSqlTable_.end()) {
627         return FAILURE;
628     }
629     std::string checkSql = "SELECT 1 FROM " + it->second.tableName_ + " WHERE " +
630         PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS + "=" +
631         std::to_string(LockScreenStatusChangeType::PERM_ACTIVE_IN_UNLOCKED);
632     int32_t checkResult = ExecuteSql(checkSql);
633     ACCESSTOKEN_LOG_INFO(LABEL, "Check result:%{public}d", checkResult);
634     if (checkResult != -1) {
635         return SUCCESS;
636     }
637 
638     std::string sql = "alter table ";
639     sql.append(it->second.tableName_ + " add column ")
640         .append(PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS)
641         .append(" integer default ")
642         .append(std::to_string(LockScreenStatusChangeType::PERM_ACTIVE_IN_UNLOCKED));
643     int32_t insertResult = ExecuteSql(sql);
644     ACCESSTOKEN_LOG_INFO(LABEL, "Insert column result:%{public}d", insertResult);
645     return insertResult;
646 }
647 
InsertPermissionUsedTypeColumn() const648 int32_t PermissionUsedRecordDb::InsertPermissionUsedTypeColumn() const
649 {
650     auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_RECORD);
651     if (it == dataTypeToSqlTable_.end()) {
652         return FAILURE;
653     }
654     std::string checkSql = "SELECT 1 FROM " + it->second.tableName_ + " WHERE " +
655         PrivacyFiledConst::FIELD_USED_TYPE + "=" +
656         std::to_string(PermissionUsedType::NORMAL_TYPE);
657     int32_t checkResult = ExecuteSql(checkSql);
658     ACCESSTOKEN_LOG_INFO(LABEL, "Check result:%{public}d", checkResult);
659     if (checkResult != -1) {
660         return SUCCESS;
661     }
662 
663     std::string sql = "alter table ";
664     sql.append(it->second.tableName_ + " add column ")
665         .append(PrivacyFiledConst::FIELD_USED_TYPE)
666         .append(" integer default ")
667         .append(std::to_string(PermissionUsedType::NORMAL_TYPE));
668     int32_t insertResult = ExecuteSql(sql);
669     ACCESSTOKEN_LOG_INFO(LABEL, "Insert column result:%{public}d", insertResult);
670     return insertResult;
671 }
672 
CreateNewPermissionRecordTable(std::string & newTableName,std::string & createNewSql)673 static void CreateNewPermissionRecordTable(std::string& newTableName, std::string& createNewSql)
674 {
675     createNewSql = CREATE_TABLE_STR;
676     createNewSql.append(newTableName + " (")
677         .append(PrivacyFiledConst::FIELD_TOKEN_ID)
678         .append(INTEGER_STR)
679         .append(PrivacyFiledConst::FIELD_OP_CODE)
680         .append(INTEGER_STR)
681         .append(PrivacyFiledConst::FIELD_STATUS)
682         .append(INTEGER_STR)
683         .append(PrivacyFiledConst::FIELD_TIMESTAMP)
684         .append(INTEGER_STR)
685         .append(PrivacyFiledConst::FIELD_ACCESS_DURATION)
686         .append(INTEGER_STR)
687         .append(PrivacyFiledConst::FIELD_ACCESS_COUNT)
688         .append(INTEGER_STR)
689         .append(PrivacyFiledConst::FIELD_REJECT_COUNT)
690         .append(INTEGER_STR)
691         .append(PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS)
692         .append(INTEGER_STR)
693         .append(PrivacyFiledConst::FIELD_USED_TYPE)
694         .append(INTEGER_STR)
695         .append("primary key(")
696         .append(PrivacyFiledConst::FIELD_TOKEN_ID)
697         .append(",")
698         .append(PrivacyFiledConst::FIELD_OP_CODE)
699         .append(",")
700         .append(PrivacyFiledConst::FIELD_STATUS)
701         .append(",")
702         .append(PrivacyFiledConst::FIELD_TIMESTAMP)
703         .append(",")
704         .append(PrivacyFiledConst::FIELD_USED_TYPE)
705         .append("))");
706 }
707 
UpdatePermissionRecordTablePrimaryKey() const708 int32_t PermissionUsedRecordDb::UpdatePermissionRecordTablePrimaryKey() const
709 {
710     auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_RECORD);
711     if (it == dataTypeToSqlTable_.end()) {
712         return FAILURE;
713     }
714 
715     std::string tableName = it->second.tableName_;
716     std::string newTableName = it->second.tableName_ + "_new";
717     std::string createNewSql;
718     CreateNewPermissionRecordTable(newTableName, createNewSql);
719 
720     BeginTransaction();
721 
722     int32_t createNewRes = ExecuteSql(createNewSql); // 1、create new table with new primary key
723     if (createNewRes != 0) {
724         ACCESSTOKEN_LOG_ERROR(LABEL, "Create new table failed, errCode is %{public}d, errMsg is %{public}s.",
725             createNewRes, SpitError().c_str());
726         return FAILURE;
727     }
728 
729     std::string copyDataSql = "insert into " + newTableName + " select * from " + tableName;
730     int32_t copyDataRes = ExecuteSql(copyDataSql); // 2、copy data from old table to new table
731     if (copyDataRes != 0) {
732         ACCESSTOKEN_LOG_ERROR(LABEL, "Copy data from old table failed, errCode is %{public}d, errMsg is %{public}s.",
733             copyDataRes, SpitError().c_str());
734         RollbackTransaction();
735         return FAILURE;
736     }
737 
738     std::string dropOldSql = "drop table " + tableName;
739     int32_t dropOldRes = ExecuteSql(dropOldSql); // 3、drop old table
740     if (dropOldRes != 0) {
741         ACCESSTOKEN_LOG_ERROR(LABEL, "Drop old table failed, errCode is %{public}d, errMsg is %{public}s.",
742             dropOldRes, SpitError().c_str());
743         RollbackTransaction();
744         return FAILURE;
745     }
746 
747     std::string renameSql = "alter table " + newTableName + " rename to " + tableName;
748     int32_t renameRes = ExecuteSql(renameSql); // 4、rename new table to old
749     if (renameRes != 0) {
750         ACCESSTOKEN_LOG_ERROR(LABEL, "Rename table failed, errCode is %{public}d, errMsg is %{public}s.",
751             renameRes, SpitError().c_str());
752         RollbackTransaction();
753         return FAILURE;
754     }
755 
756     CommitTransaction();
757 
758     return SUCCESS;
759 }
760 } // namespace AccessToken
761 } // namespace Security
762 } // namespace OHOS
763