flat-fuchsia•3y ago
Casbin causes severe lag
after adding access control using Casbin, my app becomes very laggy.
code snippet of my accessControlProvider.ts:
import { AccessControlProvider } from "@refinedev/core";
import { newModel, StringAdapter, newEnforcer } from "casbin";
import { IAccessControlRule } from "interfaces";
import { store } from "redux/store";
const model = newModel(`
[request_definition]
r = subject, object, action
[policy_definition]
p = subject, object, action, eft
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow)) \
&& !some(where (p.eft == deny))
[matchers]
m = g(r.subject, p.subject) \
&& regexMatch(r.object, p.object) \
&& regexMatch(r.action, p.action)
`);
export const accessControlProvider: AccessControlProvider = {
can: async ({ resource, action, params }) => {
const role = store?.getState()?.user?.role;
const accessControlRules = store?.getState()?.temp?.accessControlRules;
const ruleString = accessControlRules
?.map((item: IAccessControlRule) => {
return `p, ${item?.role}, ${item?.route}, ${item?.permissions?.join(
"|"
)}`;
})
?.join("\n");
let targetUrl = params?.route || resource;
if (targetUrl?.charAt(0) === "/") targetUrl = targetUrl.slice(1);
const adapter = new StringAdapter(ruleString || `p, guest, /, *`);
const enforcer = await newEnforcer(model, adapter);
const can = await enforcer.enforce(role, targetUrl, action);
return Promise.resolve({ can });
},
};
import { AccessControlProvider } from "@refinedev/core";
import { newModel, StringAdapter, newEnforcer } from "casbin";
import { IAccessControlRule } from "interfaces";
import { store } from "redux/store";
const model = newModel(`
[request_definition]
r = subject, object, action
[policy_definition]
p = subject, object, action, eft
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow)) \
&& !some(where (p.eft == deny))
[matchers]
m = g(r.subject, p.subject) \
&& regexMatch(r.object, p.object) \
&& regexMatch(r.action, p.action)
`);
export const accessControlProvider: AccessControlProvider = {
can: async ({ resource, action, params }) => {
const role = store?.getState()?.user?.role;
const accessControlRules = store?.getState()?.temp?.accessControlRules;
const ruleString = accessControlRules
?.map((item: IAccessControlRule) => {
return `p, ${item?.role}, ${item?.route}, ${item?.permissions?.join(
"|"
)}`;
})
?.join("\n");
let targetUrl = params?.route || resource;
if (targetUrl?.charAt(0) === "/") targetUrl = targetUrl.slice(1);
const adapter = new StringAdapter(ruleString || `p, guest, /, *`);
const enforcer = await newEnforcer(model, adapter);
const can = await enforcer.enforce(role, targetUrl, action);
return Promise.resolve({ can });
},
};
3 Replies
Hi @killerudin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Sorry @killerudin, I seem to be having a bit of trouble. Don't worry though, I've pinged my supprt and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
xenial-black•3mo ago
is there any fix for this ? i am also using casbin and it is extremely slow
xenial-black•3mo ago
i have cached the result of the access control but still the same issue
async function getCachedAccessResult(
role: string,
resource: string,
action: string,
resourcePath: string,
enforcer: Enforcer
): Promise<{ can: boolean; reason?: string }> {
const cacheKey = createCacheKey(role, resource, action, resourcePath);
const now = Date.now();
// Check if we have a cached result that's still valid
const cached = accessControlCache.get(cacheKey);
if (cached && (now - cached.timestamp) < ACCESS_CONTROL_CACHE_DURATION) {
return cached.result;
}
// For pattern-based caching (record-specific operations), we use the resource without ID
// This means if a user can edit one employee, they can edit any employee (based on role)
const checkPath = (action === "edit" || action === "show" || action === "delete")
? resource // Use just the resource name for pattern-based checks
: resourcePath; // Use full path for other operations
// Compute new result
const can = await enforcer.enforce(role, checkPath, action);
const result = {
can,
reason: can ? undefined : `Access denied for ${action} on ${resource}`,
};
// Cache the result
accessControlCache.set(cacheKey, { result, timestamp: now });
return result;
}
async function getCachedAccessResult(
role: string,
resource: string,
action: string,
resourcePath: string,
enforcer: Enforcer
): Promise<{ can: boolean; reason?: string }> {
const cacheKey = createCacheKey(role, resource, action, resourcePath);
const now = Date.now();
// Check if we have a cached result that's still valid
const cached = accessControlCache.get(cacheKey);
if (cached && (now - cached.timestamp) < ACCESS_CONTROL_CACHE_DURATION) {
return cached.result;
}
// For pattern-based caching (record-specific operations), we use the resource without ID
// This means if a user can edit one employee, they can edit any employee (based on role)
const checkPath = (action === "edit" || action === "show" || action === "delete")
? resource // Use just the resource name for pattern-based checks
: resourcePath; // Use full path for other operations
// Compute new result
const can = await enforcer.enforce(role, checkPath, action);
const result = {
can,
reason: can ? undefined : `Access denied for ${action} on ${resource}`,
};
// Cache the result
accessControlCache.set(cacheKey, { result, timestamp: now });
return result;
}