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 *>(¶m->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 *>(¶m->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 ¶m)
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