Skip to content
Merged

Dev #5817

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion ui/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ export default defineConfig({
*/
proxy: proxy[REACT_APP_ENV as keyof typeof proxy],
layout: {
title: '老寇IoT云平台',
// title 建议放到 src/app.tsx 的运行时 layout 中用 t('app.title') 动态返回
},
locale: {
// umi/max 内置 i18n
default: 'zh-CN',
antd: true,
title: true,
baseNavigator: true,
},
/**
* 路由的配置,不在路由中引入的文件不会编译.
Expand Down
63 changes: 42 additions & 21 deletions ui/config/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,91 +17,108 @@ export default [
redirect: '/home',
},
{
name: '首页',
name: 'menu.home',
title: 'menu.home',
path: '/home',
component: './Home',
icon: 'home'
},
{
name: 'Login',
name: 'menu.login',
title: 'menu.login',
path: '/login',
component: './Login',
layout: false,
},
{
name: '系统管理',
name: 'menu.sys',
title: 'menu.sys',
path: '/sys',
icon: 'setting',
routes: [
{
name: '权限管理',
name: 'menu.sys.permission',
title: 'menu.sys.permission',
path: '/sys/permission',
routes: [
{
name: '菜单',
name: 'menu.sys.permission.menu',
title: 'menu.sys.permission.menu',
path: '/sys/permission/menu',
component: './Sys/Permission/menu'
},
{
name: '部门',
name: 'menu.sys.permission.dept',
title: 'menu.sys.permission.dept',
path: '/sys/permission/dept',
component: './Sys/Permission/dept'
},
{
name: '角色',
name: 'menu.sys.permission.role',
title: 'menu.sys.permission.role',
path: '/sys/permission/role',
component: './Sys/Permission/role'
},
{
name: '用户',
name: 'menu.sys.permission.user',
title: 'menu.sys.permission.user',
path: '/sys/permission/user',
component: './Sys/Permission/user'
},
]
},
{
name: '日志管理',
name: 'menu.sys.log',
title: 'menu.sys.log',
path: '/sys/log',
routes: [
{
name: '登录日志',
name: 'menu.sys.log.login',
title: 'menu.sys.log.login',
path: '/sys/log/login',
component: './Sys/Log/login'
},
{
name: '通知日志',
name: 'menu.sys.log.notice',
title: 'menu.sys.log.notice',
path: '/sys/log/notice',
component: './Sys/Log/notice'
},
{
name: '操作日志',
name: 'menu.sys.log.operate',
title: 'menu.sys.log.operate',
path: '/sys/log/operate',
component: './Sys/Log/operate'
}
]
},
{
name: '对象存储',
name: 'menu.sys.oss',
title: 'menu.sys.oss',
path: '/sys/oss',
routes: [
{
name: '对象存储配置',
name: 'menu.sys.oss.config',
title: 'menu.sys.oss.config',
path: '/sys/oss/config',
component: './Sys/Oss/config'
},
{
name: '对象存储日志',
name: 'menu.sys.oss.log',
title: 'menu.sys.oss.log',
path: '/sys/oss/log',
component: './Sys/Oss/log'
}
]
},
{
name: '系统配置',
name: 'menu.sys.config',
title: 'menu.sys.config',
path: '/sys/config',
routes: [
{
name: '代码生成器',
name: 'menu.sys.config.generator',
title: 'menu.sys.config.generator',
path: '/sys/config/generator',
component: './Sys/Config/generator'
}
Expand All @@ -110,21 +127,25 @@ export default [
]
},
{
name: '物联管理',
name: 'menu.iot',
title: 'menu.iot',
path: '/iot',
icon: 'robot',
routes: [
{
name: '设备管理',
name: 'menu.iot.device',
title: 'menu.iot.device',
path: '/iot/device',
routes: [
{
name: '物模型',
name: 'menu.iot.device.thingModel',
title: 'menu.iot.device.thingModel',
path: '/iot/device/thingModel',
component: './IoT/Device/thingModel'
},
{
name: '产品类别',
name: 'menu.iot.device.productCategory',
title: 'menu.iot.device.productCategory',
path: '/iot/device/productCategory',
component: './IoT/Device/productCategory'
},
Expand Down
111 changes: 56 additions & 55 deletions ui/src/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,63 +2,64 @@ export default (initialState: any) => {
// 在这里按照初始化数据定义项目中的权限,统一管理
// 参考文档 https://umijs.org/docs/max/access
const permissions = initialState?.permissions || []
const scopes = initialState?.scopes || []
return {

canMenuGetDetail: permissions?.includes('sys:menu:detail'),
canMenuModify: permissions?.includes('sys:menu:modify'),
canMenuRemove: permissions?.includes('sys:menu:remove'),
canMenuSave: permissions?.includes('sys:menu:save'),

canDeptGetDetail: permissions?.includes('sys:dept:detail'),
canDeptModify: permissions?.includes('sys:dept:modify'),
canDeptRemove: permissions?.includes('sys:dept:remove'),
canDeptSave: permissions?.includes('sys:dept:save'),

canRoleGetDetail: permissions?.includes('sys:role:detail'),
canRoleModify: permissions?.includes('sys:role:modify'),
canRoleRemove: permissions?.includes('sys:role:remove'),
canRoleSave: permissions?.includes('sys:role:save'),

canUserGetDetail: permissions?.includes('sys:user:detail'),
canUserModify: permissions?.includes('sys:user:modify'),
canUserRemove: permissions?.includes('sys:user:remove'),
canUserSave: permissions?.includes('sys:user:save'),

canOssUpload: permissions?.includes('sys:oss:upload'),
canOssGetDetail: permissions?.includes('sys:oss:detail'),
canOssModify: permissions?.includes('sys:oss:modify'),
canOssRemove: permissions?.includes('sys:oss:remove'),
canOssSave: permissions?.includes('sys:oss:save'),

canOssLogExport: permissions?.includes('sys:oss-log:export'),

canDeviceGetDetail: permissions?.includes('iot:device:detail'),
canDeviceModify: permissions?.includes('iot:device:modify'),
canDeviceRemove: permissions?.includes('iot:device:remove'),
canDeviceSave: permissions?.includes('iot:device:save'),

canProductGetDetail: permissions?.includes('iot:product:detail'),
canProductModify: permissions?.includes('iot:product:modify'),
canProductRemove: permissions?.includes('iot:product:remove'),
canProductSave: permissions?.includes('iot:product:save'),

canThingModelGetDetail: permissions?.includes('iot:thing-model:detail'),
canThingModelModify: permissions?.includes('iot:thing-model:modify'),
canThingModelRemove: permissions?.includes('iot:thing-model:remove'),
canThingModelSave: permissions?.includes('iot:thing-model:save'),

canProductCategoryGetDetail: permissions?.includes('iot:product-category:detail'),
canProductCategoryModify: permissions?.includes('iot:product-category:modify'),
canProductCategoryRemove: permissions?.includes('iot:product-category:remove'),
canProductCategorySave: permissions?.includes('iot:product-category:save'),

canOperateLogGetDetail: permissions?.includes('sys:operate-log:detail'),
canOperateLogExport: permissions?.includes('sys:operate-log:export'),

canNoticeLogGetDetail: permissions?.includes('sys:notice-log:detail'),
canNoticeLogExport: permissions?.includes('sys:notice-log:export'),

canLoginLogExport: permissions?.includes('sys:login-log:export'),
canMenuGetDetail: permissions?.includes('sys:menu:detail') && scopes?.includes('read'),
canMenuModify: permissions?.includes('sys:menu:modify') && scopes?.includes('write'),
canMenuRemove: permissions?.includes('sys:menu:remove') && scopes?.includes('write'),
canMenuSave: permissions?.includes('sys:menu:save') && scopes?.includes('write'),

Comment on lines +5 to +12

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Scopes can disable access 🐞 Bug ⛯ Reliability

Access flags now require both permission and a matching read/write scope; if scopes isn’t
present or is unexpectedly shaped in the profile response, previously-authorized users may lose UI
capabilities (buttons/routes).
Agent Prompt
### Issue description
UI access control now depends on `initialState.scopes` containing `read`/`write`. If the backend doesn’t return `scopes` (or returns an unexpected shape), many capabilities will disappear.

### Issue Context
`scopes` is only sourced from `getUserProfile()` and immediately used to gate all permissions.

### Fix Focus Areas
- ui/src/app.tsx[99-113]
- ui/src/access.ts[4-12]

### Fix options
- Normalize `scopes` in `getInitialState()`:
  - If `result.data.scopes` is missing, default to `['read','write']` (or whatever matches your legacy behavior) until backend rollout is complete.
  - If it can be a string, split/parse it into an array.
- Alternatively, change access checks to:
  - `permissions.includes(...) && (scopes.length === 0 || scopes.includes('read'))`
  - so legacy backends don’t lock users out.
- Add a clear log/warning when scopes are missing to detect misconfiguration early.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

canDeptGetDetail: permissions?.includes('sys:dept:detail') && scopes?.includes('read'),
canDeptModify: permissions?.includes('sys:dept:modify') && scopes?.includes('write'),
canDeptRemove: permissions?.includes('sys:dept:remove') && scopes?.includes('write'),
canDeptSave: permissions?.includes('sys:dept:save') && scopes?.includes('write'),

canRoleGetDetail: permissions?.includes('sys:role:detail') && scopes?.includes('read'),
canRoleModify: permissions?.includes('sys:role:modify') && scopes?.includes('write'),
canRoleRemove: permissions?.includes('sys:role:remove') && scopes?.includes('write'),
canRoleSave: permissions?.includes('sys:role:save') && scopes?.includes('write'),

canUserGetDetail: permissions?.includes('sys:user:detail') && scopes?.includes('read'),
canUserModify: permissions?.includes('sys:user:modify') && scopes?.includes('write'),
canUserRemove: permissions?.includes('sys:user:remove') && scopes?.includes('write'),
canUserSave: permissions?.includes('sys:user:save') && scopes?.includes('write'),

canOssUpload: permissions?.includes('sys:oss:upload') && scopes?.includes('write'),
canOssGetDetail: permissions?.includes('sys:oss:detail') && scopes?.includes('read'),
canOssModify: permissions?.includes('sys:oss:modify') && scopes?.includes('write'),
canOssRemove: permissions?.includes('sys:oss:remove') && scopes?.includes('write'),
canOssSave: permissions?.includes('sys:oss:save') && scopes?.includes('write'),

canOssLogExport: permissions?.includes('sys:oss-log:export') && scopes?.includes('write'),

canDeviceGetDetail: permissions?.includes('iot:device:detail') && scopes?.includes('read'),
canDeviceModify: permissions?.includes('iot:device:modify') && scopes?.includes('write'),
canDeviceRemove: permissions?.includes('iot:device:remove') && scopes?.includes('write'),
canDeviceSave: permissions?.includes('iot:device:save') && scopes?.includes('write'),

canProductGetDetail: permissions?.includes('iot:product:detail') && scopes?.includes('read'),
canProductModify: permissions?.includes('iot:product:modify') && scopes?.includes('write'),
canProductRemove: permissions?.includes('iot:product:remove') && scopes?.includes('write'),
canProductSave: permissions?.includes('iot:product:save') && scopes?.includes('write'),

canThingModelGetDetail: permissions?.includes('iot:thing-model:detail') && scopes?.includes('read'),
canThingModelModify: permissions?.includes('iot:thing-model:modify') && scopes?.includes('write'),
canThingModelRemove: permissions?.includes('iot:thing-model:remove') && scopes?.includes('write'),
canThingModelSave: permissions?.includes('iot:thing-model:save') && scopes?.includes('write'),

canProductCategoryGetDetail: permissions?.includes('iot:product-category:detail') && scopes?.includes('read'),
canProductCategoryModify: permissions?.includes('iot:product-category:modify') && scopes?.includes('write'),
canProductCategoryRemove: permissions?.includes('iot:product-category:remove') && scopes?.includes('write'),
canProductCategorySave: permissions?.includes('iot:product-category:save') && scopes?.includes('write'),

canOperateLogGetDetail: permissions?.includes('sys:operate-log:detail') && scopes?.includes('read'),
canOperateLogExport: permissions?.includes('sys:operate-log:export') && scopes?.includes('write'),

canNoticeLogGetDetail: permissions?.includes('sys:notice-log:detail') && scopes?.includes('read'),
canNoticeLogExport: permissions?.includes('sys:notice-log:export') && scopes?.includes('write'),

canLoginLogExport: permissions?.includes('sys:login-log:export') && scopes?.includes('write'),

};
};
Expand Down
Loading
Loading