Skip to content

Commit 79c150a

Browse files
committed
casl integration
1 parent 56b5739 commit 79c150a

File tree

11 files changed

+115
-32
lines changed

11 files changed

+115
-32
lines changed

package-lock.json

Lines changed: 26 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
"private": true,
55
"dependencies": {
66
"@apollo/client": "^3.0.0-beta.44",
7+
"@casl/ability": "^4.1.4",
8+
"@casl/react": "^2.1.0",
79
"@testing-library/jest-dom": "^4.2.4",
810
"@testing-library/react": "^9.3.2",
911
"@testing-library/user-event": "^7.1.2",

src/App.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ import './App.css';
55
import {
66
Link
77
} from "react-router-dom";
8-
8+
import { Can } from './rules/Can';
9+
import { Article } from "./rules/entities";
910
function App() {
11+
12+
const article = new Article({ published: true });
13+
1014
return (
1115
<div className="App">
1216
<header className="App-header">
@@ -24,8 +28,9 @@ function App() {
2428
</a>
2529
<Link to="/books">Books</Link>
2630
<Link to="/todos">Todos</Link>
27-
28-
<ExchangeRates />
31+
<Can I="read" a={article}>
32+
{ () => <ExchangeRates /> }
33+
</Can>
2934
</header>
3035
</div>
3136
);

src/components/Books/ability.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Ability } from "@casl/ability";
2+
3+
export default new Ability([
4+
{
5+
action: "update",
6+
subject: "Author",
7+
conditions: { isShowAuthor: true }
8+
}
9+
]);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineAbility } from '@casl/ability';
2+
3+
export default defineAbility((can, cannot) => {
4+
can('read', 'GS');
5+
cannot('delete', 'User');
6+
});

src/components/Books/index.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import React, { useRef } from 'react';
22
import { useQuery, useMutation } from '@apollo/client';
33
import { GET_BOOKS, ADD_BOOK } from './gql';
4+
import { Can } from '@casl/react';
5+
import ability from './ability';
6+
import { Author } from '../../rules/entities';
47

58
export default function Books() {
69
const bookTitle = useRef(null);
@@ -13,7 +16,7 @@ export default function Books() {
1316

1417
cache.writeQuery({
1518
query: GET_BOOKS,
16-
data: {
19+
data: {
1720
books: [...books, addBook]
1821
}
1922
});
@@ -25,13 +28,16 @@ export default function Books() {
2528

2629
const handleSubmit = (event) => {
2730
event.preventDefault();
28-
29-
addBook({ variables: { title: event.target.title.value, author: event.target.author.value } });
31+
const target = event.target;
3032

31-
event.target.title = '';
32-
event.target.author = '';
33+
addBook({ variables: { title: target.title.value, author: target.author.value } });
34+
35+
target.title.value = '';
36+
target.author.value = '';
3337
}
3438

39+
const author = new Author({ isShowAuthor: data.books.length === 2 });
40+
3541
return (
3642
<section>
3743
<ul>
@@ -43,12 +49,17 @@ export default function Books() {
4349
))
4450
}
4551
</ul>
46-
<form onSubmit={(e) => handleSubmit(e)} style={{ display:'flex', flexDirection: 'row' }}>
52+
<form onSubmit={(e) => handleSubmit(e)} style={{ display: 'flex', flexDirection: 'row' }}>
4753
<label htmlFor="title">Title:</label>
4854
<input type="text" id="title" name="title" ref={bookTitle} />
49-
<label htmlFor="author">Book:</label>
50-
<input type="text" id="author" name="author" ref={bookAuthor}/>
51-
<button type="submit">Submit</button>
55+
56+
<label htmlFor="author">Book:</label>
57+
<input type="text" id="author" name="author" ref={bookAuthor} />
58+
59+
<Can I="update" a={author} ability={ability}>
60+
{() => <button type="submit">Submit</button>}
61+
</Can>
62+
5263
</form>
5364
</section>
5465
);

src/index.tsx

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import * as serviceWorker from './serviceWorker';
77
import client from './apollo/client';
88
import Books from './components/Books';
99
import Todos from './components/Todos';
10+
import { AbilityContext } from './rules/Can'
11+
import ability from './rules/abilityBuilder'
1012

1113
import {
1214
BrowserRouter as Router,
@@ -16,22 +18,23 @@ import {
1618

1719
ReactDOM.render(
1820
<ApolloProvider client={client}>
19-
<React.StrictMode>
20-
<Router>
21-
<Switch>
22-
23-
<Route path="/books">
24-
<Books />
25-
</Route>
26-
<Route path="/todos">
27-
<Todos />
28-
</Route>
29-
<Route path="/">
30-
<App />
31-
</Route>
32-
</Switch>
33-
</Router>
34-
</React.StrictMode>
21+
<AbilityContext.Provider value={ability}>
22+
<React.StrictMode>
23+
<Router>
24+
<Switch>
25+
<Route path="/books">
26+
<Books />
27+
</Route>
28+
<Route path="/todos">
29+
<Todos />
30+
</Route>
31+
<Route path="/">
32+
<App />
33+
</Route>
34+
</Switch>
35+
</Router>
36+
</React.StrictMode>
37+
</AbilityContext.Provider>
3538
</ApolloProvider>,
3639
document.getElementById('root')
3740
);

src/rules/Can.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createContext } from 'react';
2+
import { createContextualCan } from '@casl/react';
3+
import { AnyAbility, PureAbility } from "@casl/ability";
4+
5+
export const AbilityContext = createContext<AnyAbility>({} as PureAbility);
6+
export const Can = createContextualCan(AbilityContext.Consumer);

src/rules/abilityBuilder.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Ability } from "@casl/ability";
2+
3+
export default new Ability([
4+
{
5+
action: "read",
6+
subject: "Article",
7+
conditions: { published: false }
8+
}
9+
]);

src/rules/entities.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Entity {
2+
constructor(attrs) {
3+
Object.assign(this, attrs);
4+
}
5+
}
6+
7+
export class Article extends Entity {}
8+
export class Author extends Entity {}

0 commit comments

Comments
 (0)