• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_user_auth.h"
17 
18 #include "account_iam_client.h"
19 #include "account_log_wrapper.h"
20 #include "napi_account_common.h"
21 #include "napi_account_error.h"
22 #include "napi_account_iam_common.h"
23 
24 namespace OHOS {
25 namespace AccountJsKit {
26 using namespace OHOS::AccountSA;
27 
Init(napi_env env,napi_value exports)28 napi_value NapiAccountIAMUserAuth::Init(napi_env env, napi_value exports)
29 {
30     napi_value cons;
31     napi_property_descriptor clzDes[] = {
32         DECLARE_NAPI_FUNCTION("getVersion", GetVersion),
33         DECLARE_NAPI_FUNCTION("getAvailableStatus", GetAvailableStatus),
34         DECLARE_NAPI_FUNCTION("getProperty", GetProperty),
35         DECLARE_NAPI_FUNCTION("getPropertyByCredentialId", GetPropertyByCredentialId),
36         DECLARE_NAPI_FUNCTION("setProperty", SetProperty),
37         DECLARE_NAPI_FUNCTION("auth", Auth),
38         DECLARE_NAPI_FUNCTION("authUser", AuthUser),
39         DECLARE_NAPI_FUNCTION("cancelAuth", CancelAuth),
40         DECLARE_NAPI_FUNCTION("prepareRemoteAuth", PrepareRemoteAuth),
41     };
42     NAPI_CALL(env, napi_define_class(env, "UserAuth", NAPI_AUTO_LENGTH, JsConstructor,
43         nullptr, sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
44     NAPI_CALL(env, napi_set_named_property(env, exports, "UserAuth", cons));
45     return exports;
46 }
47 
JsConstructor(napi_env env,napi_callback_info info)48 napi_value NapiAccountIAMUserAuth::JsConstructor(napi_env env, napi_callback_info info)
49 {
50     if (!IsSystemApp(env)) {
51         return nullptr;
52     }
53     napi_value thisVar = nullptr;
54     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
55     return thisVar;
56 }
57 
GetVersion(napi_env env,napi_callback_info info)58 napi_value NapiAccountIAMUserAuth::GetVersion(napi_env env, napi_callback_info info)
59 {
60     if (!IsSystemApp(env)) {
61         return nullptr;
62     }
63     int32_t result = 0;
64     napi_value version = 0;
65     NAPI_CALL(env, napi_create_int32(env, result, &version));
66     return version;
67 }
68 
GetAvailableStatus(napi_env env,napi_callback_info info)69 napi_value NapiAccountIAMUserAuth::GetAvailableStatus(napi_env env, napi_callback_info info)
70 {
71     size_t argc = ARG_SIZE_TWO;
72     napi_value argv[ARG_SIZE_TWO] = {0};
73     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
74     if (argc != ARG_SIZE_TWO) {
75         ACCOUNT_LOGE("expect 2 parameters, but got %{public}zu", argc);
76         std::string errMsg = "Parameter error. The number of parameters should be at least 2";
77         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
78         return nullptr;
79     }
80     napi_valuetype valType = napi_undefined;
81     napi_typeof(env, argv[PARAM_ZERO], &valType);
82     if (valType != napi_number) {
83         std::string errMsg = "Parameter error. The type of \"authType\" must be number";
84         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
85         return nullptr;
86     }
87     int32_t authType = -1;
88     napi_get_value_int32(env, argv[PARAM_ZERO], &authType);
89     napi_typeof(env, argv[PARAM_ONE], &valType);
90     if (valType != napi_number) {
91         std::string errMsg = "Parameter error. The type of \"authTrustLevel\" must be number";
92         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
93         return nullptr;
94     }
95     int32_t authSubType = -1;
96     napi_get_value_int32(env, argv[PARAM_ONE], &authSubType);
97     int32_t status;
98     napi_value result = nullptr;
99     int32_t errCode = AccountIAMClient::GetInstance().GetAvailableStatus(
100         static_cast<AuthType>(authType), static_cast<AuthTrustLevel>(authSubType), status);
101     if (errCode == ERR_OK) {
102         if ((status != ERR_IAM_SUCCESS) && (status != ERR_IAM_TYPE_NOT_SUPPORT) &&
103             (status != ERR_IAM_TRUST_LEVEL_NOT_SUPPORT) && (status != ERR_IAM_NOT_ENROLLED)) {
104             AccountIAMNapiThrow(env, AccountIAMConvertToJSErrCode(status), true);
105         } else {
106             napi_create_int32(env, status, &result);
107         }
108     } else {
109         AccountIAMNapiThrow(env, AccountIAMConvertToJSErrCode(errCode), true);
110     }
111     return result;
112 }
113 
ParseContextForGetSetProperty(napi_env env,napi_callback_info info,CommonAsyncContext * context,napi_value * result,bool isGet=true)114 static napi_status ParseContextForGetSetProperty(
115     napi_env env, napi_callback_info info, CommonAsyncContext *context, napi_value *result, bool isGet = true)
116 {
117     size_t argc = ARG_SIZE_TWO;
118     napi_value argv[ARG_SIZE_TWO] = {0};
119     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), napi_generic_failure);
120     if (argc < ARG_SIZE_ONE) {
121         ACCOUNT_LOGE("expect at least 1 parameter, but got zero");
122         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
123         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
124         return napi_generic_failure;
125     }
126     napi_valuetype valueType = napi_undefined;
127     if (argc == ARG_SIZE_TWO) {
128         NAPI_CALL_BASE(env, napi_typeof(env, argv[PARAM_ONE], &valueType), napi_generic_failure);
129     }
130     if (valueType == napi_function) {
131         NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM_ONE], 1, &context->callbackRef),
132             napi_generic_failure);
133     } else {
134         NAPI_CALL_BASE(env, napi_create_promise(env, &context->deferred, result), napi_generic_failure);
135     }
136     if (isGet) {
137         if (ParseGetPropRequest(env, argv[PARAM_ZERO], *(reinterpret_cast<GetPropertyContext *>(context))) != napi_ok) {
138             std::string errMsg = "Parameter error. The type of \"request\" must be GetPropertyRequest";
139             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
140             return napi_generic_failure;
141         }
142     } else {
143         if (ParseSetPropRequest(env, argv[PARAM_ZERO], reinterpret_cast<SetPropertyContext *>(context)->request) !=
144             napi_ok) {
145             std::string errMsg = "Parameter error. The type of \"request\" must be SetPropertyRequest";
146             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
147             return napi_generic_failure;
148         }
149     }
150     return napi_ok;
151 }
152 
GetProperty(napi_env env,napi_callback_info info)153 napi_value NapiAccountIAMUserAuth::GetProperty(napi_env env, napi_callback_info info)
154 {
155     napi_value result = nullptr;
156     GetPropertyContext *context = new (std::nothrow) GetPropertyContext(env);
157     if (context == nullptr) {
158         ACCOUNT_LOGE("failed to create GetPropertyContext");
159         return result;
160     }
161     std::unique_ptr<GetPropertyContext> contextPtr(context);
162     if (ParseContextForGetSetProperty(env, info, context, &result) != napi_ok) {
163         return nullptr;
164     }
165     napi_value resourceName = nullptr;
166     NAPI_CALL(env, napi_create_string_utf8(env, "GetProperty", NAPI_AUTO_LENGTH, &resourceName));
167     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
168         [](napi_env env, void *data) {
169             GetPropertyContext *context = reinterpret_cast<GetPropertyContext *>(data);
170             auto getPropCallback = std::make_shared<NapiGetPropCallback>(
171                 context->env, context->callbackRef, context->deferred, context->request.keys);
172             if (getPropCallback == nullptr) {
173                 ACCOUNT_LOGE("Failed for nullptr");
174                 return;
175             }
176             context->callbackRef = nullptr;
177             if ((context->parseHasAccountId) && (!IsAccountIdValid(context->accountId))) {
178                 AccountSA::Attributes emptyInfo;
179                 getPropCallback->OnResult(ERR_JS_ACCOUNT_NOT_FOUND, emptyInfo);
180                 return;
181             }
182             AccountIAMClient::GetInstance().GetProperty(context->accountId, context->request, getPropCallback);
183         },
184         [](napi_env env, napi_status status, void *data) {
185             delete reinterpret_cast<GetPropertyContext *>(data);
186         },
187         reinterpret_cast<void *>(context), &context->work));
188     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_user_initiated));
189     contextPtr.release();
190     return result;
191 }
192 
ParseContextForGetPropertyById(napi_env env,napi_callback_info info,GetPropertyByIdContext & context,napi_value & result)193 static napi_status ParseContextForGetPropertyById(
194     napi_env env, napi_callback_info info, GetPropertyByIdContext &context, napi_value &result)
195 {
196     size_t argc = ARG_SIZE_TWO;
197     napi_value argv[ARG_SIZE_TWO] = {0};
198     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), napi_generic_failure);
199     if (argc < ARG_SIZE_TWO) {
200         ACCOUNT_LOGE("Expect 2 parameters, but got %{public}zu", argc);
201         std::string errMsg = "Parameter error. The number of parameters should be at least 2";
202         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
203         return napi_invalid_arg;
204     }
205     napi_status status = ParseUint8ArrayToNativeUint8Array(
206         env, argv[0], &context.credentialIdData, &context.credentialIdLength);
207     if (status != napi_ok) {
208         ACCOUNT_LOGE("Parse credentialId from 'Uint8TypedArray' failed");
209         std::string errMsg = "Parameter error. The type of \"credentialId\" must be Uint8Array";
210         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
211         return napi_invalid_arg;
212     }
213     std::vector<uint32_t> tempKeys;
214     if (ParseUInt32Array(env, argv[1], tempKeys) != napi_ok) {
215         ACCOUNT_LOGE("Parameter error. The type of \"keys\" must be GetPropertyType's array");
216         std::string errMsg = "Parameter error. The type of \"keys\" must be GetPropertyType's array";
217         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
218         return napi_invalid_arg;
219     }
220     NAPI_CALL_BASE(env, napi_create_promise(env, &context.deferred, &result), napi_generic_failure);
221     for (const auto &item : tempKeys) {
222         Attributes::AttributeKey key;
223         status = ConvertGetPropertyTypeToAttributeKey(static_cast<GetPropertyType>(item), key);
224         if (status != napi_ok) {
225             ACCOUNT_LOGE("Parameter error. The type of \"key\" must be 'GetPropertyType'");
226             context.errCode = ERR_JS_INVALID_PARAMETER;
227             return napi_ok;
228         }
229         context.keys.push_back(key);
230     }
231     return napi_ok;
232 }
233 
GetPropertyByCredentialId(napi_env env,napi_callback_info info)234 napi_value NapiAccountIAMUserAuth::GetPropertyByCredentialId(napi_env env, napi_callback_info info)
235 {
236     napi_value result = nullptr;
237     GetPropertyByIdContext *context = new (std::nothrow) GetPropertyByIdContext(env);
238     if (context == nullptr) {
239         ACCOUNT_LOGE("Failed to create GetPropertyContext");
240         return result;
241     }
242     std::unique_ptr<GetPropertyByIdContext> contextPtr(context);
243     if (ParseContextForGetPropertyById(env, info, *context, result) != napi_ok) {
244         return nullptr;
245     }
246     napi_value resourceName = nullptr;
247     NAPI_CALL(env, napi_create_string_utf8(env, "GetPropertyByCredentialId", NAPI_AUTO_LENGTH, &resourceName));
248     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
249         [](napi_env env, void *data) {
250             GetPropertyByIdContext *context = reinterpret_cast<GetPropertyByIdContext *>(data);
251             auto getPropCallback = std::make_shared<NapiGetPropCallback>(
252                 context->env, nullptr, context->deferred, context->keys);
253             getPropCallback->isGetById_ = true;
254             if ((context->credentialIdLength != sizeof(uint64_t)) || (context->credentialIdData == nullptr)) {
255                 ACCOUNT_LOGE("Failed to convert uint8array data to uint64_t value");
256                 context->errCode = ERR_JS_CREDENTIAL_NOT_EXIST;
257             }
258             if (context->errCode != ERR_OK) {
259                 UserIam::UserAuth::Attributes extraInfo;
260                 getPropCallback->OnResult(context->errCode, extraInfo);
261                 return;
262             }
263             context->credentialId = *(reinterpret_cast<uint64_t *>(context->credentialIdData));
264             AccountIAMClient::GetInstance().GetPropertyByCredentialId(
265                 context->credentialId, context->keys, getPropCallback);
266         },
267         [](napi_env env, napi_status status, void *data) {
268             delete reinterpret_cast<GetPropertyByIdContext *>(data);
269         },
270         reinterpret_cast<void *>(context), &context->work));
271     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_user_initiated));
272     contextPtr.release();
273     return result;
274 }
275 
SetProperty(napi_env env,napi_callback_info info)276 napi_value NapiAccountIAMUserAuth::SetProperty(napi_env env, napi_callback_info info)
277 {
278     napi_value result = nullptr;
279     SetPropertyContext *context = new (std::nothrow) SetPropertyContext(env);
280     if (context == nullptr) {
281         ACCOUNT_LOGE("failed to create SetPropertyContext");
282         return result;
283     }
284     std::unique_ptr<SetPropertyContext> contextPtr(context);
285     if (ParseContextForGetSetProperty(env, info, context, &result, false) != napi_ok) {
286         return nullptr;
287     }
288     napi_value resourceName = nullptr;
289     NAPI_CALL(env, napi_create_string_utf8(env, "SetProperty", NAPI_AUTO_LENGTH, &resourceName));
290     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
291         [](napi_env env, void *data) {
292             SetPropertyContext *context = reinterpret_cast<SetPropertyContext *>(data);
293             auto setPropCallback = std::make_shared<NapiSetPropCallback>(
294                 context->env, context->callbackRef, context->deferred);
295             context->callbackRef = nullptr;
296             AccountIAMClient::GetInstance().SetProperty(context->accountId, context->request, setPropCallback);
297         },
298         [](napi_env env, napi_status status, void *data) {
299             delete reinterpret_cast<SetPropertyContext *>(data);
300         },
301         reinterpret_cast<void *>(context), &context->work));
302     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_user_initiated));
303     contextPtr.release();
304     return result;
305 }
306 
ParseContextForRemoteAuthOptions(napi_env env,napi_value jsOptions,RemoteAuthOptions & remoteAuthOptions)307 static bool ParseContextForRemoteAuthOptions(napi_env env, napi_value jsOptions, RemoteAuthOptions &remoteAuthOptions)
308 {
309     napi_valuetype valueType = napi_undefined;
310     napi_typeof(env, jsOptions, &valueType);
311     if (valueType == napi_undefined || valueType == napi_null) {
312         ACCOUNT_LOGI("RemoteAuthOptions is undefined or null");
313         return true;
314     }
315     if (valueType != napi_object) {
316         ACCOUNT_LOGE("Invalid object.");
317         std::string errMsg = "Parameter error. The type of \"remoteAuthOptions\" must be object";
318         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
319         return false;
320     }
321     if (!GetOptionalStringPropertyByKey(env, jsOptions, "verifierNetworkId",
322         remoteAuthOptions.verifierNetworkId, remoteAuthOptions.hasVerifierNetworkId)) {
323         ACCOUNT_LOGE("Get remoteAuthOptions's verifierNetworkId failed.");
324         std::string errMsg = "Parameter error. The type of \"verifierNetworkId\" must be string";
325         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
326         return false;
327     }
328     if (!GetOptionalStringPropertyByKey(env, jsOptions, "collectorNetworkId",
329         remoteAuthOptions.collectorNetworkId, remoteAuthOptions.hasCollectorNetworkId)) {
330         ACCOUNT_LOGE("Get remoteAuthOptions's collectorNetworkId failed.");
331         std::string errMsg = "Parameter error. The type of \"collectorNetworkId\" must be string";
332         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
333         return false;
334     }
335     int32_t tokenId = 0;
336     if (!GetOptionalNumberPropertyByKey(
337         env, jsOptions, "collectorTokenId", tokenId, remoteAuthOptions.hasCollectorTokenId)) {
338         ACCOUNT_LOGE("Get remoteAuthOptions's collectorTokenId failed.");
339         std::string errMsg = "Parameter error. The type of \"collectorTokenId\" must be number";
340         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
341         return false;
342     }
343     remoteAuthOptions.collectorTokenId = static_cast<uint32_t>(tokenId);
344     return true;
345 }
346 
ParseContextForAuthOptions(napi_env env,napi_value jsOptions,AuthOptions & authOptions)347 static bool ParseContextForAuthOptions(napi_env env, napi_value jsOptions, AuthOptions &authOptions)
348 {
349     napi_valuetype valueType = napi_undefined;
350     napi_typeof(env, jsOptions, &valueType);
351     if (valueType == napi_undefined || valueType == napi_null) {
352         ACCOUNT_LOGI("AuthOption is undefined or null");
353         return true;
354     }
355     if (valueType != napi_object) {
356         ACCOUNT_LOGE("Invalid object.");
357         std::string errMsg = "Parameter error. The type of \"authOptions\" must be object";
358         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
359         return false;
360     }
361     if (!GetOptionalNumberPropertyByKey(
362         env, jsOptions, "accountId", authOptions.accountId, authOptions.hasAccountId)) {
363         ACCOUNT_LOGE("Get authOptions's accountId failed.");
364         std::string errMsg = "Parameter error. The type of \"accountId\" must be number";
365         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
366         return false;
367     }
368     int32_t authIntent = 0;
369     bool hasProp = false;
370     if (!GetOptionalNumberPropertyByKey(env, jsOptions, "authIntent", authIntent, hasProp)) {
371         ACCOUNT_LOGE("Get authOptions's authIntent failed.");
372         std::string errMsg = "Parameter error. The type of \"authIntent\" must be AuthIntent";
373         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
374         return false;
375     }
376     authOptions.authIntent = static_cast<AuthIntent>(authIntent);
377     if (IsOptionalPropertyExist(env, jsOptions, "remoteAuthOptions")) {
378         napi_value value = nullptr;
379         NAPI_CALL_BASE(env, napi_get_named_property(env, jsOptions, "remoteAuthOptions", &value), false);
380         if (!ParseContextForRemoteAuthOptions(env, value, authOptions.remoteAuthOptions)) {
381             ACCOUNT_LOGE("Parse remoteAuthOptions failed.");
382             return false;
383         }
384         authOptions.hasRemoteAuthOptions = true;
385         if (!authOptions.hasAccountId) {
386             authOptions.accountId = -1;
387         }
388     }
389     return true;
390 }
391 
ParseContextForAuth(napi_env env,napi_value * argv,size_t argc,AuthContext & context)392 static napi_status ParseContextForAuth(napi_env env, napi_value *argv, size_t argc, AuthContext &context)
393 {
394     if (argc != ARG_SIZE_FOUR && argc != ARG_SIZE_FIVE) {
395         ACCOUNT_LOGE("the number of parameter is incorrect, expect 4 or 5, but got %{public}zu", argc);
396         return napi_invalid_arg;
397     }
398     size_t index = 0;
399     if (ParseUint8TypedArrayToVector(env, argv[index++], context.challenge) != napi_ok) {
400         ACCOUNT_LOGE("fail to parse challenge");
401         std::string errMsg = "Parameter error. The type of \"challenge\" must be Uint8Array";
402         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
403         return napi_invalid_arg;
404     }
405     if (!GetIntProperty(env, argv[index++], context.authType)) {
406         ACCOUNT_LOGE("fail to parse authType");
407         std::string errMsg = "Parameter error. The type of \"authType\" must be AuthType";
408         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
409         return napi_invalid_arg;
410     }
411     if (!GetIntProperty(env, argv[index++], context.trustLevel)) {
412         ACCOUNT_LOGE("fail to parse trustLevel");
413         std::string errMsg = "Parameter error. The type of \"authTrustLevel\" must be AuthTrustLevel";
414         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
415         return napi_invalid_arg;
416     }
417     if (argc == PARAM_FIVE) {
418         if (!ParseContextForAuthOptions(env, argv[index++], context.authOptions)) {
419             ACCOUNT_LOGE("fail to parse authOptions");
420             return napi_invalid_arg;
421         }
422     }
423     std::shared_ptr<JsIAMCallback> jsCallback = std::make_shared<JsIAMCallback>(env);
424     if (ParseIAMCallback(env, argv[index++], jsCallback) != napi_ok) {
425         ACCOUNT_LOGE("fail to parse callback");
426         std::string errMsg = "Parameter error. The type of \"callback\" must be function";
427         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
428         return napi_invalid_arg;
429     }
430     context.callback = std::make_shared<NapiUserAuthCallback>(env, jsCallback);
431     return napi_ok;
432 }
433 
ParseContextForAuthUser(napi_env env,napi_value * argv,size_t argc,AuthContext & context)434 static napi_status ParseContextForAuthUser(napi_env env, napi_value *argv, size_t argc, AuthContext &context)
435 {
436     if (argc != ARG_SIZE_FIVE) {
437         ACCOUNT_LOGE("the number of parameter is incorrect, expect 5, but got %{public}zu", argc);
438         std::string errMsg = "Parameter error. The number of parameters should be at least 5";
439         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
440         return napi_invalid_arg;
441     }
442     if (!GetIntProperty(env, argv[0], context.userId)) {
443         ACCOUNT_LOGE("Get userId failed");
444         std::string errMsg = "Parameter error. The type of \"userId\" must be number";
445         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
446         return napi_invalid_arg;
447     }
448     return ParseContextForAuth(env, &argv[1], ARG_SIZE_FOUR, context);
449 }
450 
Auth(napi_env env,napi_callback_info info)451 napi_value NapiAccountIAMUserAuth::Auth(napi_env env, napi_callback_info info)
452 {
453     size_t argc = ARG_SIZE_FIVE;
454     napi_value argv[ARG_SIZE_FIVE] = {0};
455     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
456     if (argc < ARG_SIZE_FOUR) {
457         ACCOUNT_LOGE("the number of parameter is incorrect, expect 4, but got %{public}zu", argc);
458         std::string errMsg = "Parameter error. The number of parameters should be at least 4";
459         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
460         return nullptr;
461     }
462     AuthContext context;
463     if (ParseContextForAuth(env, argv, argc, context) == napi_invalid_arg) {
464         return nullptr;
465     }
466     if ((!context.authOptions.hasRemoteAuthOptions) && (context.authOptions.hasAccountId) &&
467         (!IsAccountIdValid(context.authOptions.accountId))) {
468         AccountSA::Attributes emptyInfo;
469         context.callback->OnResult(ERR_JS_ACCOUNT_NOT_FOUND, emptyInfo);
470         return nullptr;
471     }
472     uint64_t contextId = AccountIAMClient::GetInstance().Auth(context.authOptions, context.challenge,
473         static_cast<AuthType>(context.authType), static_cast<AuthTrustLevel>(context.trustLevel), context.callback);
474     return CreateUint8Array(env, reinterpret_cast<uint8_t *>(&contextId), sizeof(uint64_t));
475 }
476 
AuthUser(napi_env env,napi_callback_info info)477 napi_value NapiAccountIAMUserAuth::AuthUser(napi_env env, napi_callback_info info)
478 {
479     size_t argc = ARG_SIZE_FIVE;
480     napi_value argv[ARG_SIZE_FIVE] = {0};
481     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
482     AuthContext context;
483     if (ParseContextForAuthUser(env, argv, argc, context) == napi_invalid_arg) {
484         return nullptr;
485     }
486     if (!IsAccountIdValid(context.userId)) {
487         AccountSA::Attributes emptyInfo;
488         context.callback->OnResult(ERR_JS_ACCOUNT_NOT_FOUND, emptyInfo);
489         return nullptr;
490     }
491     context.authOptions.accountId = context.userId;
492     uint64_t contextId = AccountIAMClient::GetInstance().AuthUser(context.authOptions, context.challenge,
493         static_cast<AuthType>(context.authType), static_cast<AuthTrustLevel>(context.trustLevel), context.callback);
494     return CreateUint8Array(env, reinterpret_cast<uint8_t *>(&contextId), sizeof(uint64_t));
495 }
496 
CancelAuth(napi_env env,napi_callback_info info)497 napi_value NapiAccountIAMUserAuth::CancelAuth(napi_env env, napi_callback_info info)
498 {
499     size_t argc = ARG_SIZE_ONE;
500     napi_value argv[ARG_SIZE_ONE] = {0};
501     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
502     if (argc != ARG_SIZE_ONE) {
503         ACCOUNT_LOGE("failed to parse parameters, expect at least one parameter, but got %zu", argc);
504         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
505         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
506         return nullptr;
507     }
508     uint64_t contextId = 0;
509     if (ParseUint8TypedArrayToUint64(env, argv[0], contextId) != napi_ok) {
510         ACCOUNT_LOGE("failed to parse contextId");
511         std::string errMsg = "Parameter error. The type of \"contextID\" must be Uint8Array";
512         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
513         return nullptr;
514     }
515     int32_t result = AccountIAMClient::GetInstance().CancelAuth(contextId);
516     napi_value napiResult = nullptr;
517     if (result == ERR_OK) {
518         NAPI_CALL(env, napi_create_int32(env, result, &napiResult));
519         return napiResult;
520     }
521     AccountIAMNapiThrow(env, AccountIAMConvertToJSErrCode(result), true);
522     return nullptr;
523 }
524 
ParseContextForPrepareRemoteAuth(napi_env env,napi_callback_info info,PrepareRemoteAuthContext * context,napi_value * result)525 static napi_status ParseContextForPrepareRemoteAuth(
526     napi_env env, napi_callback_info info, PrepareRemoteAuthContext *context, napi_value *result)
527 {
528     size_t argc = ARG_SIZE_ONE;
529     napi_value argv[ARG_SIZE_ONE] = {0};
530     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), napi_generic_failure);
531     if (argc < ARG_SIZE_ONE) {
532         ACCOUNT_LOGE("Parse parameters failed, expect at least one parameter, but got %zu.", argc);
533         std::string errMsg = "Parameter error. The arg number must be at least 1 characters";
534         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
535         return napi_generic_failure;
536     }
537     if (!GetStringProperty(env, argv[0], context->remoteNetworkId)) {
538         ACCOUNT_LOGE("Get remoteNetworkId failed");
539         std::string errMsg = "Parameter error. The type of remoteNetworkId must be string";
540         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
541         return napi_generic_failure;
542     }
543     NAPI_CALL_BASE(env, napi_create_promise(env, &context->deferred, result), napi_generic_failure);
544 
545     return napi_ok;
546 }
547 
PrepareRemoteAuth(napi_env env,napi_callback_info info)548 napi_value NapiAccountIAMUserAuth::PrepareRemoteAuth(napi_env env, napi_callback_info info)
549 {
550     napi_value result = nullptr;
551     PrepareRemoteAuthContext *context = new (std::nothrow) PrepareRemoteAuthContext(env);
552     if (context == nullptr) {
553         ACCOUNT_LOGE("Create PrepareRemoteAuthContext failed.");
554         return result;
555     }
556     std::unique_ptr<PrepareRemoteAuthContext> contextPtr(context);
557 
558     if (ParseContextForPrepareRemoteAuth(env, info, context, &result) != napi_ok) {
559         return nullptr;
560     }
561 
562     napi_value resourceName = nullptr;
563     NAPI_CALL(env, napi_create_string_utf8(env, "PrepareRemoteAuth", NAPI_AUTO_LENGTH, &resourceName));
564     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
565         [](napi_env env, void *data) {
566             if (data == nullptr) {
567                 ACCOUNT_LOGE("PrepareRemoteAuth work data is nullptr.");
568                 return;
569             }
570             PrepareRemoteAuthContext *context = reinterpret_cast<PrepareRemoteAuthContext *>(data);
571             auto prepareRemoteAuthCallback = std::make_shared<NapiPrepareRemoteAuthCallback>(
572                 context->env, context->callbackRef, context->deferred);
573             context->callbackRef = nullptr;
574             context->result = AccountIAMClient::GetInstance().PrepareRemoteAuth(
575                 context->remoteNetworkId, prepareRemoteAuthCallback);
576         },
577         [](napi_env env, napi_status status, void *data) {
578             delete reinterpret_cast<PrepareRemoteAuthContext *>(data);
579         },
580         reinterpret_cast<void *>(context), &context->work));
581     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_user_initiated));
582     contextPtr.release();
583     return result;
584 }
585 }  // namespace AccountJsKit
586 }  // namespace OHOS
587