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 #include "grant_permissions.h"
16 
17 #include <string>
18 #include <vector>
19 
20 #include "access_token.h"
21 #include "accesstoken_kit.h"
22 #include "ipc_skeleton.h"
23 #include "js_native_api.h"
24 #include "log.h"
25 #include "n_napi.h"
26 #include "parameter.h"
27 #include "tokenid_kit.h"
28 
29 namespace OHOS {
30 namespace AppFileService {
31 namespace ModuleFileShare {
32 using namespace OHOS::FileManagement::LibN;
33 using namespace std;
34 
GetErrData(napi_env env, deque<struct PolicyErrorResult> &errorResults)35 static napi_value GetErrData(napi_env env, deque<struct PolicyErrorResult> &errorResults)
36 {
37     napi_value res = nullptr;
38     napi_status status = napi_create_array(env, &res);
39     if (status != napi_ok) {
40         LOGE("Failed to create array");
41         return nullptr;
42     }
43     size_t index = 0;
44     for (auto &iter : errorResults) {
45         NVal obj = NVal::CreateObject(env);
46         obj.AddProp("uri", NVal::CreateUTF8String(env, iter.uri).val_);
47         obj.AddProp("code", NVal::CreateInt32(env, iter.code).val_);
48         obj.AddProp("message", NVal::CreateUTF8String(env, iter.message).val_);
49         status = napi_set_element(env, res, index++, obj.val_);
50         if (status != napi_ok) {
51             LOGE("Failed to set element on data");
52             return nullptr;
53         }
54     }
55     return res;
56 }
57 
GetResultData(napi_env env, const vector<bool> &results)58 static napi_value GetResultData(napi_env env, const vector<bool> &results)
59 {
60     napi_value res = nullptr;
61     napi_status status = napi_create_array(env, &res);
62     if (status != napi_ok) {
63         LOGE("Failed to create array");
64         return nullptr;
65     }
66     size_t index = 0;
67     for (const auto &iter : results) {
68         napi_value value;
69         napi_get_boolean(env, iter, &value);
70         status = napi_set_element(env, res, index++, value);
71         if (status != napi_ok) {
72             LOGE("Failed to set element on data");
73             return nullptr;
74         }
75     }
76     return res;
77 }
78 
GetUriPoliciesArg(napi_env env, napi_value agrv, std::vector<UriPolicyInfo> &uriPolicies)79 static napi_status GetUriPoliciesArg(napi_env env, napi_value agrv, std::vector<UriPolicyInfo> &uriPolicies)
80 {
81     uint32_t count;
82     napi_status status = napi_get_array_length(env, agrv, &count);
83     if (status != napi_ok) {
84         LOGE("get array length failed");
85         return status;
86     }
87     if (count > MAX_ARRAY_SIZE) {
88         LOGE("The length of the array is extra-long");
89         return napi_invalid_arg;
90     }
91     for (uint32_t i = 0; i < count; i++) {
92         napi_handle_scope scope;
93         status = napi_open_handle_scope(env, &scope);
94         if (status != napi_ok) {
95             return status;
96         }
97         napi_value object;
98         status = napi_get_element(env, agrv, i, &object);
99         if (status != napi_ok) {
100             LOGE("get element failed");
101             return status;
102         }
103         napi_value uriValue;
104         napi_value modeValue;
105         status = napi_get_named_property(env, object, "uri", &uriValue);
106         if (status != napi_ok) {
107             LOGE("get named property failed");
108             return status;
109         }
110         status = napi_get_named_property(env, object, "operationMode", &modeValue);
111         if (status != napi_ok) {
112             LOGE("get named property failed");
113             return status;
114         }
115         auto [succStr, str, ignore] = NVal(env, uriValue).ToUTF8String();
116         auto [succMode, mode] = NVal(env, modeValue).ToUint32();
117         if (!succStr || !succMode) {
118             LOGE("the argument error");
119             return napi_invalid_arg;
120         }
121         UriPolicyInfo uriPolicy {.uri = str.get(), .mode = mode};
122         uriPolicies.emplace_back(uriPolicy);
123         status = napi_close_handle_scope(env, scope);
124         if (status != napi_ok) {
125             return status;
126         }
127     }
128     return napi_ok;
129 }
130 
PersistPermission(napi_env env, napi_callback_info info)131 napi_value PersistPermission(napi_env env, napi_callback_info info)
132 {
133     NFuncArg funcArg(env, info);
134     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
135         LOGE("PersistPermission Number of arguments unmatched");
136         NError(E_PARAMS).ThrowErr(env);
137         return nullptr;
138     }
139     std::vector<UriPolicyInfo> uriPolicies;
140     if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
141         NError(E_PARAMS).ThrowErr(env);
142         return nullptr;
143     }
144     shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
145     auto cbExec = [uriPolicies, arg]() -> NError {
146         arg->errNo = FilePermission::PersistPermission(uriPolicies, arg->errorResults);
147         return NError(arg->errNo);
148     };
149     auto cbCompl = [arg](napi_env env, NError err) -> NVal {
150         if (err) {
151             if (arg->errNo == EPERM) {
152                 napi_value data = err.GetNapiErr(env);
153                 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
154                 return NVal(env, data);
155             }
156             return {env, err.GetNapiErr(env)};
157         }
158         return NVal::CreateUndefined(env);
159     };
160     const string procedureName = "persist_permission";
161     NVal thisVar(env, funcArg.GetThisVar());
162     return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
163 }
164 
RevokePermission(napi_env env, napi_callback_info info)165 napi_value RevokePermission(napi_env env, napi_callback_info info)
166 {
167     NFuncArg funcArg(env, info);
168     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
169         LOGE("RevokePermission Number of arguments unmatched");
170         NError(E_PARAMS).ThrowErr(env);
171         return nullptr;
172     }
173     std::vector<UriPolicyInfo> uriPolicies;
174     if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
175         NError(E_PARAMS).ThrowErr(env);
176         return nullptr;
177     }
178     shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
179     auto cbExec = [uriPolicies, arg]() -> NError {
180         arg->errNo = FilePermission::RevokePermission(uriPolicies, arg->errorResults);
181         return NError(arg->errNo);
182     };
183     auto cbCompl = [arg](napi_env env, NError err) -> NVal {
184         if (err) {
185             if (arg->errNo == EPERM) {
186                 napi_value data = err.GetNapiErr(env);
187                 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
188                 return NVal(env, data);
189             }
190             return {env, err.GetNapiErr(env)};
191         }
192         return NVal::CreateUndefined(env);
193     };
194     const string procedureName = "revoke_permission";
195     NVal thisVar(env, funcArg.GetThisVar());
196     return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
197 }
198 
ActivatePermission(napi_env env, napi_callback_info info)199 napi_value ActivatePermission(napi_env env, napi_callback_info info)
200 {
201     NFuncArg funcArg(env, info);
202     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
203         LOGE("ActivatePermission Number of arguments unmatched");
204         NError(E_PARAMS).ThrowErr(env);
205         return nullptr;
206     }
207     std::vector<UriPolicyInfo> uriPolicies;
208     if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
209         NError(E_PARAMS).ThrowErr(env);
210         return nullptr;
211     }
212     shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
213     auto cbExec = [uriPolicies, arg]() -> NError {
214         arg->errNo = FilePermission::ActivatePermission(uriPolicies, arg->errorResults);
215         return NError(arg->errNo);
216     };
217     auto cbCompl = [arg](napi_env env, NError err) -> NVal {
218         if (err) {
219             if (arg->errNo == EPERM) {
220                 napi_value data = err.GetNapiErr(env);
221                 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
222                 return NVal(env, data);
223             }
224             return {env, err.GetNapiErr(env)};
225         }
226         return NVal::CreateUndefined(env);
227     };
228     const string procedureName = "activate_permission";
229     NVal thisVar(env, funcArg.GetThisVar());
230     return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
231 }
232 
DeactivatePermission(napi_env env, napi_callback_info info)233 napi_value DeactivatePermission(napi_env env, napi_callback_info info)
234 {
235     NFuncArg funcArg(env, info);
236     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
237         LOGE("DeactivatePermission Number of arguments unmatched");
238         NError(E_PARAMS).ThrowErr(env);
239         return nullptr;
240     }
241     std::vector<UriPolicyInfo> uriPolicies;
242     if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
243         NError(E_PARAMS).ThrowErr(env);
244         return nullptr;
245     }
246     shared_ptr<PolicyErrorArgs> arg = make_shared<PolicyErrorArgs>();
247     auto cbExec = [uriPolicies, arg]() -> NError {
248         arg->errNo = FilePermission::DeactivatePermission(uriPolicies, arg->errorResults);
249         return NError(arg->errNo);
250     };
251     auto cbCompl = [arg](napi_env env, NError err) -> NVal {
252         if (err) {
253             if (arg->errNo == EPERM) {
254                 napi_value data = err.GetNapiErr(env);
255                 napi_set_named_property(env, data, FILEIO_TAG_ERR_DATA.c_str(), GetErrData(env, arg->errorResults));
256                 return NVal(env, data);
257             }
258             return {env, err.GetNapiErr(env)};
259         }
260         return NVal::CreateUndefined(env);
261     };
262     const string procedureName = "deactivate_permission";
263     NVal thisVar(env, funcArg.GetThisVar());
264     return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
265 }
266 
CheckPersistentPermission(napi_env env, napi_callback_info info)267 napi_value CheckPersistentPermission(napi_env env, napi_callback_info info)
268 {
269     NFuncArg funcArg(env, info);
270     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
271         LOGE("ActivatePermission Number of arguments unmatched");
272         NError(E_PARAMS).ThrowErr(env);
273         return nullptr;
274     }
275     std::vector<UriPolicyInfo> uriPolicies;
276     if (GetUriPoliciesArg(env, funcArg[NARG_POS::FIRST], uriPolicies) != napi_ok) {
277         NError(E_PARAMS).ThrowErr(env);
278         return nullptr;
279     }
280     shared_ptr<PolicyInfoResultArgs> arg = make_shared<PolicyInfoResultArgs>();
281     auto cbExec = [uriPolicies, arg]() -> NError {
282         arg->errNo = FilePermission::CheckPersistentPermission(uriPolicies, arg->resultData);
283         return NError(arg->errNo);
284     };
285     auto cbCompl = [arg](napi_env env, NError err) -> NVal {
286         if (arg->errNo != 0) {
287             return {env, err.GetNapiErr(env)};
288         }
289         return {env, GetResultData(env, arg->resultData)};
290     };
291     const string procedureName = "check_persist_permission";
292     NVal thisVar(env, funcArg.GetThisVar());
293     return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
294 }
295 
296 } // namespace ModuleFileShare
297 } // namespace AppFileService
298 } // namespace OHOS
299