@cloudbase/auth 3.1.9 → 3.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.ts +61 -61
- package/dist/cjs/index.js +1675 -1676
- package/dist/esm/index.d.ts +61 -61
- package/dist/esm/index.js +1675 -1676
- package/dist/miniprogram/index.js +1 -1
- package/package.json +5 -5
- package/src/index.ts +1615 -1639
package/src/index.ts
CHANGED
|
@@ -397,1019 +397,827 @@ class Auth extends AuthV1Compat {
|
|
|
397
397
|
this.setAccessKey()
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
|
|
401
|
-
* 绑定手机号
|
|
402
|
-
* @param phoneNumber
|
|
403
|
-
* @param phoneCode
|
|
404
|
-
*/
|
|
405
|
-
@catchErrorsDecorator({
|
|
406
|
-
title: '绑定手机号失败',
|
|
407
|
-
messages: [
|
|
408
|
-
'请确认以下各项:',
|
|
409
|
-
' 1 - 调用 auth().bindPhoneNumber() 的语法或参数是否正确',
|
|
410
|
-
' 2 - 当前环境是否开通了短信验证码登录',
|
|
411
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
412
|
-
],
|
|
413
|
-
})
|
|
414
|
-
public async bindPhoneNumber(params: authModels.BindPhoneRequest) {
|
|
415
|
-
return this.oauthInstance.authApi.editContact(params)
|
|
416
|
-
}
|
|
400
|
+
// ========== new auth api methods merged below ==========
|
|
417
401
|
|
|
418
402
|
/**
|
|
419
|
-
*
|
|
420
|
-
*
|
|
403
|
+
* https://supabase.com/docs/reference/javascript/auth-signinanonymously
|
|
404
|
+
* Sign in a user anonymously.
|
|
405
|
+
* const { data, error } = await auth.signInAnonymously();
|
|
406
|
+
* @param params
|
|
407
|
+
* @returns Promise<SignInRes>
|
|
421
408
|
*/
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
' 1 - 调用 auth().unbindProvider() 的语法或参数是否正确',
|
|
427
|
-
' 2 - 当前账户是否已经与此登录方式解绑',
|
|
428
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
429
|
-
],
|
|
430
|
-
})
|
|
431
|
-
public async unbindProvider(params: authModels.UnbindProviderRequest): Promise<void> {
|
|
432
|
-
return this.oauthInstance.authApi.unbindProvider(params)
|
|
433
|
-
}
|
|
409
|
+
async signInAnonymously(params: SignInAnonymouslyReq): Promise<SignInRes> {
|
|
410
|
+
try {
|
|
411
|
+
await this.oauthInstance.authApi.signInAnonymously(params)
|
|
412
|
+
const loginState = await this.createLoginState()
|
|
434
413
|
|
|
435
|
-
|
|
436
|
-
* 更新邮箱地址
|
|
437
|
-
* @param email
|
|
438
|
-
* @param sudo_token
|
|
439
|
-
* @param verification_token
|
|
440
|
-
*/
|
|
441
|
-
@catchErrorsDecorator({
|
|
442
|
-
title: '绑定邮箱地址失败',
|
|
443
|
-
messages: [
|
|
444
|
-
'请确认以下各项:',
|
|
445
|
-
' 1 - 调用 auth().bindEmail() 的语法或参数是否正确',
|
|
446
|
-
' 2 - 当前环境是否开通了邮箱密码登录',
|
|
447
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
448
|
-
],
|
|
449
|
-
})
|
|
450
|
-
public bindEmail(params: authModels.BindEmailRequest) {
|
|
451
|
-
return this.oauthInstance.authApi.editContact(params)
|
|
452
|
-
}
|
|
414
|
+
const { data: { session } = {} } = await this.getSession()
|
|
453
415
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
*/
|
|
460
|
-
@catchErrorsDecorator({
|
|
461
|
-
title: '验证码验证失败',
|
|
462
|
-
messages: [
|
|
463
|
-
'请确认以下各项:',
|
|
464
|
-
' 1 - 调用 auth().verify() 的语法或参数是否正确',
|
|
465
|
-
' 2 - 当前环境是否开通了手机验证码/邮箱登录',
|
|
466
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
467
|
-
],
|
|
468
|
-
})
|
|
469
|
-
public async verify(params: authModels.VerifyRequest): Promise<authModels.VerifyResponse> {
|
|
470
|
-
return this.oauthInstance.authApi.verify(params)
|
|
416
|
+
// loginState返回是为了兼容v2版本
|
|
417
|
+
return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
418
|
+
} catch (error) {
|
|
419
|
+
return { data: {}, error: new AuthError(error) }
|
|
420
|
+
}
|
|
471
421
|
}
|
|
472
422
|
|
|
473
423
|
/**
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
* @
|
|
477
|
-
* @
|
|
424
|
+
* https://supabase.com/docs/reference/javascript/auth-signup
|
|
425
|
+
* Sign up a new user with email or phone using a one-time password (OTP). If the account not exist, a new account will be created.
|
|
426
|
+
* @param params
|
|
427
|
+
* @returns Promise<SignUpRes>
|
|
478
428
|
*/
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
messages: [
|
|
482
|
-
'请确认以下各项:',
|
|
483
|
-
' 1 - 调用 auth().getVerification() 的语法或参数是否正确',
|
|
484
|
-
' 2 - 当前环境是否开通了手机验证码/邮箱登录',
|
|
485
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
486
|
-
],
|
|
487
|
-
})
|
|
488
|
-
public async getVerification(
|
|
489
|
-
params: authModels.GetVerificationRequest,
|
|
490
|
-
options?: { withCaptcha: boolean },
|
|
491
|
-
): Promise<authModels.GetVerificationResponse> {
|
|
492
|
-
if (params.phone_number) {
|
|
429
|
+
async signUp(params: authModels.SignUpRequest & { phone?: string }): Promise<SignUpRes> {
|
|
430
|
+
if (params.phone_number || params.verification_code || params.verification_token || params.provider_token) {
|
|
493
431
|
params.phone_number = this.formatPhone(params.phone_number)
|
|
432
|
+
await this.oauthInstance.authApi.signUp(params)
|
|
433
|
+
return this.createLoginState() as any
|
|
494
434
|
}
|
|
495
|
-
|
|
496
|
-
|
|
435
|
+
try {
|
|
436
|
+
// 参数校验:email或phone必填其一
|
|
437
|
+
this.validateAtLeastOne(params, [['email'], ['phone']], 'You must provide either an email or phone number')
|
|
497
438
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
*/
|
|
501
|
-
get currentUser() {
|
|
502
|
-
if (this.cache.mode === 'async') {
|
|
503
|
-
// async storage的平台调用此API提示
|
|
504
|
-
printWarn(
|
|
505
|
-
ERRORS.INVALID_OPERATION,
|
|
506
|
-
'current platform\'s storage is asynchronous, please use getCurrentUser instead',
|
|
507
|
-
)
|
|
508
|
-
return
|
|
509
|
-
}
|
|
439
|
+
// 第一步:发送验证码并存储 verificationInfo
|
|
440
|
+
const verificationInfo = await this.getVerification(params.email ? { email: params.email } : { phone_number: this.formatPhone(params.phone) },)
|
|
510
441
|
|
|
511
|
-
|
|
442
|
+
return {
|
|
443
|
+
data: {
|
|
444
|
+
// 第二步:等待用户输入验证码(通过 Promise 包装用户输入事件)
|
|
445
|
+
verifyOtp: async ({ token, messageId = verificationInfo.verification_id }): Promise<SignInRes> => {
|
|
446
|
+
try {
|
|
447
|
+
// 第三步:待用户输入完验证码之后,验证短信验证码
|
|
448
|
+
const verificationTokenRes = await this.verify({
|
|
449
|
+
verification_id: messageId || verificationInfo.verification_id,
|
|
450
|
+
verification_code: token,
|
|
451
|
+
})
|
|
512
452
|
|
|
513
|
-
|
|
514
|
-
|
|
453
|
+
// 第四步:注册并登录或直接登录
|
|
454
|
+
// 如果用户已经存在,直接登录
|
|
455
|
+
if (verificationInfo.is_user) {
|
|
456
|
+
await this.signIn({
|
|
457
|
+
username: params.email || this.formatPhone(params.phone),
|
|
458
|
+
verification_token: verificationTokenRes.verification_token,
|
|
459
|
+
})
|
|
460
|
+
} else {
|
|
461
|
+
// 如果用户不存在,注册用户
|
|
462
|
+
const data = JSON.parse(JSON.stringify(params))
|
|
463
|
+
delete data.email
|
|
464
|
+
delete data.phone
|
|
465
|
+
|
|
466
|
+
await this.oauthInstance.authApi.signUp({
|
|
467
|
+
...data,
|
|
468
|
+
...(params.email ? { email: params.email } : { phone_number: this.formatPhone(params.phone) }),
|
|
469
|
+
verification_token: verificationTokenRes.verification_token,
|
|
470
|
+
verification_code: token,
|
|
471
|
+
})
|
|
472
|
+
await this.createLoginState()
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const { data: { session } = {} } = await this.getSession()
|
|
476
|
+
|
|
477
|
+
return { data: { user: session.user, session }, error: null }
|
|
478
|
+
} catch (error) {
|
|
479
|
+
return { data: {}, error: new AuthError(error) }
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
error: null,
|
|
484
|
+
}
|
|
485
|
+
} catch (error) {
|
|
486
|
+
return { data: {}, error: new AuthError(error) }
|
|
515
487
|
}
|
|
516
|
-
return null
|
|
517
488
|
}
|
|
518
489
|
|
|
519
490
|
/**
|
|
520
|
-
*
|
|
491
|
+
* https://supabase.com/docs/reference/javascript/auth-signout
|
|
492
|
+
* const result = await auth.signOut();
|
|
493
|
+
*
|
|
494
|
+
* @param params
|
|
521
495
|
*/
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
496
|
+
async signOut(params?: authModels.SignoutRequest,): Promise<authModels.SignoutResponse & { data: Object; error: AuthError }> {
|
|
497
|
+
try {
|
|
498
|
+
const { userInfoKey } = this.cache.keys
|
|
499
|
+
const res = await this.oauthInstance.authApi.signOut(params)
|
|
500
|
+
await this.cache.removeStoreAsync(userInfoKey)
|
|
501
|
+
this.setAccessKey()
|
|
502
|
+
|
|
503
|
+
this.config.eventBus?.fire(EVENTS.LOGIN_STATE_CHANGED, { eventType: LOGIN_STATE_CHANGED_TYPE.SIGN_OUT })
|
|
504
|
+
|
|
505
|
+
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.SIGNED_OUT })
|
|
506
|
+
|
|
507
|
+
// res返回是为了兼容v2版本
|
|
508
|
+
return { ...res, data: {}, error: null }
|
|
509
|
+
} catch (error) {
|
|
510
|
+
return { data: {}, error: new AuthError(error) }
|
|
536
511
|
}
|
|
537
|
-
return null
|
|
538
512
|
}
|
|
539
513
|
|
|
540
|
-
// /**
|
|
541
|
-
// * 匿名登录
|
|
542
|
-
// * @returns {Promise<LoginState>}
|
|
543
|
-
// * @memberof Auth
|
|
544
|
-
// */
|
|
545
|
-
// @catchErrorsDecorator({
|
|
546
|
-
// title: '匿名登录失败',
|
|
547
|
-
// messages: [
|
|
548
|
-
// '请确认以下各项:',
|
|
549
|
-
// ' 1 - 当前环境是否开启了匿名登录',
|
|
550
|
-
// ' 2 - 调用 auth().signInAnonymously() 的语法或参数是否正确',
|
|
551
|
-
// `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
552
|
-
// ],
|
|
553
|
-
// })
|
|
554
|
-
// public async signInAnonymously(data: {
|
|
555
|
-
// provider_token?: string
|
|
556
|
-
// } = {},): Promise<LoginState> {
|
|
557
|
-
// await this.oauthInstance.authApi.signInAnonymously(data)
|
|
558
|
-
// return this.createLoginState()
|
|
559
|
-
// }
|
|
560
|
-
|
|
561
514
|
/**
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
* @
|
|
515
|
+
* https://supabase.com/docs/reference/javascript/auth-onauthstatechange
|
|
516
|
+
* Receive a notification every time an auth event happens.
|
|
517
|
+
* @param callback
|
|
518
|
+
* @returns Promise<{ data: { subscription: Subscription }, error: Error | null }>
|
|
565
519
|
*/
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
' 1 - 当前环境是否开启了匿名登录',
|
|
571
|
-
' 2 - 调用 auth().signInAnonymouslyInWx() 的语法或参数是否正确',
|
|
572
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
573
|
-
],
|
|
574
|
-
})
|
|
575
|
-
public async signInAnonymouslyInWx({
|
|
576
|
-
useWxCloud,
|
|
577
|
-
}: {
|
|
578
|
-
useWxCloud?: boolean
|
|
579
|
-
} = {}): Promise<LoginState> {
|
|
580
|
-
if (!adapterForWxMp.isMatch()) {
|
|
581
|
-
throw Error('wx api undefined')
|
|
520
|
+
onAuthStateChange(callback: OnAuthStateChangeCallback) {
|
|
521
|
+
if (!this.hasListenerSetUp) {
|
|
522
|
+
this.setupListeners()
|
|
523
|
+
this.hasListenerSetUp = true
|
|
582
524
|
}
|
|
583
|
-
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
584
525
|
|
|
585
|
-
const
|
|
586
|
-
let result: authModels.GrantProviderTokenResponse | undefined = undefined
|
|
587
|
-
let credentials: Credentials | undefined = undefined
|
|
526
|
+
const id = Math.random().toString(36)
|
|
588
527
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
provider_id: wxInfo?.appId,
|
|
593
|
-
provider_code: code,
|
|
594
|
-
provider_params: {
|
|
595
|
-
provider_code_type: 'open_id',
|
|
596
|
-
appid: wxInfo?.appId,
|
|
597
|
-
},
|
|
598
|
-
},
|
|
599
|
-
useWxCloud,
|
|
600
|
-
)
|
|
601
|
-
|
|
602
|
-
if ((result as any)?.error_code || !result.provider_token) {
|
|
603
|
-
throw result
|
|
604
|
-
}
|
|
528
|
+
if (!this.listeners.has(id)) {
|
|
529
|
+
this.listeners.set(id, new Set())
|
|
530
|
+
}
|
|
605
531
|
|
|
606
|
-
|
|
607
|
-
{ provider_token: result.provider_token },
|
|
608
|
-
useWxCloud,
|
|
609
|
-
)
|
|
532
|
+
this.listeners.get(id)!.add(callback)
|
|
610
533
|
|
|
611
|
-
|
|
612
|
-
|
|
534
|
+
// 返回 Subscription 对象
|
|
535
|
+
const subscription = {
|
|
536
|
+
id,
|
|
537
|
+
callback,
|
|
538
|
+
unsubscribe: () => {
|
|
539
|
+
const callbacks = this.listeners.get(id)
|
|
540
|
+
if (callbacks) {
|
|
541
|
+
callbacks.delete(callback)
|
|
542
|
+
if (callbacks.size === 0) {
|
|
543
|
+
this.listeners.delete(id)
|
|
544
|
+
}
|
|
613
545
|
}
|
|
614
|
-
}
|
|
615
|
-
throw error
|
|
616
|
-
}
|
|
546
|
+
},
|
|
617
547
|
}
|
|
618
548
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
try {
|
|
623
|
-
await mainFunc(res.code)
|
|
624
|
-
resolve(true)
|
|
625
|
-
} catch (error) {
|
|
626
|
-
reject(error)
|
|
627
|
-
}
|
|
628
|
-
},
|
|
629
|
-
fail: (res: any) => {
|
|
630
|
-
const error = new Error(res?.errMsg)
|
|
631
|
-
;(error as any).code = res?.errno
|
|
632
|
-
reject(error)
|
|
633
|
-
},
|
|
634
|
-
})
|
|
635
|
-
})
|
|
636
|
-
|
|
637
|
-
return this.createLoginState(undefined, { asyncRefreshUser: true })
|
|
549
|
+
return {
|
|
550
|
+
data: { subscription },
|
|
551
|
+
}
|
|
638
552
|
}
|
|
639
553
|
|
|
640
554
|
/**
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
* @
|
|
555
|
+
* https://supabase.com/docs/reference/javascript/auth-signinwithpassword
|
|
556
|
+
* Log in an existing user with an email and password or phone and password or username and password.
|
|
557
|
+
* @param params
|
|
558
|
+
* @returns Promise<SignInRes>
|
|
644
559
|
*/
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
throw Error('wx api undefined')
|
|
657
|
-
}
|
|
658
|
-
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
659
|
-
|
|
660
|
-
const mainFunc = async (code) => {
|
|
661
|
-
let result: authModels.GrantProviderTokenResponse | undefined = undefined
|
|
662
|
-
|
|
663
|
-
try {
|
|
664
|
-
result = await this.oauthInstance.authApi.grantProviderToken({
|
|
665
|
-
provider_id: wxInfo?.appId,
|
|
666
|
-
provider_code: code,
|
|
667
|
-
provider_params: {
|
|
668
|
-
provider_code_type: 'open_id',
|
|
669
|
-
appid: wxInfo?.appId,
|
|
670
|
-
},
|
|
671
|
-
})
|
|
560
|
+
async signInWithPassword(params: SignInWithPasswordReq): Promise<SignInRes> {
|
|
561
|
+
try {
|
|
562
|
+
// 参数校验:username/email/phone三选一,password必填
|
|
563
|
+
this.validateAtLeastOne(
|
|
564
|
+
params,
|
|
565
|
+
[['username'], ['email'], ['phone']],
|
|
566
|
+
'You must provide either username, email, or phone',
|
|
567
|
+
)
|
|
568
|
+
this.validateParams(params, {
|
|
569
|
+
password: { required: true, message: 'Password is required' },
|
|
570
|
+
})
|
|
672
571
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
572
|
+
await this.signIn({
|
|
573
|
+
username: params.username || params.email || this.formatPhone(params.phone),
|
|
574
|
+
password: params.password,
|
|
575
|
+
...(params.is_encrypt ? { isEncrypt: true, version: 'v2' } : {}),
|
|
576
|
+
})
|
|
577
|
+
const { data: { session } = {} } = await this.getSession()
|
|
676
578
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
579
|
+
return { data: { user: session.user, session }, error: null }
|
|
580
|
+
} catch (error) {
|
|
581
|
+
const authError = new AuthError(error)
|
|
582
|
+
// 优化错误提示:登录失败时提供更友好的排查指引
|
|
583
|
+
if (authError.message?.includes('密码不正确') || authError.message?.includes('password')) {
|
|
584
|
+
console.warn('[CloudBase Auth] 登录失败提示:\n'
|
|
585
|
+
+ ' 1. 请确认用户名/邮箱/手机号是否正确\n'
|
|
586
|
+
+ ' 2. 请确认密码是否正确\n'
|
|
587
|
+
+ ' 3. 如果用户不存在,请先通过 auth.signUp() 注册用户,或在云开发控制台手动创建用户\n'
|
|
588
|
+
+ ' 4. 确认当前环境已开启对应的登录方式(控制台 → 环境 → 登录授权)',)
|
|
680
589
|
}
|
|
590
|
+
return { data: {}, error: authError }
|
|
681
591
|
}
|
|
592
|
+
}
|
|
682
593
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
const error = new Error(res?.errMsg)
|
|
695
|
-
;(error as any).code = res?.errno
|
|
696
|
-
reject(error)
|
|
697
|
-
},
|
|
594
|
+
/**
|
|
595
|
+
* https://supabase.com/docs/reference/javascript/auth-signinwithidtoken
|
|
596
|
+
* 第三方平台登录。如果用户不存在,会根据云开发平台-登录方式中对应身份源的登录模式配置,判断是否自动注册
|
|
597
|
+
* @param params
|
|
598
|
+
* @returns Promise<SignInRes>
|
|
599
|
+
*/
|
|
600
|
+
async signInWithIdToken(params: SignInWithIdTokenReq): Promise<SignInRes> {
|
|
601
|
+
try {
|
|
602
|
+
// 参数校验:token必填
|
|
603
|
+
this.validateParams(params, {
|
|
604
|
+
token: { required: true, message: 'Token is required' },
|
|
698
605
|
})
|
|
699
|
-
})
|
|
700
606
|
|
|
701
|
-
|
|
607
|
+
await this.signInWithProvider({
|
|
608
|
+
provider_token: params.token,
|
|
609
|
+
})
|
|
610
|
+
const { data: { session } = {} } = await this.getSession()
|
|
611
|
+
|
|
612
|
+
return { data: { user: session.user, session }, error: null }
|
|
613
|
+
} catch (error) {
|
|
614
|
+
return { data: {}, error: new AuthError(error) }
|
|
615
|
+
}
|
|
702
616
|
}
|
|
703
617
|
|
|
704
618
|
/**
|
|
705
|
-
*
|
|
706
|
-
*
|
|
707
|
-
* @
|
|
619
|
+
* https://supabase.com/docs/reference/javascript/auth-signinwithotp
|
|
620
|
+
* Log in a user using a one-time password (OTP).
|
|
621
|
+
* @param params
|
|
622
|
+
* @returns Promise<SignInWithOtpRes>
|
|
708
623
|
*/
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
716
|
-
],
|
|
717
|
-
})
|
|
718
|
-
public async signInWithUnionId(): Promise<LoginState> {
|
|
719
|
-
if (!adapterForWxMp.isMatch()) {
|
|
720
|
-
throw Error('wx api undefined')
|
|
624
|
+
async signInWithOtp(params: SignInWithOtpReq): Promise<SignInWithOtpRes> {
|
|
625
|
+
if (params.options?.shouldCreateUser === undefined || !!params.options?.shouldCreateUser) {
|
|
626
|
+
return this.signUp({
|
|
627
|
+
email: params.email,
|
|
628
|
+
phone: params.phone,
|
|
629
|
+
})
|
|
721
630
|
}
|
|
722
|
-
try {
|
|
723
|
-
await new Promise((resolve, reject) => {
|
|
724
|
-
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
725
|
-
wx.login({
|
|
726
|
-
success: async (res: { code: string }) => {
|
|
727
|
-
const providerId = wxInfo?.appId
|
|
728
|
-
try {
|
|
729
|
-
const result = await this.oauthInstance.authApi.grantProviderToken({
|
|
730
|
-
provider_code: res.code,
|
|
731
|
-
provider_id: providerId,
|
|
732
|
-
provider_params: {
|
|
733
|
-
provider_code_type: 'union_id',
|
|
734
|
-
appid: wxInfo?.appId,
|
|
735
|
-
},
|
|
736
|
-
})
|
|
737
|
-
|
|
738
|
-
const { provider_token: providerToken } = result
|
|
739
631
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
}
|
|
632
|
+
try {
|
|
633
|
+
// 参数校验:email或phone必填其一
|
|
634
|
+
this.validateAtLeastOne(params, [['email'], ['phone']], 'You must provide either an email or phone number')
|
|
744
635
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
provider_token: providerToken,
|
|
748
|
-
})
|
|
636
|
+
// 第一步:发送验证码并存储 verificationInfo
|
|
637
|
+
const verificationInfo = await this.getVerification(params.email ? { email: params.email } : { phone_number: this.formatPhone(params.phone) },)
|
|
749
638
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
})
|
|
765
|
-
})
|
|
639
|
+
return {
|
|
640
|
+
data: {
|
|
641
|
+
user: null,
|
|
642
|
+
session: null,
|
|
643
|
+
// 第二步:等待用户输入验证码(通过 Promise 包装用户输入事件)
|
|
644
|
+
verifyOtp: async ({ token, messageId = verificationInfo.verification_id }): Promise<SignInRes> => this.verifyOtp({
|
|
645
|
+
email: params.email,
|
|
646
|
+
phone: params.phone,
|
|
647
|
+
token,
|
|
648
|
+
messageId,
|
|
649
|
+
}),
|
|
650
|
+
},
|
|
651
|
+
error: null,
|
|
652
|
+
}
|
|
766
653
|
} catch (error) {
|
|
767
|
-
|
|
654
|
+
return { data: {}, error: new AuthError(error) }
|
|
768
655
|
}
|
|
769
|
-
|
|
770
|
-
return this.createLoginState()
|
|
771
656
|
}
|
|
772
657
|
|
|
773
658
|
/**
|
|
774
|
-
*
|
|
775
|
-
* @
|
|
776
|
-
* @
|
|
659
|
+
* 校验第三方平台授权登录回调
|
|
660
|
+
* @param params
|
|
661
|
+
* @returns Promise<SignInRes>
|
|
777
662
|
*/
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
messages: [
|
|
781
|
-
'请确认以下各项:',
|
|
782
|
-
' 1 - 当前环境是否开启了小程序短信验证码登陆',
|
|
783
|
-
' 2 - 调用 auth().signInWithSms() 的语法或参数是否正确',
|
|
784
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
785
|
-
],
|
|
786
|
-
})
|
|
787
|
-
public async signInWithSms({
|
|
788
|
-
verificationInfo = { verification_id: '', is_user: false },
|
|
789
|
-
verificationCode = '',
|
|
790
|
-
phoneNum = '',
|
|
791
|
-
bindInfo = undefined,
|
|
792
|
-
}): Promise<LoginState> {
|
|
663
|
+
async verifyOAuth(params?: VerifyOAuthReq): Promise<VerifyOAuthRes> {
|
|
664
|
+
const data: any = {}
|
|
793
665
|
try {
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
bindInfo,
|
|
798
|
-
username: phoneNum,
|
|
799
|
-
loginType: 'sms',
|
|
800
|
-
})
|
|
801
|
-
} catch (error) {
|
|
802
|
-
throw error
|
|
803
|
-
}
|
|
804
|
-
}
|
|
666
|
+
// 回调至 provider_redirect_uri 地址(url query中携带 授权code,state等参数),此时检查 state 是否符合预期(如 自己设置的 wx_open)
|
|
667
|
+
const code = params?.code || utils.getQuery('code')
|
|
668
|
+
const state = params?.state || utils.getQuery('state')
|
|
805
669
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
*/
|
|
811
|
-
@catchErrorsDecorator({
|
|
812
|
-
title: '邮箱验证码登陆',
|
|
813
|
-
messages: [
|
|
814
|
-
'请确认以下各项:',
|
|
815
|
-
' 1 - 当前环境是否开启了邮箱登陆',
|
|
816
|
-
' 2 - 调用 auth().signInWithEmail() 的语法或参数是否正确',
|
|
817
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
818
|
-
],
|
|
819
|
-
})
|
|
820
|
-
public async signInWithEmail({
|
|
821
|
-
verificationInfo = { verification_id: '', is_user: false },
|
|
822
|
-
verificationCode = '',
|
|
823
|
-
bindInfo = undefined,
|
|
824
|
-
email = '',
|
|
825
|
-
}): Promise<LoginState> {
|
|
826
|
-
try {
|
|
827
|
-
return this.signInWithUsername({
|
|
828
|
-
verificationInfo,
|
|
829
|
-
verificationCode,
|
|
830
|
-
bindInfo,
|
|
831
|
-
username: email,
|
|
832
|
-
loginType: 'email',
|
|
833
|
-
})
|
|
834
|
-
} catch (error) {
|
|
835
|
-
throw error
|
|
836
|
-
}
|
|
837
|
-
}
|
|
670
|
+
// 参数校验:code和state必填
|
|
671
|
+
if (!code) {
|
|
672
|
+
return { data: {}, error: new AuthError({ message: 'Code is required' }) }
|
|
673
|
+
}
|
|
838
674
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
* @memberof Auth
|
|
843
|
-
*/
|
|
844
|
-
public setCustomSignFunc(getTickFn: authModels.GetCustomSignTicketFn): void {
|
|
845
|
-
this.oauthInstance.authApi.setCustomSignFunc(getTickFn)
|
|
846
|
-
}
|
|
675
|
+
if (!state) {
|
|
676
|
+
return { data: {}, error: new AuthError({ message: 'State is required' }) }
|
|
677
|
+
}
|
|
847
678
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
* @returns {Promise<LoginState>}
|
|
851
|
-
* @memberof Auth
|
|
852
|
-
*/
|
|
853
|
-
// @catchErrorsDecorator({
|
|
854
|
-
// title: '自定义登录失败',
|
|
855
|
-
// messages: [
|
|
856
|
-
// '请确认以下各项:',
|
|
857
|
-
// ' 1 - 当前环境是否开启了自定义登录',
|
|
858
|
-
// ' 2 - 调用 auth().signInWithCustomTicket() 的语法或参数是否正确',
|
|
859
|
-
// ' 3 - ticket 是否归属于当前环境',
|
|
860
|
-
// ' 4 - 创建 ticket 的自定义登录私钥是否过期',
|
|
861
|
-
// `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
862
|
-
// ],
|
|
863
|
-
// })
|
|
864
|
-
// public async signInWithCustomTicket(): Promise<LoginState> {
|
|
865
|
-
// await this.oauthInstance.authApi.signInWithCustomTicket()
|
|
866
|
-
// return this.createLoginState()
|
|
867
|
-
// }
|
|
679
|
+
const cacheData = getBrowserSession(state)
|
|
680
|
+
data.type = cacheData?.type
|
|
868
681
|
|
|
869
|
-
|
|
870
|
-
*
|
|
871
|
-
* @param {authModels.SignInRequest} params
|
|
872
|
-
* @returns {Promise<LoginState>}
|
|
873
|
-
* @memberof Auth
|
|
874
|
-
*/
|
|
875
|
-
public async signIn(params: authModels.SignInRequest): Promise<LoginState> {
|
|
876
|
-
await this.oauthInstance.authApi.signIn(params)
|
|
877
|
-
return this.createLoginState(params)
|
|
878
|
-
}
|
|
682
|
+
const provider = params?.provider || cacheData?.provider || utils.getQuery('provider')
|
|
879
683
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
// * @returns {Promise<LoginState>}
|
|
884
|
-
// * @memberof Auth
|
|
885
|
-
// */
|
|
886
|
-
// @catchErrorsDecorator({
|
|
887
|
-
// title: '注册失败',
|
|
888
|
-
// messages: [
|
|
889
|
-
// '请确认以下各项:',
|
|
890
|
-
// ' 1 - 当前环境是否开启了指定登录方式',
|
|
891
|
-
// ' 2 - 调用 auth().signUp() 的语法或参数是否正确',
|
|
892
|
-
// `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
893
|
-
// ],
|
|
894
|
-
// })
|
|
895
|
-
// public async signUp(params: authModels.SignUpRequest): Promise<any> {
|
|
896
|
-
// await this.oauthInstance.authApi.signUp(params)
|
|
897
|
-
// return this.createLoginState()
|
|
898
|
-
// }
|
|
684
|
+
if (!provider) {
|
|
685
|
+
return { data, error: new AuthError({ message: 'Provider is required' }) }
|
|
686
|
+
}
|
|
899
687
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
public async setPassword(params: authModels.SetPasswordRequest): Promise<void> {
|
|
907
|
-
return this.oauthInstance.authApi.setPassword(params)
|
|
908
|
-
}
|
|
688
|
+
// state符合预期,则获取该三方平台token
|
|
689
|
+
const { provider_token: token } = await this.grantProviderToken({
|
|
690
|
+
provider_id: provider,
|
|
691
|
+
provider_redirect_uri: location.origin + location.pathname, // 指定三方平台跳回的 url 地址
|
|
692
|
+
provider_code: code, // 第三方平台跳转回页面时,url param 中携带的 code 参数
|
|
693
|
+
})
|
|
909
694
|
|
|
910
|
-
|
|
911
|
-
* 检测用户名是否已经占用
|
|
912
|
-
* @param username
|
|
913
|
-
*/
|
|
914
|
-
@catchErrorsDecorator({
|
|
915
|
-
title: '获取用户是否被占用失败',
|
|
916
|
-
messages: [
|
|
917
|
-
'请确认以下各项:',
|
|
918
|
-
' 1 - 调用 auth().isUsernameRegistered() 的语法或参数是否正确',
|
|
919
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
920
|
-
],
|
|
921
|
-
})
|
|
922
|
-
public async isUsernameRegistered(username: string): Promise<boolean> {
|
|
923
|
-
if (typeof username !== 'string') {
|
|
924
|
-
throwError(ERRORS.INVALID_PARAMS, 'username must be a string')
|
|
925
|
-
}
|
|
695
|
+
let res: VerifyOAuthRes
|
|
926
696
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
697
|
+
if (cacheData.type === OAUTH_TYPE.BIND_IDENTITY) {
|
|
698
|
+
res = await this.oauthInstance.authApi.toBindIdentity({ provider_token: token, provider, fireEvent: true })
|
|
699
|
+
} else {
|
|
700
|
+
// 通过 provider_token 仅登录或登录并注册(与云开发平台-登录方式-身份源登录模式配置有关)
|
|
701
|
+
res = await this.signInWithIdToken({
|
|
702
|
+
token,
|
|
703
|
+
})
|
|
704
|
+
res.data = { ...data, ...res.data }
|
|
705
|
+
}
|
|
930
706
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
printWarn(
|
|
938
|
-
ERRORS.INVALID_OPERATION,
|
|
939
|
-
'current platform\'s storage is asynchronous, please use getLoginState instead',
|
|
707
|
+
const localSearch = new URLSearchParams(location?.search)
|
|
708
|
+
localSearch.delete('code')
|
|
709
|
+
localSearch.delete('state')
|
|
710
|
+
res.data.redirectUrl = addUrlSearch(
|
|
711
|
+
cacheData?.search === undefined ? `?${localSearch.toString()}` : cacheData?.search,
|
|
712
|
+
cacheData?.hash || location.hash,
|
|
940
713
|
)
|
|
941
|
-
|
|
942
|
-
}
|
|
714
|
+
removeBrowserSession(state)
|
|
943
715
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
envId: this.config.env,
|
|
948
|
-
cache: this.cache,
|
|
949
|
-
oauthInstance: this.oauthInstance,
|
|
950
|
-
})
|
|
951
|
-
return loginState
|
|
716
|
+
return res
|
|
717
|
+
} catch (error) {
|
|
718
|
+
return { data, error: new AuthError(error) }
|
|
952
719
|
}
|
|
953
|
-
return null
|
|
954
720
|
}
|
|
955
721
|
|
|
956
722
|
/**
|
|
957
|
-
*
|
|
958
|
-
*
|
|
723
|
+
* https://supabase.com/docs/reference/javascript/auth-signinwithoauth
|
|
724
|
+
* 生成第三方平台授权 Uri (如微信二维码扫码授权网页)
|
|
725
|
+
* @param params
|
|
726
|
+
* @returns Promise<SignInOAuthRes>
|
|
959
727
|
*/
|
|
960
|
-
|
|
961
|
-
title: '获取本地登录态失败',
|
|
962
|
-
messages: [
|
|
963
|
-
'请确认以下各项:',
|
|
964
|
-
' 1 - 调用 auth().getLoginState() 的语法或参数是否正确',
|
|
965
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
966
|
-
],
|
|
967
|
-
})
|
|
968
|
-
public async getLoginState() {
|
|
969
|
-
let oauthLoginState = null
|
|
970
|
-
|
|
728
|
+
async signInWithOAuth(params: SignInWithOAuthReq): Promise<SignInOAuthRes> {
|
|
971
729
|
try {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
if (oauthLoginState) {
|
|
978
|
-
const loginState = new LoginState({
|
|
979
|
-
envId: this.config.env,
|
|
980
|
-
cache: this.cache,
|
|
981
|
-
oauthInstance: this.oauthInstance,
|
|
730
|
+
// 参数校验:provider必填
|
|
731
|
+
this.validateParams(params, {
|
|
732
|
+
provider: { required: true, message: 'Provider is required' },
|
|
982
733
|
})
|
|
983
|
-
return loginState
|
|
984
|
-
}
|
|
985
734
|
|
|
986
|
-
|
|
987
|
-
}
|
|
735
|
+
const href = params.options?.redirectTo || location.href
|
|
988
736
|
|
|
989
|
-
|
|
990
|
-
* @deprecated 使用 getCurrentUser 代替,因为与node-sdk方法名冲突
|
|
991
|
-
* @returns
|
|
992
|
-
*/
|
|
993
|
-
@catchErrorsDecorator({
|
|
994
|
-
title: '获取用户信息失败',
|
|
995
|
-
messages: [
|
|
996
|
-
'请确认以下各项:',
|
|
997
|
-
' 1 - 是否已登录',
|
|
998
|
-
' 2 - 调用 auth().getUserInfo() 的语法或参数是否正确',
|
|
999
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1000
|
-
],
|
|
1001
|
-
})
|
|
1002
|
-
public async getUserInfo(): Promise<(authModels.UserInfo & Partial<User>) | null> {
|
|
1003
|
-
return this.getCurrentUser()
|
|
1004
|
-
}
|
|
737
|
+
const urlObject = new URL(href)
|
|
1005
738
|
|
|
1006
|
-
|
|
1007
|
-
title: '获取微搭插件用户信息失败',
|
|
1008
|
-
messages: [
|
|
1009
|
-
'请确认以下各项:',
|
|
1010
|
-
' 1 - 是否已登录',
|
|
1011
|
-
' 2 - 调用 auth().getWedaUserInfo() 的语法或参数是否正确',
|
|
1012
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1013
|
-
],
|
|
1014
|
-
})
|
|
1015
|
-
public async getWedaUserInfo(): Promise<any> {
|
|
1016
|
-
return this.oauthInstance.authApi.getWedaUserInfo()
|
|
1017
|
-
}
|
|
739
|
+
const provider_redirect_uri = urlObject.origin + urlObject.pathname
|
|
1018
740
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
if (loginState) {
|
|
1022
|
-
await (loginState.user as User).updateUserBasicInfo(params)
|
|
1023
|
-
}
|
|
1024
|
-
return
|
|
1025
|
-
}
|
|
741
|
+
const state = params.options?.state || `prd-${params.provider}-${Math.random().toString(36)
|
|
742
|
+
.slice(2)}`
|
|
1026
743
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
console.error('Auth.getAuthHeader API 已废弃')
|
|
1033
|
-
return {}
|
|
1034
|
-
}
|
|
744
|
+
const { uri } = await this.genProviderRedirectUri({
|
|
745
|
+
provider_id: params.provider,
|
|
746
|
+
provider_redirect_uri,
|
|
747
|
+
state,
|
|
748
|
+
})
|
|
1035
749
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
* @param {authModels.BindWithProviderRequest} params
|
|
1039
|
-
* @returns {Promise<void>}
|
|
1040
|
-
* @memberof Auth
|
|
1041
|
-
*/
|
|
1042
|
-
@catchErrorsDecorator({
|
|
1043
|
-
title: '绑定第三方登录方式失败',
|
|
1044
|
-
messages: [
|
|
1045
|
-
'请确认以下各项:',
|
|
1046
|
-
' 1 - 调用 auth().bindWithProvider() 的语法或参数是否正确',
|
|
1047
|
-
' 2 - 此账户是否已经绑定此第三方',
|
|
1048
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1049
|
-
],
|
|
1050
|
-
})
|
|
1051
|
-
public async bindWithProvider(params: authModels.BindWithProviderRequest): Promise<void> {
|
|
1052
|
-
return this.oauthInstance.authApi.bindWithProvider(params)
|
|
1053
|
-
}
|
|
750
|
+
// 对 URL 进行解码
|
|
751
|
+
const decodedUri = decodeURIComponent(uri)
|
|
1054
752
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
* @param {authModels.QueryUserProfileRequest} appended_params
|
|
1058
|
-
* @returns {Promise<authModels.UserProfile>}
|
|
1059
|
-
* @memberof Auth
|
|
1060
|
-
*/
|
|
1061
|
-
public async queryUser(queryObj: authModels.QueryUserProfileRequest): Promise<authModels.QueryUserProfileResponse> {
|
|
1062
|
-
return this.oauthInstance.authApi.queryUserProfile(queryObj)
|
|
1063
|
-
}
|
|
753
|
+
// 合并额外的查询参数
|
|
754
|
+
let finalUri = decodedUri
|
|
1064
755
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
756
|
+
if (params.options?.queryParams) {
|
|
757
|
+
const url = new URL(decodedUri)
|
|
758
|
+
Object.entries(params.options.queryParams).forEach(([key, value]) => {
|
|
759
|
+
url.searchParams.set(key, value)
|
|
760
|
+
})
|
|
761
|
+
finalUri = url.toString()
|
|
762
|
+
}
|
|
1072
763
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
764
|
+
saveToBrowserSession(state, {
|
|
765
|
+
provider: params.provider,
|
|
766
|
+
search: urlObject.search,
|
|
767
|
+
hash: urlObject.hash,
|
|
768
|
+
type: params.options?.type || OAUTH_TYPE.SIGN_IN,
|
|
769
|
+
})
|
|
1076
770
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
771
|
+
if (isBrowser() && !params.options?.skipBrowserRedirect) {
|
|
772
|
+
window.location.assign(finalUri)
|
|
773
|
+
}
|
|
1080
774
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
775
|
+
return { data: { url: finalUri, provider: params.provider }, error: null }
|
|
776
|
+
} catch (error) {
|
|
777
|
+
return { data: {}, error: new AuthError(error) }
|
|
778
|
+
}
|
|
1084
779
|
}
|
|
1085
780
|
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
781
|
+
// https://supabase.com/docs/reference/javascript/auth-getclaims
|
|
782
|
+
async getClaims(): Promise<GetClaimsRes> {
|
|
783
|
+
try {
|
|
784
|
+
const { accessToken } = await this.getAccessToken()
|
|
785
|
+
const parsedToken = weAppJwtDecodeAll(accessToken)
|
|
786
|
+
return { data: parsedToken, error: null }
|
|
787
|
+
} catch (error) {
|
|
788
|
+
return { data: {}, error: new AuthError(error) }
|
|
789
|
+
}
|
|
1089
790
|
}
|
|
1090
791
|
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
792
|
+
/**
|
|
793
|
+
* https://supabase.com/docs/reference/javascript/auth-resetpasswordforemail
|
|
794
|
+
* 通过 email 或手机号重置密码
|
|
795
|
+
* @param emailOrPhone 邮箱或手机号
|
|
796
|
+
* @returns Promise<ResetPasswordForEmailRes>
|
|
797
|
+
*/
|
|
798
|
+
async resetPasswordForEmail(
|
|
799
|
+
emailOrPhone: string,
|
|
800
|
+
options?: { redirectTo?: string },
|
|
801
|
+
): Promise<ResetPasswordForEmailRes> {
|
|
802
|
+
try {
|
|
803
|
+
// 参数校验:emailOrPhone必填
|
|
804
|
+
this.validateParams(
|
|
805
|
+
{ emailOrPhone },
|
|
806
|
+
{
|
|
807
|
+
emailOrPhone: { required: true, message: 'Email or phone is required' },
|
|
808
|
+
},
|
|
809
|
+
)
|
|
1095
810
|
|
|
1096
|
-
|
|
1097
|
-
return this.oauthInstance.authApi.genProviderRedirectUri(params)
|
|
1098
|
-
}
|
|
811
|
+
const { redirectTo } = options || {}
|
|
1099
812
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
813
|
+
// 判断是邮箱还是手机号
|
|
814
|
+
const isEmail = emailOrPhone.includes('@')
|
|
815
|
+
let verificationParams: { email?: string; phone_number?: string }
|
|
1103
816
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
817
|
+
if (isEmail) {
|
|
818
|
+
verificationParams = { email: emailOrPhone }
|
|
819
|
+
} else {
|
|
820
|
+
// 正规化手机号
|
|
821
|
+
const formattedPhone = this.formatPhone(emailOrPhone)
|
|
822
|
+
verificationParams = { phone_number: formattedPhone }
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// 第一步:发送验证码并存储 verificationInfo
|
|
826
|
+
const verificationInfo = await this.getVerification(verificationParams)
|
|
1107
827
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
828
|
+
return {
|
|
829
|
+
data: {
|
|
830
|
+
// 第二步:等待用户输入验证码(通过 Promise 包装用户输入事件)
|
|
831
|
+
updateUser: async (attributes: UpdateUserAttributes): Promise<SignInRes> => {
|
|
832
|
+
this.validateParams(attributes, {
|
|
833
|
+
nonce: { required: true, message: 'Nonce is required' },
|
|
834
|
+
password: { required: true, message: 'Password is required' },
|
|
835
|
+
})
|
|
836
|
+
try {
|
|
837
|
+
// 第三步:待用户输入完验证码之后,验证验证码
|
|
838
|
+
const verificationTokenRes = await this.verify({
|
|
839
|
+
verification_id: verificationInfo.verification_id,
|
|
840
|
+
verification_code: attributes.nonce,
|
|
841
|
+
})
|
|
1111
842
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
843
|
+
await this.oauthInstance.authApi.resetPassword({
|
|
844
|
+
email: isEmail ? emailOrPhone : undefined,
|
|
845
|
+
phone_number: !isEmail ? emailOrPhone : undefined,
|
|
846
|
+
new_password: attributes.password,
|
|
847
|
+
verification_token: verificationTokenRes.verification_token,
|
|
848
|
+
})
|
|
1115
849
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
850
|
+
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, {
|
|
851
|
+
event: AUTH_STATE_CHANGED_TYPE.PASSWORD_RECOVERY,
|
|
852
|
+
})
|
|
1119
853
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
854
|
+
const res = await this.signInWithPassword({
|
|
855
|
+
email: isEmail ? emailOrPhone : undefined,
|
|
856
|
+
phone: !isEmail ? emailOrPhone : undefined,
|
|
857
|
+
password: attributes.password,
|
|
858
|
+
})
|
|
1123
859
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
860
|
+
if (redirectTo && isBrowser()) {
|
|
861
|
+
window.location.assign(redirectTo)
|
|
862
|
+
}
|
|
1127
863
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
864
|
+
return res
|
|
865
|
+
} catch (error) {
|
|
866
|
+
return { data: {}, error: new AuthError(error) }
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
},
|
|
870
|
+
error: null,
|
|
871
|
+
}
|
|
872
|
+
} catch (error) {
|
|
873
|
+
return { data: {}, error: new AuthError(error) }
|
|
874
|
+
}
|
|
1137
875
|
}
|
|
1138
876
|
|
|
1139
|
-
// v1 兼容 API 方法已移至 AuthV1Compat 基类 (v1-compat.ts)
|
|
1140
|
-
|
|
1141
877
|
/**
|
|
1142
|
-
*
|
|
1143
|
-
* @param
|
|
878
|
+
* 通过旧密码重置密码
|
|
879
|
+
* @param new_password
|
|
880
|
+
* @param old_password
|
|
1144
881
|
* @returns
|
|
1145
882
|
*/
|
|
1146
|
-
|
|
1147
|
-
|
|
883
|
+
async resetPasswordForOld(params: ResetPasswordForOldReq) {
|
|
884
|
+
try {
|
|
885
|
+
await this.oauthInstance.authApi.updatePasswordByOld({
|
|
886
|
+
old_password: params.old_password,
|
|
887
|
+
new_password: params.new_password,
|
|
888
|
+
})
|
|
889
|
+
|
|
890
|
+
const { data: { session } = {} } = await this.getSession()
|
|
891
|
+
|
|
892
|
+
return { data: { user: session.user, session }, error: null }
|
|
893
|
+
} catch (error) {
|
|
894
|
+
return { data: {}, error: new AuthError(error) }
|
|
895
|
+
}
|
|
1148
896
|
}
|
|
1149
897
|
|
|
1150
898
|
/**
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
899
|
+
* https://supabase.com/docs/reference/javascript/auth-verifyotp
|
|
900
|
+
* Log in a user given a User supplied OTP and verificationId received through mobile or email.
|
|
901
|
+
* @param params
|
|
902
|
+
* @returns Promise<SignInRes>
|
|
1153
903
|
*/
|
|
1154
|
-
|
|
1155
|
-
|
|
904
|
+
async verifyOtp(params: VerifyOtpReq): Promise<SignInRes> {
|
|
905
|
+
try {
|
|
906
|
+
const { type } = params
|
|
907
|
+
// 参数校验:token和verificationInfo必填
|
|
908
|
+
this.validateParams(params, {
|
|
909
|
+
token: { required: true, message: 'Token is required' },
|
|
910
|
+
messageId: { required: true, message: 'messageId is required' },
|
|
911
|
+
})
|
|
912
|
+
|
|
913
|
+
if (['phone_change', 'email_change'].includes(type)) {
|
|
914
|
+
await this.verify({
|
|
915
|
+
verification_id: params.messageId,
|
|
916
|
+
verification_code: params.token,
|
|
917
|
+
})
|
|
918
|
+
} else {
|
|
919
|
+
await this.signInWithUsername({
|
|
920
|
+
verificationInfo: { verification_id: params.messageId, is_user: true },
|
|
921
|
+
verificationCode: params.token,
|
|
922
|
+
username: params.email || this.formatPhone(params.phone) || '',
|
|
923
|
+
loginType: params.email ? 'email' : 'phone',
|
|
924
|
+
})
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
const { data: { session } = {} } = await this.getSession()
|
|
928
|
+
|
|
929
|
+
return { data: { user: session.user, session }, error: null }
|
|
930
|
+
} catch (error) {
|
|
931
|
+
return { data: {}, error: new AuthError(error) }
|
|
932
|
+
}
|
|
1156
933
|
}
|
|
934
|
+
|
|
1157
935
|
/**
|
|
1158
|
-
*
|
|
936
|
+
* https://supabase.com/docs/reference/javascript/auth-getSession
|
|
937
|
+
* Returns the session, refreshing it if necessary.
|
|
938
|
+
* @returns Promise<SignInRes>
|
|
1159
939
|
*/
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
940
|
+
async getSession(): Promise<SignInRes> {
|
|
941
|
+
try {
|
|
942
|
+
const credentials: Credentials = await this.oauthInstance.oauth2client.getCredentials()
|
|
1163
943
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
'请确认以下各项:',
|
|
1168
|
-
' 1 - 调用 auth().getProviderSubType() 的语法或参数是否正确',
|
|
1169
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1170
|
-
],
|
|
1171
|
-
})
|
|
1172
|
-
public async getProviderSubType(): Promise<authModels.ProviderSubType> {
|
|
1173
|
-
return this.oauthInstance.authApi.getProviderSubType()
|
|
1174
|
-
}
|
|
944
|
+
if (!credentials || credentials.scope === 'accessKey') {
|
|
945
|
+
return { data: { session: null }, error: null }
|
|
946
|
+
}
|
|
1175
947
|
|
|
1176
|
-
|
|
1177
|
-
return this.oauthInstance.authApi.createCaptchaData(params)
|
|
1178
|
-
}
|
|
948
|
+
const { data: { user } = {} } = await this.getUser()
|
|
1179
949
|
|
|
1180
|
-
|
|
1181
|
-
|
|
950
|
+
return { data: { session: { ...credentials, user }, user }, error: null }
|
|
951
|
+
} catch (error) {
|
|
952
|
+
return { data: {}, error: new AuthError(error) }
|
|
953
|
+
}
|
|
1182
954
|
}
|
|
1183
955
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
956
|
+
/**
|
|
957
|
+
* https://supabase.com/docs/reference/javascript/auth-refreshsession
|
|
958
|
+
* 无论过期状态如何,都返回一个新的会话
|
|
959
|
+
* @param refresh_token
|
|
960
|
+
* @returns Promise<SignInRes>
|
|
961
|
+
*/
|
|
962
|
+
async refreshSession(refresh_token?: string): Promise<SignInRes> {
|
|
963
|
+
try {
|
|
964
|
+
const credentials: Credentials = await this.oauthInstance.oauth2client.localCredentials.getCredentials()
|
|
965
|
+
credentials.refresh_token = refresh_token || credentials.refresh_token
|
|
966
|
+
const newTokens = await this.oauthInstance.oauth2client.refreshToken(credentials)
|
|
967
|
+
const { data: { user } = {} } = await this.getUser()
|
|
1187
968
|
|
|
1188
|
-
|
|
1189
|
-
|
|
969
|
+
return { data: { user, session: { ...newTokens, user } }, error: null }
|
|
970
|
+
} catch (error) {
|
|
971
|
+
return { data: {}, error: new AuthError(error) }
|
|
972
|
+
}
|
|
1190
973
|
}
|
|
1191
974
|
|
|
1192
|
-
|
|
1193
|
-
|
|
975
|
+
/**
|
|
976
|
+
* https://supabase.com/docs/reference/javascript/auth-getuser
|
|
977
|
+
* 如果存在现有会话,则获取当前用户详细信息
|
|
978
|
+
* @returns Promise<GetUserRes>
|
|
979
|
+
*/
|
|
980
|
+
async getUser(): Promise<GetUserRes> {
|
|
981
|
+
try {
|
|
982
|
+
const user = this.convertToUser(await this.getCurrentUser())
|
|
983
|
+
return { data: { user }, error: null }
|
|
984
|
+
} catch (error) {
|
|
985
|
+
return { data: {}, error: new AuthError(error) }
|
|
986
|
+
}
|
|
1194
987
|
}
|
|
1195
988
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
989
|
+
/**
|
|
990
|
+
* 刷新用户信息
|
|
991
|
+
* @returns Promise<CommonRes>
|
|
992
|
+
*/
|
|
993
|
+
async refreshUser(): Promise<CommonRes> {
|
|
994
|
+
try {
|
|
995
|
+
await this.currentUser.refresh()
|
|
1199
996
|
|
|
1200
|
-
|
|
1201
|
-
|
|
997
|
+
const { data: { session } = {} } = await this.getSession()
|
|
998
|
+
return { data: { user: session.user, session }, error: null }
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
return { data: {}, error: new AuthError(error) }
|
|
1001
|
+
}
|
|
1202
1002
|
}
|
|
1203
1003
|
|
|
1204
1004
|
/**
|
|
1205
|
-
*
|
|
1005
|
+
* https://supabase.com/docs/reference/javascript/auth-updateuser
|
|
1006
|
+
* 更新用户信息
|
|
1007
|
+
* @param params
|
|
1008
|
+
* @returns Promise<GetUserRes | UpdateUserWithVerificationRes>
|
|
1206
1009
|
*/
|
|
1207
|
-
|
|
1208
|
-
verificationInfo = { verification_id: '', is_user: false },
|
|
1209
|
-
verificationCode = '',
|
|
1210
|
-
username: rawUsername = '',
|
|
1211
|
-
bindInfo = undefined,
|
|
1212
|
-
loginType = '',
|
|
1213
|
-
}: {
|
|
1214
|
-
verificationInfo?: authModels.GetVerificationResponse
|
|
1215
|
-
verificationCode?: string
|
|
1216
|
-
username?: string
|
|
1217
|
-
bindInfo?: any
|
|
1218
|
-
loginType?: string
|
|
1219
|
-
}): Promise<LoginState> {
|
|
1010
|
+
async updateUser(params: UpdateUserReq): Promise<GetUserRes | UpdateUserWithVerificationRes> {
|
|
1220
1011
|
try {
|
|
1221
|
-
//
|
|
1222
|
-
const
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
})
|
|
1226
|
-
|
|
1227
|
-
if ((verifyRes as any)?.error_code) {
|
|
1228
|
-
throw verifyRes
|
|
1012
|
+
// 参数校验:至少有一个更新字段被提供
|
|
1013
|
+
const hasValue = Object.keys(params).some(key => params[key] !== undefined && params[key] !== null && params[key] !== '',)
|
|
1014
|
+
if (!hasValue) {
|
|
1015
|
+
throw new AuthError({ message: 'At least one field must be provided for update' })
|
|
1229
1016
|
}
|
|
1230
1017
|
|
|
1231
|
-
|
|
1232
|
-
const { verification_token } = verifyRes
|
|
1018
|
+
const { email, phone, ...restParams } = params
|
|
1233
1019
|
|
|
1234
|
-
//
|
|
1235
|
-
|
|
1236
|
-
|
|
1020
|
+
// 检查是否需要更新 email 或 phone
|
|
1021
|
+
const needsEmailVerification = email !== undefined
|
|
1022
|
+
const needsPhoneVerification = phone !== undefined
|
|
1237
1023
|
|
|
1238
|
-
|
|
1239
|
-
if (loginType === 'email') {
|
|
1240
|
-
username = rawUsername
|
|
1241
|
-
signUpParam = { email: username }
|
|
1242
|
-
}
|
|
1024
|
+
let extraRes = {}
|
|
1243
1025
|
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
username,
|
|
1249
|
-
verification_token,
|
|
1250
|
-
})
|
|
1026
|
+
if (needsEmailVerification || needsPhoneVerification) {
|
|
1027
|
+
// 需要发送验证码
|
|
1028
|
+
let verificationParams: { email?: string; phone_number?: string }
|
|
1029
|
+
let verificationType: 'email_change' | 'phone_change'
|
|
1251
1030
|
|
|
1252
|
-
if (
|
|
1253
|
-
|
|
1031
|
+
if (needsEmailVerification) {
|
|
1032
|
+
verificationParams = { email: params.email }
|
|
1033
|
+
verificationType = 'email_change'
|
|
1034
|
+
} else {
|
|
1035
|
+
// 正规化手机号
|
|
1036
|
+
const formattedPhone = this.formatPhone(params.phone)
|
|
1037
|
+
verificationParams = { phone_number: formattedPhone }
|
|
1038
|
+
verificationType = 'phone_change'
|
|
1254
1039
|
}
|
|
1255
1040
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
provider_token: (bindInfo as any)?.providerToken,
|
|
1259
|
-
})
|
|
1041
|
+
// 发送验证码
|
|
1042
|
+
const verificationInfo = await this.getVerification(verificationParams)
|
|
1260
1043
|
|
|
1261
|
-
|
|
1262
|
-
throw bindRes
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
} else {
|
|
1266
|
-
// 自定义应用走signUp逻辑
|
|
1267
|
-
const signUpRes = await this.oauthInstance.authApi.signUp({
|
|
1268
|
-
...signUpParam,
|
|
1269
|
-
verification_token,
|
|
1270
|
-
provider_token: (bindInfo as any)?.providerId,
|
|
1271
|
-
})
|
|
1044
|
+
Object.keys(restParams).length > 0 && (await this.updateUserBasicInfo(restParams))
|
|
1272
1045
|
|
|
1273
|
-
|
|
1274
|
-
|
|
1046
|
+
extraRes = {
|
|
1047
|
+
messageId: verificationInfo.verification_id,
|
|
1048
|
+
verifyOtp: async (verifyParams: { email?: string; phone?: string; token: string }): Promise<GetUserRes> => {
|
|
1049
|
+
try {
|
|
1050
|
+
if (verifyParams.email && params.email === verifyParams.email) {
|
|
1051
|
+
// 验证码验证
|
|
1052
|
+
await this.verifyOtp({
|
|
1053
|
+
type: 'email_change',
|
|
1054
|
+
email: params.email,
|
|
1055
|
+
token: verifyParams.token,
|
|
1056
|
+
messageId: verificationInfo.verification_id,
|
|
1057
|
+
})
|
|
1058
|
+
await this.updateUserBasicInfo({ email: params.email })
|
|
1059
|
+
} else if (verifyParams.phone && params.phone === verifyParams.phone) {
|
|
1060
|
+
// 验证码验证
|
|
1061
|
+
await this.verifyOtp({
|
|
1062
|
+
type: 'phone_change',
|
|
1063
|
+
phone: params.phone,
|
|
1064
|
+
token: verifyParams.token,
|
|
1065
|
+
messageId: verificationInfo.verification_id,
|
|
1066
|
+
})
|
|
1067
|
+
await this.updateUserBasicInfo({ phone: this.formatPhone(params.phone) })
|
|
1068
|
+
} else {
|
|
1069
|
+
await this.verifyOtp({
|
|
1070
|
+
type: verificationType,
|
|
1071
|
+
email: needsEmailVerification ? params.email : undefined,
|
|
1072
|
+
phone: !needsEmailVerification ? params.phone : undefined,
|
|
1073
|
+
token: verifyParams.token,
|
|
1074
|
+
messageId: verificationInfo.verification_id,
|
|
1075
|
+
})
|
|
1076
|
+
// 验证成功后更新用户信息
|
|
1077
|
+
await this.updateUserBasicInfo(params)
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
const {
|
|
1081
|
+
data: { user },
|
|
1082
|
+
} = await this.getUser()
|
|
1083
|
+
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.USER_UPDATED })
|
|
1084
|
+
|
|
1085
|
+
return { data: { user }, error: null }
|
|
1086
|
+
} catch (error) {
|
|
1087
|
+
return { data: {}, error: new AuthError(error) }
|
|
1088
|
+
}
|
|
1089
|
+
},
|
|
1275
1090
|
}
|
|
1091
|
+
} else {
|
|
1092
|
+
// 不需要验证,直接更新
|
|
1093
|
+
await this.updateUserBasicInfo(params)
|
|
1276
1094
|
}
|
|
1095
|
+
const {
|
|
1096
|
+
data: { user },
|
|
1097
|
+
} = await this.getUser()
|
|
1098
|
+
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.USER_UPDATED })
|
|
1277
1099
|
|
|
1278
|
-
return
|
|
1100
|
+
return { data: { user, ...extraRes }, error: null }
|
|
1279
1101
|
} catch (error) {
|
|
1280
|
-
|
|
1102
|
+
return { data: {}, error: new AuthError(error) }
|
|
1281
1103
|
}
|
|
1282
1104
|
}
|
|
1283
1105
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
})
|
|
1293
|
-
|
|
1294
|
-
await loginState.checkLocalStateAsync()
|
|
1106
|
+
/**
|
|
1107
|
+
* https://supabase.com/docs/reference/javascript/auth-getuseridentities
|
|
1108
|
+
* 获取所有身份源
|
|
1109
|
+
* @returns Promise<GetUserIdentitiesRes>
|
|
1110
|
+
*/
|
|
1111
|
+
async getUserIdentities(): Promise<GetUserIdentitiesRes> {
|
|
1112
|
+
try {
|
|
1113
|
+
const providers = await this.oauthInstance.authApi.getProviders()
|
|
1295
1114
|
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
} else {
|
|
1302
|
-
await loginState.user.refresh(params)
|
|
1115
|
+
return {
|
|
1116
|
+
data: {
|
|
1117
|
+
identities: providers?.data?.filter(v => !!v.bind) as unknown as GetUserIdentitiesRes['data']['identities'],
|
|
1118
|
+
},
|
|
1119
|
+
error: null,
|
|
1303
1120
|
}
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
return { data: {}, error: new AuthError(error) }
|
|
1304
1123
|
}
|
|
1305
|
-
|
|
1306
|
-
this.config.eventBus?.fire(EVENTS.LOGIN_STATE_CHANGED, { eventType: LOGIN_STATE_CHANGED_TYPE.SIGN_IN })
|
|
1307
|
-
|
|
1308
|
-
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.SIGNED_IN })
|
|
1309
|
-
return loginState
|
|
1310
1124
|
}
|
|
1311
1125
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
accessToken = ''
|
|
1320
|
-
scope = DEFAULT_NODE_ACCESS_SCOPE
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
if (!scope) {
|
|
1324
|
-
return
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1126
|
+
/**
|
|
1127
|
+
* https://supabase.com/docs/reference/javascript/auth-linkidentity
|
|
1128
|
+
* 绑定身份源到当前用户
|
|
1129
|
+
* @param params
|
|
1130
|
+
* @returns Promise<LinkIdentityRes>
|
|
1131
|
+
*/
|
|
1132
|
+
async linkIdentity(params: LinkIdentityReq): Promise<LinkIdentityRes> {
|
|
1327
1133
|
try {
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1134
|
+
// 参数校验:provider必填
|
|
1135
|
+
this.validateParams(params, {
|
|
1136
|
+
provider: { required: true, message: 'Provider is required' },
|
|
1137
|
+
})
|
|
1138
|
+
|
|
1139
|
+
await this.signInWithOAuth({
|
|
1140
|
+
provider: params.provider,
|
|
1141
|
+
options: {
|
|
1142
|
+
type: OAUTH_TYPE.BIND_IDENTITY,
|
|
1143
|
+
},
|
|
1334
1144
|
})
|
|
1145
|
+
|
|
1146
|
+
return { data: { provider: params.provider }, error: null }
|
|
1335
1147
|
} catch (error) {
|
|
1336
|
-
|
|
1148
|
+
return { data: {}, error: new AuthError(error) }
|
|
1337
1149
|
}
|
|
1338
1150
|
}
|
|
1339
1151
|
|
|
1340
|
-
// ========== new auth api methods merged below ==========
|
|
1341
|
-
|
|
1342
1152
|
/**
|
|
1343
|
-
* https://supabase.com/docs/reference/javascript/auth-
|
|
1344
|
-
*
|
|
1345
|
-
* const { data, error } = await auth.signInAnonymously();
|
|
1153
|
+
* https://supabase.com/docs/reference/javascript/auth-unlinkidentity
|
|
1154
|
+
* 解绑身份源
|
|
1346
1155
|
* @param params
|
|
1347
|
-
* @returns
|
|
1156
|
+
* @returns Promise<CommonRes>
|
|
1348
1157
|
*/
|
|
1349
|
-
async
|
|
1158
|
+
async unlinkIdentity(params: UnlinkIdentityReq): Promise<CommonRes> {
|
|
1350
1159
|
try {
|
|
1351
|
-
|
|
1352
|
-
|
|
1160
|
+
// 参数校验:provider必填
|
|
1161
|
+
this.validateParams(params, {
|
|
1162
|
+
provider: { required: true, message: 'Provider is required' },
|
|
1163
|
+
})
|
|
1353
1164
|
|
|
1354
|
-
|
|
1165
|
+
await this.oauthInstance.authApi.unbindProvider({ provider_id: params.provider })
|
|
1355
1166
|
|
|
1356
|
-
|
|
1357
|
-
return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
1167
|
+
return { data: {}, error: null }
|
|
1358
1168
|
} catch (error) {
|
|
1359
1169
|
return { data: {}, error: new AuthError(error) }
|
|
1360
1170
|
}
|
|
1361
1171
|
}
|
|
1362
1172
|
|
|
1363
1173
|
/**
|
|
1364
|
-
* https://supabase.com/docs/reference/javascript/auth-
|
|
1365
|
-
*
|
|
1366
|
-
* @
|
|
1367
|
-
* @returns Promise<SignUpRes>
|
|
1174
|
+
* https://supabase.com/docs/reference/javascript/auth-reauthentication
|
|
1175
|
+
* 重新认证
|
|
1176
|
+
* @returns Promise<ReauthenticateRes>
|
|
1368
1177
|
*/
|
|
1369
|
-
async
|
|
1370
|
-
if (params.phone_number || params.verification_code || params.verification_token || params.provider_token) {
|
|
1371
|
-
params.phone_number = this.formatPhone(params.phone_number)
|
|
1372
|
-
await this.oauthInstance.authApi.signUp(params)
|
|
1373
|
-
return this.createLoginState() as any
|
|
1374
|
-
}
|
|
1178
|
+
async reauthenticate(): Promise<ReauthenticateRes> {
|
|
1375
1179
|
try {
|
|
1376
|
-
|
|
1377
|
-
|
|
1180
|
+
const {
|
|
1181
|
+
data: { user },
|
|
1182
|
+
} = await this.getUser()
|
|
1183
|
+
|
|
1184
|
+
this.validateAtLeastOne(user, [['email', 'phone']], 'You must provide either an email or phone number')
|
|
1185
|
+
const userInfo = user.email ? { email: user.email } : { phone_number: this.formatPhone(user.phone) }
|
|
1378
1186
|
|
|
1379
1187
|
// 第一步:发送验证码并存储 verificationInfo
|
|
1380
|
-
const verificationInfo = await this.getVerification(
|
|
1188
|
+
const verificationInfo = await this.getVerification(userInfo)
|
|
1381
1189
|
|
|
1382
1190
|
return {
|
|
1383
1191
|
data: {
|
|
1384
1192
|
// 第二步:等待用户输入验证码(通过 Promise 包装用户输入事件)
|
|
1385
|
-
|
|
1193
|
+
updateUser: async (attributes: UpdateUserAttributes): Promise<SignInRes> => {
|
|
1194
|
+
this.validateParams(attributes, {
|
|
1195
|
+
nonce: { required: true, message: 'Nonce is required' },
|
|
1196
|
+
})
|
|
1386
1197
|
try {
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1198
|
+
if (attributes.password) {
|
|
1199
|
+
// 第三步:待用户输入完验证码之后,验证验证码
|
|
1200
|
+
const verificationTokenRes = await this.verify({
|
|
1201
|
+
verification_id: verificationInfo.verification_id,
|
|
1202
|
+
verification_code: attributes.nonce,
|
|
1203
|
+
})
|
|
1392
1204
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
if (verificationInfo.is_user) {
|
|
1396
|
-
await this.signIn({
|
|
1397
|
-
username: params.email || this.formatPhone(params.phone),
|
|
1205
|
+
// 第四步:获取 sudo_token
|
|
1206
|
+
const sudoRes = await this.oauthInstance.authApi.sudo({
|
|
1398
1207
|
verification_token: verificationTokenRes.verification_token,
|
|
1399
1208
|
})
|
|
1400
|
-
} else {
|
|
1401
|
-
// 如果用户不存在,注册用户
|
|
1402
|
-
const data = JSON.parse(JSON.stringify(params))
|
|
1403
|
-
delete data.email
|
|
1404
|
-
delete data.phone
|
|
1405
1209
|
|
|
1406
|
-
await this.oauthInstance.authApi.
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1210
|
+
await this.oauthInstance.authApi.setPassword({
|
|
1211
|
+
new_password: attributes.password,
|
|
1212
|
+
sudo_token: sudoRes.sudo_token,
|
|
1213
|
+
})
|
|
1214
|
+
} else {
|
|
1215
|
+
await this.signInWithUsername({
|
|
1216
|
+
verificationInfo,
|
|
1217
|
+
verificationCode: attributes.nonce,
|
|
1218
|
+
...userInfo,
|
|
1219
|
+
loginType: userInfo.email ? 'email' : 'phone',
|
|
1411
1220
|
})
|
|
1412
|
-
await this.createLoginState()
|
|
1413
1221
|
}
|
|
1414
1222
|
|
|
1415
1223
|
const { data: { session } = {} } = await this.getSession()
|
|
@@ -1428,1056 +1236,1225 @@ class Auth extends AuthV1Compat {
|
|
|
1428
1236
|
}
|
|
1429
1237
|
|
|
1430
1238
|
/**
|
|
1431
|
-
* https://supabase.com/docs/reference/javascript/auth-
|
|
1432
|
-
*
|
|
1433
|
-
*
|
|
1239
|
+
* https://supabase.com/docs/reference/javascript/auth-resend
|
|
1240
|
+
* 重新发送验证码
|
|
1434
1241
|
* @param params
|
|
1242
|
+
* @returns Promise<ResendRes>
|
|
1435
1243
|
*/
|
|
1436
|
-
async
|
|
1244
|
+
async resend(params: ResendReq): Promise<ResendRes> {
|
|
1437
1245
|
try {
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
await this.cache.removeStoreAsync(userInfoKey)
|
|
1441
|
-
this.setAccessKey()
|
|
1246
|
+
// 参数校验:email或phone必填其一
|
|
1247
|
+
this.validateAtLeastOne(params, [['email'], ['phone']], 'You must provide either an email or phone number')
|
|
1442
1248
|
|
|
1443
|
-
|
|
1249
|
+
const target = params.type === 'signup' ? 'ANY' : 'USER'
|
|
1250
|
+
const data: { email?: string; phone_number?: string; target: 'USER' | 'ANY' } = { target }
|
|
1251
|
+
if ('email' in params) {
|
|
1252
|
+
data.email = params.email
|
|
1253
|
+
}
|
|
1444
1254
|
|
|
1445
|
-
|
|
1255
|
+
if ('phone' in params) {
|
|
1256
|
+
data.phone_number = this.formatPhone(params.phone)
|
|
1257
|
+
}
|
|
1446
1258
|
|
|
1447
|
-
//
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
return {
|
|
1259
|
+
// 重新发送验证码
|
|
1260
|
+
const { verification_id: verificationId } = await this.oauthInstance.authApi.getVerification(data)
|
|
1261
|
+
|
|
1262
|
+
return {
|
|
1263
|
+
data: { messageId: verificationId },
|
|
1264
|
+
error: null,
|
|
1265
|
+
}
|
|
1266
|
+
} catch (error: any) {
|
|
1267
|
+
return {
|
|
1268
|
+
data: {},
|
|
1269
|
+
error: new AuthError(error),
|
|
1270
|
+
}
|
|
1451
1271
|
}
|
|
1452
1272
|
}
|
|
1453
1273
|
|
|
1454
1274
|
/**
|
|
1455
|
-
* https://supabase.com/docs/reference/javascript/auth-
|
|
1456
|
-
*
|
|
1457
|
-
* @param
|
|
1458
|
-
* @returns Promise<
|
|
1275
|
+
* https://supabase.com/docs/reference/javascript/auth-setsession
|
|
1276
|
+
* 使用access_token和refresh_token来设置会话
|
|
1277
|
+
* @param params
|
|
1278
|
+
* @returns Promise<SignInRes>
|
|
1459
1279
|
*/
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
this.
|
|
1463
|
-
|
|
1464
|
-
|
|
1280
|
+
async setSession(params: SetSessionReq): Promise<SignInRes> {
|
|
1281
|
+
try {
|
|
1282
|
+
this.validateParams(params, {
|
|
1283
|
+
access_token: { required: true, message: 'Access token is required' },
|
|
1284
|
+
refresh_token: { required: true, message: 'Refresh token is required' },
|
|
1285
|
+
})
|
|
1465
1286
|
|
|
1466
|
-
|
|
1287
|
+
await this.oauthInstance.oauth2client.refreshToken(params, { throwError: true })
|
|
1467
1288
|
|
|
1468
|
-
|
|
1469
|
-
this.listeners.set(id, new Set())
|
|
1470
|
-
}
|
|
1289
|
+
const { data: { session } = {} } = await this.getSession()
|
|
1471
1290
|
|
|
1472
|
-
|
|
1291
|
+
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.SIGNED_IN })
|
|
1473
1292
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
callback,
|
|
1478
|
-
unsubscribe: () => {
|
|
1479
|
-
const callbacks = this.listeners.get(id)
|
|
1480
|
-
if (callbacks) {
|
|
1481
|
-
callbacks.delete(callback)
|
|
1482
|
-
if (callbacks.size === 0) {
|
|
1483
|
-
this.listeners.delete(id)
|
|
1484
|
-
}
|
|
1485
|
-
}
|
|
1486
|
-
},
|
|
1293
|
+
return { data: { user: session.user, session }, error: null }
|
|
1294
|
+
} catch (error) {
|
|
1295
|
+
return { data: {}, error: new AuthError(error) }
|
|
1487
1296
|
}
|
|
1297
|
+
}
|
|
1488
1298
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1299
|
+
// https://supabase.com/docs/reference/javascript/auth-exchangecodeforsession
|
|
1300
|
+
async exchangeCodeForSession() {
|
|
1301
|
+
//
|
|
1492
1302
|
}
|
|
1493
1303
|
|
|
1494
1304
|
/**
|
|
1495
|
-
*
|
|
1496
|
-
* Log in an existing user with an email and password or phone and password or username and password.
|
|
1305
|
+
* 删除当前用户
|
|
1497
1306
|
* @param params
|
|
1498
|
-
* @returns
|
|
1307
|
+
* @returns
|
|
1499
1308
|
*/
|
|
1500
|
-
async
|
|
1309
|
+
async deleteUser(params: DeleteMeReq): Promise<CommonRes> {
|
|
1501
1310
|
try {
|
|
1502
|
-
// 参数校验:username/email/phone三选一,password必填
|
|
1503
|
-
this.validateAtLeastOne(
|
|
1504
|
-
params,
|
|
1505
|
-
[['username'], ['email'], ['phone']],
|
|
1506
|
-
'You must provide either username, email, or phone',
|
|
1507
|
-
)
|
|
1508
1311
|
this.validateParams(params, {
|
|
1509
1312
|
password: { required: true, message: 'Password is required' },
|
|
1510
1313
|
})
|
|
1511
1314
|
|
|
1512
|
-
await this.
|
|
1513
|
-
username: params.username || params.email || this.formatPhone(params.phone),
|
|
1514
|
-
password: params.password,
|
|
1515
|
-
...(params.is_encrypt ? { isEncrypt: true, version: 'v2' } : {}),
|
|
1516
|
-
})
|
|
1517
|
-
const { data: { session } = {} } = await this.getSession()
|
|
1315
|
+
const { sudo_token } = await this.oauthInstance.authApi.sudo(params)
|
|
1518
1316
|
|
|
1519
|
-
|
|
1317
|
+
await this.oauthInstance.authApi.deleteMe({ sudo_token })
|
|
1318
|
+
|
|
1319
|
+
return { data: {}, error: null }
|
|
1520
1320
|
} catch (error) {
|
|
1521
|
-
|
|
1522
|
-
// 优化错误提示:登录失败时提供更友好的排查指引
|
|
1523
|
-
if (authError.message?.includes('密码不正确') || authError.message?.includes('password')) {
|
|
1524
|
-
console.warn('[CloudBase Auth] 登录失败提示:\n'
|
|
1525
|
-
+ ' 1. 请确认用户名/邮箱/手机号是否正确\n'
|
|
1526
|
-
+ ' 2. 请确认密码是否正确\n'
|
|
1527
|
-
+ ' 3. 如果用户不存在,请先通过 auth.signUp() 注册用户,或在云开发控制台手动创建用户\n'
|
|
1528
|
-
+ ' 4. 确认当前环境已开启对应的登录方式(控制台 → 环境 → 登录授权)',)
|
|
1529
|
-
}
|
|
1530
|
-
return { data: {}, error: authError }
|
|
1321
|
+
return { data: {}, error: new AuthError(error) }
|
|
1531
1322
|
}
|
|
1532
1323
|
}
|
|
1533
1324
|
|
|
1534
1325
|
/**
|
|
1535
|
-
*
|
|
1536
|
-
*
|
|
1537
|
-
* @
|
|
1538
|
-
* @returns Promise<SignInRes>
|
|
1326
|
+
* 跳转系统默认登录页
|
|
1327
|
+
* @returns {Promise<authModels.ToDefaultLoginPage>}
|
|
1328
|
+
* @memberof Auth
|
|
1539
1329
|
*/
|
|
1540
|
-
async
|
|
1330
|
+
async toDefaultLoginPage(params: authModels.ToDefaultLoginPage = {}): Promise<CommonRes> {
|
|
1541
1331
|
try {
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
await this.signInWithProvider({
|
|
1548
|
-
provider_token: params.token,
|
|
1549
|
-
})
|
|
1550
|
-
const { data: { session } = {} } = await this.getSession()
|
|
1332
|
+
const configVersion = params.config_version || 'env'
|
|
1333
|
+
const query = Object.keys(params.query || {})
|
|
1334
|
+
.map(key => `${key}=${params.query[key]}`)
|
|
1335
|
+
.join('&')
|
|
1551
1336
|
|
|
1552
|
-
|
|
1337
|
+
if (adapterForWxMp.isMatch()) {
|
|
1338
|
+
wx.navigateTo({ url: `/packages/$wd_system/pages/login/index${query ? `?${query}` : ''}` })
|
|
1339
|
+
} else {
|
|
1340
|
+
const redirectUri = params.redirect_uri || window.location.href
|
|
1341
|
+
const urlObj = new URL(redirectUri)
|
|
1342
|
+
const loginPage = `${urlObj.origin}/__auth/?app_id=${params.app_id || ''}&env_id=${this.config.env}&client_id=${
|
|
1343
|
+
this.config.clientId || this.config.env
|
|
1344
|
+
}&config_version=${configVersion}&redirect_uri=${encodeURIComponent(redirectUri)}${query ? `&${query}` : ''}`
|
|
1345
|
+
window.location.href = loginPage
|
|
1346
|
+
}
|
|
1347
|
+
return { data: {}, error: null }
|
|
1553
1348
|
} catch (error) {
|
|
1554
1349
|
return { data: {}, error: new AuthError(error) }
|
|
1555
1350
|
}
|
|
1556
1351
|
}
|
|
1557
1352
|
|
|
1558
1353
|
/**
|
|
1559
|
-
*
|
|
1560
|
-
*
|
|
1561
|
-
* @
|
|
1562
|
-
* @returns Promise<SignInWithOtpRes>
|
|
1354
|
+
* 自定义登录
|
|
1355
|
+
* @param getTickFn () => Promise<string>, 获取自定义登录 ticket 的函数
|
|
1356
|
+
* @returns
|
|
1563
1357
|
*/
|
|
1564
|
-
async
|
|
1565
|
-
if (
|
|
1566
|
-
|
|
1567
|
-
email: params.email,
|
|
1568
|
-
phone: params.phone,
|
|
1569
|
-
})
|
|
1358
|
+
async signInWithCustomTicket(getTickFn?: authModels.GetCustomSignTicketFn): Promise<SignInRes> {
|
|
1359
|
+
if (getTickFn) {
|
|
1360
|
+
this.setCustomSignFunc(getTickFn)
|
|
1570
1361
|
}
|
|
1571
1362
|
|
|
1572
1363
|
try {
|
|
1573
|
-
|
|
1574
|
-
|
|
1364
|
+
await this.oauthInstance.authApi.signInWithCustomTicket()
|
|
1365
|
+
const loginState = await this.createLoginState()
|
|
1575
1366
|
|
|
1576
|
-
|
|
1577
|
-
const verificationInfo = await this.getVerification(params.email ? { email: params.email } : { phone_number: this.formatPhone(params.phone) },)
|
|
1367
|
+
const { data: { session } = {} } = await this.getSession()
|
|
1578
1368
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
user: null,
|
|
1582
|
-
session: null,
|
|
1583
|
-
// 第二步:等待用户输入验证码(通过 Promise 包装用户输入事件)
|
|
1584
|
-
verifyOtp: async ({ token, messageId = verificationInfo.verification_id }): Promise<SignInRes> => this.verifyOtp({
|
|
1585
|
-
email: params.email,
|
|
1586
|
-
phone: params.phone,
|
|
1587
|
-
token,
|
|
1588
|
-
messageId,
|
|
1589
|
-
}),
|
|
1590
|
-
},
|
|
1591
|
-
error: null,
|
|
1592
|
-
}
|
|
1369
|
+
// loginState返回是为了兼容v2版本
|
|
1370
|
+
return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
1593
1371
|
} catch (error) {
|
|
1594
1372
|
return { data: {}, error: new AuthError(error) }
|
|
1595
1373
|
}
|
|
1596
1374
|
}
|
|
1597
1375
|
|
|
1598
1376
|
/**
|
|
1599
|
-
*
|
|
1377
|
+
* 小程序openId静默登录
|
|
1600
1378
|
* @param params
|
|
1601
1379
|
* @returns Promise<SignInRes>
|
|
1602
1380
|
*/
|
|
1603
|
-
async
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
const state = params?.state || utils.getQuery('state')
|
|
1381
|
+
async signInWithOpenId({ useWxCloud = true } = {}): Promise<SignInRes> {
|
|
1382
|
+
if (!adapterForWxMp.isMatch()) {
|
|
1383
|
+
throw Error('wx api undefined')
|
|
1384
|
+
}
|
|
1385
|
+
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
1609
1386
|
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
}
|
|
1387
|
+
const mainFunc = async (code) => {
|
|
1388
|
+
let result: authModels.GrantProviderTokenResponse | undefined = undefined
|
|
1389
|
+
let credentials: Credentials | undefined = undefined
|
|
1614
1390
|
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1391
|
+
try {
|
|
1392
|
+
result = await this.oauthInstance.authApi.grantProviderToken(
|
|
1393
|
+
{
|
|
1394
|
+
provider_id: wxInfo?.appId,
|
|
1395
|
+
provider_code: code,
|
|
1396
|
+
provider_params: {
|
|
1397
|
+
provider_code_type: 'open_id',
|
|
1398
|
+
appid: wxInfo?.appId,
|
|
1399
|
+
},
|
|
1400
|
+
},
|
|
1401
|
+
useWxCloud,
|
|
1402
|
+
)
|
|
1618
1403
|
|
|
1619
|
-
|
|
1620
|
-
|
|
1404
|
+
if ((result as any)?.error_code || !result.provider_token) {
|
|
1405
|
+
throw result
|
|
1406
|
+
}
|
|
1621
1407
|
|
|
1622
|
-
|
|
1408
|
+
credentials = await this.oauthInstance.authApi.signInWithProvider(
|
|
1409
|
+
{ provider_token: result.provider_token },
|
|
1410
|
+
useWxCloud,
|
|
1411
|
+
)
|
|
1623
1412
|
|
|
1624
|
-
|
|
1625
|
-
|
|
1413
|
+
if ((credentials as any)?.error_code) {
|
|
1414
|
+
throw credentials
|
|
1415
|
+
}
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
throw error
|
|
1626
1418
|
}
|
|
1419
|
+
await this.oauthInstance.oauth2client.setCredentials(credentials as Credentials)
|
|
1420
|
+
}
|
|
1627
1421
|
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1422
|
+
try {
|
|
1423
|
+
await new Promise((resolve, reject) => {
|
|
1424
|
+
wx.login({
|
|
1425
|
+
success: async (res: { code: string }) => {
|
|
1426
|
+
try {
|
|
1427
|
+
await mainFunc(res.code)
|
|
1428
|
+
resolve(true)
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
reject(error)
|
|
1431
|
+
}
|
|
1432
|
+
},
|
|
1433
|
+
fail: (res: any) => {
|
|
1434
|
+
const error = new Error(res?.errMsg)
|
|
1435
|
+
;(error as any).code = res?.errno
|
|
1436
|
+
reject(error)
|
|
1437
|
+
},
|
|
1438
|
+
})
|
|
1633
1439
|
})
|
|
1634
1440
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
if (cacheData.type === OAUTH_TYPE.BIND_IDENTITY) {
|
|
1638
|
-
res = await this.oauthInstance.authApi.toBindIdentity({ provider_token: token, provider, fireEvent: true })
|
|
1639
|
-
} else {
|
|
1640
|
-
// 通过 provider_token 仅登录或登录并注册(与云开发平台-登录方式-身份源登录模式配置有关)
|
|
1641
|
-
res = await this.signInWithIdToken({
|
|
1642
|
-
token,
|
|
1643
|
-
})
|
|
1644
|
-
res.data = { ...data, ...res.data }
|
|
1645
|
-
}
|
|
1441
|
+
const loginState = await this.createLoginState()
|
|
1646
1442
|
|
|
1647
|
-
const
|
|
1648
|
-
localSearch.delete('code')
|
|
1649
|
-
localSearch.delete('state')
|
|
1650
|
-
res.data.redirectUrl = addUrlSearch(
|
|
1651
|
-
cacheData?.search === undefined ? `?${localSearch.toString()}` : cacheData?.search,
|
|
1652
|
-
cacheData?.hash || location.hash,
|
|
1653
|
-
)
|
|
1654
|
-
removeBrowserSession(state)
|
|
1443
|
+
const { data: { session } = {} } = await this.getSession()
|
|
1655
1444
|
|
|
1656
|
-
|
|
1445
|
+
// loginState返回是为了兼容v2版本
|
|
1446
|
+
return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
1657
1447
|
} catch (error) {
|
|
1658
|
-
return { data, error: new AuthError(error) }
|
|
1448
|
+
return { data: {}, error: new AuthError(error) }
|
|
1659
1449
|
}
|
|
1660
1450
|
}
|
|
1661
1451
|
|
|
1662
1452
|
/**
|
|
1663
|
-
*
|
|
1664
|
-
* 生成第三方平台授权 Uri (如微信二维码扫码授权网页)
|
|
1453
|
+
* 小程序手机号授权登录
|
|
1665
1454
|
* @param params
|
|
1666
|
-
* @returns Promise<
|
|
1455
|
+
* @returns Promise<SignInRes>
|
|
1667
1456
|
*/
|
|
1668
|
-
async
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1457
|
+
// async signInWithPhoneAuth({ phoneCode = '', useWxCloud = false }): Promise<SignInRes> {
|
|
1458
|
+
async signInWithPhoneAuth({ phoneCode = '' }): Promise<SignInRes> {
|
|
1459
|
+
// if (!adapterForWxMp.isMatch()) {
|
|
1460
|
+
// return { data: {}, error: new AuthError({ message: 'wx api undefined' }) }
|
|
1461
|
+
// }
|
|
1462
|
+
// const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
1463
|
+
// const providerInfo = {
|
|
1464
|
+
// provider_params: { provider_code_type: 'phone', code: phoneCode, appid: wxInfo.appId },
|
|
1465
|
+
// provider_id: wxInfo.appId,
|
|
1466
|
+
// }
|
|
1674
1467
|
|
|
1675
|
-
|
|
1468
|
+
// const { code } = await wx.login()
|
|
1469
|
+
// ;(providerInfo as any).provider_code = code
|
|
1676
1470
|
|
|
1677
|
-
|
|
1471
|
+
// try {
|
|
1472
|
+
// const providerToken = await this.oauthInstance.authApi.grantProviderToken(providerInfo, useWxCloud)
|
|
1473
|
+
// if (providerToken.error_code) {
|
|
1474
|
+
// throw providerToken
|
|
1475
|
+
// }
|
|
1678
1476
|
|
|
1679
|
-
|
|
1477
|
+
// const signInRes = await this.oauthInstance.authApi.signInWithProvider({
|
|
1478
|
+
// provider_token: providerToken.provider_token,
|
|
1479
|
+
// }, useWxCloud)
|
|
1680
1480
|
|
|
1681
|
-
|
|
1682
|
-
|
|
1481
|
+
// if ((signInRes as any)?.error_code) {
|
|
1482
|
+
// throw signInRes
|
|
1483
|
+
// }
|
|
1484
|
+
// } catch (error) {
|
|
1485
|
+
// return { data: {}, error: new AuthError(error) }
|
|
1486
|
+
// }
|
|
1683
1487
|
|
|
1684
|
-
|
|
1685
|
-
provider_id: params.provider,
|
|
1686
|
-
provider_redirect_uri,
|
|
1687
|
-
state,
|
|
1688
|
-
})
|
|
1488
|
+
// const loginState = await this.createLoginState()
|
|
1689
1489
|
|
|
1690
|
-
|
|
1691
|
-
const decodedUri = decodeURIComponent(uri)
|
|
1490
|
+
// const { data: { session } = {} } = await this.getSession()
|
|
1692
1491
|
|
|
1693
|
-
|
|
1694
|
-
|
|
1492
|
+
// // loginState返回是为了兼容v2版本
|
|
1493
|
+
// return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
1494
|
+
if (!adapterForWxMp.isMatch()) {
|
|
1495
|
+
return { data: {}, error: new AuthError({ message: 'wx api undefined' }) }
|
|
1496
|
+
}
|
|
1497
|
+
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
1498
|
+
const providerInfo = {
|
|
1499
|
+
provider_params: { provider_code_type: 'phone' },
|
|
1500
|
+
provider_id: wxInfo.appId,
|
|
1501
|
+
}
|
|
1695
1502
|
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1503
|
+
const { code } = await wx.login()
|
|
1504
|
+
;(providerInfo as any).provider_code = code
|
|
1505
|
+
|
|
1506
|
+
try {
|
|
1507
|
+
let providerToken = await this.oauthInstance.authApi.grantProviderToken(providerInfo)
|
|
1508
|
+
if (providerToken.error_code) {
|
|
1509
|
+
throw providerToken
|
|
1702
1510
|
}
|
|
1703
1511
|
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1512
|
+
providerToken = await this.oauthInstance.authApi.patchProviderToken({
|
|
1513
|
+
provider_token: providerToken.provider_token,
|
|
1514
|
+
provider_id: wxInfo.appId,
|
|
1515
|
+
provider_params: {
|
|
1516
|
+
code: phoneCode,
|
|
1517
|
+
provider_code_type: 'phone',
|
|
1518
|
+
},
|
|
1709
1519
|
})
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
window.location.assign(finalUri)
|
|
1520
|
+
if (providerToken.error_code) {
|
|
1521
|
+
throw providerToken
|
|
1713
1522
|
}
|
|
1714
1523
|
|
|
1715
|
-
|
|
1524
|
+
const signInRes = await this.oauthInstance.authApi.signInWithProvider({
|
|
1525
|
+
provider_token: providerToken.provider_token,
|
|
1526
|
+
})
|
|
1527
|
+
|
|
1528
|
+
if ((signInRes as any)?.error_code) {
|
|
1529
|
+
throw signInRes
|
|
1530
|
+
}
|
|
1716
1531
|
} catch (error) {
|
|
1717
1532
|
return { data: {}, error: new AuthError(error) }
|
|
1718
1533
|
}
|
|
1534
|
+
|
|
1535
|
+
const loginState = await this.createLoginState()
|
|
1536
|
+
|
|
1537
|
+
const { data: { session } = {} } = await this.getSession()
|
|
1538
|
+
|
|
1539
|
+
// loginState返回是为了兼容v2版本
|
|
1540
|
+
return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
1719
1541
|
}
|
|
1720
1542
|
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1543
|
+
/**
|
|
1544
|
+
* 绑定手机号
|
|
1545
|
+
* @param phoneNumber
|
|
1546
|
+
* @param phoneCode
|
|
1547
|
+
*/
|
|
1548
|
+
@catchErrorsDecorator({
|
|
1549
|
+
title: '绑定手机号失败',
|
|
1550
|
+
messages: [
|
|
1551
|
+
'请确认以下各项:',
|
|
1552
|
+
' 1 - 调用 auth().bindPhoneNumber() 的语法或参数是否正确',
|
|
1553
|
+
' 2 - 当前环境是否开通了短信验证码登录',
|
|
1554
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1555
|
+
],
|
|
1556
|
+
})
|
|
1557
|
+
public async bindPhoneNumber(params: authModels.BindPhoneRequest) {
|
|
1558
|
+
return this.oauthInstance.authApi.editContact(params)
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
/**
|
|
1562
|
+
* 解绑三方绑定
|
|
1563
|
+
* @param loginType
|
|
1564
|
+
*/
|
|
1565
|
+
@catchErrorsDecorator({
|
|
1566
|
+
title: '解除三方绑定失败',
|
|
1567
|
+
messages: [
|
|
1568
|
+
'请确认以下各项:',
|
|
1569
|
+
' 1 - 调用 auth().unbindProvider() 的语法或参数是否正确',
|
|
1570
|
+
' 2 - 当前账户是否已经与此登录方式解绑',
|
|
1571
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1572
|
+
],
|
|
1573
|
+
})
|
|
1574
|
+
public async unbindProvider(params: authModels.UnbindProviderRequest): Promise<void> {
|
|
1575
|
+
return this.oauthInstance.authApi.unbindProvider(params)
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
/**
|
|
1579
|
+
* 更新邮箱地址
|
|
1580
|
+
* @param email
|
|
1581
|
+
* @param sudo_token
|
|
1582
|
+
* @param verification_token
|
|
1583
|
+
*/
|
|
1584
|
+
@catchErrorsDecorator({
|
|
1585
|
+
title: '绑定邮箱地址失败',
|
|
1586
|
+
messages: [
|
|
1587
|
+
'请确认以下各项:',
|
|
1588
|
+
' 1 - 调用 auth().bindEmail() 的语法或参数是否正确',
|
|
1589
|
+
' 2 - 当前环境是否开通了邮箱密码登录',
|
|
1590
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1591
|
+
],
|
|
1592
|
+
})
|
|
1593
|
+
public bindEmail(params: authModels.BindEmailRequest) {
|
|
1594
|
+
return this.oauthInstance.authApi.editContact(params)
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/**
|
|
1598
|
+
* verify
|
|
1599
|
+
* @param {authModels.VerifyRequest} params
|
|
1600
|
+
* @returns {Promise<authModels.VerifyResponse>}
|
|
1601
|
+
* @memberof User
|
|
1602
|
+
*/
|
|
1603
|
+
@catchErrorsDecorator({
|
|
1604
|
+
title: '验证码验证失败',
|
|
1605
|
+
messages: [
|
|
1606
|
+
'请确认以下各项:',
|
|
1607
|
+
' 1 - 调用 auth().verify() 的语法或参数是否正确',
|
|
1608
|
+
' 2 - 当前环境是否开通了手机验证码/邮箱登录',
|
|
1609
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1610
|
+
],
|
|
1611
|
+
})
|
|
1612
|
+
public async verify(params: authModels.VerifyRequest): Promise<authModels.VerifyResponse> {
|
|
1613
|
+
return this.oauthInstance.authApi.verify(params)
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
/**
|
|
1617
|
+
* 获取验证码
|
|
1618
|
+
* @param {authModels.GetVerificationRequest} params
|
|
1619
|
+
* @returns {Promise<authModels.GetVerificationResponse>}
|
|
1620
|
+
* @memberof User
|
|
1621
|
+
*/
|
|
1622
|
+
@catchErrorsDecorator({
|
|
1623
|
+
title: '获取验证码失败',
|
|
1624
|
+
messages: [
|
|
1625
|
+
'请确认以下各项:',
|
|
1626
|
+
' 1 - 调用 auth().getVerification() 的语法或参数是否正确',
|
|
1627
|
+
' 2 - 当前环境是否开通了手机验证码/邮箱登录',
|
|
1628
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1629
|
+
],
|
|
1630
|
+
})
|
|
1631
|
+
public async getVerification(
|
|
1632
|
+
params: authModels.GetVerificationRequest,
|
|
1633
|
+
options?: { withCaptcha: boolean },
|
|
1634
|
+
): Promise<authModels.GetVerificationResponse> {
|
|
1635
|
+
if (params.phone_number) {
|
|
1636
|
+
params.phone_number = this.formatPhone(params.phone_number)
|
|
1729
1637
|
}
|
|
1638
|
+
return this.oauthInstance.authApi.getVerification(params, options)
|
|
1730
1639
|
}
|
|
1731
1640
|
|
|
1732
1641
|
/**
|
|
1733
|
-
*
|
|
1734
|
-
* 通过 email 或手机号重置密码
|
|
1735
|
-
* @param emailOrPhone 邮箱或手机号
|
|
1736
|
-
* @returns Promise<ResetPasswordForEmailRes>
|
|
1642
|
+
* 获取当前登录的用户信息-同步
|
|
1737
1643
|
*/
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
this.validateParams(
|
|
1745
|
-
{ emailOrPhone },
|
|
1746
|
-
{
|
|
1747
|
-
emailOrPhone: { required: true, message: 'Email or phone is required' },
|
|
1748
|
-
},
|
|
1644
|
+
get currentUser() {
|
|
1645
|
+
if (this.cache.mode === 'async') {
|
|
1646
|
+
// async storage的平台调用此API提示
|
|
1647
|
+
printWarn(
|
|
1648
|
+
ERRORS.INVALID_OPERATION,
|
|
1649
|
+
'current platform\'s storage is asynchronous, please use getCurrentUser instead',
|
|
1749
1650
|
)
|
|
1651
|
+
return
|
|
1652
|
+
}
|
|
1750
1653
|
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
// 判断是邮箱还是手机号
|
|
1754
|
-
const isEmail = emailOrPhone.includes('@')
|
|
1755
|
-
let verificationParams: { email?: string; phone_number?: string }
|
|
1654
|
+
const loginState = this.hasLoginState()
|
|
1756
1655
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
verificationParams = { phone_number: formattedPhone }
|
|
1763
|
-
}
|
|
1656
|
+
if (loginState) {
|
|
1657
|
+
return loginState.user || null
|
|
1658
|
+
}
|
|
1659
|
+
return null
|
|
1660
|
+
}
|
|
1764
1661
|
|
|
1765
|
-
|
|
1766
|
-
|
|
1662
|
+
/**
|
|
1663
|
+
* 获取当前登录的用户信息-异步
|
|
1664
|
+
*/
|
|
1665
|
+
@catchErrorsDecorator({
|
|
1666
|
+
title: '获取用户信息失败',
|
|
1667
|
+
messages: [
|
|
1668
|
+
'请确认以下各项:',
|
|
1669
|
+
' 1 - 调用 auth().getCurrentUser() 的语法或参数是否正确',
|
|
1670
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1671
|
+
],
|
|
1672
|
+
})
|
|
1673
|
+
public async getCurrentUser(): Promise<(authModels.UserInfo & Partial<User>) | null> {
|
|
1674
|
+
const loginState = await this.getLoginState()
|
|
1675
|
+
if (loginState) {
|
|
1676
|
+
const userInfo = loginState.user.getLocalUserInfo() as authModels.UserInfo
|
|
1677
|
+
await loginState.user.checkLocalInfoAsync()
|
|
1678
|
+
return { ...loginState.user, ...userInfo } as unknown as authModels.UserInfo & Partial<User>
|
|
1679
|
+
}
|
|
1680
|
+
return null
|
|
1681
|
+
}
|
|
1767
1682
|
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1683
|
+
/**
|
|
1684
|
+
* 匿名登录
|
|
1685
|
+
* @returns {Promise<LoginState>}
|
|
1686
|
+
* @memberof Auth
|
|
1687
|
+
*/
|
|
1688
|
+
@catchErrorsDecorator({
|
|
1689
|
+
title: '小程序匿名登录失败',
|
|
1690
|
+
messages: [
|
|
1691
|
+
'请确认以下各项:',
|
|
1692
|
+
' 1 - 当前环境是否开启了匿名登录',
|
|
1693
|
+
' 2 - 调用 auth().signInAnonymouslyInWx() 的语法或参数是否正确',
|
|
1694
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1695
|
+
],
|
|
1696
|
+
})
|
|
1697
|
+
public async signInAnonymouslyInWx({
|
|
1698
|
+
useWxCloud,
|
|
1699
|
+
}: {
|
|
1700
|
+
useWxCloud?: boolean
|
|
1701
|
+
} = {}): Promise<LoginState> {
|
|
1702
|
+
if (!adapterForWxMp.isMatch()) {
|
|
1703
|
+
throw Error('wx api undefined')
|
|
1704
|
+
}
|
|
1705
|
+
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
1782
1706
|
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
new_password: attributes.password,
|
|
1787
|
-
verification_token: verificationTokenRes.verification_token,
|
|
1788
|
-
})
|
|
1707
|
+
const mainFunc = async (code) => {
|
|
1708
|
+
let result: authModels.GrantProviderTokenResponse | undefined = undefined
|
|
1709
|
+
let credentials: Credentials | undefined = undefined
|
|
1789
1710
|
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1711
|
+
try {
|
|
1712
|
+
result = await this.oauthInstance.authApi.grantProviderToken(
|
|
1713
|
+
{
|
|
1714
|
+
provider_id: wxInfo?.appId,
|
|
1715
|
+
provider_code: code,
|
|
1716
|
+
provider_params: {
|
|
1717
|
+
provider_code_type: 'open_id',
|
|
1718
|
+
appid: wxInfo?.appId,
|
|
1719
|
+
},
|
|
1720
|
+
},
|
|
1721
|
+
useWxCloud,
|
|
1722
|
+
)
|
|
1793
1723
|
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
password: attributes.password,
|
|
1798
|
-
})
|
|
1724
|
+
if ((result as any)?.error_code || !result.provider_token) {
|
|
1725
|
+
throw result
|
|
1726
|
+
}
|
|
1799
1727
|
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1728
|
+
credentials = await this.oauthInstance.authApi.signInAnonymously(
|
|
1729
|
+
{ provider_token: result.provider_token },
|
|
1730
|
+
useWxCloud,
|
|
1731
|
+
)
|
|
1803
1732
|
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
},
|
|
1810
|
-
error: null,
|
|
1733
|
+
if ((credentials as any)?.error_code) {
|
|
1734
|
+
throw credentials
|
|
1735
|
+
}
|
|
1736
|
+
} catch (error) {
|
|
1737
|
+
throw error
|
|
1811
1738
|
}
|
|
1812
|
-
} catch (error) {
|
|
1813
|
-
return { data: {}, error: new AuthError(error) }
|
|
1814
1739
|
}
|
|
1815
|
-
}
|
|
1816
1740
|
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1741
|
+
await new Promise((resolve, reject) => {
|
|
1742
|
+
wx.login({
|
|
1743
|
+
success: async (res: { code: string }) => {
|
|
1744
|
+
try {
|
|
1745
|
+
await mainFunc(res.code)
|
|
1746
|
+
resolve(true)
|
|
1747
|
+
} catch (error) {
|
|
1748
|
+
reject(error)
|
|
1749
|
+
}
|
|
1750
|
+
},
|
|
1751
|
+
fail: (res: any) => {
|
|
1752
|
+
const error = new Error(res?.errMsg)
|
|
1753
|
+
;(error as any).code = res?.errno
|
|
1754
|
+
reject(error)
|
|
1755
|
+
},
|
|
1828
1756
|
})
|
|
1757
|
+
})
|
|
1829
1758
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
return { data: { user: session.user, session }, error: null }
|
|
1833
|
-
} catch (error) {
|
|
1834
|
-
return { data: {}, error: new AuthError(error) }
|
|
1835
|
-
}
|
|
1759
|
+
return this.createLoginState(undefined, { asyncRefreshUser: true })
|
|
1836
1760
|
}
|
|
1837
1761
|
|
|
1838
1762
|
/**
|
|
1839
|
-
*
|
|
1840
|
-
*
|
|
1841
|
-
* @
|
|
1842
|
-
* @returns Promise<SignInRes>
|
|
1763
|
+
* 小程序绑定OpenID
|
|
1764
|
+
* @returns {Promise<LoginState>}
|
|
1765
|
+
* @memberof Auth
|
|
1843
1766
|
*/
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1767
|
+
@catchErrorsDecorator({
|
|
1768
|
+
title: '小程序绑定OpenID失败',
|
|
1769
|
+
messages: [
|
|
1770
|
+
'请确认以下各项:',
|
|
1771
|
+
' 1 - 当前环境是否开启了小程序openId静默登录',
|
|
1772
|
+
' 2 - 调用 auth().bindOpenId() 的语法或参数是否正确',
|
|
1773
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1774
|
+
],
|
|
1775
|
+
})
|
|
1776
|
+
public async bindOpenId(): Promise<void> {
|
|
1777
|
+
if (!adapterForWxMp.isMatch()) {
|
|
1778
|
+
throw Error('wx api undefined')
|
|
1779
|
+
}
|
|
1780
|
+
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
1852
1781
|
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1782
|
+
const mainFunc = async (code) => {
|
|
1783
|
+
let result: authModels.GrantProviderTokenResponse | undefined = undefined
|
|
1784
|
+
|
|
1785
|
+
try {
|
|
1786
|
+
result = await this.oauthInstance.authApi.grantProviderToken({
|
|
1787
|
+
provider_id: wxInfo?.appId,
|
|
1788
|
+
provider_code: code,
|
|
1789
|
+
provider_params: {
|
|
1790
|
+
provider_code_type: 'open_id',
|
|
1791
|
+
appid: wxInfo?.appId,
|
|
1792
|
+
},
|
|
1864
1793
|
})
|
|
1794
|
+
|
|
1795
|
+
if ((result as any)?.error_code || !result.provider_token) {
|
|
1796
|
+
throw result
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
await this.oauthInstance.authApi.bindWithProvider({ provider_token: result.provider_token })
|
|
1800
|
+
} catch (error) {
|
|
1801
|
+
throw error
|
|
1865
1802
|
}
|
|
1803
|
+
}
|
|
1866
1804
|
|
|
1867
|
-
|
|
1805
|
+
await new Promise((resolve, reject) => {
|
|
1806
|
+
wx.login({
|
|
1807
|
+
success: async (res: { code: string }) => {
|
|
1808
|
+
try {
|
|
1809
|
+
await mainFunc(res.code)
|
|
1810
|
+
resolve(true)
|
|
1811
|
+
} catch (error) {
|
|
1812
|
+
reject(error)
|
|
1813
|
+
}
|
|
1814
|
+
},
|
|
1815
|
+
fail: (res: any) => {
|
|
1816
|
+
const error = new Error(res?.errMsg)
|
|
1817
|
+
;(error as any).code = res?.errno
|
|
1818
|
+
reject(error)
|
|
1819
|
+
},
|
|
1820
|
+
})
|
|
1821
|
+
})
|
|
1868
1822
|
|
|
1869
|
-
|
|
1870
|
-
} catch (error) {
|
|
1871
|
-
return { data: {}, error: new AuthError(error) }
|
|
1872
|
-
}
|
|
1823
|
+
return
|
|
1873
1824
|
}
|
|
1874
1825
|
|
|
1875
1826
|
/**
|
|
1876
|
-
*
|
|
1877
|
-
*
|
|
1878
|
-
* @
|
|
1827
|
+
* 小程序unionId静默登录
|
|
1828
|
+
* @returns {Promise<LoginState>}
|
|
1829
|
+
* @memberof Auth
|
|
1879
1830
|
*/
|
|
1880
|
-
|
|
1831
|
+
@catchErrorsDecorator({
|
|
1832
|
+
title: '小程序unionId静默登录失败',
|
|
1833
|
+
messages: [
|
|
1834
|
+
'请确认以下各项:',
|
|
1835
|
+
' 1 - 当前环境是否开启了小程序unionId静默登录',
|
|
1836
|
+
' 2 - 调用 auth().signInWithUnionId() 的语法或参数是否正确',
|
|
1837
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1838
|
+
],
|
|
1839
|
+
})
|
|
1840
|
+
public async signInWithUnionId(): Promise<LoginState> {
|
|
1841
|
+
if (!adapterForWxMp.isMatch()) {
|
|
1842
|
+
throw Error('wx api undefined')
|
|
1843
|
+
}
|
|
1881
1844
|
try {
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1845
|
+
await new Promise((resolve, reject) => {
|
|
1846
|
+
const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
1847
|
+
wx.login({
|
|
1848
|
+
success: async (res: { code: string }) => {
|
|
1849
|
+
const providerId = wxInfo?.appId
|
|
1850
|
+
try {
|
|
1851
|
+
const result = await this.oauthInstance.authApi.grantProviderToken({
|
|
1852
|
+
provider_code: res.code,
|
|
1853
|
+
provider_id: providerId,
|
|
1854
|
+
provider_params: {
|
|
1855
|
+
provider_code_type: 'union_id',
|
|
1856
|
+
appid: wxInfo?.appId,
|
|
1857
|
+
},
|
|
1858
|
+
})
|
|
1887
1859
|
|
|
1888
|
-
|
|
1860
|
+
const { provider_token: providerToken } = result
|
|
1889
1861
|
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
}
|
|
1862
|
+
if (!providerToken) {
|
|
1863
|
+
reject(result)
|
|
1864
|
+
return
|
|
1865
|
+
}
|
|
1895
1866
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
* @returns Promise<SignInRes>
|
|
1901
|
-
*/
|
|
1902
|
-
async refreshSession(refresh_token?: string): Promise<SignInRes> {
|
|
1903
|
-
try {
|
|
1904
|
-
const credentials: Credentials = await this.oauthInstance.oauth2client.localCredentials.getCredentials()
|
|
1905
|
-
credentials.refresh_token = refresh_token || credentials.refresh_token
|
|
1906
|
-
const newTokens = await this.oauthInstance.oauth2client.refreshToken(credentials)
|
|
1907
|
-
const { data: { user } = {} } = await this.getUser()
|
|
1867
|
+
const signInRes = await this.oauthInstance.authApi.signInWithProvider({
|
|
1868
|
+
provider_id: providerId,
|
|
1869
|
+
provider_token: providerToken,
|
|
1870
|
+
})
|
|
1908
1871
|
|
|
1909
|
-
|
|
1872
|
+
if ((signInRes as any)?.error_code) {
|
|
1873
|
+
reject(signInRes)
|
|
1874
|
+
return
|
|
1875
|
+
}
|
|
1876
|
+
resolve(true)
|
|
1877
|
+
} catch (error) {
|
|
1878
|
+
reject(error)
|
|
1879
|
+
}
|
|
1880
|
+
},
|
|
1881
|
+
fail: (res: any) => {
|
|
1882
|
+
const error = new Error(res?.errMsg)
|
|
1883
|
+
;(error as any).code = res?.errno
|
|
1884
|
+
reject(error)
|
|
1885
|
+
},
|
|
1886
|
+
})
|
|
1887
|
+
})
|
|
1910
1888
|
} catch (error) {
|
|
1911
|
-
|
|
1889
|
+
throw error
|
|
1912
1890
|
}
|
|
1891
|
+
|
|
1892
|
+
return this.createLoginState()
|
|
1913
1893
|
}
|
|
1914
1894
|
|
|
1915
1895
|
/**
|
|
1916
|
-
*
|
|
1917
|
-
*
|
|
1918
|
-
* @
|
|
1896
|
+
* 小程序短信验证码登陆
|
|
1897
|
+
* @returns {Promise<LoginState>}
|
|
1898
|
+
* @memberof Auth
|
|
1919
1899
|
*/
|
|
1920
|
-
|
|
1900
|
+
@catchErrorsDecorator({
|
|
1901
|
+
title: '短信验证码登陆',
|
|
1902
|
+
messages: [
|
|
1903
|
+
'请确认以下各项:',
|
|
1904
|
+
' 1 - 当前环境是否开启了小程序短信验证码登陆',
|
|
1905
|
+
' 2 - 调用 auth().signInWithSms() 的语法或参数是否正确',
|
|
1906
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1907
|
+
],
|
|
1908
|
+
})
|
|
1909
|
+
public async signInWithSms({
|
|
1910
|
+
verificationInfo = { verification_id: '', is_user: false },
|
|
1911
|
+
verificationCode = '',
|
|
1912
|
+
phoneNum = '',
|
|
1913
|
+
bindInfo = undefined,
|
|
1914
|
+
}): Promise<LoginState> {
|
|
1921
1915
|
try {
|
|
1922
|
-
|
|
1923
|
-
|
|
1916
|
+
return this.signInWithUsername({
|
|
1917
|
+
verificationInfo,
|
|
1918
|
+
verificationCode,
|
|
1919
|
+
bindInfo,
|
|
1920
|
+
username: phoneNum,
|
|
1921
|
+
loginType: 'sms',
|
|
1922
|
+
})
|
|
1924
1923
|
} catch (error) {
|
|
1925
|
-
|
|
1924
|
+
throw error
|
|
1926
1925
|
}
|
|
1927
1926
|
}
|
|
1928
1927
|
|
|
1929
1928
|
/**
|
|
1930
|
-
*
|
|
1931
|
-
* @returns Promise<
|
|
1929
|
+
* 邮箱验证码登陆
|
|
1930
|
+
* @returns {Promise<LoginState>}
|
|
1931
|
+
* @memberof Auth
|
|
1932
1932
|
*/
|
|
1933
|
-
|
|
1933
|
+
@catchErrorsDecorator({
|
|
1934
|
+
title: '邮箱验证码登陆',
|
|
1935
|
+
messages: [
|
|
1936
|
+
'请确认以下各项:',
|
|
1937
|
+
' 1 - 当前环境是否开启了邮箱登陆',
|
|
1938
|
+
' 2 - 调用 auth().signInWithEmail() 的语法或参数是否正确',
|
|
1939
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1940
|
+
],
|
|
1941
|
+
})
|
|
1942
|
+
public async signInWithEmail({
|
|
1943
|
+
verificationInfo = { verification_id: '', is_user: false },
|
|
1944
|
+
verificationCode = '',
|
|
1945
|
+
bindInfo = undefined,
|
|
1946
|
+
email = '',
|
|
1947
|
+
}): Promise<LoginState> {
|
|
1934
1948
|
try {
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1949
|
+
return this.signInWithUsername({
|
|
1950
|
+
verificationInfo,
|
|
1951
|
+
verificationCode,
|
|
1952
|
+
bindInfo,
|
|
1953
|
+
username: email,
|
|
1954
|
+
loginType: 'email',
|
|
1955
|
+
})
|
|
1939
1956
|
} catch (error) {
|
|
1940
|
-
|
|
1957
|
+
throw error
|
|
1941
1958
|
}
|
|
1942
1959
|
}
|
|
1943
1960
|
|
|
1944
|
-
/**
|
|
1945
|
-
*
|
|
1946
|
-
*
|
|
1947
|
-
* @
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
// 参数校验:至少有一个更新字段被提供
|
|
1953
|
-
const hasValue = Object.keys(params).some(key => params[key] !== undefined && params[key] !== null && params[key] !== '',)
|
|
1954
|
-
if (!hasValue) {
|
|
1955
|
-
throw new AuthError({ message: 'At least one field must be provided for update' })
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
|
-
const { email, phone, ...restParams } = params
|
|
1959
|
-
|
|
1960
|
-
// 检查是否需要更新 email 或 phone
|
|
1961
|
-
const needsEmailVerification = email !== undefined
|
|
1962
|
-
const needsPhoneVerification = phone !== undefined
|
|
1963
|
-
|
|
1964
|
-
let extraRes = {}
|
|
1965
|
-
|
|
1966
|
-
if (needsEmailVerification || needsPhoneVerification) {
|
|
1967
|
-
// 需要发送验证码
|
|
1968
|
-
let verificationParams: { email?: string; phone_number?: string }
|
|
1969
|
-
let verificationType: 'email_change' | 'phone_change'
|
|
1970
|
-
|
|
1971
|
-
if (needsEmailVerification) {
|
|
1972
|
-
verificationParams = { email: params.email }
|
|
1973
|
-
verificationType = 'email_change'
|
|
1974
|
-
} else {
|
|
1975
|
-
// 正规化手机号
|
|
1976
|
-
const formattedPhone = this.formatPhone(params.phone)
|
|
1977
|
-
verificationParams = { phone_number: formattedPhone }
|
|
1978
|
-
verificationType = 'phone_change'
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
// 发送验证码
|
|
1982
|
-
const verificationInfo = await this.getVerification(verificationParams)
|
|
1983
|
-
|
|
1984
|
-
Object.keys(restParams).length > 0 && (await this.updateUserBasicInfo(restParams))
|
|
1985
|
-
|
|
1986
|
-
extraRes = {
|
|
1987
|
-
messageId: verificationInfo.verification_id,
|
|
1988
|
-
verifyOtp: async (verifyParams: { email?: string; phone?: string; token: string }): Promise<GetUserRes> => {
|
|
1989
|
-
try {
|
|
1990
|
-
if (verifyParams.email && params.email === verifyParams.email) {
|
|
1991
|
-
// 验证码验证
|
|
1992
|
-
await this.verifyOtp({
|
|
1993
|
-
type: 'email_change',
|
|
1994
|
-
email: params.email,
|
|
1995
|
-
token: verifyParams.token,
|
|
1996
|
-
messageId: verificationInfo.verification_id,
|
|
1997
|
-
})
|
|
1998
|
-
await this.updateUserBasicInfo({ email: params.email })
|
|
1999
|
-
} else if (verifyParams.phone && params.phone === verifyParams.phone) {
|
|
2000
|
-
// 验证码验证
|
|
2001
|
-
await this.verifyOtp({
|
|
2002
|
-
type: 'phone_change',
|
|
2003
|
-
phone: params.phone,
|
|
2004
|
-
token: verifyParams.token,
|
|
2005
|
-
messageId: verificationInfo.verification_id,
|
|
2006
|
-
})
|
|
2007
|
-
await this.updateUserBasicInfo({ phone: this.formatPhone(params.phone) })
|
|
2008
|
-
} else {
|
|
2009
|
-
await this.verifyOtp({
|
|
2010
|
-
type: verificationType,
|
|
2011
|
-
email: needsEmailVerification ? params.email : undefined,
|
|
2012
|
-
phone: !needsEmailVerification ? params.phone : undefined,
|
|
2013
|
-
token: verifyParams.token,
|
|
2014
|
-
messageId: verificationInfo.verification_id,
|
|
2015
|
-
})
|
|
2016
|
-
// 验证成功后更新用户信息
|
|
2017
|
-
await this.updateUserBasicInfo(params)
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
const {
|
|
2021
|
-
data: { user },
|
|
2022
|
-
} = await this.getUser()
|
|
2023
|
-
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.USER_UPDATED })
|
|
1961
|
+
/**
|
|
1962
|
+
* 设置获取自定义登录 ticket 函数
|
|
1963
|
+
* @param {authModels.GetCustomSignTicketFn} getTickFn
|
|
1964
|
+
* @memberof Auth
|
|
1965
|
+
*/
|
|
1966
|
+
public setCustomSignFunc(getTickFn: authModels.GetCustomSignTicketFn): void {
|
|
1967
|
+
this.oauthInstance.authApi.setCustomSignFunc(getTickFn)
|
|
1968
|
+
}
|
|
2024
1969
|
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
1970
|
+
/**
|
|
1971
|
+
*
|
|
1972
|
+
* @returns {Promise<LoginState>}
|
|
1973
|
+
* @memberof Auth
|
|
1974
|
+
*/
|
|
1975
|
+
// @catchErrorsDecorator({
|
|
1976
|
+
// title: '自定义登录失败',
|
|
1977
|
+
// messages: [
|
|
1978
|
+
// '请确认以下各项:',
|
|
1979
|
+
// ' 1 - 当前环境是否开启了自定义登录',
|
|
1980
|
+
// ' 2 - 调用 auth().signInWithCustomTicket() 的语法或参数是否正确',
|
|
1981
|
+
// ' 3 - ticket 是否归属于当前环境',
|
|
1982
|
+
// ' 4 - 创建 ticket 的自定义登录私钥是否过期',
|
|
1983
|
+
// `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
1984
|
+
// ],
|
|
1985
|
+
// })
|
|
1986
|
+
// public async signInWithCustomTicket(): Promise<LoginState> {
|
|
1987
|
+
// await this.oauthInstance.authApi.signInWithCustomTicket()
|
|
1988
|
+
// return this.createLoginState()
|
|
1989
|
+
// }
|
|
2039
1990
|
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
1991
|
+
/**
|
|
1992
|
+
*
|
|
1993
|
+
* @param {authModels.SignInRequest} params
|
|
1994
|
+
* @returns {Promise<LoginState>}
|
|
1995
|
+
* @memberof Auth
|
|
1996
|
+
*/
|
|
1997
|
+
public async signIn(params: authModels.SignInRequest): Promise<LoginState> {
|
|
1998
|
+
await this.oauthInstance.authApi.signIn(params)
|
|
1999
|
+
return this.createLoginState(params)
|
|
2044
2000
|
}
|
|
2045
2001
|
|
|
2002
|
+
// /**
|
|
2003
|
+
// *
|
|
2004
|
+
// * @param {authModels.SignUpRequest} params
|
|
2005
|
+
// * @returns {Promise<LoginState>}
|
|
2006
|
+
// * @memberof Auth
|
|
2007
|
+
// */
|
|
2008
|
+
// @catchErrorsDecorator({
|
|
2009
|
+
// title: '注册失败',
|
|
2010
|
+
// messages: [
|
|
2011
|
+
// '请确认以下各项:',
|
|
2012
|
+
// ' 1 - 当前环境是否开启了指定登录方式',
|
|
2013
|
+
// ' 2 - 调用 auth().signUp() 的语法或参数是否正确',
|
|
2014
|
+
// `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2015
|
+
// ],
|
|
2016
|
+
// })
|
|
2017
|
+
// public async signUp(params: authModels.SignUpRequest): Promise<any> {
|
|
2018
|
+
// await this.oauthInstance.authApi.signUp(params)
|
|
2019
|
+
// return this.createLoginState()
|
|
2020
|
+
// }
|
|
2021
|
+
|
|
2046
2022
|
/**
|
|
2047
|
-
*
|
|
2048
|
-
*
|
|
2049
|
-
* @returns Promise<
|
|
2023
|
+
* 设置密码
|
|
2024
|
+
* @param {authModels.SetPasswordRequest} params
|
|
2025
|
+
* @returns {Promise<void>}
|
|
2026
|
+
* @memberof Auth
|
|
2050
2027
|
*/
|
|
2051
|
-
async
|
|
2052
|
-
|
|
2053
|
-
|
|
2028
|
+
public async setPassword(params: authModels.SetPasswordRequest): Promise<void> {
|
|
2029
|
+
return this.oauthInstance.authApi.setPassword(params)
|
|
2030
|
+
}
|
|
2054
2031
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2032
|
+
/**
|
|
2033
|
+
* 检测用户名是否已经占用
|
|
2034
|
+
* @param username
|
|
2035
|
+
*/
|
|
2036
|
+
@catchErrorsDecorator({
|
|
2037
|
+
title: '获取用户是否被占用失败',
|
|
2038
|
+
messages: [
|
|
2039
|
+
'请确认以下各项:',
|
|
2040
|
+
' 1 - 调用 auth().isUsernameRegistered() 的语法或参数是否正确',
|
|
2041
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2042
|
+
],
|
|
2043
|
+
})
|
|
2044
|
+
public async isUsernameRegistered(username: string): Promise<boolean> {
|
|
2045
|
+
if (typeof username !== 'string') {
|
|
2046
|
+
throwError(ERRORS.INVALID_PARAMS, 'username must be a string')
|
|
2063
2047
|
}
|
|
2048
|
+
|
|
2049
|
+
const { exist } = await this.oauthInstance.authApi.checkIfUserExist({ username })
|
|
2050
|
+
return exist
|
|
2064
2051
|
}
|
|
2065
2052
|
|
|
2066
2053
|
/**
|
|
2067
|
-
*
|
|
2068
|
-
* 绑定身份源到当前用户
|
|
2069
|
-
* @param params
|
|
2070
|
-
* @returns Promise<LinkIdentityRes>
|
|
2054
|
+
* 获取本地登录态-同步
|
|
2071
2055
|
*/
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
//
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2056
|
+
public hasLoginState(): LoginState | null {
|
|
2057
|
+
if (this.cache.mode === 'async') {
|
|
2058
|
+
// async storage的平台调用此API提示
|
|
2059
|
+
printWarn(
|
|
2060
|
+
ERRORS.INVALID_OPERATION,
|
|
2061
|
+
'current platform\'s storage is asynchronous, please use getLoginState instead',
|
|
2062
|
+
)
|
|
2063
|
+
return
|
|
2064
|
+
}
|
|
2078
2065
|
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2066
|
+
const oauthLoginState = this.oauthInstance?.authApi.hasLoginStateSync()
|
|
2067
|
+
if (oauthLoginState) {
|
|
2068
|
+
const loginState = new LoginState({
|
|
2069
|
+
envId: this.config.env,
|
|
2070
|
+
cache: this.cache,
|
|
2071
|
+
oauthInstance: this.oauthInstance,
|
|
2084
2072
|
})
|
|
2085
|
-
|
|
2086
|
-
return { data: { provider: params.provider }, error: null }
|
|
2087
|
-
} catch (error) {
|
|
2088
|
-
return { data: {}, error: new AuthError(error) }
|
|
2073
|
+
return loginState
|
|
2089
2074
|
}
|
|
2075
|
+
return null
|
|
2090
2076
|
}
|
|
2091
2077
|
|
|
2092
2078
|
/**
|
|
2093
|
-
*
|
|
2094
|
-
*
|
|
2095
|
-
* @param params
|
|
2096
|
-
* @returns Promise<CommonRes>
|
|
2079
|
+
* 获取本地登录态-异步
|
|
2080
|
+
* 此API为兼容异步storage的平台
|
|
2097
2081
|
*/
|
|
2098
|
-
|
|
2082
|
+
@catchErrorsDecorator({
|
|
2083
|
+
title: '获取本地登录态失败',
|
|
2084
|
+
messages: [
|
|
2085
|
+
'请确认以下各项:',
|
|
2086
|
+
' 1 - 调用 auth().getLoginState() 的语法或参数是否正确',
|
|
2087
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2088
|
+
],
|
|
2089
|
+
})
|
|
2090
|
+
public async getLoginState() {
|
|
2091
|
+
let oauthLoginState = null
|
|
2092
|
+
|
|
2099
2093
|
try {
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2094
|
+
oauthLoginState = await this.oauthInstance.authApi.getLoginState()
|
|
2095
|
+
} catch (error) {
|
|
2096
|
+
return null
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
if (oauthLoginState) {
|
|
2100
|
+
const loginState = new LoginState({
|
|
2101
|
+
envId: this.config.env,
|
|
2102
|
+
cache: this.cache,
|
|
2103
|
+
oauthInstance: this.oauthInstance,
|
|
2103
2104
|
})
|
|
2105
|
+
return loginState
|
|
2106
|
+
}
|
|
2104
2107
|
|
|
2105
|
-
|
|
2108
|
+
return null
|
|
2109
|
+
}
|
|
2106
2110
|
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2111
|
+
/**
|
|
2112
|
+
* @deprecated 使用 getCurrentUser 代替,因为与node-sdk方法名冲突
|
|
2113
|
+
* @returns
|
|
2114
|
+
*/
|
|
2115
|
+
@catchErrorsDecorator({
|
|
2116
|
+
title: '获取用户信息失败',
|
|
2117
|
+
messages: [
|
|
2118
|
+
'请确认以下各项:',
|
|
2119
|
+
' 1 - 是否已登录',
|
|
2120
|
+
' 2 - 调用 auth().getUserInfo() 的语法或参数是否正确',
|
|
2121
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2122
|
+
],
|
|
2123
|
+
})
|
|
2124
|
+
public async getUserInfo(): Promise<(authModels.UserInfo & Partial<User>) | null> {
|
|
2125
|
+
return this.getCurrentUser()
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
@catchErrorsDecorator({
|
|
2129
|
+
title: '获取微搭插件用户信息失败',
|
|
2130
|
+
messages: [
|
|
2131
|
+
'请确认以下各项:',
|
|
2132
|
+
' 1 - 是否已登录',
|
|
2133
|
+
' 2 - 调用 auth().getWedaUserInfo() 的语法或参数是否正确',
|
|
2134
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2135
|
+
],
|
|
2136
|
+
})
|
|
2137
|
+
public async getWedaUserInfo(): Promise<any> {
|
|
2138
|
+
return this.oauthInstance.authApi.getWedaUserInfo()
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
public async updateUserBasicInfo(params: authModels.ModifyUserBasicInfoRequest) {
|
|
2142
|
+
const loginState = await this.getLoginState()
|
|
2143
|
+
if (loginState) {
|
|
2144
|
+
await (loginState.user as User).updateUserBasicInfo(params)
|
|
2110
2145
|
}
|
|
2146
|
+
return
|
|
2111
2147
|
}
|
|
2112
2148
|
|
|
2113
2149
|
/**
|
|
2114
|
-
*
|
|
2115
|
-
*
|
|
2116
|
-
* @returns Promise<ReauthenticateRes>
|
|
2150
|
+
* getAuthHeader 兼容处理
|
|
2151
|
+
* 返回空对象
|
|
2117
2152
|
*/
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
} = await this.getUser()
|
|
2123
|
-
|
|
2124
|
-
this.validateAtLeastOne(user, [['email', 'phone']], 'You must provide either an email or phone number')
|
|
2125
|
-
const userInfo = user.email ? { email: user.email } : { phone_number: this.formatPhone(user.phone) }
|
|
2153
|
+
public getAuthHeader(): {} {
|
|
2154
|
+
console.error('Auth.getAuthHeader API 已废弃')
|
|
2155
|
+
return {}
|
|
2156
|
+
}
|
|
2126
2157
|
|
|
2127
|
-
|
|
2128
|
-
|
|
2158
|
+
/**
|
|
2159
|
+
* 为已有账户绑第三方账户
|
|
2160
|
+
* @param {authModels.BindWithProviderRequest} params
|
|
2161
|
+
* @returns {Promise<void>}
|
|
2162
|
+
* @memberof Auth
|
|
2163
|
+
*/
|
|
2164
|
+
@catchErrorsDecorator({
|
|
2165
|
+
title: '绑定第三方登录方式失败',
|
|
2166
|
+
messages: [
|
|
2167
|
+
'请确认以下各项:',
|
|
2168
|
+
' 1 - 调用 auth().bindWithProvider() 的语法或参数是否正确',
|
|
2169
|
+
' 2 - 此账户是否已经绑定此第三方',
|
|
2170
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2171
|
+
],
|
|
2172
|
+
})
|
|
2173
|
+
public async bindWithProvider(params: authModels.BindWithProviderRequest): Promise<void> {
|
|
2174
|
+
return this.oauthInstance.authApi.bindWithProvider(params)
|
|
2175
|
+
}
|
|
2129
2176
|
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
// 第三步:待用户输入完验证码之后,验证验证码
|
|
2140
|
-
const verificationTokenRes = await this.verify({
|
|
2141
|
-
verification_id: verificationInfo.verification_id,
|
|
2142
|
-
verification_code: attributes.nonce,
|
|
2143
|
-
})
|
|
2177
|
+
/**
|
|
2178
|
+
* 查询用户
|
|
2179
|
+
* @param {authModels.QueryUserProfileRequest} appended_params
|
|
2180
|
+
* @returns {Promise<authModels.UserProfile>}
|
|
2181
|
+
* @memberof Auth
|
|
2182
|
+
*/
|
|
2183
|
+
public async queryUser(queryObj: authModels.QueryUserProfileRequest): Promise<authModels.QueryUserProfileResponse> {
|
|
2184
|
+
return this.oauthInstance.authApi.queryUserProfile(queryObj)
|
|
2185
|
+
}
|
|
2144
2186
|
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2187
|
+
public async getAccessToken() {
|
|
2188
|
+
const oauthAccessTokenRes = await this.oauthInstance.oauth2client.getAccessToken()
|
|
2189
|
+
return {
|
|
2190
|
+
accessToken: oauthAccessTokenRes,
|
|
2191
|
+
env: this.config.env,
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2149
2194
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
})
|
|
2154
|
-
} else {
|
|
2155
|
-
await this.signInWithUsername({
|
|
2156
|
-
verificationInfo,
|
|
2157
|
-
verificationCode: attributes.nonce,
|
|
2158
|
-
...userInfo,
|
|
2159
|
-
loginType: userInfo.email ? 'email' : 'phone',
|
|
2160
|
-
})
|
|
2161
|
-
}
|
|
2195
|
+
public async grantProviderToken(params: authModels.GrantProviderTokenRequest,): Promise<authModels.GrantProviderTokenResponse> {
|
|
2196
|
+
return this.oauthInstance.authApi.grantProviderToken(params)
|
|
2197
|
+
}
|
|
2162
2198
|
|
|
2163
|
-
|
|
2199
|
+
public async patchProviderToken(params: authModels.PatchProviderTokenRequest,): Promise<authModels.PatchProviderTokenResponse> {
|
|
2200
|
+
return this.oauthInstance.authApi.patchProviderToken(params)
|
|
2201
|
+
}
|
|
2164
2202
|
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
}
|
|
2169
|
-
},
|
|
2170
|
-
},
|
|
2171
|
-
error: null,
|
|
2172
|
-
}
|
|
2173
|
-
} catch (error) {
|
|
2174
|
-
return { data: {}, error: new AuthError(error) }
|
|
2175
|
-
}
|
|
2203
|
+
public async signInWithProvider(params: authModels.SignInWithProviderRequest): Promise<LoginState> {
|
|
2204
|
+
await this.oauthInstance.authApi.signInWithProvider(params)
|
|
2205
|
+
return this.createLoginState(params)
|
|
2176
2206
|
}
|
|
2177
2207
|
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
* @returns Promise<ResendRes>
|
|
2183
|
-
*/
|
|
2184
|
-
async resend(params: ResendReq): Promise<ResendRes> {
|
|
2185
|
-
try {
|
|
2186
|
-
// 参数校验:email或phone必填其一
|
|
2187
|
-
this.validateAtLeastOne(params, [['email'], ['phone']], 'You must provide either an email or phone number')
|
|
2208
|
+
public async signInWithWechat(params: any = {}) {
|
|
2209
|
+
await this.oauthInstance.authApi.signInWithWechat(params)
|
|
2210
|
+
return this.createLoginState(params)
|
|
2211
|
+
}
|
|
2188
2212
|
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
}
|
|
2213
|
+
public async grantToken(params: authModels.GrantTokenRequest): Promise<LoginState> {
|
|
2214
|
+
await this.oauthInstance.authApi.grantToken(params)
|
|
2215
|
+
return this.createLoginState()
|
|
2216
|
+
}
|
|
2194
2217
|
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2218
|
+
public async genProviderRedirectUri(params: authModels.GenProviderRedirectUriRequest,): Promise<authModels.GenProviderRedirectUriResponse> {
|
|
2219
|
+
return this.oauthInstance.authApi.genProviderRedirectUri(params)
|
|
2220
|
+
}
|
|
2198
2221
|
|
|
2199
|
-
|
|
2200
|
-
|
|
2222
|
+
public async resetPassword(params: authModels.ResetPasswordRequest): Promise<void> {
|
|
2223
|
+
return this.oauthInstance.authApi.resetPassword(params)
|
|
2224
|
+
}
|
|
2201
2225
|
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
error: null,
|
|
2205
|
-
}
|
|
2206
|
-
} catch (error: any) {
|
|
2207
|
-
return {
|
|
2208
|
-
data: {},
|
|
2209
|
-
error: new AuthError(error),
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2226
|
+
public async deviceAuthorize(params: authModels.DeviceAuthorizeRequest): Promise<authModels.DeviceAuthorizeResponse> {
|
|
2227
|
+
return this.oauthInstance.authApi.deviceAuthorize(params)
|
|
2212
2228
|
}
|
|
2213
2229
|
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
* @param params
|
|
2218
|
-
* @returns Promise<SignInRes>
|
|
2219
|
-
*/
|
|
2220
|
-
async setSession(params: SetSessionReq): Promise<SignInRes> {
|
|
2221
|
-
try {
|
|
2222
|
-
this.validateParams(params, {
|
|
2223
|
-
access_token: { required: true, message: 'Access token is required' },
|
|
2224
|
-
refresh_token: { required: true, message: 'Refresh token is required' },
|
|
2225
|
-
})
|
|
2230
|
+
public async sudo(params: authModels.SudoRequest): Promise<authModels.SudoResponse> {
|
|
2231
|
+
return this.oauthInstance.authApi.sudo(params)
|
|
2232
|
+
}
|
|
2226
2233
|
|
|
2227
|
-
|
|
2234
|
+
public async deleteMe(params: authModels.WithSudoRequest): Promise<authModels.UserProfile> {
|
|
2235
|
+
return this.oauthInstance.authApi.deleteMe(params)
|
|
2236
|
+
}
|
|
2228
2237
|
|
|
2229
|
-
|
|
2238
|
+
public async getProviders(): Promise<authModels.ProvidersResponse> {
|
|
2239
|
+
return this.oauthInstance.authApi.getProviders()
|
|
2240
|
+
}
|
|
2230
2241
|
|
|
2231
|
-
|
|
2242
|
+
public async loginScope(): Promise<string> {
|
|
2243
|
+
return this.oauthInstance.authApi.loginScope()
|
|
2244
|
+
}
|
|
2232
2245
|
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
return { data: {}, error: new AuthError(error) }
|
|
2236
|
-
}
|
|
2246
|
+
public async loginGroups(): Promise<string[]> {
|
|
2247
|
+
return this.oauthInstance.authApi.loginGroups()
|
|
2237
2248
|
}
|
|
2238
2249
|
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2250
|
+
public async onLoginStateChanged(callback: Function) {
|
|
2251
|
+
this.config.eventBus?.on(EVENTS.LOGIN_STATE_CHANGED, async (params) => {
|
|
2252
|
+
// getLoginState会重复触发getCredentials,导致死循环,所以getCredentials出错不再出发getLoginState
|
|
2253
|
+
const loginState = params?.data?.eventType !== LOGIN_STATE_CHANGED_TYPE.CREDENTIALS_ERROR ? await this.getLoginState() : {}
|
|
2254
|
+
callback.call(this, { ...params, ...loginState })
|
|
2255
|
+
})
|
|
2256
|
+
// 立刻执行一次回调
|
|
2257
|
+
const loginState = await this.getLoginState()
|
|
2258
|
+
callback.call(this, loginState)
|
|
2242
2259
|
}
|
|
2243
2260
|
|
|
2244
2261
|
/**
|
|
2245
|
-
*
|
|
2262
|
+
* 强制刷新token
|
|
2246
2263
|
* @param params
|
|
2247
2264
|
* @returns
|
|
2248
2265
|
*/
|
|
2249
|
-
async
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
password: { required: true, message: 'Password is required' },
|
|
2253
|
-
})
|
|
2266
|
+
public async refreshTokenForce(params: { version?: string }): Promise<Credentials> {
|
|
2267
|
+
return this.oauthInstance.authApi.refreshTokenForce(params)
|
|
2268
|
+
}
|
|
2254
2269
|
|
|
2255
|
-
|
|
2270
|
+
/**
|
|
2271
|
+
* 获取身份信息
|
|
2272
|
+
* @returns
|
|
2273
|
+
*/
|
|
2274
|
+
public async getCredentials(): Promise<Credentials> {
|
|
2275
|
+
return this.oauthInstance.authApi.getCredentials()
|
|
2276
|
+
}
|
|
2277
|
+
/**
|
|
2278
|
+
* 写入身份信息
|
|
2279
|
+
*/
|
|
2280
|
+
public async setCredentials(credentials: Credentials) {
|
|
2281
|
+
await this.oauthInstance.oauth2client.setCredentials(credentials)
|
|
2282
|
+
}
|
|
2256
2283
|
|
|
2257
|
-
|
|
2284
|
+
@catchErrorsDecorator({
|
|
2285
|
+
title: '获取身份源类型',
|
|
2286
|
+
messages: [
|
|
2287
|
+
'请确认以下各项:',
|
|
2288
|
+
' 1 - 调用 auth().getProviderSubType() 的语法或参数是否正确',
|
|
2289
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
2290
|
+
],
|
|
2291
|
+
})
|
|
2292
|
+
public async getProviderSubType(): Promise<authModels.ProviderSubType> {
|
|
2293
|
+
return this.oauthInstance.authApi.getProviderSubType()
|
|
2294
|
+
}
|
|
2258
2295
|
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
return { data: {}, error: new AuthError(error) }
|
|
2262
|
-
}
|
|
2296
|
+
public async createCaptchaData(params: { state: string; redirect_uri?: string }) {
|
|
2297
|
+
return this.oauthInstance.authApi.createCaptchaData(params)
|
|
2263
2298
|
}
|
|
2264
2299
|
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
* @memberof Auth
|
|
2269
|
-
*/
|
|
2270
|
-
async toDefaultLoginPage(params: authModels.ToDefaultLoginPage = {}): Promise<CommonRes> {
|
|
2271
|
-
try {
|
|
2272
|
-
const configVersion = params.config_version || 'env'
|
|
2273
|
-
const query = Object.keys(params.query || {})
|
|
2274
|
-
.map(key => `${key}=${params.query[key]}`)
|
|
2275
|
-
.join('&')
|
|
2300
|
+
public async verifyCaptchaData(params: { token: string; key: string }) {
|
|
2301
|
+
return this.oauthInstance.authApi.verifyCaptchaData(params)
|
|
2302
|
+
}
|
|
2276
2303
|
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
} else {
|
|
2280
|
-
const redirectUri = params.redirect_uri || window.location.href
|
|
2281
|
-
const urlObj = new URL(redirectUri)
|
|
2282
|
-
const loginPage = `${urlObj.origin}/__auth/?app_id=${params.app_id || ''}&env_id=${this.config.env}&client_id=${
|
|
2283
|
-
this.config.clientId || this.config.env
|
|
2284
|
-
}&config_version=${configVersion}&redirect_uri=${encodeURIComponent(redirectUri)}${query ? `&${query}` : ''}`
|
|
2285
|
-
window.location.href = loginPage
|
|
2286
|
-
}
|
|
2287
|
-
return { data: {}, error: null }
|
|
2288
|
-
} catch (error) {
|
|
2289
|
-
return { data: {}, error: new AuthError(error) }
|
|
2290
|
-
}
|
|
2304
|
+
public async getMiniProgramQrCode(params: authModels.GetMiniProgramQrCodeRequest,): Promise<authModels.GetMiniProgramQrCodeResponse> {
|
|
2305
|
+
return this.oauthInstance.authApi.getMiniProgramCode(params)
|
|
2291
2306
|
}
|
|
2292
2307
|
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
* @returns
|
|
2297
|
-
*/
|
|
2298
|
-
async signInWithCustomTicket(getTickFn?: authModels.GetCustomSignTicketFn): Promise<SignInRes> {
|
|
2299
|
-
if (getTickFn) {
|
|
2300
|
-
this.setCustomSignFunc(getTickFn)
|
|
2301
|
-
}
|
|
2308
|
+
public async getMiniProgramQrCodeStatus(params: authModels.GetMiniProgramQrCodeStatusRequest,): Promise<authModels.GetMiniProgramQrCodeStatusResponse> {
|
|
2309
|
+
return this.oauthInstance.authApi.getMiniProgramQrCodeStatus(params)
|
|
2310
|
+
}
|
|
2302
2311
|
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2312
|
+
public async modifyPassword(params: authModels.ModifyUserBasicInfoRequest): Promise<void> {
|
|
2313
|
+
return this.oauthInstance.authApi.modifyPassword(params)
|
|
2314
|
+
}
|
|
2306
2315
|
|
|
2307
|
-
|
|
2316
|
+
public async modifyPasswordWithoutLogin(params: authModels.ModifyPasswordWithoutLoginRequest): Promise<void> {
|
|
2317
|
+
return this.oauthInstance.authApi.modifyPasswordWithoutLogin(params)
|
|
2318
|
+
}
|
|
2308
2319
|
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
} catch (error) {
|
|
2312
|
-
return { data: {}, error: new AuthError(error) }
|
|
2313
|
-
}
|
|
2320
|
+
public async getUserBehaviorLog(params: authModels.GetUserBehaviorLog): Promise<authModels.GetUserBehaviorLogRes> {
|
|
2321
|
+
return this.oauthInstance.authApi.getUserBehaviorLog(params)
|
|
2314
2322
|
}
|
|
2315
2323
|
|
|
2316
2324
|
/**
|
|
2317
|
-
*
|
|
2318
|
-
* @param params
|
|
2319
|
-
* @returns Promise<SignInRes>
|
|
2325
|
+
* sms/email 验证码登录/注册,逻辑一致收敛
|
|
2320
2326
|
*/
|
|
2321
|
-
async
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2327
|
+
public async signInWithUsername({
|
|
2328
|
+
verificationInfo = { verification_id: '', is_user: false },
|
|
2329
|
+
verificationCode = '',
|
|
2330
|
+
username: rawUsername = '',
|
|
2331
|
+
bindInfo = undefined,
|
|
2332
|
+
loginType = '',
|
|
2333
|
+
}: {
|
|
2334
|
+
verificationInfo?: authModels.GetVerificationResponse
|
|
2335
|
+
verificationCode?: string
|
|
2336
|
+
username?: string
|
|
2337
|
+
bindInfo?: any
|
|
2338
|
+
loginType?: string
|
|
2339
|
+
}): Promise<LoginState> {
|
|
2340
|
+
try {
|
|
2341
|
+
// 1. 验证验证码
|
|
2342
|
+
const verifyRes = await this.oauthInstance.authApi.verify({
|
|
2343
|
+
verification_id: verificationInfo.verification_id,
|
|
2344
|
+
verification_code: verificationCode,
|
|
2345
|
+
})
|
|
2330
2346
|
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
provider_id: wxInfo?.appId,
|
|
2335
|
-
provider_code: code,
|
|
2336
|
-
provider_params: {
|
|
2337
|
-
provider_code_type: 'open_id',
|
|
2338
|
-
appid: wxInfo?.appId,
|
|
2339
|
-
},
|
|
2340
|
-
},
|
|
2341
|
-
useWxCloud,
|
|
2342
|
-
)
|
|
2347
|
+
if ((verifyRes as any)?.error_code) {
|
|
2348
|
+
throw verifyRes
|
|
2349
|
+
}
|
|
2343
2350
|
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
}
|
|
2351
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
2352
|
+
const { verification_token } = verifyRes
|
|
2347
2353
|
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
)
|
|
2354
|
+
// 手机登录参数
|
|
2355
|
+
let username = this.formatPhone(rawUsername)
|
|
2356
|
+
let signUpParam: any = { phone_number: username }
|
|
2352
2357
|
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
throw error
|
|
2358
|
+
// 邮箱登录参数
|
|
2359
|
+
if (loginType === 'email') {
|
|
2360
|
+
username = rawUsername
|
|
2361
|
+
signUpParam = { email: username }
|
|
2358
2362
|
}
|
|
2359
|
-
await this.oauthInstance.oauth2client.setCredentials(credentials as Credentials)
|
|
2360
|
-
}
|
|
2361
2363
|
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
resolve(true)
|
|
2369
|
-
} catch (error) {
|
|
2370
|
-
reject(error)
|
|
2371
|
-
}
|
|
2372
|
-
},
|
|
2373
|
-
fail: (res: any) => {
|
|
2374
|
-
const error = new Error(res?.errMsg)
|
|
2375
|
-
;(error as any).code = res?.errno
|
|
2376
|
-
reject(error)
|
|
2377
|
-
},
|
|
2364
|
+
// 2. 根据是否已经是用户,分别走登录或注册逻辑
|
|
2365
|
+
if (verificationInfo.is_user) {
|
|
2366
|
+
// 私有化环境或者自定义应用走v1版本的老逻辑
|
|
2367
|
+
const signInRes = await this.oauthInstance.authApi.signIn({
|
|
2368
|
+
username,
|
|
2369
|
+
verification_token,
|
|
2378
2370
|
})
|
|
2379
|
-
})
|
|
2380
2371
|
|
|
2381
|
-
|
|
2372
|
+
if ((signInRes as any)?.error_code) {
|
|
2373
|
+
throw signInRes
|
|
2374
|
+
}
|
|
2382
2375
|
|
|
2383
|
-
|
|
2376
|
+
if (bindInfo) {
|
|
2377
|
+
const bindRes = await this.oauthInstance.authApi.bindWithProvider({
|
|
2378
|
+
provider_token: (bindInfo as any)?.providerToken,
|
|
2379
|
+
})
|
|
2384
2380
|
|
|
2385
|
-
|
|
2386
|
-
|
|
2381
|
+
if ((bindRes as any)?.error_code) {
|
|
2382
|
+
throw bindRes
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
} else {
|
|
2386
|
+
// 自定义应用走signUp逻辑
|
|
2387
|
+
const signUpRes = await this.oauthInstance.authApi.signUp({
|
|
2388
|
+
...signUpParam,
|
|
2389
|
+
verification_token,
|
|
2390
|
+
provider_token: (bindInfo as any)?.providerId,
|
|
2391
|
+
})
|
|
2392
|
+
|
|
2393
|
+
if ((signUpRes as any)?.error_code) {
|
|
2394
|
+
throw signUpRes
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
return this.createLoginState()
|
|
2387
2399
|
} catch (error) {
|
|
2388
|
-
|
|
2400
|
+
throw error
|
|
2389
2401
|
}
|
|
2390
2402
|
}
|
|
2391
2403
|
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
// }
|
|
2402
|
-
// const wxInfo = wx.getAccountInfoSync().miniProgram
|
|
2403
|
-
// const providerInfo = {
|
|
2404
|
-
// provider_params: { provider_code_type: 'phone', code: phoneCode, appid: wxInfo.appId },
|
|
2405
|
-
// provider_id: wxInfo.appId,
|
|
2406
|
-
// }
|
|
2407
|
-
|
|
2408
|
-
// const { code } = await wx.login()
|
|
2409
|
-
// ;(providerInfo as any).provider_code = code
|
|
2410
|
-
|
|
2411
|
-
// try {
|
|
2412
|
-
// const providerToken = await this.oauthInstance.authApi.grantProviderToken(providerInfo, useWxCloud)
|
|
2413
|
-
// if (providerToken.error_code) {
|
|
2414
|
-
// throw providerToken
|
|
2415
|
-
// }
|
|
2404
|
+
async createLoginState(
|
|
2405
|
+
params?: { version?: string; query?: any },
|
|
2406
|
+
options?: { asyncRefreshUser?: boolean; userInfo?: any },
|
|
2407
|
+
): Promise<LoginState> {
|
|
2408
|
+
const loginState = new LoginState({
|
|
2409
|
+
envId: this.config.env,
|
|
2410
|
+
cache: this.cache,
|
|
2411
|
+
oauthInstance: this.oauthInstance,
|
|
2412
|
+
})
|
|
2416
2413
|
|
|
2417
|
-
|
|
2418
|
-
// provider_token: providerToken.provider_token,
|
|
2419
|
-
// }, useWxCloud)
|
|
2414
|
+
await loginState.checkLocalStateAsync()
|
|
2420
2415
|
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2416
|
+
if (options?.userInfo) {
|
|
2417
|
+
loginState.user.setLocalUserInfo(options.userInfo)
|
|
2418
|
+
} else {
|
|
2419
|
+
if (options?.asyncRefreshUser) {
|
|
2420
|
+
loginState.user.refresh(params)
|
|
2421
|
+
} else {
|
|
2422
|
+
await loginState.user.refresh(params)
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2427
2425
|
|
|
2428
|
-
|
|
2426
|
+
this.config.eventBus?.fire(EVENTS.LOGIN_STATE_CHANGED, { eventType: LOGIN_STATE_CHANGED_TYPE.SIGN_IN })
|
|
2429
2427
|
|
|
2430
|
-
|
|
2428
|
+
this.config.eventBus?.fire(EVENTS.AUTH_STATE_CHANGED, { event: AUTH_STATE_CHANGED_TYPE.SIGNED_IN })
|
|
2429
|
+
return loginState
|
|
2430
|
+
}
|
|
2431
2431
|
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2432
|
+
async setAccessKey() {
|
|
2433
|
+
let accessToken = ''
|
|
2434
|
+
let scope = ''
|
|
2435
|
+
if (this.config.accessKey) {
|
|
2436
|
+
accessToken = this.config.accessKey
|
|
2437
|
+
scope = 'accessKey'
|
|
2438
|
+
} else if (this.config.auth?.secretId && this.config.auth?.secretKey) {
|
|
2439
|
+
accessToken = ''
|
|
2440
|
+
scope = DEFAULT_NODE_ACCESS_SCOPE
|
|
2441
2441
|
}
|
|
2442
2442
|
|
|
2443
|
-
|
|
2444
|
-
|
|
2443
|
+
if (!scope) {
|
|
2444
|
+
return
|
|
2445
|
+
}
|
|
2445
2446
|
|
|
2446
2447
|
try {
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
provider_token: providerToken.provider_token,
|
|
2454
|
-
provider_id: wxInfo.appId,
|
|
2455
|
-
provider_params: {
|
|
2456
|
-
code: phoneCode,
|
|
2457
|
-
provider_code_type: 'phone',
|
|
2458
|
-
},
|
|
2459
|
-
})
|
|
2460
|
-
if (providerToken.error_code) {
|
|
2461
|
-
throw providerToken
|
|
2462
|
-
}
|
|
2463
|
-
|
|
2464
|
-
const signInRes = await this.oauthInstance.authApi.signInWithProvider({
|
|
2465
|
-
provider_token: providerToken.provider_token,
|
|
2448
|
+
this.oauthInstance.oauth2client.setAccessKeyCredentials({
|
|
2449
|
+
access_token: accessToken,
|
|
2450
|
+
token_type: 'Bearer',
|
|
2451
|
+
scope,
|
|
2452
|
+
expires_at: new Date(+new Date() + +new Date()),
|
|
2453
|
+
expires_in: +new Date() + +new Date(),
|
|
2466
2454
|
})
|
|
2467
|
-
|
|
2468
|
-
if ((signInRes as any)?.error_code) {
|
|
2469
|
-
throw signInRes
|
|
2470
|
-
}
|
|
2471
2455
|
} catch (error) {
|
|
2472
|
-
|
|
2456
|
+
console.warn('accessKey error: ', error)
|
|
2473
2457
|
}
|
|
2474
|
-
|
|
2475
|
-
const loginState = await this.createLoginState()
|
|
2476
|
-
|
|
2477
|
-
const { data: { session } = {} } = await this.getSession()
|
|
2478
|
-
|
|
2479
|
-
// loginState返回是为了兼容v2版本
|
|
2480
|
-
return { ...(loginState as any), data: { user: session.user, session }, error: null }
|
|
2481
2458
|
}
|
|
2482
2459
|
|
|
2483
2460
|
protected formatPhone(phone: string) {
|
|
@@ -2742,13 +2719,12 @@ function levenshteinDistance(a: string, b: string): number {
|
|
|
2742
2719
|
function findSimilarMethod(target: string, methods: string[]): string | null {
|
|
2743
2720
|
let bestMatch: string | null = null
|
|
2744
2721
|
let bestDistance = Infinity
|
|
2745
|
-
const maxDistance = Math.max(3, Math.floor(target.length * 0.4)) // 允许 40% 的编辑距离
|
|
2746
2722
|
|
|
2747
2723
|
for (const method of methods) {
|
|
2748
2724
|
// 跳过私有方法和构造函数
|
|
2749
2725
|
if (method.startsWith('_') || method === 'constructor') continue
|
|
2750
2726
|
const distance = levenshteinDistance(target, method)
|
|
2751
|
-
if (distance < bestDistance
|
|
2727
|
+
if (distance < bestDistance) {
|
|
2752
2728
|
bestDistance = distance
|
|
2753
2729
|
bestMatch = method
|
|
2754
2730
|
}
|