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