rbac/wwwroot/userpassword_login.dspy
yumoqing 3fdd4efeff feat(rbac): add login tracking, lockout, secure cache
- Add created_at, last_login, login_fail_count, last_login_fail fields
- 3 failed logins locks account for 5 minutes
- LRU+TTL cache for UserPermissions, thread-safe
- All login methods update last_login
- Migration SQL for existing databases
2026-04-26 10:49:01 +08:00

23 lines
1.0 KiB
Plaintext

username = params_kw.get('username')
passwd = params_kw.get('passwd')
if not passwd:
return UiError(title='Login failed', message='Password is required')
passwd = password_encode(passwd)
rzt = await check_user_password(request, username, passwd)
if rzt:
return UiMessage(title='Logined', message='Welcome back')
# Check if account is locked for better error message
db = DBPools()
dbname = get_module_dbname('rbac')
async with db.sqlorContext(dbname) as sor:
r = await sor.sqlExe('select login_fail_count, last_login_fail from users where username=${username}$', {'username': username})
if r:
fail_count = getattr(r[0], 'login_fail_count', 0) or 0
if fail_count >= 3:
return UiError(title='Account Locked', message='Account locked due to too many failed login attempts. Please try again in 5 minutes.')
remaining = 3 - fail_count
return UiError(title='Login failed', message=f'User and password mismatch ({remaining} attempts remaining)')
return UiError(title='Login failed', message='User and password mismatch')