-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreact.tsx
145 lines (123 loc) · 3.62 KB
/
react.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { ReactNode, useCallback, useEffect, useState } from "react";
import { CAuthorizer } from "../src";
import { getPermissionsFromBackend } from "./configs";
// ? !!! IMPORTANT
// ? this code not runs in this project
// ? try to run following code in your project, and see how it works
const Authorizer = new CAuthorizer();
let isLoading = false;
const loadPermissions = async (onInitCallback?: () => void) => {
if (onInitCallback) Authorizer.onInitDisposableCallbacks.push(onInitCallback);
if (isLoading) return;
try {
isLoading = true;
const data = await getPermissionsFromBackend();
await Authorizer.init(data.m, data.p);
isLoading = false;
} catch (e) {
isLoading = false;
throw e;
}
};
/**
* @returns permissions for given rvals
*/
export function useAuthorizerCan(rvals: string[]) {
const [available, setAvailable] = useState(false);
const loadIsAvailable = useCallback(async () => {
const setAvailableAfterInit = async () => {
setAvailable(await Authorizer.can(rvals));
};
try {
if (!Authorizer.isInited()) {
await loadPermissions(setAvailableAfterInit);
} else {
await setAvailableAfterInit();
}
} catch (error) {
console.error("loadIsAvailable", error);
setAvailable(false);
}
}, [...rvals]);
useEffect(() => {
loadIsAvailable();
}, [...rvals, Authorizer.isInited()]);
useEffect(() => {
const syncFunction = loadIsAvailable;
Authorizer.onInitCallbacks.push(syncFunction);
return () => {
Authorizer.onInitCallbacks.remove(syncFunction);
};
}, []);
return { available };
}
/**
* @returns children - if `Authorizer.can(rvals)` returns true
* @returns childrenOnRestricted - if `Authorizer.can(rvals)` returns false
*/
export const AuthorizerCan = ({
rvals,
children,
childrenOnRestricted,
}: {
rvals: string[];
children: ReactNode;
childrenOnRestricted?: ReactNode;
}) => {
const { available } = useAuthorizerCan(rvals);
if (available) return children;
return childrenOnRestricted;
};
/**
*
* @param listRvals array of rvals
* @returns filtered array of rvals where `Authorizer.can()` returned true
*/
export function useAuthorizerCanListRvals(listRvals: string[][]) {
const [availableListRvals, setAvailableListRvals] = useState<string[][]>([]);
const loadIsAvailable = async () => {
const setAvailableAfterInit = async () => {
let result: string[][] = await Authorizer.filterByCan(listRvals);
setAvailableListRvals(result);
};
try {
if (!Authorizer.isInited()) {
await loadPermissions(setAvailableAfterInit);
} else {
await setAvailableAfterInit();
}
} catch (error) {
console.error("loadIsAvailable", error);
setAvailableListRvals([]);
}
};
useEffect(() => {
loadIsAvailable();
}, [...listRvals, Authorizer.isInited()]);
return { availableListRvals };
}
export function App() {
const { availableListRvals } = useAuthorizerCanListRvals([
["fish", "swim", "water"],
["bird", "swim", "water"],
["bird", "breathe", "water"],
]);
return (
<div>
<h1>Authorizer Usage Example on react</h1>
<AuthorizerCan rvals={["fish", "swim", "water"]}>
<h2>Fish can swim water</h2>
</AuthorizerCan>
<AuthorizerCan rvals={["fish", "fly", "air"]}>
<h2>Fish can fly air</h2>
</AuthorizerCan>
<AuthorizerCan rvals={["cat", "swim", "water"]}>
<h2>Cat can swim water</h2>
</AuthorizerCan>
<p>useAuthorizerCanListRvals result</p>
{availableListRvals.map((rvals) => {
return <h2>{rvals}</h2>;
})}
</div>
);
}