- login.ui: SMS tab now uses fetch for gen_sms_code.dspy and phone_login.dspy - Added _webbricks_=1 to fetch URLs (prevents HTML wrapping) - Added 60s countdown timer on send-code button - Added multi-account selection UI (status=choose response) - Fixed uitype 'hide' -> 'hidden' for codeid field - Dispatches user_logined event after successful phone login - gen_sms_code.dspy: improved error message for SMS service config issues - phone_login.dspy: added mark_used parameter for multi-account flow - phone_login.js: sageSelectAccount handler for account selection
123 lines
3.0 KiB
Plaintext
123 lines
3.0 KiB
Plaintext
# 用短信模块检查验证码是否正确
|
|
debug(f'phone_login.dspy:{params_kw=}')
|
|
if params_kw.cellphone is None:
|
|
return {
|
|
"status": "error",
|
|
"data":{
|
|
"message": "需输入手机号"
|
|
}
|
|
}
|
|
if params_kw.sms_code is None:
|
|
return {
|
|
"status": "error",
|
|
"data": {
|
|
"message": "需输入验证码"
|
|
}
|
|
}
|
|
if params_kw.key is None:
|
|
return {
|
|
"status": "error",
|
|
"data": {
|
|
"message": "需要短信验证key"
|
|
}
|
|
}
|
|
|
|
# First check (no selected_id): verify code but don't consume it yet
|
|
# (multi-account flow needs the code to remain valid for the second call)
|
|
# Second check (with selected_id): verify and consume the code
|
|
mark_used = bool(params_kw.selected_id)
|
|
f = await sms_engine.check_sms_code(params_kw.key, params_kw.sms_code, mark_used=mark_used)
|
|
if not f:
|
|
return {
|
|
"status": "error",
|
|
"data": {
|
|
"message": "手机短信验证码出错"
|
|
}
|
|
}
|
|
|
|
ns = {
|
|
"username": params_kw.cellphone,
|
|
"password": "^&%UHI",
|
|
"cfm_password": "^&%UHI",
|
|
"mobile": params_kw.cellphone,
|
|
"user_status": "0"
|
|
}
|
|
udata = DictObject(**ns)
|
|
try:
|
|
async with get_sor_context(request._run_ns, 'rbac') as sor:
|
|
recs = await sor.R('users', {'mobile': params_kw.cellphone})
|
|
if recs:
|
|
if len(recs) == 1:
|
|
r = recs[0]
|
|
# Single account: code already verified, now mark as used
|
|
if not mark_used:
|
|
await sms_engine.check_sms_code(params_kw.key, params_kw.sms_code, mark_used=True)
|
|
now_str = timestampstr()
|
|
await sor.sqlExe("""
|
|
UPDATE users
|
|
SET last_login = ${now}$, login_fail_count = 0,
|
|
last_login_fail = NULL
|
|
WHERE id = ${id}$
|
|
""", {'id': r.id, 'now': now_str})
|
|
await remember_user(r.id, username=r.username, userorgid=r.orgid)
|
|
return {
|
|
"status": "ok",
|
|
"data":{
|
|
"user": r
|
|
}
|
|
}
|
|
if params_kw.selected_id:
|
|
for r in recs:
|
|
if r.id == params_kw.selected_id:
|
|
now_str = timestampstr()
|
|
await sor.sqlExe("""
|
|
UPDATE users
|
|
SET last_login = ${now}$, login_fail_count = 0,
|
|
last_login_fail = NULL
|
|
WHERE id = ${id}$
|
|
""", {'id': r.id, 'now': now_str})
|
|
await remember_user(r.id, username=r.username, userorgid=r.orgid)
|
|
return {
|
|
"status": "ok",
|
|
"data":{
|
|
"user": r
|
|
}
|
|
}
|
|
else:
|
|
return {
|
|
"status": "choose",
|
|
"data": {
|
|
"key": params_kw.key,
|
|
"users": recs
|
|
}
|
|
}
|
|
|
|
d = await register_user(sor, udata)
|
|
if d['status'] == 'error':
|
|
return d
|
|
try:
|
|
ownerid = await get_owner_orgid(sor, orgid)
|
|
await openCustomerAccounts(sor, ownerid, orgid)
|
|
except Exception as e:
|
|
exception(f'{e}')
|
|
|
|
# New user registered: code already verified, mark as used
|
|
if not mark_used:
|
|
await sms_engine.check_sms_code(params_kw.key, params_kw.sms_code, mark_used=True)
|
|
r = d['data']['user']
|
|
await remember_user(r.id, username=r.username, userorgid=r.orgid)
|
|
return {
|
|
"status": "ok",
|
|
"data":{
|
|
"user": r
|
|
}
|
|
}
|
|
except Exception as e:
|
|
exception(f'Error happend{e}')
|
|
return {
|
|
"status": "error",
|
|
"data":{
|
|
"message": f"{e}"
|
|
}
|
|
}
|