feat(core): add use guard hook (#11180)

Previously, we used `useLiveData(guardService.can$())` to get the guard result, but `guardService.can$()` will request the server to revalidate the permission when calling it, will cause additional network requests when re-render.

This pr make a new hook `useGuard` to fix this problem.

And the side effect in `can$` is moved to `revalidateCan()` to make that the subscribe method is pure
This commit is contained in:
EYHN
2025-03-25 14:15:29 +00:00
parent a10acf304b
commit 3df51a217d
28 changed files with 154 additions and 163 deletions

View File

@@ -66,17 +66,6 @@ export class GuardService extends Service {
const docId = args[0];
return LiveData.from(
new Observable(subscriber => {
// revalidate permission
if (docId) {
this.revalidateDocPermission(docId);
} else {
this.revalidateWorkspacePermission();
}
// revalidate workspace permission if it's not initialized
if (this.isAdmin$.value === null) {
this.workspacePermissionService.permission.revalidate();
}
let prev: boolean | undefined = undefined;
const subscription = combineLatest([
@@ -128,6 +117,29 @@ export class GuardService extends Service {
return permissions[action as keyof typeof permissions] ?? false;
}
revalidateCan<T extends WorkspacePermissionActions | DocPermissionActions>(
_action: T,
...args: T extends DocPermissionActions ? [string] : []
) {
// revalidate workspace permission if it's not initialized
if (this.isAdmin$.value === null) {
this.workspacePermissionService.permission.revalidate();
}
if (this.isAdmin$.value === true) {
// if the user is admin, the permission is always true
return;
}
const docId = args[0];
// revalidate permission
if (docId) {
this.revalidateDocPermission(docId);
} else {
this.revalidateWorkspacePermission();
}
}
private readonly revalidateWorkspacePermission = effect(
exhaustMapWithTrailing(() =>
fromPromise(() => this.guardStore.getWorkspacePermissions()).pipe(