Giao diện
Troubleshooting
Bảng vấn đề thường gặp
| Triệu chứng | Nguyên nhân | Giải pháp |
|---|---|---|
| Toàn bộ API trả 403 sau deploy | ACL chưa nạp role từ DB | Xem log write roles to ACL lúc afterStart; chạy migration; gọi writeRolesToACL() thủ công |
| 403 chỉ khi destroy | Middleware so count destroy vượt scope | Đảm bảo request dùng filterByTargetKey đúng; filter không "mở" hơn scope cho phép |
| User mới không có quyền gì | Không có role default | Tạo hoặc đánh dấu một role default: true (thường member) |
Hai role cùng default: true | Dữ liệu lệch | Lưu lại một role default trên UI - hook sẽ tự gỡ default role khác |
| Instance B không khớp quyền instance A | Sync cluster lỗi | Kiểm tra sendSyncMessage / handleSyncMessage và message bus giữa instances |
| Collection mới không hiện trong UI role | Strategy resource chưa đăng ký | Kiểm tra appendStrategyResource hook; collection phải có loadedFromCollectionManager |
| Field mới không có trong permission cũ | Hook fields.afterCreate chưa chạy | Kiểm tra log; repair bằng cách lưu lại permission trên UI |
| Xóa field nhưng permission vẫn còn | Hook fields.afterDestroy lỗi | Hook chạy trong lockManager.runExclusive - nếu lock kẹt, xem log; repair DB thủ công |
Error withACLMeta trong log | Exception trong middleware meta | ctx.logger.error đã bọc; tra stack trace - thường lỗi downstream response |
roles:check trả thiếu permission | ACL chưa đồng bộ resource | Lưu lại role trên UI hoặc restart app |
Debug steps
1. Kiểm tra role đã nạp vào ACL
typescript
// Trong server console hoặc action handler
const acl = app.acl;
const role = acl.getRole('member');
console.log('Strategy:', role.strategy);
console.log('Resources:', [...role.resources.keys()]);2. Kiểm tra quyền cụ thể
typescript
const result = acl.can({
role: 'member',
resource: 'orders',
action: 'update',
});
console.log('Can?', result);
// { role: 'member', resource: 'orders', action: 'update', params: { fields, filter } }
// hoặc null nếu không có quyền3. Kiểm tra role của user
typescript
// Cache
const cached = await app.cache.get(`roles:${userId}`);
console.log('Cached roles:', cached);
// DB
const rolesUsers = app.db.getRepository('rolesUsers');
const userRoles = await rolesUsers.find({ filter: { userId } });
console.log('DB roles:', userRoles.map(r => r.roleName));4. Xem log đồng bộ
Tìm trong log:
write roles to ACL- nạp role lúc khởi động.syncRole- đồng bộ multi-instance.- Lỗi ACL middleware - stack trace khi permission check fail.
5. Force đồng bộ lại
typescript
const aclPlugin = app.pm.get('acl');
// Đồng bộ một role
const roleModel = await app.db.getRepository('roles').findOne({
filter: { name: 'member' },
appends: ['resources', 'resources.actions', 'resources.actions.scope'],
});
await aclPlugin.writeRoleToACL(roleModel);
// Đồng bộ tất cả
await aclPlugin.writeRolesToACL({});Sửa dữ liệu thủ công
DANGER
Chỉ thực hiện trên môi trường staging/development. Backup DB trước khi sửa.
Sau khi sửa trực tiếp bảng roles, dataSourcesRolesResources, dataSourcesRolesResourcesActions:
- Restart app -
afterStartsẽwriteRolesToACL()lại. - Hoặc gọi API lưu lại role trên UI - hooks sẽ đồng bộ.
- Hoặc gọi thủ công
writeRolesToACL({})qua console/API.
Log quan trọng
| Log message | Ý nghĩa |
|---|---|
write roles to ACL | Nạp role lúc khởi động |
acl:writeResources | Đồng bộ resource sau khi role được nạp |
syncRole: <roleName> | Đồng bộ cluster |
NoPermissionError | Request bị chặn bởi ACL |
checkQueryPermission | Filter query theo quyền |