Skip to content

Commit f8daa8f

Browse files
committed
add casbin role based access control
1 parent 520ce6d commit f8daa8f

File tree

22 files changed

+238
-80
lines changed

22 files changed

+238
-80
lines changed

middleware/auth.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,16 @@ const mongoose = require('mongoose');
44
const db = mongoose.connection.useDb('auth');
55

66
/**
7-
* Auth + Authz middleware
8-
*
9-
* @returns {Function}
7+
* Authentication middleware
108
*/
11-
module.exports = (role) => async (ctx, next) => {
9+
module.exports = async (ctx, next) => {
1210
const key = ctx.request.headers['spacex-key'];
1311
if (key) {
14-
const data = await db.collection('users').findOne({ key });
15-
if (data && data.key === key) {
16-
if (role) {
17-
if (data.roles && data.roles.includes(role)) {
18-
await next();
19-
return;
20-
}
21-
} else {
22-
await next();
23-
return;
24-
}
12+
const user = await db.collection('users').findOne({ key });
13+
if (user && user.key === key) {
14+
ctx.state.role = user.role;
15+
await next();
16+
return;
2517
}
2618
}
2719
ctx.status = 401;

middleware/authz/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
const { newEnforcer } = require('casbin');
3+
4+
/**
5+
* Authorization middleware
6+
*/
7+
module.exports = async (ctx, next) => {
8+
const { role } = ctx.state;
9+
const { path, method } = ctx;
10+
const enforcer = await newEnforcer(`${__dirname}/model.conf`, `${__dirname}/policy.csv`);
11+
const allowed = await enforcer.enforce(role, path, method);
12+
if (allowed) {
13+
await next();
14+
return;
15+
}
16+
ctx.status = 403;
17+
};

middleware/authz/model.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act
6+
7+
[role_definition]
8+
g = _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && (r.act == p.act || p.act == "*")

middleware/authz/policy.csv

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
p, root, /*, *
2+
3+
p, create:capsule, /v4/capsules, POST
4+
p, update:capsule, /v4/capsules/:id, PUT
5+
p, delete:capsule, /v4/capsules/:id, DELETE
6+
7+
p, create:cores, /v4/cores, POST
8+
p, update:cores, /v4/cores/:id, PUT
9+
p, delete:cores, /v4/cores/:id, DELETE
10+
11+
p, create:crew, /v4/crew, POST
12+
p, update:crew, /v4/crew/:id, PUT
13+
p, delete:crew, /v4/crew/:id, DELETE
14+
15+
p, create:dragons, /v4/dragons, POST
16+
p, update:dragons, /v4/dragons/:id, PUT
17+
p, delete:dragons, /v4/dragons/:id, DELETE
18+
19+
p, create:landpads, /v4/landpads, POST
20+
p, update:landpads, /v4/landpads/:id, PUT
21+
p, delete:landpads, /v4/landpads/:id, DELETE
22+
23+
p, create:launches, /v4/launches, POST
24+
p, update:launches, /v4/launches/:id, PUT
25+
p, delete:launches, /v4/launches/:id, DELETE
26+
27+
p, create:launchpads, /v4/launchpads, POST
28+
p, update:launchpads, /v4/launchpads/:id, PUT
29+
p, delete:launchpads, /v4/launchpads/:id, DELETE
30+
31+
p, create:payloads, /v4/payloads, POST
32+
p, update:payloads, /v4/payloads/:id, PUT
33+
p, delete:payloads, /v4/payloads/:id, DELETE
34+
35+
p, create:rockets, /v4/rockets, POST
36+
p, update:rockets, /v4/rockets/:id, PUT
37+
p, delete:rockets, /v4/rockets/:id, DELETE
38+
39+
p, create:ships, /v4/ships, POST
40+
p, update:ships, /v4/ships/:id, PUT
41+
p, delete:ships, /v4/ships/:id, DELETE
42+
43+
p, update:company, /v4/company/:id, PUT
44+
45+
p, update:roadster, /v4/roadster/:id, PUT
46+
47+
p, get:user, /v4/users, GET
48+
p, get-one:user, /v4/users/:id, GET
49+
p, query:user, /v4/users/query, POST
50+
p, create:user, /v4/users, POST
51+
p, update:user, /v4/users/:id, PUT
52+
p, delete:user, /v4/users/:id, DELETE
53+
54+
p, clear-cache, /v4/admin/cache, DELETE
55+
56+
g, superuser, root
57+
58+
g, create, create:capsule
59+
g, update, update:capsule
60+
g, delete, delete:capsule
61+
62+
g, create, create:cores
63+
g, update, update:cores
64+
g, delete, delete:cores
65+
66+
g, create, create:crew
67+
g, update, update:crew
68+
g, delete, delete:crew
69+
70+
g, create, create:dragons
71+
g, update, update:dragons
72+
g, delete, delete:dragons
73+
74+
g, create, create:landpads
75+
g, update, update:landpads
76+
g, delete, delete:landpads
77+
78+
g, create, create:launches
79+
g, update, update:launches
80+
g, delete, delete:launches
81+
82+
g, create, create:launchpads
83+
g, update, update:launchpads
84+
g, delete, delete:launchpads
85+
86+
g, create, create:payloads
87+
g, update, update:payloads
88+
g, delete, delete:payloads
89+
90+
g, create, create:rockets
91+
g, update, update:rockets
92+
g, delete, delete:rockets
93+
94+
g, create, create:ships
95+
g, update, update:ships
96+
g, delete, delete:ships
97+
98+
g, update, update:company
99+
100+
g, update, update:roadster
101+
102+
g, user, create
103+
g, user, update
104+
g, user, delete

middleware/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Export middleware
33
*/
44
module.exports.auth = require('./auth');
5+
module.exports.authz = require('./authz');
56
module.exports.cache = require('./cache');
67
module.exports.responseTime = require('./response-time');
78
module.exports.logger = require('./logger');

package-lock.json

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

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
},
2929
"homepage": "https://github.com/r-spacex/SpaceX-API",
3030
"dependencies": {
31+
"casbin": "^5.0.3",
3132
"cheerio": "^1.0.0-rc.3",
3233
"cron": "^1.8.2",
3334
"fuzzball": "^1.3.0",

services/v4/admin/routes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11

22
const Router = require('koa-router');
3-
const { auth, cache } = require('../../../middleware');
3+
const { auth, authz, cache } = require('../../../middleware');
44

55
const router = new Router({
66
prefix: '/admin',
77
});
88

99
// Clear redis cache
10-
router.delete('/cache', auth('basic'), async (ctx) => {
10+
router.delete('/cache', auth, authz, async (ctx) => {
1111
try {
1212
await cache.redis.flushall();
1313
ctx.status = 200;

services/v4/capsules/routes.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
const Router = require('koa-router');
33
const Capsule = require('./model');
4-
const { auth } = require('../../../middleware');
4+
const { auth, authz } = require('../../../middleware');
55

66
const router = new Router({
77
prefix: '/capsules',
@@ -48,7 +48,7 @@ router.post('/query', async (ctx) => {
4848
});
4949

5050
// Create capsule
51-
router.post('/', auth('basic'), async (ctx) => {
51+
router.post('/', auth, authz, async (ctx) => {
5252
try {
5353
const capsule = new Capsule(ctx.request.body);
5454
await capsule.save();
@@ -59,7 +59,7 @@ router.post('/', auth('basic'), async (ctx) => {
5959
});
6060

6161
// Update capsule
62-
router.patch('/:id', auth('basic'), async (ctx) => {
62+
router.patch('/:id', auth, authz, async (ctx) => {
6363
try {
6464
await Capsule.findByIdAndUpdate(ctx.params.id, ctx.request.body, { runValidators: true });
6565
ctx.status = 200;
@@ -69,7 +69,7 @@ router.patch('/:id', auth('basic'), async (ctx) => {
6969
});
7070

7171
// Delete capsule
72-
router.delete('/:id', auth('basic'), async (ctx) => {
72+
router.delete('/:id', auth, authz, async (ctx) => {
7373
try {
7474
await Capsule.findByIdAndDelete(ctx.params.id);
7575
ctx.status = 200;

services/v4/company/routes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
const Router = require('koa-router');
33
const Company = require('./model');
4-
const { auth } = require('../../../middleware');
4+
const { auth, authz } = require('../../../middleware');
55

66
const router = new Router({
77
prefix: '/company',
@@ -20,7 +20,7 @@ router.get('/', async (ctx) => {
2020
});
2121

2222
// Update company info
23-
router.patch('/:id', auth('basic'), async (ctx) => {
23+
router.patch('/:id', auth, authz, async (ctx) => {
2424
try {
2525
await Company.findByIdAndUpdate(ctx.params.id, ctx.request.body, { runValidators: true });
2626
ctx.status = 200;

0 commit comments

Comments
 (0)