feat: domain-based reseller binding on registration + test SMS bypass
This commit is contained in:
parent
35750d5938
commit
18913e7064
@ -118,6 +118,8 @@ async def register_user(sor, ns):
|
|||||||
ns.created_at = timestampstr()
|
ns.created_at = timestampstr()
|
||||||
ns.login_fail_count = 0
|
ns.login_fail_count = 0
|
||||||
ns1 = DictObject(id=id, orgname=ns.username)
|
ns1 = DictObject(id=id, orgname=ns.username)
|
||||||
|
if ns.get('parentid'):
|
||||||
|
ns1.parentid = ns.parentid
|
||||||
await create_org(sor, ns1)
|
await create_org(sor, ns1)
|
||||||
roles = [
|
roles = [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,36 +1,40 @@
|
|||||||
|
# TEST MODE: 不发送真实短信,返回固定验证码 123456
|
||||||
phone = params_kw.cellphone
|
phone = params_kw.cellphone
|
||||||
if phone is None:
|
if phone is None:
|
||||||
return {
|
return {
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"data":{
|
"data": {
|
||||||
"message": "没有收到手机号"
|
"message": "没有收到手机号"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# 使用短信模块发布的sms_engine实例生成验证码,参数手机号
|
|
||||||
try:
|
try:
|
||||||
xx = await sms_engine.generate_sms_code(phone)
|
code = '123456'
|
||||||
|
code_id = getID()
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
expire_time = datetime.now() + timedelta(minutes=5)
|
||||||
|
env = request._run_ns
|
||||||
|
async with get_sor_context(env, 'smssend') as sor:
|
||||||
|
await sor.C('validatecode', {
|
||||||
|
'id': code_id,
|
||||||
|
'vcode': code,
|
||||||
|
'expire_time': expire_time,
|
||||||
|
'del_flg': '0',
|
||||||
|
'create_at': datetime.now()
|
||||||
|
})
|
||||||
|
debug(f'TEST MODE: code_id={code_id}, code={code}, phone={phone}')
|
||||||
|
return {
|
||||||
|
"status": "ok",
|
||||||
|
"data": {
|
||||||
|
"message": f"测试模式: 验证码 {code}",
|
||||||
|
"key": code_id
|
||||||
|
}
|
||||||
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug(f'gen_sms_code error: {e}')
|
debug(f'gen_sms_code error: {e}')
|
||||||
exception(f'gen_sms_code error for {phone}: {e}')
|
exception(f'gen_sms_code error for {phone}: {e}')
|
||||||
return {
|
return {
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"data": {
|
"data": {
|
||||||
"message": f"发送验证码出错: {e}"
|
"message": f"发送验证码出错: {e}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if xx is None:
|
|
||||||
return {
|
|
||||||
"status": "error",
|
|
||||||
"data": {
|
|
||||||
"message": "发送验证码出错,请检查短信模板配置和百度API连接"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
id, code = xx
|
|
||||||
debug(f'{id=},{code=}')
|
|
||||||
return {
|
|
||||||
"status": "ok",
|
|
||||||
"data": {
|
|
||||||
"message": "短信码已生成",
|
|
||||||
"key": id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,78 +1,96 @@
|
|||||||
debug(f'register.dspy: {params_kw=}')
|
debug(f'register.dspy: {params_kw=}')
|
||||||
db = DBPools()
|
db = DBPools()
|
||||||
dbname = get_module_dbname('rbac')
|
dbname = get_module_dbname('rbac')
|
||||||
|
|
||||||
|
# 根据注册域名查找所属分销商
|
||||||
|
parentid = None
|
||||||
|
try:
|
||||||
|
host = request.host
|
||||||
|
env = request._run_ns
|
||||||
|
domain_info = await env.get_domain_by_host(request, host)
|
||||||
|
if domain_info:
|
||||||
|
parentid = domain_info.resellerid
|
||||||
|
debug(f'register: domain={host} -> resellerid={parentid}')
|
||||||
|
else:
|
||||||
|
debug(f'register: domain={host} not found in tenant_domain')
|
||||||
|
except Exception as e:
|
||||||
|
exception(f'register: domain lookup error: {e}')
|
||||||
|
|
||||||
|
if parentid:
|
||||||
|
params_kw.parentid = parentid
|
||||||
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
async with db.sqlorContext(dbname) as sor:
|
||||||
data = await register_user(sor, params_kw)
|
data = await register_user(sor, params_kw)
|
||||||
data = DictObject(**data)
|
data = DictObject(**data)
|
||||||
if data.status == 'error':
|
if data.status == 'error':
|
||||||
debug(f"register error: {data.data.message}")
|
debug(f"register error: {data.data.message}")
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 5,
|
"timeout": 5,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": data.data.message
|
"message": data.data.message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
user = data.data.user
|
user = data.data.user
|
||||||
orgid = user.orgid
|
orgid = user.orgid
|
||||||
try:
|
try:
|
||||||
await openCustomerAccounts(sor, '0', orgid)
|
await openCustomerAccounts(sor, '0', orgid)
|
||||||
debug(f'{orgid} accounts opened')
|
debug(f'{orgid} accounts opened')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
exception(f'{e},{orgid=}')
|
exception(f'{e},{orgid=}')
|
||||||
|
|
||||||
# 检查是否有促销码,如果有则绑定客户归属关系
|
# 检查是否有促销码,如果有则绑定客户归属关系
|
||||||
promo_code_id = params_kw.get('promo_code_id')
|
promo_code_id = params_kw.get('promo_code_id')
|
||||||
if promo_code_id:
|
if promo_code_id:
|
||||||
try:
|
try:
|
||||||
await bind_customer(request, DictObject(promo_code_id=promo_code_id, customerid=orgid))
|
await bind_customer(request, DictObject(promo_code_id=promo_code_id, customerid=orgid))
|
||||||
debug(f'register: customer {orgid} bound via promo_code {promo_code_id}')
|
debug(f'register: customer {orgid} bound via promo_code {promo_code_id}')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
exception(f'register: bind_customer failed for {orgid} via {promo_code_id}: {e}')
|
exception(f'register: bind_customer failed for {orgid} via {promo_code_id}: {e}')
|
||||||
|
|
||||||
# 注册成功后自动登录
|
# 注册成功后自动登录
|
||||||
await remember_user(user.id, username=user.username, userorgid=user.orgid)
|
await remember_user(user.id, username=user.username, userorgid=user.orgid)
|
||||||
return {
|
return {
|
||||||
"widgettype": "Message",
|
"widgettype": "Message",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"auto_open": True,
|
"auto_open": True,
|
||||||
"title": "注册成功",
|
"title": "注册成功",
|
||||||
"message": f"{user.username} 注册成功,已自动登录"
|
"message": f"{user.username} 注册成功,已自动登录"
|
||||||
},
|
},
|
||||||
"binds": [
|
"binds": [
|
||||||
{
|
{
|
||||||
"wid": "self",
|
"wid": "self",
|
||||||
"event": "dismissed",
|
"event": "dismissed",
|
||||||
"actiontype": "urlwidget",
|
"actiontype": "urlwidget",
|
||||||
"target": "window.user_container",
|
"target": "window.user_container",
|
||||||
"options": {
|
"options": {
|
||||||
"url": entire_url('/rbac/user/userinfo.ui')
|
"url": entire_url('/rbac/user/userinfo.ui')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"wid": "self",
|
"wid": "self",
|
||||||
"event": "dismissed",
|
"event": "dismissed",
|
||||||
"actiontype": "script",
|
"actiontype": "script",
|
||||||
"target": "body.login_window",
|
"target": "body.login_window",
|
||||||
"script": "if(this.destroy) this.destroy()"
|
"script": "if(this.destroy) this.destroy()"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"wid": "self",
|
"wid": "self",
|
||||||
"event": "dismissed",
|
"event": "dismissed",
|
||||||
"actiontype": "script",
|
"actiontype": "script",
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"script": "if(bricks.app && bricks.app.dispatch) bricks.app.dispatch('user_logined')"
|
"script": "if(bricks.app && bricks.app.dispatch) bricks.app.dispatch('user_logined')"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 5,
|
"timeout": 5,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "系统错误,请稍后重试"
|
"message": "系统错误,请稍后重试"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,186 +11,203 @@ cfm_password = params_kw.cfm_password
|
|||||||
|
|
||||||
# 基本参数校验
|
# 基本参数校验
|
||||||
if not username:
|
if not username:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "请输入用户名"
|
"message": "请输入用户名"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if not mobile:
|
if not mobile:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "请输入手机号"
|
"message": "请输入手机号"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if not password:
|
if not password:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "请输入密码"
|
"message": "请输入密码"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if password != cfm_password:
|
if password != cfm_password:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "两次输入的密码不一致"
|
"message": "两次输入的密码不一致"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if not key or not sms_code:
|
if not key or not sms_code:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "请先发送并输入短信验证码"
|
"message": "请先发送并输入短信验证码"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 验证短信码
|
# 验证短信码
|
||||||
try:
|
try:
|
||||||
ok = await sms_engine.check_sms_code(key, sms_code)
|
ok = await sms_engine.check_sms_code(key, sms_code)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
exception(f'sms_register sms check error: {e}')
|
exception(f'sms_register sms check error: {e}')
|
||||||
ok = False
|
ok = False
|
||||||
|
|
||||||
if not ok:
|
if not ok:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 3,
|
"timeout": 3,
|
||||||
"title": "验证失败",
|
"title": "验证失败",
|
||||||
"message": "短信验证码错误或已过期,请重新获取"
|
"message": "短信验证码错误或已过期,请重新获取"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 根据注册域名查找所属分销商
|
||||||
|
parentid = None
|
||||||
|
try:
|
||||||
|
host = request.host
|
||||||
|
env = request._run_ns
|
||||||
|
domain_info = await env.get_domain_by_host(request, host)
|
||||||
|
if domain_info:
|
||||||
|
parentid = domain_info.resellerid
|
||||||
|
debug(f'sms_register: domain={host} -> resellerid={parentid}')
|
||||||
|
else:
|
||||||
|
debug(f'sms_register: domain={host} not found in tenant_domain')
|
||||||
|
except Exception as e:
|
||||||
|
exception(f'sms_register: domain lookup error: {e}')
|
||||||
|
|
||||||
# 短信验证通过,注册用户
|
# 短信验证通过,注册用户
|
||||||
db = DBPools()
|
db = DBPools()
|
||||||
dbname = get_module_dbname('rbac')
|
dbname = get_module_dbname('rbac')
|
||||||
try:
|
try:
|
||||||
async with db.sqlorContext(dbname) as sor:
|
async with db.sqlorContext(dbname) as sor:
|
||||||
# 检查手机号是否已注册
|
# 检查手机号是否已注册
|
||||||
existing = await sor.R('users', {'mobile': mobile})
|
existing = await sor.R('users', {'mobile': mobile})
|
||||||
if existing:
|
if existing:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 5,
|
"timeout": 5,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "该手机号已注册,请直接登录"
|
"message": "该手机号已注册,请直接登录"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 检查用户名是否已存在
|
# 检查用户名是否已存在
|
||||||
existing_user = await sor.R('users', {'username': username})
|
existing_user = await sor.R('users', {'username': username})
|
||||||
if existing_user:
|
if existing_user:
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 5,
|
"timeout": 5,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "用户名已被占用"
|
"message": "用户名已被占用"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 调用注册函数
|
# 调用注册函数
|
||||||
reg_params = DictObject(
|
reg_params = DictObject(
|
||||||
username=username,
|
username=username,
|
||||||
mobile=mobile,
|
mobile=mobile,
|
||||||
password=password,
|
password=password,
|
||||||
cfm_password=cfm_password
|
cfm_password=cfm_password
|
||||||
)
|
)
|
||||||
data = await register_user(sor, reg_params)
|
if parentid:
|
||||||
data = DictObject(**data)
|
reg_params.parentid = parentid
|
||||||
if data.status == 'error':
|
|
||||||
debug(f"sms_register error: {data.data.message}")
|
|
||||||
return {
|
|
||||||
"widgettype": "Error",
|
|
||||||
"options": {
|
|
||||||
"timeout": 5,
|
|
||||||
"title": "注册失败",
|
|
||||||
"message": data.data.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user = data.data.user
|
data = await register_user(sor, reg_params)
|
||||||
orgid = user.orgid
|
data = DictObject(**data)
|
||||||
try:
|
if data.status == 'error':
|
||||||
await openCustomerAccounts(sor, '0', orgid)
|
debug(f"sms_register error: {data.data.message}")
|
||||||
debug(f'{orgid} accounts opened')
|
return {
|
||||||
except Exception as e:
|
"widgettype": "Error",
|
||||||
exception(f'{e},{orgid=}')
|
"options": {
|
||||||
|
"timeout": 5,
|
||||||
|
"title": "注册失败",
|
||||||
|
"message": data.data.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# 检查是否有促销码,如果有则绑定客户归属关系
|
user = data.data.user
|
||||||
promo_code_id = params_kw.get('promo_code_id')
|
orgid = user.orgid
|
||||||
if promo_code_id:
|
try:
|
||||||
try:
|
await openCustomerAccounts(sor, '0', orgid)
|
||||||
await bind_customer(request, DictObject(promo_code_id=promo_code_id, customerid=orgid))
|
debug(f'{orgid} accounts opened')
|
||||||
debug(f'sms_register: customer {orgid} bound via promo_code {promo_code_id}')
|
except Exception as e:
|
||||||
except Exception as e:
|
exception(f'{e},{orgid=}')
|
||||||
exception(f'sms_register: bind_customer failed for {orgid} via {promo_code_id}: {e}')
|
|
||||||
|
|
||||||
# 注册成功后自动登录
|
# 检查是否有促销码,如果有则绑定客户归属关系
|
||||||
await remember_user(user.id, username=user.username, userorgid=user.orgid)
|
promo_code_id = params_kw.get('promo_code_id')
|
||||||
return {
|
if promo_code_id:
|
||||||
"widgettype": "Message",
|
try:
|
||||||
"options": {
|
await bind_customer(request, DictObject(promo_code_id=promo_code_id, customerid=orgid))
|
||||||
"timeout": 3,
|
debug(f'sms_register: customer {orgid} bound via promo_code {promo_code_id}')
|
||||||
"auto_open": True,
|
except Exception as e:
|
||||||
"title": "注册成功",
|
exception(f'sms_register: bind_customer failed for {orgid} via {promo_code_id}: {e}')
|
||||||
"message": f"{user.username} 注册成功,已自动登录"
|
|
||||||
},
|
# 注册成功后自动登录
|
||||||
"binds": [
|
await remember_user(user.id, username=user.username, userorgid=user.orgid)
|
||||||
{
|
return {
|
||||||
"wid": "self",
|
"widgettype": "Message",
|
||||||
"event": "dismissed",
|
"options": {
|
||||||
"actiontype": "urlwidget",
|
"timeout": 3,
|
||||||
"target": "window.user_container",
|
"auto_open": True,
|
||||||
"options": {
|
"title": "注册成功",
|
||||||
"url": entire_url('/rbac/user/userinfo.ui')
|
"message": f"{user.username} 注册成功,已自动登录"
|
||||||
}
|
},
|
||||||
},
|
"binds": [
|
||||||
{
|
{
|
||||||
"wid": "self",
|
"wid": "self",
|
||||||
"event": "dismissed",
|
"event": "dismissed",
|
||||||
"actiontype": "script",
|
"actiontype": "urlwidget",
|
||||||
"target": "body.login_window",
|
"target": "window.user_container",
|
||||||
"script": "this.destroy()"
|
"options": {
|
||||||
},
|
"url": entire_url('/rbac/user/userinfo.ui')
|
||||||
{
|
}
|
||||||
"wid": "self",
|
},
|
||||||
"event": "dismissed",
|
{
|
||||||
"actiontype": "script",
|
"wid": "self",
|
||||||
"target": "self",
|
"event": "dismissed",
|
||||||
"script": "if(bricks.app && bricks.app.dispatch) bricks.app.dispatch('user_logined')"
|
"actiontype": "script",
|
||||||
}
|
"target": "body.login_window",
|
||||||
]
|
"script": "this.destroy()"
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "dismissed",
|
||||||
|
"actiontype": "script",
|
||||||
|
"target": "self",
|
||||||
|
"script": "if(bricks.app && bricks.app.dispatch) bricks.app.dispatch('user_logined')"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
exception(f'sms_register error: {e}')
|
exception(f'sms_register error: {e}')
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 5,
|
"timeout": 5,
|
||||||
"title": "系统错误",
|
"title": "系统错误",
|
||||||
"message": f"注册失败: {e}"
|
"message": f"注册失败: {e}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"widgettype": "Error",
|
"widgettype": "Error",
|
||||||
"options": {
|
"options": {
|
||||||
"timeout": 5,
|
"timeout": 5,
|
||||||
"title": "注册失败",
|
"title": "注册失败",
|
||||||
"message": "系统错误,请稍后重试"
|
"message": "系统错误,请稍后重试"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user