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