Bỏ qua, đến nội dung

Troubleshooting ​

Bảng vấn đề thường gặp ​

Triệu chứngNguyên nhânGiải pháp
Toàn bộ API trả 403 sau deployACL chưa nạp role từ DBXem log write roles to ACL lúc afterStart; chạy migration; gọi writeRolesToACL() thủ công
403 chỉ khi destroyMiddleware 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 defaultTạo hoặc đánh dấu một role default: true (thường member)
Hai role cùng default: trueDữ liệu lệchLư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 ASync cluster lỗiKiểm tra sendSyncMessage / handleSyncMessage và message bus giữa instances
Collection mới không hiện trong UI roleStrategy 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ạyKiể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ònHook fields.afterDestroy lỗiHook chạy trong lockManager.runExclusive - nếu lock kẹt, xem log; repair DB thủ công
Error withACLMeta trong logException trong middleware metactx.logger.error đã bọc; tra stack trace - thường lỗi downstream response
roles:check trả thiếu permissionACL chưa đồng bộ resourceLư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ền

3. 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:

  1. Restart app - afterStart sẽ writeRolesToACL() lại.
  2. Hoặc gọi API lưu lại role trên UI - hooks sẽ đồng bộ.
  3. Hoặc gọi thủ công writeRolesToACL({}) qua console/API.

Log quan trọng ​

Log messageÝ nghĩa
write roles to ACLNạp role lúc khởi động
acl:writeResourcesĐồng bộ resource sau khi role được nạp
syncRole: <roleName>Đồng bộ cluster
NoPermissionErrorRequest bị chặn bởi ACL
checkQueryPermissionFilter query theo quyền