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