1 /*
2 * Copyright (c) 2022 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_identity_manager.h"
17
18 #include <memory>
19 #include "account_log_wrapper.h"
20 #include "account_iam_client.h"
21 #include "napi_account_iam_common.h"
22 #include "napi_account_common.h"
23 #include "napi_account_error.h"
24
25 namespace OHOS {
26 namespace AccountJsKit {
27 using namespace OHOS::AccountSA;
28
Init(napi_env env,napi_value exports)29 napi_value NapiAccountIAMIdentityManager::Init(napi_env env, napi_value exports)
30 {
31 napi_value cons;
32 napi_property_descriptor clzDes[] = {
33 DECLARE_NAPI_FUNCTION("openSession", OpenSession),
34 DECLARE_NAPI_FUNCTION("addCredential", AddCredential),
35 DECLARE_NAPI_FUNCTION("updateCredential", UpdateCredential),
36 DECLARE_NAPI_FUNCTION("closeSession", CloseSession),
37 DECLARE_NAPI_FUNCTION("cancel", Cancel),
38 DECLARE_NAPI_FUNCTION("delUser", DelUser),
39 DECLARE_NAPI_FUNCTION("delCred", DelCred),
40 DECLARE_NAPI_FUNCTION("getAuthInfo", GetAuthInfo),
41 };
42 NAPI_CALL(env, napi_define_class(env, "UserIdentityManager", NAPI_AUTO_LENGTH, JsConstructor,
43 nullptr, sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
44 NAPI_CALL(env, napi_set_named_property(env, exports, "UserIdentityManager", cons));
45 return exports;
46 }
47
JsConstructor(napi_env env,napi_callback_info info)48 napi_value NapiAccountIAMIdentityManager::JsConstructor(napi_env env, napi_callback_info info)
49 {
50 napi_value thisVar = nullptr;
51 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
52 return thisVar;
53 }
54
ParseContextForOpenSession(napi_env env,napi_callback_info info,IDMContext * context)55 static bool ParseContextForOpenSession(
56 napi_env env, napi_callback_info info, IDMContext *context)
57 {
58 size_t argc = ARG_SIZE_ONE;
59 napi_value argv[ARG_SIZE_ONE] = {0};
60 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), false);
61
62 if (argc > 0) {
63 if (!GetCallbackProperty(env, argv[0], context->callbackRef, 1)) {
64 std::string errMsg = "The type of arg 1 must be function";
65 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
66 return false;
67 }
68 }
69 return true;
70 }
71
OpenSession(napi_env env,napi_callback_info info)72 napi_value NapiAccountIAMIdentityManager::OpenSession(napi_env env, napi_callback_info info)
73 {
74 IDMContext *context = new (std::nothrow) IDMContext(env);
75 if (context == nullptr) {
76 ACCOUNT_LOGE("failed to create IDMContext for insufficient memory");
77 return nullptr;
78 }
79 std::unique_ptr<IDMContext> contextPtr(context);
80 if (!ParseContextForOpenSession(env, info, context)) {
81 return nullptr;
82 }
83
84 napi_value result = nullptr;
85 if (context->callbackRef == nullptr) {
86 napi_create_promise(env, &context->deferred, &result);
87 } else {
88 napi_get_undefined(env, &result);
89 }
90
91 napi_value resourceName = nullptr;
92 NAPI_CALL(env, napi_create_string_utf8(env, "OpenSession", NAPI_AUTO_LENGTH, &resourceName));
93 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
94 [](napi_env env, void *data) {
95 IDMContext *context = reinterpret_cast<IDMContext *>(data);
96 context->errCode = AccountIAMClient::GetInstance().OpenSession(0, context->challenge);
97 },
98 [](napi_env env, napi_status status, void *data) {
99 IDMContext *context = reinterpret_cast<IDMContext *>(data);
100 napi_value errJs = nullptr;
101 napi_value dataJs = nullptr;
102 if (context->errCode != 0) {
103 int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
104 errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
105 napi_get_null(env, &dataJs);
106 } else {
107 napi_get_null(env, &errJs);
108 dataJs = CreateUint8Array(env, context->challenge.data(), context->challenge.size());
109 }
110 CallbackAsyncOrPromise(env, context, errJs, dataJs);
111 delete context;
112 },
113 reinterpret_cast<void *>(context), &context->work));
114 NAPI_CALL(env, napi_queue_async_work(env, context->work));
115 contextPtr.release();
116 return result;
117 }
118
ParseContextForUpdateCredential(napi_env env,napi_callback_info info,IDMContext * context)119 static bool ParseContextForUpdateCredential(napi_env env, napi_callback_info info, IDMContext *context)
120 {
121 size_t argc = ARG_SIZE_TWO;
122 napi_value argv[ARG_SIZE_TWO] = {0};
123 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), false);
124 if (argc < ARG_SIZE_TWO) {
125 std::string errMsg = "The arg number must be at least 2 characters";
126 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
127 return false;
128 }
129 if (ParseAddCredInfo(env, argv[PARAM_ZERO], context->addCredInfo) != napi_ok) {
130 std::string errMsg = "The type of arg 1 must be valid CredentialInfo";
131 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
132 return false;
133 }
134 if (ParseIAMCallback(env, argv[PARAM_ONE], context->callback) != napi_ok) {
135 std::string errMsg = "The type of arg 2 must be valid IIdmCallback";
136 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
137 return false;
138 }
139 return true;
140 }
141
AddCredential(napi_env env,napi_callback_info info)142 napi_value NapiAccountIAMIdentityManager::AddCredential(napi_env env, napi_callback_info info)
143 {
144 IDMContext *context = new (std::nothrow) IDMContext(env);
145 if (context == nullptr) {
146 ACCOUNT_LOGE("failed to create IDMContext");
147 return nullptr;
148 }
149 std::unique_ptr<IDMContext> contextPtr(context);
150 if (!ParseContextForUpdateCredential(env, info, context)) {
151 return nullptr;
152 }
153
154 napi_value resourceName = nullptr;
155 NAPI_CALL(env, napi_create_string_utf8(env, "AddCredential", NAPI_AUTO_LENGTH, &resourceName));
156 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
157 [](napi_env env, void *data) {
158 IDMContext *context = reinterpret_cast<IDMContext *>(data);
159 auto idmCallback = std::make_shared<NapiIDMCallback>(context->env, context->callback);
160 AccountIAMClient::GetInstance().AddCredential(0, context->addCredInfo, idmCallback);
161 },
162 [](napi_env env, napi_status status, void *data) {
163 delete reinterpret_cast<IDMContext *>(data);
164 },
165 reinterpret_cast<void *>(context), &context->work));
166 NAPI_CALL(env, napi_queue_async_work(env, context->work));
167 contextPtr.release();
168 return nullptr;
169 }
170
UpdateCredential(napi_env env,napi_callback_info info)171 napi_value NapiAccountIAMIdentityManager::UpdateCredential(napi_env env, napi_callback_info info)
172 {
173 IDMContext *context = new (std::nothrow) IDMContext(env);
174 if (context == nullptr) {
175 ACCOUNT_LOGE("failed to create IDMContext");
176 return nullptr;
177 }
178 std::unique_ptr<IDMContext> contextPtr(context);
179 if (!ParseContextForUpdateCredential(env, info, context)) {
180 return nullptr;
181 }
182
183 napi_value resourceName = nullptr;
184 NAPI_CALL(env, napi_create_string_utf8(env, "UpdateCredential", NAPI_AUTO_LENGTH, &resourceName));
185 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
186 [](napi_env env, void *data) {
187 IDMContext *context = reinterpret_cast<IDMContext *>(data);
188 auto idmCallback = std::make_shared<NapiIDMCallback>(context->env, context->callback);
189 AccountIAMClient::GetInstance().UpdateCredential(0, context->addCredInfo, idmCallback);
190 },
191 [](napi_env env, napi_status status, void *data) {
192 delete reinterpret_cast<IDMContext *>(data);
193 },
194 reinterpret_cast<void *>(context), &context->work));
195 NAPI_CALL(env, napi_queue_async_work(env, context->work));
196 contextPtr.release();
197 return nullptr;
198 }
199
CloseSession(napi_env env,napi_callback_info info)200 napi_value NapiAccountIAMIdentityManager::CloseSession(napi_env env, napi_callback_info info)
201 {
202 AccountIAMClient::GetInstance().CloseSession(0);
203 napi_value result = nullptr;
204 napi_get_null(env, &result);
205 return result;
206 }
207
Cancel(napi_env env,napi_callback_info info)208 napi_value NapiAccountIAMIdentityManager::Cancel(napi_env env, napi_callback_info info)
209 {
210 size_t argc = ARG_SIZE_ONE;
211 napi_value argv[ARG_SIZE_ONE] = {0};
212 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
213 if (argc < ARG_SIZE_ONE) {
214 ACCOUNT_LOGE("failed to parse parameters, expect one parameter, but got %{public}zu", argc);
215 std::string errMsg = "The arg number must be at least 1 characters";
216 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
217 return nullptr;
218 }
219 uint8_t *data = nullptr;
220 size_t length = 0;
221 napi_status status = ParseUint8TypedArray(env, argv[0], &data, &length);
222 if ((status != napi_ok) || (length < sizeof(uint64_t))) {
223 std::string errMsg = "The type of arg 1 must be a uint8_t array";
224 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
225 return nullptr;
226 }
227 int32_t ret = AccountIAMClient::GetInstance().Cancel(0);
228 napi_value napiResult = nullptr;
229 if (ret == ERR_OK) {
230 napi_create_int32(env, ret, &napiResult);
231 return napiResult;
232 }
233 ACCOUNT_LOGE("Failed to cancel account, ret = %d", ret);
234 AccountIAMNapiThrow(env, AccountIAMConvertToJSErrCode(ret), true);
235 return nullptr;
236 }
237
ParseContextForDelUser(napi_env env,napi_callback_info info,IDMContext * context)238 static napi_status ParseContextForDelUser(napi_env env, napi_callback_info info, IDMContext *context)
239 {
240 size_t argc = ARG_SIZE_TWO;
241 napi_value argv[ARG_SIZE_TWO] = {0};
242 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
243 if (argc != ARG_SIZE_TWO) {
244 ACCOUNT_LOGE("failed to parse parameters, expect two parameters, but got one");
245 std::string errMsg = "The arg number must be at least 2 characters";
246 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
247 return napi_invalid_arg;
248 }
249 if (ParseUint8TypedArrayToVector(env, argv[0], context->token) != napi_ok) {
250 std::string errMsg = "The type of arg 1 must be a uint8_t array";
251 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
252 return napi_invalid_arg;
253 }
254 if (ParseIAMCallback(env, argv[PARAM_ONE], context->callback) != napi_ok) {
255 std::string errMsg = "The type of arg 2 must be valid IIdmCallback";
256 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
257 return napi_invalid_arg;
258 }
259 return napi_ok;
260 }
261
DelUser(napi_env env,napi_callback_info info)262 napi_value NapiAccountIAMIdentityManager::DelUser(napi_env env, napi_callback_info info)
263 {
264 IDMContext *context = new (std::nothrow) IDMContext(env);
265 if (context == nullptr) {
266 ACCOUNT_LOGE("failed to create IDMContext");
267 return nullptr;
268 }
269 std::unique_ptr<IDMContext> contextPtr(context);
270 NAPI_CALL(env, ParseContextForDelUser(env, info, context));
271 napi_value resourceName = nullptr;
272 NAPI_CALL(env, napi_create_string_utf8(env, "DelUser", NAPI_AUTO_LENGTH, &resourceName));
273 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
274 [](napi_env env, void *data) {
275 IDMContext *context = reinterpret_cast<IDMContext *>(data);
276 auto idmCallback = std::make_shared<NapiIDMCallback>(context->env, context->callback);
277 AccountIAMClient::GetInstance().DelUser(0, context->token, idmCallback);
278 },
279 [](napi_env env, napi_status status, void *data) {
280 delete reinterpret_cast<IDMContext *>(data);
281 },
282 reinterpret_cast<void *>(context), &context->work));
283 NAPI_CALL(env, napi_queue_async_work(env, context->work));
284 contextPtr.release();
285 return nullptr;
286 }
287
ParseContextForDelCred(napi_env env,napi_callback_info info,IDMContext * context)288 static napi_status ParseContextForDelCred(napi_env env, napi_callback_info info, IDMContext *context)
289 {
290 size_t argc = ARG_SIZE_THREE;
291 napi_value argv[ARG_SIZE_THREE] = {0};
292 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
293 if (argc != ARG_SIZE_THREE) {
294 ACCOUNT_LOGE("failed to parse parameters, expect three parameters, but got %zu", argc);
295 std::string errMsg = "The arg number must be at least 3 characters";
296 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
297 return napi_invalid_arg;
298 }
299 if (ParseUint8TypedArrayToUint64(env, argv[0], context->credentialId) != napi_ok) {
300 std::string errMsg = "The type of arg 1 must be a uint8_t array";
301 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
302 return napi_invalid_arg;
303 }
304 if (ParseUint8TypedArrayToVector(env, argv[PARAM_ONE], context->token) != napi_ok) {
305 std::string errMsg = "The type of arg 2 must be a uint8_t array";
306 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
307 return napi_invalid_arg;
308 }
309 if (ParseIAMCallback(env, argv[PARAM_TWO], context->callback) != napi_ok) {
310 std::string errMsg = "The type of arg 3 must be valid IIdmCallback";
311 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
312 return napi_invalid_arg;
313 }
314 return napi_ok;
315 }
316
DelCred(napi_env env,napi_callback_info info)317 napi_value NapiAccountIAMIdentityManager::DelCred(napi_env env, napi_callback_info info)
318 {
319 IDMContext *context = new (std::nothrow) IDMContext(env);
320 if (context == nullptr) {
321 ACCOUNT_LOGE("failed to create IDMContext");
322 return nullptr;
323 }
324 std::unique_ptr<IDMContext> contextPtr(context);
325 NAPI_CALL(env, ParseContextForDelCred(env, info, context));
326 napi_value resourceName = nullptr;
327 NAPI_CALL(env, napi_create_string_utf8(env, "DelCred", NAPI_AUTO_LENGTH, &resourceName));
328 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
329 [](napi_env env, void *data) {
330 IDMContext *context = reinterpret_cast<IDMContext *>(data);
331 auto idmCallback = std::make_shared<NapiIDMCallback>(context->env, context->callback);
332 AccountIAMClient::GetInstance().DelCred(0, context->credentialId, context->token, idmCallback);
333 },
334 [](napi_env env, napi_status status, void *data) {
335 delete reinterpret_cast<IDMContext *>(data);
336 },
337 reinterpret_cast<void *>(context), &context->work));
338 NAPI_CALL(env, napi_queue_async_work(env, context->work));
339 contextPtr.release();
340 return nullptr;
341 }
342
ParseOneParamForGetAuthInfo(napi_env env,GetAuthInfoContext * context,napi_value * result,napi_value argv,int32_t & authType)343 static napi_status ParseOneParamForGetAuthInfo(napi_env env, GetAuthInfoContext *context,
344 napi_value *result, napi_value argv, int32_t &authType)
345 {
346 napi_valuetype valueType = napi_undefined;
347 NAPI_CALL_BASE(env, napi_typeof(env, argv, &valueType), napi_generic_failure);
348 if (valueType == napi_function) {
349 if (!GetCallbackProperty(env, argv, context->callbackRef, 1)) {
350 ACCOUNT_LOGE("Get callbackRef failed");
351 std::string errMsg = "The type of arg 1 must be function";
352 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
353 return napi_invalid_arg;
354 }
355 } else if (valueType == napi_number) {
356 if (!GetIntProperty(env, argv, authType)) {
357 ACCOUNT_LOGE("Get authType failed");
358 std::string errMsg = "The type of arg 1 must be number";
359 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
360 return napi_invalid_arg;
361 }
362 NAPI_CALL_BASE(env, napi_create_promise(env, &context->deferred, result), napi_generic_failure);
363 } else {
364 ACCOUNT_LOGE("Get arg 1 failed");
365 std::string errMsg = "The type of arg 1 must be number or function";
366 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
367 return napi_invalid_arg;
368 }
369 return napi_ok;
370 }
371
ParseContextForGetAuthInfo(napi_env env,napi_callback_info info,GetAuthInfoContext * context,napi_value * result)372 static napi_status ParseContextForGetAuthInfo(
373 napi_env env, napi_callback_info info, GetAuthInfoContext *context, napi_value *result)
374 {
375 size_t argc = ARG_SIZE_TWO;
376 napi_value argv[ARG_SIZE_TWO] = {0};
377 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), napi_generic_failure);
378 int32_t authType = 0;
379 if (argc == 0) {
380 NAPI_CALL_BASE(env, napi_create_promise(env, &context->deferred, result), napi_generic_failure);
381 return napi_ok;
382 }
383 if (argc == ARG_SIZE_ONE) {
384 if (ParseOneParamForGetAuthInfo(env, context, result, argv[PARAM_ZERO], authType) != napi_ok) {
385 return napi_invalid_arg;
386 }
387 }
388 if (argc == ARG_SIZE_TWO) {
389 if (!GetCallbackProperty(env, argv[PARAM_ONE], context->callbackRef, 1)) {
390 ACCOUNT_LOGE("Get callbackRef failed");
391 std::string errMsg = "The type of arg 2 must be function";
392 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
393 return napi_invalid_arg;
394 }
395 if (!GetIntProperty(env, argv[PARAM_ZERO], authType)) {
396 ACCOUNT_LOGE("Get authType failed");
397 std::string errMsg = "The type of arg 1 must be number";
398 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
399 return napi_invalid_arg;
400 }
401 }
402
403 context->authType = static_cast<AuthType>(authType);
404 return napi_ok;
405 }
406
GetAuthInfo(napi_env env,napi_callback_info info)407 napi_value NapiAccountIAMIdentityManager::GetAuthInfo(napi_env env, napi_callback_info info)
408 {
409 napi_value result = nullptr;
410 GetAuthInfoContext *context = new (std::nothrow) GetAuthInfoContext(env);
411 if (context == nullptr) {
412 ACCOUNT_LOGE("failed to create GetAuthInfoContext");
413 return result;
414 }
415 std::unique_ptr<GetAuthInfoContext> contextPtr(context);
416 NAPI_CALL(env, ParseContextForGetAuthInfo(env, info, context, &result));
417 napi_value resourceName = nullptr;
418 NAPI_CALL(env, napi_create_string_utf8(env, "GetAuthInfo", NAPI_AUTO_LENGTH, &resourceName));
419 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
420 [](napi_env env, void *data) {
421 GetAuthInfoContext *context = reinterpret_cast<GetAuthInfoContext *>(data);
422 auto idmCallback = std::make_shared<NapiGetInfoCallback>(
423 context->env, context->callbackRef, context->deferred);
424 AccountIAMClient::GetInstance().GetCredentialInfo(0, context->authType, idmCallback);
425 context->callbackRef = nullptr;
426 },
427 [](napi_env env, napi_status status, void *data) {
428 delete reinterpret_cast<GetAuthInfoContext *>(data);
429 },
430 reinterpret_cast<void *>(context), &context->work));
431 NAPI_CALL(env, napi_queue_async_work(env, context->work));
432 contextPtr.release();
433 return result;
434 }
435 } // namespace AccountJsKit
436 } // namespace OHOS
437