1/*
2 * Copyright (c) 2021-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
16const fs = require('fs');
17const path = require('path');
18const { getAPINote, ErrorType, ErrorLevel, FileType, systemPermissionFile, checkOption } = require('./utils');
19const { addAPICheckErrorLogs } = require('./compile_info');
20
21const permissionCheckWhitelist = new Set(['@ohos.wifi.d.ts', '@ohos.wifiManager.d.ts']);
22
23/**
24 * 门禁环境优先使用systemPermissionFile
25 * 本地环境从指定分支上下载
26 * 下载失败则使用默认配置
27 *
28 * @returns Set<string>
29 */
30function getPermissionBank() {
31  const permissionTags = ['ohos.permission.HEALTH_DATA', 'ohos.permission.HEART_RATE', 'ohos.permission.ACCELERATION'];
32  let permissionFileContent;
33  if (fs.existsSync(systemPermissionFile)) {
34    permissionFileContent = require(systemPermissionFile);
35  } else if (checkOption.permissionContent) {
36    permissionFileContent = JSON.parse(checkOption.permissionContent);
37  } else {
38    permissionFileContent = require('../config/config.json');
39  }
40  const permissionTagsObj = permissionFileContent.module.definePermissions;
41  permissionTagsObj.forEach((item) => {
42    permissionTags.push(item.name);
43  });
44  const permissionRuleSets = new Set(permissionTags);
45  return permissionRuleSets;
46}
47exports.getPermissionBank = getPermissionBank;
48
49function checkPermission(node, sourcefile, fileName) {
50  const permissionRuleSet = getPermissionBank();
51  const apiNote = getAPINote(node);
52  let hasPermissionError = false;
53  let errorInfo = '';
54  let apiNoteArr = [];
55  if (apiNote.match(new RegExp('@permission'))) {
56    apiNoteArr = apiNote.split(/ *\* *\@/g);
57  }
58  apiNoteArr.forEach(note => {
59    // 找到jsdoc中的permission标签关键字并拿到待校验的permission字段
60    if (note.match(new RegExp(/^permission\b/))) {
61      const permissionNote = note.replace(/(^permission\b|[(\r\n)\r\n ]|(\*\/|\*))/g, '').trim();
62      if (/(or|and)/g.test(permissionNote)) {
63        const permissionArr = permissionNote.replace(/( |or|and|\(|\))/g, '$').split('$');
64        permissionArr.forEach(permissionStr => {
65          if (permissionStr !== '') {
66            if (!permissionRuleSet.has(permissionStr)) {
67              hasPermissionError = true;
68              if (errorInfo !== '') {
69                errorInfo += `,${permissionStr}`;
70              } else {
71                errorInfo += permissionStr;
72              }
73            }
74          }
75        });
76      } else {
77        if (!permissionRuleSet.has(permissionNote)) {
78          hasPermissionError = true;
79          if (errorInfo !== '') {
80            errorInfo += `,${permissionNote}`;
81          } else {
82            errorInfo += permissionNote;
83          }
84        }
85      }
86    }
87  });
88
89  if (hasPermissionError && !permissionCheckWhitelist.has(path.basename(fileName))) {
90    addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.UNKNOW_PERMISSION, errorInfo, FileType.API,
91      ErrorLevel.MIDDLE);
92  } else if (hasPermissionError && permissionCheckWhitelist.has(path.basename(fileName))) {
93    addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.UNKNOW_PERMISSION, errorInfo, FileType.API,
94      ErrorLevel.LOW);
95  }
96}
97exports.checkPermission = checkPermission;
98