• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 "napi_account_iam_common.h"
17 
18 #include <map>
19 
20 #include <uv.h>
21 #include "account_error_no.h"
22 #include "account_iam_info.h"
23 #include "account_iam_info_parse.h"
24 #include "account_log_wrapper.h"
25 #include "napi_account_error.h"
26 #include "napi_account_common.h"
27 #include "napi_account_iam_constant.h"
28 #include "securec.h"
29 
30 namespace OHOS {
31 namespace AccountJsKit {
32 using namespace OHOS::AccountSA;
33 typedef UserIam::UserAuth::Attributes Attributes;
34 namespace {
35 static const std::unordered_map<int32_t, int32_t> IAM_ERRCODE_MAP = {
36     {ERR_IAM_SUCCESS, ERR_JS_SUCCESS},
37     {ERR_IAM_FAIL, ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR},
38     {ERR_IAM_AUTH_TOKEN_CHECK_FAILED, ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR},
39     {ERR_IAM_AUTH_TOKEN_EXPIRED, ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR},
40     {ERR_IAM_TOKEN_TIMEOUT, ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR},
41     {ERR_IAM_TOKEN_AUTH_FAILED, ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR},
42     {ERR_IAM_TRUST_LEVEL_NOT_SUPPORT, ERR_JS_TRUST_LEVEL_NOT_SUPPORTED},
43     {ERR_IAM_TYPE_NOT_SUPPORT, ERR_JS_AUTH_TYPE_NOT_SUPPORTED},
44     {ERR_IAM_TIMEOUT, ERR_JS_AUTH_TIMEOUT},
45     {ERR_IAM_CANCELED, ERR_JS_AUTH_CANCELLED},
46     {ERR_IAM_BUSY, ERR_JS_AUTH_SERVICE_BUSY},
47     {ERR_IAM_LOCKED, ERR_JS_AUTH_SERVICE_LOCKED},
48     {ERR_IAM_NOT_ENROLLED, ERR_JS_CREDENTIAL_NOT_EXIST},
49     {ERR_IAM_PIN_IS_EXPIRED, ERR_JS_PIN_IS_EXPIRED},
50     {ERR_IAM_COMPLEXITY_CHECK_FAILED, ERR_JS_COMPLEXITY_CHECK_FAILED},
51     {ERR_IAM_INVALID_CONTEXT_ID, ERR_JS_INVALID_CONTEXT_ID},
52     {ERR_ACCOUNT_COMMON_INVALID_PARAMETER, ERR_JS_INVALID_PARAMETER},
53     {ERR_IAM_INVALID_PARAMETERS, ERR_JS_INVALID_PARAMETER},
54     {ERR_ACCOUNT_IAM_KIT_INPUTER_ALREADY_REGISTERED, ERR_JS_CREDENTIAL_INPUTER_ALREADY_EXIST},
55     {ERR_ACCOUNT_IAM_KIT_INPUTER_NOT_REGISTERED, ERR_JS_CREDENTIAL_INPUTER_NOT_EXIST},
56     {ERR_ACCOUNT_IAM_UNSUPPORTED_AUTH_TYPE, ERR_JS_AUTH_TYPE_NOT_SUPPORTED},
57     {ERR_DOMAIN_ACCOUNT_SERVICE_NOT_DOMAIN_ACCOUNT, ERR_JS_AUTH_TYPE_NOT_SUPPORTED},
58     {ERR_DOMAIN_ACCOUNT_NOT_SUPPORT_BACKGROUND_ACCOUNT_REQUEST, ERR_JS_AUTH_TYPE_NOT_SUPPORTED},
59     {ERR_IAM_CREDENTIAL_NUMBER_REACH_LIMIT, ERR_JS_CREDENTIAL_NUMBER_REACH_LIMIT},
60     {ERR_IAM_SESSION_TIMEOUT, ERR_JS_SESSION_TIMEOUT},
61     {ERR_IAM_CHECK_SYSTEM_APP_FAILED, ERR_JS_IS_NOT_SYSTEM_APP}
62 };
63 }
64 
65 
AccountIAMConvertOtherToJSErrCode(int32_t errCode)66 static int32_t AccountIAMConvertOtherToJSErrCode(int32_t errCode)
67 {
68     auto it = IAM_ERRCODE_MAP.find(errCode);
69     if (it == IAM_ERRCODE_MAP.end()) {
70         return ERR_JS_SYSTEM_SERVICE_EXCEPTION;
71     }
72     return it->second;
73 }
74 
AccountIAMConvertToJSErrCode(int32_t errCode)75 int32_t AccountIAMConvertToJSErrCode(int32_t errCode)
76 {
77     if (CheckJsErrorCode(errCode)) {
78         return errCode;
79     }
80     if (errCode == ERR_ACCOUNT_COMMON_NOT_SYSTEM_APP_ERROR) {
81         return ERR_JS_IS_NOT_SYSTEM_APP;
82     } else if (errCode == ERR_ACCOUNT_COMMON_PERMISSION_DENIED || errCode == ERR_IAM_CHECK_PERMISSION_FAILED) {
83         return ERR_JS_PERMISSION_DENIED;
84     } else if (errCode == ERR_ACCOUNT_COMMON_INVALID_PARAMETER) {
85         return ERR_JS_INVALID_PARAMETER;
86     } else if (errCode == ERR_ACCOUNT_COMMON_ACCOUNT_NOT_EXIST_ERROR) {
87         return ERR_JS_ACCOUNT_NOT_FOUND;
88     } else if (errCode == ERR_ACCOUNT_COMMON_ACCOUNT_IS_RESTRICTED) {
89         return ERR_JS_ACCOUNT_RESTRICTED;
90     } else if (errCode == ERR_IAM_CROSS_DEVICE_COMMUNICATION_FAILED) {
91         return ERR_JS_ACCOUNT_CROSS_DEVICE_COMMUNICATION_FAILED;
92     } else if (errCode == ERR_IAM_CROSS_DEVICE_CAPABILITY_NOT_SUPPORT) {
93         return ERR_JS_ACCOUNT_CROSS_DEVICE_CAPABILITY_NOT_SUPPORT;
94     } else {
95         return AccountIAMConvertOtherToJSErrCode(errCode);
96     }
97 }
98 
~IDMContext()99 IDMContext::~IDMContext()
100 {
101     std::fill(token.begin(), token.end(), 0);
102 }
103 
104 #ifdef HAS_USER_AUTH_PART
NapiIDMCallback(napi_env env,const std::shared_ptr<JsIAMCallback> & callback)105 NapiIDMCallback::NapiIDMCallback(napi_env env, const std::shared_ptr<JsIAMCallback> &callback)
106     : env_(env), callback_(callback)
107 {}
108 
~NapiIDMCallback()109 NapiIDMCallback::~NapiIDMCallback()
110 {}
111 
OnResult(int32_t result,const Attributes & extraInfo)112 void NapiIDMCallback::OnResult(int32_t result, const Attributes &extraInfo)
113 {
114     std::lock_guard<std::mutex> lock(mutex_);
115     if (callback_->onResultCalled) {
116         ACCOUNT_LOGE("Call twice is not allowed");
117         return;
118     }
119     callback_->onResultCalled = true;
120     std::shared_ptr<IDMCallbackParam> param = std::make_shared<IDMCallbackParam>(env_);
121     if (param == nullptr) {
122         ACCOUNT_LOGE("Failed for nullptr");
123         return;
124     }
125     param->result = result;
126     extraInfo.GetUint64Value(Attributes::AttributeKey::ATTR_CREDENTIAL_ID, param->credentialId);
127     param->callback = callback_;
128     auto task = [param]() {
129         ACCOUNT_LOGI("Enter NapiIDMCallback::OnResult task");
130         napi_handle_scope scope = nullptr;
131         napi_open_handle_scope(param->env, &scope);
132         if (scope == nullptr) {
133             ACCOUNT_LOGE("Failed to open scope");
134             return;
135         }
136         napi_value argv[ARG_SIZE_TWO] = {0};
137         napi_create_int32(param->env, AccountIAMConvertToJSErrCode(param->result), &argv[PARAM_ZERO]);
138         napi_create_object(param->env, &argv[PARAM_ONE]);
139         napi_value credentialId =
140             CreateUint8Array(param->env, reinterpret_cast<uint8_t *>(&param->credentialId), sizeof(uint64_t));
141         napi_set_named_property(param->env, argv[PARAM_ONE], "credentialId", credentialId);
142         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->callback->onResult);
143         napi_close_handle_scope(param->env, scope);
144         return;
145     };
146     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
147         ACCOUNT_LOGE("Failed to send event for auth");
148         return;
149     }
150     ACCOUNT_LOGI("Post OnResult task finish");
151 }
152 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const Attributes & extraInfo)153 void NapiIDMCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, const Attributes &extraInfo)
154 {
155     std::lock_guard<std::mutex> lock(mutex_);
156     if (!callback_->hasOnAcquireInfo) {
157         ACCOUNT_LOGE("No 'OnAcquireInfo' callback need return");
158         return;
159     }
160     if (callback_->onResultCalled) {
161         ACCOUNT_LOGE("Call after OnResult is not allowed");
162         return;
163     }
164     std::shared_ptr<IDMCallbackParam> param = std::make_shared<IDMCallbackParam>(env_);
165     if (param == nullptr) {
166         ACCOUNT_LOGE("Failed for nullptr");
167         return;
168     }
169     param->callback = callback_;
170     param->module = module;
171     param->acquire = acquireInfo;
172     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_EXTRA_INFO, param->extraInfo);
173     auto task = [param]() {
174         ACCOUNT_LOGI("Enter NapiIDMCallback::OnAcquireInfo task");
175         napi_handle_scope scope = nullptr;
176         napi_open_handle_scope(param->env, &scope);
177         if (scope == nullptr) {
178             ACCOUNT_LOGE("Fail to open scope");
179             return;
180         }
181         napi_value argv[ARG_SIZE_THREE] = {0};
182         napi_env env = param->env;
183         napi_create_int32(env, param->module, &argv[PARAM_ZERO]);
184         napi_create_int32(env, param->acquire, &argv[PARAM_ONE]);
185         argv[PARAM_TWO] = CreateUint8Array(env, param->extraInfo.data(), param->extraInfo.size());
186         NapiCallVoidFunction(env, argv, ARG_SIZE_THREE, param->callback->onAcquireInfo);
187         napi_close_handle_scope(param->env, scope);
188         return;
189     };
190     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
191         ACCOUNT_LOGE("Failed to send event for auth");
192         return;
193     }
194     ACCOUNT_LOGI("Post OnAcquireInfo task finish");
195 }
196 
ParseAddCredInfo(napi_env env,napi_value value,IDMContext & context)197 napi_status ParseAddCredInfo(napi_env env, napi_value value, IDMContext &context)
198 {
199     napi_valuetype valueType = napi_undefined;
200     napi_typeof(env, value, &valueType);
201     if (valueType != napi_object) {
202         ACCOUNT_LOGE("value is not an object");
203         return napi_invalid_arg;
204     }
205     napi_value result = nullptr;
206     NAPI_CALL_BASE(env, napi_get_named_property(env, value, "credType", &result), napi_invalid_arg);
207     int32_t credType = -1;
208     NAPI_CALL_BASE(env, napi_get_value_int32(env, result, &credType), napi_invalid_arg);
209     context.addCredInfo.authType = static_cast<AuthType>(credType);
210     NAPI_CALL_BASE(env, napi_get_named_property(env, value, "credSubType", &result), napi_invalid_arg);
211     int32_t credSubType = -1;
212     NAPI_CALL_BASE(env, napi_get_value_int32(env, result, &credSubType), napi_invalid_arg);
213     context.addCredInfo.pinType = static_cast<PinSubType>(credSubType);
214     NAPI_CALL_BASE(env, napi_get_named_property(env, value, "token", &result), napi_invalid_arg);
215     if (ParseUint8TypedArrayToVector(env, result, context.addCredInfo.token) != napi_ok) {
216         ACCOUNT_LOGE("Get Uint8Array data failed");
217         return napi_invalid_arg;
218     }
219     if (!GetOptionalNumberPropertyByKey(env, value, "accountId", context.accountId, context.parseHasAccountId)) {
220         ACCOUNT_LOGE("Get accountId data failed");
221         return napi_invalid_arg;
222     }
223     return napi_ok;
224 }
225 
ParseIAMCallback(napi_env env,napi_value object,std::shared_ptr<JsIAMCallback> & callback)226 napi_status ParseIAMCallback(napi_env env, napi_value object, std::shared_ptr<JsIAMCallback> &callback)
227 {
228     napi_valuetype valueType = napi_undefined;
229     napi_typeof(env, object, &valueType);
230     if (valueType != napi_object) {
231         ACCOUNT_LOGE("invalid object");
232         return napi_invalid_arg;
233     }
234     napi_value result = nullptr;
235     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "onResult", &result), napi_invalid_arg);
236     napi_typeof(env, result, &valueType);
237     if (valueType == napi_function) {
238         NAPI_CALL_BASE(env, napi_create_reference(env, result, 1, &callback->onResult), napi_generic_failure);
239     } else {
240         ACCOUNT_LOGE("onResult is not a function");
241         return napi_invalid_arg;
242     }
243     napi_has_named_property(env, object, "onAcquireInfo", &callback->hasOnAcquireInfo);
244     if (!callback->hasOnAcquireInfo) {
245         return napi_ok;
246     }
247     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "onAcquireInfo", &result), napi_invalid_arg);
248     napi_typeof(env, result, &valueType);
249     if (valueType == napi_function) {
250         NAPI_CALL_BASE(env, napi_create_reference(env, result, 1, &callback->onAcquireInfo), napi_generic_failure);
251     } else if ((valueType == napi_undefined) || (valueType == napi_null)) {
252         ACCOUNT_LOGI("onAcquireInfo is undefined or null");
253     } else {
254         ACCOUNT_LOGE("onAcquireInfo is not a function");
255         return napi_invalid_arg;
256     }
257     return napi_ok;
258 }
259 
CreateCredInfoArray(napi_env env,const std::vector<CredentialInfo> & info)260 napi_value CreateCredInfoArray(napi_env env, const std::vector<CredentialInfo> &info)
261 {
262     napi_value arr = nullptr;
263     napi_create_array_with_length(env, info.size(), &arr);
264     uint32_t index = 0;
265     for (auto item : info) {
266         napi_value obj;
267         NAPI_CALL(env, napi_create_object(env, &obj));
268         napi_value credentialId = CreateUint8Array(
269             env, reinterpret_cast<uint8_t *>(&item.credentialId), sizeof(uint64_t));
270         napi_value authType;
271         NAPI_CALL(env, napi_create_uint32(env, item.authType, &authType));
272         napi_value napiPinType;
273         PinSubType pinType = item.pinType.value_or(PinSubType::PIN_MAX);
274         NAPI_CALL(env, napi_create_uint32(env, pinType, &napiPinType));
275         napi_value templateId = CreateUint8Array(
276             env, reinterpret_cast<uint8_t *>(&item.templateId), sizeof(uint64_t));
277         NAPI_CALL(env, napi_set_named_property(env, obj, "credentialId", credentialId));
278         NAPI_CALL(env, napi_set_named_property(env, obj, "authType", authType));
279         NAPI_CALL(env, napi_set_named_property(env, obj, "authSubType", napiPinType));
280         NAPI_CALL(env, napi_set_named_property(env, obj, "templateId", templateId));
281 
282         napi_value napiIsAbandoned = nullptr;
283         NAPI_CALL(env, napi_get_boolean(env, item.isAbandoned, &napiIsAbandoned));
284         NAPI_CALL(env, napi_set_named_property(env, obj, "isAbandoned", napiIsAbandoned));
285 
286         if (item.validityPeriod >= 0) {
287             napi_value napiValidityPeriod = nullptr;
288             NAPI_CALL(env, napi_create_int64(env, item.validityPeriod, &napiValidityPeriod));
289             NAPI_CALL(env, napi_set_named_property(env, obj, "validityPeriod", napiValidityPeriod));
290         }
291         NAPI_CALL(env, napi_set_element(env, arr, index, obj));
292         index++;
293     }
294     return arr;
295 }
296 
ConvertGetPropertyTypeToAttributeKey(GetPropertyType in,Attributes::AttributeKey & out)297 napi_status ConvertGetPropertyTypeToAttributeKey(GetPropertyType in,
298     Attributes::AttributeKey &out)
299 {
300     static const std::map<GetPropertyType, Attributes::AttributeKey> type2Key = {
301         { AUTH_SUB_TYPE, Attributes::AttributeKey::ATTR_PIN_SUB_TYPE },
302         { REMAIN_TIMES, Attributes::AttributeKey::ATTR_REMAIN_TIMES },
303         { FREEZING_TIME, Attributes::AttributeKey::ATTR_FREEZING_TIME },
304         { ENROLLMENT_PROGRESS, Attributes::AttributeKey::ATTR_ENROLL_PROGRESS },
305         { SENSOR_INFO, Attributes::AttributeKey::ATTR_SENSOR_INFO },
306         { NEXT_PHASE_FREEZING_TIME, Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION },
307         { CREDENTIAL_LENGTH, Attributes::AttributeKey::ATTR_CREDENTIAL_LENGTH },
308     };
309 
310     auto iter = type2Key.find(in);
311     if (iter == type2Key.end()) {
312         ACCOUNT_LOGE("GetPropertyType %{public}d is invalid", in);
313         return napi_invalid_arg;
314     } else {
315         out = iter->second;
316     }
317     return napi_ok;
318 }
319 
ParseGetPropKeys(napi_env env,napi_value napiKeys,std::vector<Attributes::AttributeKey> & keys)320 napi_status ParseGetPropKeys(napi_env env, napi_value napiKeys, std::vector<Attributes::AttributeKey> &keys)
321 {
322     std::vector<uint32_t> tempKeys;
323     if (ParseUInt32Array(env, napiKeys, tempKeys) != napi_ok) {
324         ACCOUNT_LOGE("Parameter error. The type of \"keys\" must be GetPropertyType's array");
325         return napi_invalid_arg;
326     }
327     for (const auto &item : tempKeys) {
328         Attributes::AttributeKey key;
329         napi_status status = ConvertGetPropertyTypeToAttributeKey(static_cast<GetPropertyType>(item), key);
330         if (status != napi_ok) {
331             ACCOUNT_LOGE("Parameter error. The type of \"key\" must be 'GetPropertyType'");
332             return napi_invalid_arg;
333         }
334         keys.push_back(key);
335     }
336     return napi_ok;
337 }
338 
ParseGetPropRequest(napi_env env,napi_value object,GetPropertyContext & context)339 napi_status ParseGetPropRequest(napi_env env, napi_value object, GetPropertyContext &context)
340 {
341     napi_valuetype valueType = napi_undefined;
342     napi_typeof(env, object, &valueType);
343     if (valueType != napi_object) {
344         ACCOUNT_LOGE("invalid object");
345         return napi_invalid_arg;
346     }
347     napi_value napiAuthType = nullptr;
348     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "authType", &napiAuthType), napi_invalid_arg);
349     int32_t authType = -1;
350     napi_get_value_int32(env, napiAuthType, &authType);
351     context.request.authType = static_cast<AuthType>(authType);
352     napi_value napiKeys = nullptr;
353     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "keys", &napiKeys), napi_generic_failure);
354     if (ParseGetPropKeys(env, napiKeys, context.request.keys) != napi_ok) {
355         ACCOUNT_LOGE("Get getPropRequest's keys failed");
356         return napi_invalid_arg;
357     }
358     if (!GetOptionalNumberPropertyByKey(env, object, "accountId", context.accountId, context.parseHasAccountId)) {
359         ACCOUNT_LOGE("Get getPropRequest's accountId failed");
360         return napi_invalid_arg;
361     }
362     return napi_ok;
363 }
364 
ParseSetPropRequest(napi_env env,napi_value object,SetPropertyRequest & request)365 napi_status ParseSetPropRequest(napi_env env, napi_value object, SetPropertyRequest &request)
366 {
367     napi_valuetype valueType = napi_undefined;
368     napi_typeof(env, object, &valueType);
369     if (valueType != napi_object) {
370         ACCOUNT_LOGE("invalid object");
371         return napi_invalid_arg;
372     }
373     napi_value napiKey = nullptr;
374     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "key", &napiKey), napi_invalid_arg);
375     int32_t key = -1;
376     napi_get_value_int32(env, napiKey, &key);
377     request.mode = static_cast<PropertyMode>(key);
378     napi_value napiAuthType = nullptr;
379     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "authType", &napiAuthType), napi_invalid_arg);
380     int32_t authType = -1;
381     napi_get_value_int32(env, napiAuthType, &authType);
382     request.authType = static_cast<AuthType>(authType);
383     napi_value napiSetInfo = nullptr;
384     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "setInfo", &napiSetInfo), napi_invalid_arg);
385     std::vector<uint8_t> setInfo;
386     ParseUint8TypedArrayToVector(env, napiSetInfo, setInfo);
387     request.attrs.SetUint8ArrayValue(Attributes::AttributeKey(key), setInfo);
388     return napi_ok;
389 }
390 
SetOptionalInt32ToJsProperty(napi_env env,std::optional<int32_t> number,const std::string & propertyName,napi_value & dataJs)391 static void SetOptionalInt32ToJsProperty(
392     napi_env env, std::optional<int32_t> number, const std::string &propertyName, napi_value &dataJs)
393 {
394     if (!number.has_value()) {
395         ACCOUNT_LOGW("No optional '%{public}s' of the propertyInfo returned.", propertyName.c_str());
396         return;
397     }
398     SetInt32ToJsProperty(env, number.value(), propertyName, dataJs);
399 }
400 
SetOptionalStringToJsProperty(napi_env env,std::optional<std::string> nativeStringData,const std::string & propertyName,napi_value & jsProperty)401 static void SetOptionalStringToJsProperty(napi_env env, std::optional<std::string> nativeStringData,
402     const std::string &propertyName, napi_value &jsProperty)
403 {
404     if (!nativeStringData.has_value()) {
405         ACCOUNT_LOGW("No optional '%{public}s' of the propertyInfo returned.", propertyName.c_str());
406         return;
407     }
408     napi_value jsStringData = nullptr;
409     napi_create_string_utf8(env, nativeStringData.value().c_str(), NAPI_AUTO_LENGTH, &jsStringData);
410     napi_set_named_property(env, jsProperty, propertyName.c_str(), jsStringData);
411 }
412 
GeneratePropertyJs(napi_env env,const GetPropertyCommonContext & context,napi_value & dataJs)413 static void GeneratePropertyJs(napi_env env, const GetPropertyCommonContext &context, napi_value &dataJs)
414 {
415     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &dataJs));
416     napi_value napiResult = nullptr;
417     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, context.propertyInfo.result, &napiResult));
418     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, "result", napiResult));
419     for (const auto &key : context.keys) {
420         switch (key) {
421             case Attributes::AttributeKey::ATTR_PIN_SUB_TYPE: {
422                 SetInt32ToJsProperty(env, context.propertyInfo.authSubType, "authSubType", dataJs);
423                 break;
424             }
425             case Attributes::AttributeKey::ATTR_REMAIN_TIMES: {
426                 SetOptionalInt32ToJsProperty(env, context.propertyInfo.remainTimes, "remainTimes", dataJs);
427                 break;
428             }
429             case Attributes::AttributeKey::ATTR_FREEZING_TIME: {
430                 SetOptionalInt32ToJsProperty(env, context.propertyInfo.freezingTime, "freezingTime", dataJs);
431                 break;
432             }
433             case Attributes::AttributeKey::ATTR_ENROLL_PROGRESS: {
434                 SetOptionalStringToJsProperty(env,
435                     context.propertyInfo.enrollmentProgress, "enrollmentProgress", dataJs);
436                 break;
437             }
438             case Attributes::AttributeKey::ATTR_SENSOR_INFO: {
439                 SetOptionalStringToJsProperty(env, context.propertyInfo.sensorInfo, "sensorInfo", dataJs);
440                 break;
441             }
442             case Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION: {
443                 SetOptionalInt32ToJsProperty(env, context.propertyInfo.nextPhaseFreezingTime,
444                     "nextPhaseFreezingTime", dataJs);
445                 break;
446             }
447             case Attributes::AttributeKey::ATTR_CREDENTIAL_LENGTH: {
448                 SetOptionalInt32ToJsProperty(env, context.propertyInfo.credentialLength, "credentialLength", dataJs);
449                 break;
450             }
451             default:
452                 break;
453         }
454     }
455 }
456 
CreateExecutorProperty(napi_env env,GetPropertyCommonContext & context,napi_value & errJs,napi_value & dataJs)457 static void CreateExecutorProperty(
458     napi_env env, GetPropertyCommonContext &context, napi_value &errJs, napi_value &dataJs)
459 {
460     context.errCode = context.propertyInfo.result;
461     if (!context.isGetById && context.errCode == ERR_IAM_NOT_ENROLLED) {
462         context.errCode = ERR_OK;
463     }
464     if (context.errCode != ERR_OK) {
465         int32_t jsErrCode = AccountIAMConvertToJSErrCode(context.propertyInfo.result);
466         errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
467         napi_get_null(env, &dataJs);
468         return;
469     }
470     context.errCode = ERR_OK;
471     napi_get_null(env, &errJs);
472     GeneratePropertyJs(env, context, dataJs);
473 }
474 
GenerateAuthResult(napi_env env,AuthCallbackParam * param)475 static napi_value GenerateAuthResult(napi_env env, AuthCallbackParam *param)
476 {
477     napi_value object = CreateAuthResult(param->env, param->token, param->remainTimes, param->freezingTime);
478     if (param->hasNextPhaseFreezingTime) {
479         SetInt32ToJsProperty(env, param->nextPhaseFreezingTime, "nextPhaseFreezingTime", object);
480     }
481     if (param->hasCredentialId) {
482         napi_value napiCredentialId =
483             CreateUint8Array(env, reinterpret_cast<uint8_t *>(&param->credentialId), sizeof(uint64_t));
484         NAPI_CALL(env, napi_set_named_property(env, object, "credentialId", napiCredentialId));
485     }
486     if (param->hasAccountId) {
487         SetInt32ToJsProperty(env, param->accountId, "accountId", object);
488     }
489     if (param->hasPinValidityPeriod) {
490         napi_value napiPinValidityPeriod = nullptr;
491         NAPI_CALL(env, napi_create_int64(env, param->pinValidityPeriod, &napiPinValidityPeriod));
492         NAPI_CALL(env, napi_set_named_property(env, object, "pinValidityPeriod", napiPinValidityPeriod));
493     }
494     return object;
495 }
496 
NapiUserAuthCallback(napi_env env,const std::shared_ptr<JsIAMCallback> & callback)497 NapiUserAuthCallback::NapiUserAuthCallback(napi_env env, const std::shared_ptr<JsIAMCallback> &callback)
498     : env_(env), callback_(callback)
499 {}
500 
~NapiUserAuthCallback()501 NapiUserAuthCallback::~NapiUserAuthCallback()
502 {}
503 
PrepareAuthResult(int32_t result,const Attributes & extraInfo,AuthCallbackParam & param)504 void NapiUserAuthCallback::PrepareAuthResult(int32_t result, const Attributes &extraInfo, AuthCallbackParam &param)
505 {
506     param.resultCode = result;
507     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_SIGNATURE, param.token);
508     extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_REMAIN_TIMES, param.remainTimes);
509     extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_FREEZING_TIME, param.freezingTime);
510     if (extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION,
511                                 param.nextPhaseFreezingTime)) {
512         param.hasNextPhaseFreezingTime = true;
513     }
514     if (extraInfo.GetUint64Value(Attributes::AttributeKey::ATTR_CREDENTIAL_ID, param.credentialId)) {
515         param.hasCredentialId = true;
516     }
517     if (extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_USER_ID, param.accountId)) {
518         param.hasAccountId = true;
519     }
520     if (extraInfo.GetInt64Value(Attributes::AttributeKey::ATTR_PIN_EXPIRED_INFO, param.pinValidityPeriod)) {
521         param.hasPinValidityPeriod = true;
522     }
523     param.callback = callback_;
524 }
525 
OnResult(int32_t result,const Attributes & extraInfo)526 void NapiUserAuthCallback::OnResult(int32_t result, const Attributes &extraInfo)
527 {
528     std::lock_guard<std::mutex> lock(mutex_);
529     if (callback_->onResultCalled) {
530         ACCOUNT_LOGE("call twice is not allowed");
531         return;
532     }
533     callback_->onResultCalled = true;
534     AuthCallbackParam *param = new (std::nothrow) AuthCallbackParam(env_);
535     if (param == nullptr) {
536         ACCOUNT_LOGE("fail for nullptr");
537         return;
538     }
539     PrepareAuthResult(result, extraInfo, *param);
540     auto task = [param = std::move(param)]() {
541         ACCOUNT_LOGI("Enter NapiUserAuthCallback::OnResult task");
542         napi_handle_scope scope = nullptr;
543         napi_open_handle_scope(param->env, &scope);
544         if (scope == nullptr) {
545             ACCOUNT_LOGE("Fail to open scope");
546             delete param;
547             return;
548         }
549         napi_value argv[ARG_SIZE_TWO] = {nullptr};
550         napi_create_int32(param->env, AccountIAMConvertToJSErrCode(param->resultCode), &argv[PARAM_ZERO]);
551         argv[PARAM_ONE] = GenerateAuthResult(param->env, param);
552         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->callback->onResult);
553         napi_close_handle_scope(param->env, scope);
554         delete param;
555         return;
556     };
557     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
558         delete param;
559         return;
560     }
561     ACCOUNT_LOGI("Post NapiUserAuthCallback::OnResult task finish");
562 }
563 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const Attributes & extraInfo)564 void NapiUserAuthCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, const Attributes &extraInfo)
565 {
566     std::lock_guard<std::mutex> lock(mutex_);
567     if (!callback_->hasOnAcquireInfo) {
568         ACCOUNT_LOGE("no 'OnAcquireInfo' callback need return");
569         return;
570     }
571     if (callback_->onResultCalled) {
572         ACCOUNT_LOGE("call after OnResult is not allowed");
573         return;
574     }
575     AuthCallbackParam *param = new (std::nothrow) AuthCallbackParam(env_);
576     if (param == nullptr) {
577         ACCOUNT_LOGE("Failed for nullptr");
578         return;
579     }
580     param->module = module;
581     param->acquireInfo = acquireInfo;
582     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_EXTRA_INFO, param->extraInfo);
583     param->callback = callback_;
584     auto task = [param = std::move(param)]() {
585         ACCOUNT_LOGI("Enter NapiUserAuthCallback::OnAcquireInfo task");
586         napi_handle_scope scope = nullptr;
587         napi_open_handle_scope(param->env, &scope);
588         if (scope == nullptr) {
589             ACCOUNT_LOGE("Fail to open scope");
590             delete param;
591             return;
592         }
593         napi_value argv[ARG_SIZE_THREE] = {nullptr};
594         napi_create_int32(param->env, param->module, &argv[PARAM_ZERO]);
595         napi_create_uint32(param->env, param->acquireInfo, &argv[PARAM_ONE]);
596         argv[PARAM_TWO] = CreateUint8Array(param->env, param->extraInfo.data(), param->extraInfo.size());
597         NapiCallVoidFunction(param->env, argv, ARG_SIZE_THREE, param->callback->onAcquireInfo);
598         napi_close_handle_scope(param->env, scope);
599         delete param;
600         return;
601     };
602     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
603         ACCOUNT_LOGE("Failed to send event for auth");
604         delete param;
605         return;
606     }
607     ACCOUNT_LOGI("Post NapiUserAuthCallback::OnAcquireInfo task finish");
608 }
609 
NapiGetInfoCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)610 NapiGetInfoCallback::NapiGetInfoCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
611     : env_(env), deferred_(deferred)
612 {
613     callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
614 }
615 
~NapiGetInfoCallback()616 NapiGetInfoCallback::~NapiGetInfoCallback()
617 {}
618 
OnCredentialInfo(int32_t result,const std::vector<AccountSA::CredentialInfo> & infoList)619 void NapiGetInfoCallback::OnCredentialInfo(int32_t result, const std::vector<AccountSA::CredentialInfo> &infoList)
620 {
621     ACCOUNT_LOGI("Get gredential info result = %{public}d", result);
622     std::lock_guard<std::mutex> lock(mutex_);
623     if (onResultCalled_) {
624         ACCOUNT_LOGE("Call twice is not allowed");
625         return;
626     }
627     onResultCalled_ = true;
628     std::shared_ptr<GetAuthInfoContext> context = std::make_shared<GetAuthInfoContext>(env_);
629     if (context == nullptr) {
630         ACCOUNT_LOGE("Failed for nullptr");
631         return;
632     }
633     context->callback = callback_;
634     context->deferred = deferred_;
635     context->errCode = result;
636     context->credInfo = infoList;
637     auto task = [context = std::move(context)]() {
638         ACCOUNT_LOGI("Enter NapiGetInfoCallback::OnCredentialInfo task");
639         napi_handle_scope scope = nullptr;
640         napi_open_handle_scope(context->env, &scope);
641         if (scope == nullptr) {
642             ACCOUNT_LOGE("Failed to open scope");
643             return;
644         }
645         napi_env env = context->env;
646         CommonCallbackInfo callbackInfo(env);
647         callbackInfo.callbackRef = context->callback->callbackRef;
648         callbackInfo.deferred = context->deferred;
649         callbackInfo.errCode = context->errCode;
650         if (context->errCode != ERR_OK) {
651             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
652             callbackInfo.errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
653             napi_get_null(env, &callbackInfo.dataJs);
654         } else {
655             napi_get_null(env, &callbackInfo.errJs);
656             callbackInfo.dataJs = CreateCredInfoArray(env, context->credInfo);
657         }
658         CallbackAsyncOrPromise(callbackInfo);
659         napi_close_handle_scope(context->env, scope);
660         return;
661     };
662     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
663         ACCOUNT_LOGE("Failed to send event for auth");
664         return;
665     }
666     ACCOUNT_LOGI("Post OnCredentialInfo task finish");
667 }
668 
NapiGetEnrolledIdCallback(napi_env env,napi_deferred deferred)669 NapiGetEnrolledIdCallback::NapiGetEnrolledIdCallback(napi_env env, napi_deferred deferred)
670     : env_(env), deferred_(deferred)
671 {}
672 
~NapiGetEnrolledIdCallback()673 NapiGetEnrolledIdCallback::~NapiGetEnrolledIdCallback()
674 {}
675 
OnEnrolledId(int32_t result,uint64_t enrolledId)676 void NapiGetEnrolledIdCallback::OnEnrolledId(int32_t result, uint64_t enrolledId)
677 {
678     std::shared_ptr<GetEnrolledIdContext> context = std::make_shared<GetEnrolledIdContext>(env_);
679     if (context == nullptr) {
680         ACCOUNT_LOGE("Failed for nullptr");
681         return;
682     }
683     context->deferred = deferred_;
684     context->errCode = result;
685     context->enrolledId = enrolledId;
686     auto task = [context]() {
687         ACCOUNT_LOGI("Enter NapiGetEnrolledIdCallback::OnEnrolledId task");
688         napi_handle_scope scope = nullptr;
689         napi_open_handle_scope(context->env, &scope);
690         if (scope == nullptr) {
691             ACCOUNT_LOGE("Failed to open scope");
692             return;
693         }
694         napi_env env = context->env;
695         napi_value errJs = nullptr;
696         napi_value dataJs = nullptr;
697         if (context->errCode != ERR_OK) {
698             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
699             errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
700             napi_get_null(env, &dataJs);
701         } else {
702             napi_get_null(env, &errJs);
703             dataJs = CreateUint8Array(env, reinterpret_cast<uint8_t *>(&context->enrolledId), sizeof(uint64_t));
704         }
705         CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
706         napi_close_handle_scope(env, scope);
707         return;
708     };
709     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
710         ACCOUNT_LOGE("Failed to send event for auth");
711         return;
712     }
713     ACCOUNT_LOGI("Post OnEnrolledId task finish");
714 }
715 
NapiGetPropCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred,const std::vector<Attributes::AttributeKey> & keys)716 NapiGetPropCallback::NapiGetPropCallback(
717     napi_env env, napi_ref callbackRef, napi_deferred deferred, const std::vector<Attributes::AttributeKey> &keys)
718     : env_(env), deferred_(deferred), keys_(keys)
719 {
720     callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
721 }
722 
~NapiGetPropCallback()723 NapiGetPropCallback::~NapiGetPropCallback()
724 {}
725 
PraseAttributesToExecutorProperty(const std::vector<Attributes::AttributeKey> & keys,const Attributes & extraInfo,ExecutorProperty & propertyInfo)726 static void PraseAttributesToExecutorProperty(const std::vector<Attributes::AttributeKey> &keys,
727     const Attributes &extraInfo, ExecutorProperty &propertyInfo)
728 {
729     // parse subtype
730     GetValueFromAttributes(keys, Attributes::AttributeKey::ATTR_PIN_SUB_TYPE, extraInfo, propertyInfo.authSubType);
731     // parse remainTimes
732     GetOptionalValueFromAttributes(keys,
733         Attributes::AttributeKey::ATTR_REMAIN_TIMES, extraInfo, propertyInfo.remainTimes);
734     // parse freezingTime;
735     GetOptionalValueFromAttributes(keys,
736         Attributes::AttributeKey::ATTR_FREEZING_TIME, extraInfo, propertyInfo.freezingTime);
737     // parse enrollmentProgress
738     GetOptionalValueFromAttributes(keys,
739         Attributes::AttributeKey::ATTR_ENROLL_PROGRESS, extraInfo, propertyInfo.enrollmentProgress);
740     // parse sensorInfo
741     GetOptionalValueFromAttributes(keys,
742         Attributes::AttributeKey::ATTR_SENSOR_INFO, extraInfo, propertyInfo.sensorInfo);
743     // parse nextPhaseFreezingTime
744     GetOptionalValueFromAttributes(keys,
745         Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION, extraInfo, propertyInfo.nextPhaseFreezingTime);
746     // parse credentialLength
747     GetOptionalValueFromAttributes(keys,
748         Attributes::AttributeKey::ATTR_CREDENTIAL_LENGTH, extraInfo, propertyInfo.credentialLength);
749 }
750 
GetExecutorPropertys(const UserIam::UserAuth::Attributes & extraInfo,ExecutorProperty & propertyInfo)751 void NapiGetPropCallback::GetExecutorPropertys(
752     const UserIam::UserAuth::Attributes &extraInfo, ExecutorProperty &propertyInfo)
753 {
754     PraseAttributesToExecutorProperty(keys_, extraInfo, propertyInfo);
755     return;
756 }
757 
OnResult(int32_t result,const UserIam::UserAuth::Attributes & extraInfo)758 void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
759 {
760     std::lock_guard<std::mutex> lock(mutex_);
761     if ((callback_->callbackRef == nullptr) && (deferred_ == nullptr)) {
762         ACCOUNT_LOGE("Return for nullptr");
763         return;
764     }
765     if (onResultCalled_) {
766         ACCOUNT_LOGE("Call twice is not allowed");
767         return;
768     }
769     onResultCalled_ = true;
770     std::shared_ptr<GetPropertyCommonContext> context = std::make_shared<GetPropertyCommonContext>(env_);
771     if (context == nullptr) {
772         ACCOUNT_LOGE("Failed for nullptr");
773         return;
774     }
775     // create context data
776     GetExecutorPropertys(extraInfo, context->propertyInfo);
777     context->isGetById = isGetById_;
778     context->callback = callback_;
779     context->deferred = deferred_;
780     context->errCode = ERR_OK;
781     context->propertyInfo.result = result;
782     context->keys = keys_;
783     auto task = [context = std::move(context)]() {
784         ACCOUNT_LOGI("Enter NapiGetPropCallback::OnResult task");
785         napi_handle_scope scope = nullptr;
786         napi_open_handle_scope(context->env, &scope);
787         if (scope == nullptr) {
788             ACCOUNT_LOGE("Failed to open scope");
789             return;
790         }
791         CommonCallbackInfo callbackInfo(context->env);
792         callbackInfo.callbackRef = context->callback->callbackRef;
793         callbackInfo.deferred = context->deferred;
794         CreateExecutorProperty(context->env, *context, callbackInfo.errJs, callbackInfo.dataJs);
795         callbackInfo.errCode = context->errCode;
796         CallbackAsyncOrPromise(callbackInfo);
797         napi_close_handle_scope(context->env, scope);
798         return;
799     };
800     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
801         ACCOUNT_LOGE("Failed to send event for auth");
802         return;
803     }
804     ACCOUNT_LOGI("Post OnResult task finish");
805 }
806 
NapiSetPropCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)807 NapiSetPropCallback::NapiSetPropCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
808     : env_(env), deferred_(deferred)
809 {
810     callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
811 }
812 
~NapiSetPropCallback()813 NapiSetPropCallback::~NapiSetPropCallback()
814 {}
815 
NapiPrepareRemoteAuthCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)816 NapiPrepareRemoteAuthCallback::NapiPrepareRemoteAuthCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
817     : env_(env), callbackRef_(callbackRef), deferred_(deferred)
818 {}
819 
~NapiPrepareRemoteAuthCallback()820 NapiPrepareRemoteAuthCallback::~NapiPrepareRemoteAuthCallback()
821 {
822     if (callbackRef_ != nullptr) {
823         ReleaseNapiRefAsync(env_, callbackRef_);
824         callbackRef_ = nullptr;
825     }
826     deferred_ = nullptr;
827 }
828 
OnResult(int32_t result)829 void NapiPrepareRemoteAuthCallback::OnResult(int32_t result)
830 {
831     std::lock_guard<std::mutex> lock(mutex_);
832     if ((callbackRef_ == nullptr) && (deferred_ == nullptr)) {
833         return;
834     }
835     if (onResultCalled_) {
836         ACCOUNT_LOGE("Call twice is not allowed");
837         return;
838     }
839     onResultCalled_ = true;
840     std::shared_ptr<PrepareRemoteAuthContext> context = std::make_shared<PrepareRemoteAuthContext>(env_);
841     if (context == nullptr) {
842         ACCOUNT_LOGE("Nullptr fail.");
843         return;
844     }
845     context->deferred = deferred_;
846     context->errCode = ERR_OK;
847     context->result = result;
848     auto task = [context]() {
849         ACCOUNT_LOGI("Enter NapiPrepareRemoteAuthCallback::OnResult task");
850         napi_handle_scope scope = nullptr;
851         napi_open_handle_scope(context->env, &scope);
852         if (scope == nullptr) {
853             ACCOUNT_LOGE("Failed to open scope");
854             return;
855         }
856         napi_env env = context->env;
857         napi_value errJs = nullptr;
858         napi_value dataJs = nullptr;
859         context->errCode = context->result;
860         if (context->result != ERR_OK) {
861             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->result);
862             errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
863             napi_get_null(env, &dataJs);
864         } else {
865             napi_get_null(env, &errJs);
866             napi_get_null(env, &dataJs);
867         }
868         CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
869         napi_close_handle_scope(context->env, scope);
870         return;
871     };
872     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
873         ACCOUNT_LOGE("Failed to send event for auth");
874         return;
875     }
876     ACCOUNT_LOGI("Post OnResult task finish");
877 }
878 
OnResult(int32_t result,const UserIam::UserAuth::Attributes & extraInfo)879 void NapiSetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
880 {
881     std::lock_guard<std::mutex> lock(mutex_);
882     if ((callback_->callbackRef == nullptr) && (deferred_ == nullptr)) {
883         return;
884     }
885     if (onResultCalled_) {
886         ACCOUNT_LOGE("Call twice is not allowed");
887         return;
888     }
889     onResultCalled_ = true;
890     std::shared_ptr<SetPropertyContext> context = std::make_shared<SetPropertyContext>(env_);
891     if (context == nullptr) {
892         ACCOUNT_LOGE("Failed for nullptr");
893         return;
894     }
895     context->callback = callback_;
896     context->deferred = deferred_;
897     context->errCode = ERR_OK;
898     context->result = result;
899     auto task = [context = std::move(context)]() {
900         ACCOUNT_LOGI("Enter NapiSetPropCallback::OnResult task");
901         napi_handle_scope scope = nullptr;
902         napi_open_handle_scope(context->env, &scope);
903         if (scope == nullptr) {
904             ACCOUNT_LOGE("Failed to open scope");
905             return;
906         }
907         napi_env env = context->env;
908         CommonCallbackInfo callbackInfo(env);
909         callbackInfo.callbackRef = context->callback->callbackRef;
910         callbackInfo.deferred = context->deferred;
911         callbackInfo.errCode = context->result;
912         if (context->result != ERR_OK) {
913             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->result);
914             callbackInfo.errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
915             napi_get_null(env, &callbackInfo.dataJs);
916         } else {
917             napi_get_null(env, &callbackInfo.errJs);
918             napi_get_null(env, &callbackInfo.dataJs);
919         }
920         CallbackAsyncOrPromise(callbackInfo);
921         napi_close_handle_scope(env, scope);
922         return;
923     };
924     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
925         ACCOUNT_LOGE("Failed to send event for auth");
926         return;
927     }
928     ACCOUNT_LOGI("Post OnResult task finish");
929 }
930 #endif  // HAS_USER_AUTH_PART
931 
932 #ifdef HAS_PIN_AUTH_PART
InputDataConstructor(napi_env env,napi_callback_info info)933 napi_value InputDataConstructor(napi_env env, napi_callback_info info)
934 {
935     napi_value thisVar;
936     void *data;
937     size_t argc = ARG_SIZE_ONE;
938     napi_value argv[ARG_SIZE_ONE] = {nullptr};
939     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
940     InputerContext *context = static_cast<InputerContext *>(data);
941     if (thisVar == nullptr) {
942         ACCOUNT_LOGE("thisVar is nullptr");
943         return nullptr;
944     }
945     if (context == nullptr) {
946         ACCOUNT_LOGE("inputerData is nullptr");
947         return nullptr;
948     }
949     NAPI_CALL(env, napi_wrap(env, thisVar, context,
950         [](napi_env env, void *data, void *hint) {
951             InputerContext *context = static_cast<InputerContext *>(data);
952             if (context != nullptr) {
953                 delete context;
954             }
955         },
956         nullptr, nullptr));
957     return thisVar;
958 }
959 
OnSetData(napi_env env,napi_callback_info info)960 napi_value OnSetData(napi_env env, napi_callback_info info)
961 {
962     if (!IsSystemApp(env)) {
963         return nullptr;
964     }
965     size_t argc = ARG_SIZE_TWO;
966     napi_value thisVar = nullptr;
967     napi_value argv[ARG_SIZE_TWO] = {nullptr};
968     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
969     if (argc != ARG_SIZE_TWO) {
970         ACCOUNT_LOGE("failed to parse parameters, expect three parameters, but got %{public}zu", argc);
971         std::string errMsg = "Parameter error. The number of parameters should be 2";
972         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
973         return nullptr;
974     }
975     InputerContext *context = nullptr;
976     NAPI_CALL(env, napi_unwrap(env, thisVar, (void **)&context));
977     if (context == nullptr || context->inputerData == nullptr) {
978         ACCOUNT_LOGE("context or inputerData is nullptr");
979         return nullptr;
980     }
981     int32_t authSubType;
982     if (!GetIntProperty(env, argv[PARAM_ZERO], authSubType)) {
983         ACCOUNT_LOGE("Get authSubType failed");
984         std::string errMsg = "Parameter error. The type of \"authSubType\" must be AuthSubType";
985         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
986         return nullptr;
987     }
988     std::vector<uint8_t> data;
989     if (ParseUint8TypedArrayToVector(env, argv[PARAM_ONE], data) != napi_ok) {
990         ACCOUNT_LOGE("Get data failed");
991         std::string errMsg = "Parameter error. The type of \"data\" must be Uint8Array";
992         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
993         return nullptr;
994     }
995     ACCOUNT_LOGI("Call OnSetData, authSubType: %{public}d", authSubType);
996     context->inputerData->OnSetData(authSubType, data);
997     std::fill(data.begin(), data.end(), 0);
998     context->inputerData = nullptr;
999     return nullptr;
1000 }
1001 
GetCtorIInputerData(napi_env env,const std::shared_ptr<AccountSA::IInputerData> & inputerData)1002 napi_value GetCtorIInputerData(napi_env env, const std::shared_ptr<AccountSA::IInputerData> &inputerData)
1003 {
1004     if (inputerData == nullptr) {
1005         ACCOUNT_LOGE("inputerData nullptr");
1006         return nullptr;
1007     }
1008     InputerContext *context = new (std::nothrow) InputerContext();
1009     if (context == nullptr) {
1010         ACCOUNT_LOGE("inputer context is nullptr");
1011         return nullptr;
1012     }
1013     napi_property_descriptor clzDes[] = {
1014         DECLARE_NAPI_FUNCTION("onSetData", OnSetData),
1015     };
1016     context->inputerData = inputerData;
1017     napi_value cons;
1018     NAPI_CALL(env, napi_define_class(env, "InputerData", NAPI_AUTO_LENGTH,
1019         InputDataConstructor, reinterpret_cast<void *>(context),
1020         sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
1021     return cons;
1022 }
1023 
GetInputerInstance(InputerContext * context,napi_value * inputerDataVarCtor)1024 static napi_status GetInputerInstance(InputerContext *context, napi_value *inputerDataVarCtor)
1025 {
1026     napi_value cons = GetCtorIInputerData(context->env, context->inputerData);
1027     if (cons == nullptr) {
1028         ACCOUNT_LOGD("failed to GetCtorIInputerData");
1029         return napi_generic_failure;
1030     }
1031     return napi_new_instance(context->env, cons, 0, nullptr, inputerDataVarCtor);
1032 }
1033 
NapiGetDataCallback(napi_env env,const std::shared_ptr<NapiCallbackRef> & callback)1034 NapiGetDataCallback::NapiGetDataCallback(napi_env env, const std::shared_ptr<NapiCallbackRef> &callback)
1035     : env_(env), callback_(callback)
1036 {}
1037 
~NapiGetDataCallback()1038 NapiGetDataCallback::~NapiGetDataCallback()
1039 {}
1040 
OnGetData(int32_t authSubType,std::vector<uint8_t> challenge,const std::shared_ptr<AccountSA::IInputerData> inputerData)1041 void NapiGetDataCallback::OnGetData(int32_t authSubType, std::vector<uint8_t> challenge,
1042     const std::shared_ptr<AccountSA::IInputerData> inputerData)
1043 {
1044     if (callback_ == nullptr) {
1045         ACCOUNT_LOGE("The onGetData function is undefined");
1046         return;
1047     }
1048     std::shared_ptr<InputerContext> context = std::make_shared<InputerContext>();
1049     if (context == nullptr) {
1050         ACCOUNT_LOGE("Failed for nullptr");
1051         return;
1052     }
1053     context->env = env_;
1054     context->callback = callback_;
1055     context->authSubType = authSubType;
1056     context->challenge = challenge;
1057     context->inputerData = inputerData;
1058     auto task = [context]() {
1059         ACCOUNT_LOGI("Enter NapiGetDataCallback::OnGetData task");
1060         napi_env env = context->env;
1061         napi_handle_scope scope = nullptr;
1062         napi_open_handle_scope(env, &scope);
1063         if (scope == nullptr) {
1064             ACCOUNT_LOGE("Failed to open scope");
1065             return;
1066         }
1067         napi_value argv[ARG_SIZE_THREE] = {0};
1068         napi_create_int32(env, context->authSubType, &argv[PARAM_ZERO]);
1069         GetInputerInstance(context.get(), &argv[PARAM_ONE]);
1070         napi_create_object(env, &argv[PARAM_TWO]);
1071         if (!(context->challenge.empty())) {
1072             napi_value dataJs = nullptr;
1073             dataJs = CreateUint8Array(env, context->challenge.data(), context->challenge.size());
1074             napi_set_named_property(env, argv[PARAM_TWO], "challenge", dataJs);
1075         }
1076         NapiCallVoidFunction(env, argv, ARG_SIZE_THREE, context->callback->callbackRef);
1077         napi_close_handle_scope(env, scope);
1078         return;
1079     };
1080     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
1081         ACCOUNT_LOGE("Failed to send event for auth");
1082         return;
1083     }
1084     ACCOUNT_LOGI("Post OnGetData task finish");
1085 }
1086 #endif  // HAS_PIN_AUTH_PART
1087 
CallbackAsyncOrPromise(const CommonCallbackInfo & callbackInfo)1088 void CallbackAsyncOrPromise(const CommonCallbackInfo &callbackInfo)
1089 {
1090     if (callbackInfo.callbackRef) {
1091         napi_value argv[ARG_SIZE_TWO] = {callbackInfo.errJs, callbackInfo.dataJs};
1092         ACCOUNT_LOGI("call js function");
1093         NapiCallVoidFunction(callbackInfo.env, argv, ARG_SIZE_TWO, callbackInfo.callbackRef);
1094     } else {
1095         if (callbackInfo.errCode == ERR_OK) {
1096             napi_resolve_deferred(callbackInfo.env, callbackInfo.deferred, callbackInfo.dataJs);
1097         } else {
1098             napi_reject_deferred(callbackInfo.env, callbackInfo.deferred, callbackInfo.errJs);
1099         }
1100     }
1101 }
1102 
CallbackAsyncOrPromise(napi_env env,CommonAsyncContext * context,napi_value errJs,napi_value dataJs)1103 void CallbackAsyncOrPromise(napi_env env, CommonAsyncContext *context, napi_value errJs, napi_value dataJs)
1104 {
1105     CommonCallbackInfo callbackInfo(env);
1106     callbackInfo.callbackRef = context->callbackRef;
1107     callbackInfo.deferred = context->deferred;
1108     callbackInfo.errJs = errJs;
1109     callbackInfo.dataJs = dataJs;
1110     callbackInfo.errCode = context->errCode;
1111     CallbackAsyncOrPromise(callbackInfo);
1112 }
1113 
ParseUInt32Array(napi_env env,napi_value value,std::vector<uint32_t> & data)1114 napi_status ParseUInt32Array(napi_env env, napi_value value, std::vector<uint32_t> &data)
1115 {
1116     data.clear();
1117     bool isArray = false;
1118     napi_is_array(env, value, &isArray);
1119     if (!isArray) {
1120         ACCOUNT_LOGE("value is not an array");
1121         return napi_invalid_arg;
1122     }
1123     uint32_t arrLen = 0;
1124     napi_get_array_length(env, value, &arrLen);
1125     for (uint32_t i = 0; i < arrLen; ++i) {
1126         napi_value item = nullptr;
1127         napi_get_element(env, value, i, &item);
1128         uint32_t num = 0;
1129         if (napi_get_value_uint32(env, item, &num) != napi_ok) {
1130             data.clear();
1131             return napi_number_expected;
1132         }
1133         data.push_back(num);
1134     }
1135     return napi_ok;
1136 }
1137 
CreateErrorObject(napi_env env,int32_t code)1138 napi_value CreateErrorObject(napi_env env, int32_t code)
1139 {
1140     napi_value errObj = nullptr;
1141     NAPI_CALL(env, napi_create_object(env, &errObj));
1142     napi_value number = 0;
1143     NAPI_CALL(env, napi_create_int32(env, code, &number));
1144     NAPI_CALL(env, napi_set_named_property(env, errObj, "code", number));
1145     return errObj;
1146 }
1147 
IsAccountIdValid(int32_t accountId)1148 bool IsAccountIdValid(int32_t accountId)
1149 {
1150     if (accountId < 0) {
1151         ACCOUNT_LOGI("The account id is invalid");
1152         return false;
1153     }
1154     return true;
1155 }
1156 }  // namespace AccountJsKit
1157 }  // namespace OHOS
1158