• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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