62e1985ecb
bugfix
2026-06-09 16:58:15 +08:00
df212ea40d
bugfix
2026-06-09 16:52:12 +08:00
e453883b61
chore: exclude last_login_fail, last_login, sync_from from users edit form
2026-06-05 11:14:14 +08:00
002226d17c
fix: change created_at type from timestamp to date for proper Date control
2026-06-04 16:50:20 +08:00
5809a81646
debug: add hot_reload handler logging
2026-06-01 22:53:07 +08:00
b72a487df7
fix: use ServerEnv().userpermissions instead of new UserPermissions() in event handlers
2026-06-01 18:15:37 +08:00
ce7eb2a193
refactor: bind hot_reload event via EventDispatcher, add on_hot_reload to UserPermissions
2026-06-01 18:10:29 +08:00
c949a51f2e
fix: gen_sms_code.dspy handle both None return and exception from generate_sms_code
2026-05-31 12:26:55 +08:00
4038b7d0b9
fix: gen_sms_code.dspy catch exception and return actual error message
2026-05-31 11:56:46 +08:00
7f2c3d25dd
feat: 用户菜单添加完善信息功能 - 新增 edit_profile.dspy/save_profile.dspy - usermenu.ui 添加完善信息入口 - load_path.py 注册权限路径
2026-05-31 10:52:13 +08:00
26d1fd1447
feat: register_user 添加 customer.admin 角色,注册时同时分配 customer 和 admin 权限
2026-05-31 10:38:32 +08:00
c9dd80a484
fix: 暗色主题输入框颜色全局优化
...
- bricks.css: inputbox背景 #1E293B → #0F172A
- login.css: 同步更新保持一致
2026-05-30 14:32:11 +08:00
b0d6b59613
fix: 注册表单仅输入区域滚动,暗色主题输入框颜色优化
...
- 注册Tab结构: Text(固定) + VScrollPanel(仅Form) + Button(固定)
- 暗色主题输入框背景 #0f172a -> #1e293b,更协调
2026-05-30 14:27:33 +08:00
d1b3ca0914
fix: 修复登录弹窗三个显示问题
...
- 注册表单超出无滚动: 三个Tab内容均包裹VScrollPanel(scrollpanel)
- Form toolbar不可见: 滚动容器让submit/reset按钮可达
- 文本未国际化: title/label/otext均加i18n:true, archor纠正
- CSS: tabpanel flex布局, tabpanel-content flex:1+min-height:0
- PopupWindow cheight 28->30 给更多显示空间
2026-05-30 14:16:00 +08:00
36569c0e41
feat: 现代化登录/注册界面改造
...
- login.css: 全新现代化样式,支持亮/暗主题
- login.ui: 三Tab布局(密码登录/手机登录/注册),手机登录支持短信验证码
- sms_register.dspy: 短信验证注册后端,验证通过后自动注册并登录
- load_path.py: 添加 sms_register.dspy 到 any 权限
- 修复手机登录 setValue 调用 (上一轮已提交)
- 注册流程: 手机号+短信验证码+用户名+密码,短信验证通过后才允许注册
2026-05-30 14:08:11 +08:00
019e9702fc
fix: use setValue() on codeid field widget instead of direct value assignment
2026-05-30 13:36:54 +08:00
cec79caf88
fix: phone login form.setValue is not a function - use name_inputs direct value set
2026-05-30 13:35:07 +08:00
b532548d19
fix: keep previous rp_caches when DB returns empty result
...
sqlExe can return [] without raising an exception (bad connection,
cursor issue). When load_roleperms gets 0 records but had valid
cache before, keep the old cache instead of replacing with {}.
Prevents intermittent 403 from transient DB issues.
2026-05-30 11:34:13 +08:00
fbbe011a8d
fix: rp_caches race condition causing intermittent 403
...
load_roleperms() was setting self.rp_caches = {} before the async
DB query. During the await, other coroutines saw {} (not None),
skipped the load, and checked permissions against an empty dict,
causing intermittent 403 on random paths.
Fix: build in local dict first, assign atomically when complete.
2026-05-30 11:19:32 +08:00
c776c0b3b5
fix: rp_cache should reload from DB when cache is disabled
2026-05-30 10:19:00 +08:00
04e9b718db
fix: check_roles_path supports % wildcard alongside **
...
load_path.py scripts across modules register paths like '/module/api/%'
using SQL LIKE wildcard, but check_roles_path() only recognized '**' as
wildcard suffix. This caused all %-terminated paths to be treated as
exact matches, resulting in 403 for any sub-path.
Now both '/module/api/%' and '/module/api/**' work as prefix wildcards.
2026-05-29 23:12:22 +08:00
67687883ff
fix: RBAC crash when cache disabled - return roles directly from get_userroles
...
When module_cache.rbac=false in config.json, LRUCache.get() always returns
None and LRUCache.set() is a no-op. This caused get_userroles() to store
roles into a disabled cache, then callers read back None, leading to
TypeError in check_roles_path() when iterating over None.
Fix: get_userroles() now returns the roles list directly. Callers use the
return value instead of relying solely on cache reads. Added safety
fallback to deny access if roles is somehow still None.
2026-05-29 22:43:39 +08:00
fa9f7f5146
fix: wrap Tabular in VBox with cheight for proper scrolling
2026-05-29 22:09:56 +08:00
cf18e592c7
feat: respect module_cache config for RBAC LRU cache
2026-05-29 17:59:04 +08:00
342fc6652a
refactor: rewrite SMS login UI using pure bricks patterns
...
- login.ui: use actiontype:urlwidget for Form submit → code_login.dspy
- Removed custom JavaScript (phone_login.js)
- Send code button: minimal script action to fetch and set form value
- Login flow: bricks returns Message/Error/VBox widgets directly
- Multi-account selection: code_login.dspy returns VBox with Buttons
2026-05-29 11:58:30 +08:00
8528eebf10
revert: restore gen_sms_code.dspy (API used by other systems)
2026-05-29 11:38:35 +08:00
e65fddbe61
revert: restore phone_login.dspy to original (API used by other systems)
2026-05-29 11:37:39 +08:00
cf186a632b
fix: revert uitype to 'hide' (bricks framework uses 'hide' not 'hidden')
2026-05-29 11:36:05 +08:00
567513789e
feat: rewrite SMS login UI with fetch-based flow matching phone_login.dspy API
...
- 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
2026-05-29 11:31:39 +08:00
cfd3810a0a
fix: remove _webbricks_=1 from SMS code generation API call
...
The _webbricks_=1 parameter was causing the response to be wrapped as a widget instead of plain JSON, which prevented the frontend from correctly parsing the response and setting the codeid field.
Now the API returns plain JSON {status: 'ok', data: {key: '...'}} and the form's hidden codeid field gets properly set after successful SMS generation.
2026-05-28 18:39:25 +08:00
969a72b528
fix: SMS verification code URL - replace undefined bricks.app.baseUrl with entire_url template
...
The send verification code button was sending requests to https://token.opencomputing.cn/undefined/rbac/gen_sms_code.dspy because bricks.app.baseUrl doesn't exist in the bricks framework (it uses baseURI on widgets).
Fix: Use Jinja2 entire_url() template function like all other URLs in the file.
2026-05-28 18:24:39 +08:00
ff03efb50a
fix: Button label更新改用set_otext()支持国际化
...
set_text()直接设置innerHTML跳过i18n翻译,
set_otext()会先调用i18n._()翻译再set_text,
与Button初始化时i18n:true的配置保持一致。
2026-05-28 17:00:57 +08:00
f44104b8a5
fix: Button label更新使用text_w.set_text()替代options.label赋值
...
根因:
1. script上下文中this为undefined,无法通过this.options.label访问
2. btn.options.label只修改属性不更新DOM,需调用text_w.set_text()
3. Button内部label是bricks.Text子组件(text_w),需通过其API更新
2026-05-28 16:52:26 +08:00
53111aa2fd
fix: Form.getValue()返回FormData对象,改用_getValue()获取普通对象
...
根因:bricks Form的getValue()内部调用get_formdata()返回浏览器
原生FormData对象,不支持.cell_no属性访问。
改用_getValue()返回{name:value}普通JS对象。
2026-05-28 16:27:56 +08:00
92627c9c96
fix: 手机验证码tab改用VBox+独立Button,避免toolbar tool触发submit导致tab跳转
...
根因:Form toolbar tool点击会同时触发Form的submit事件,
submit的urlwidget替换Form后TabPanel重置到第一个tab。
改为VBox包裹Form和独立Button,Button通过bricks.getWidgetById
读取Form值,fetch加_webbricks_=1确保返回纯JSON。
2026-05-28 15:03:50 +08:00
7200ee43a0
fix: 手机验证码gen_code按钮用datawidget/datamethod传表单值给script
...
原script中this.getValue()在toolbar tool事件上下文中拿不到表单数据,
改用datawidget/datamethod机制将表单值通过params传入script。
回写codeid用.bind(this)保持Form引用。
2026-05-28 14:10:37 +08:00
de21b9fd38
feat: 手机验证码登录对接 + 注册tab + user_logined事件派发
...
- 新增 code_login.dspy: 接收前端表单(cell_no/codeid/check_code)
映射到sms_engine验证,返回UI widget含自动登录binds
- 修复 login.ui 手机验证码tab: gen_code按钮改用script调用
gen_sms_code.dspy并回写key到隐藏字段,submit指向code_login.dspy
- login.ui 新增注册tab: 用户名/手机号/密码/确认密码表单
- register.dspy: 注册成功后自动remember_user并返回含binds的
Message widget(加载userinfo、销毁登录窗、派发user_logined)
- up_login.dspy: 补充user_logined事件派发bind
- load_path.py: code_login.dspy加入any权限,gen_sms_code.dspy
从logined移至any(验证码发送在登录前)
2026-05-28 13:50:17 +08:00
54b0f3d7b6
fix: dispatch user_logined event after successful login
...
After login message is dismissed, dispatches 'user_logined' on bricks.app
so the sidebar menu reloads without requiring manual page reload.
2026-05-28 13:42:03 +08:00
9d2a94131a
feat: improve logout.dspy with refresh button
...
After logout, show success message with a button to reload the page,
which triggers the sidebar menu to re-render with unauthenticated state.
2026-05-27 17:58:15 +08:00
0a5bfa4c64
feat: add load_path.py RBAC permission registration script
2026-05-27 13:16:09 +08:00
39f8eb7d94
Revert "feat: add cross-process cache invalidation via Redis Pub/Sub"
...
This reverts commit 8cec17c04295665eb4b750e2070c17fa3b06a939.
2026-05-26 18:31:04 +08:00
8fdb31a850
Revert "fix: add app parameter to start_cache_sync for aiohttp on_startup hook"
...
This reverts commit c0bbe63845e1f5ca255a0e2fe821fcf4f88786aa.
2026-05-26 18:31:04 +08:00
c0bbe63845
fix: add app parameter to start_cache_sync for aiohttp on_startup hook
2026-05-26 17:20:52 +08:00
835a2ff3f7
fix: add filler css + overflowY:auto to content container
2026-05-26 13:57:42 +08:00
8cec17c042
feat: add cross-process cache invalidation via Redis Pub/Sub
...
- userperm.py: All invalidate_* and on_* handlers changed to async
- Each invalidation now broadcasts via cache_sync.invalidate()
- invalidate_user_cache() -> 'rbac:ur:{userid}'
- invalidate_all_user_caches() -> 'rbac:ur:all'
- invalidate_rp_cache() -> 'rbac:rp'
- init.py: Added start_cache_sync() async function
- Starts Redis Pub/Sub subscription
- Registers callbacks for rbac:rp and rbac:ur:all channels
- set_role_perms.py: CLI script now sends invalidation after execution
- send_rbac_invalidation() starts cache_sync, publishes, then stops
Compatible with existing EventDispatcher (already supports async handlers)
2026-05-26 13:52:10 +08:00
1b21f46336
feat: add index.ui as module entry with user management, path roles, and unauth file scan cards
2026-05-26 12:11:32 +08:00
f8c8a4ce4d
refactor: move RBAC tools logic to rbac/rbac_tools.py, dspy files call via request._run_ns
2026-05-26 09:32:38 +08:00
0b456486db
feat: add RBAC tools — list_path_roles, find_unauth_files, and permission registration script
2026-05-26 09:18:04 +08:00
c53c16d54c
feat: add RBAC tools — list_path_roles and find_unauth_files
2026-05-26 09:12:33 +08:00
fd9ef322c7
bugfix
2026-05-22 17:21:00 +08:00