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