-
Star
(453)
You must be signed in to star a gist -
Fork
(126)
You must be signed in to fork a gist
-
-
Save joshnuss/37ebaf958fe65a18d4ff to your computer and use it in GitHub Desktop.
// the main app file | |
import express from "express"; | |
import loadDb from "./loadDb"; // dummy middleware to load db (sets request.db) | |
import authenticate from "./authentication"; // middleware for doing authentication | |
import permit from "./authorization"; // middleware for checking if user's role is permitted to make request | |
const app = express(), | |
api = express.Router(); | |
// first middleware will setup db connection | |
app.use(loadDb); | |
// authenticate each request | |
// will set `request.user` | |
app.use(authenticate); | |
// setup permission middleware, | |
// check `request.user.role` and decide if ok to continue | |
app.use("/api/private", permit("admin")); | |
app.use(["/api/foo", "/api/bar"], permit("manager", "employee")); | |
// setup requests handlers | |
api.get("/private/whatever", (req, res) => res.json({whatever: true})); | |
api.get("/foo", (req, res) => res.json({currentUser: req.user})); | |
api.get("/bar", (req, res) => res.json({currentUser: req.user})); | |
// setup permissions based on HTTP Method | |
// account creation is public | |
api.post("/account", (req, res) => res.json({message: "created"})); | |
// account update & delete (PATCH & DELETE) are only available to managers | |
api.patch("/account", permit('manager'), (req, res) => res.json({message: "updated"})); | |
api.delete("/account", permit('manager'), (req, res) => res.json({message: "deleted"})); | |
// viewing account "GET" available to manager and employee | |
api.get("/account", permit('manager', 'employee'), (req, res) => res.json({currentUser: req.user})); | |
// mount api router | |
app.use("/api", api); | |
// start 'er up | |
app.listen(process.env.PORT || 3000); |
// middleware for authentication | |
export default async function authorize(request, _response, next) { | |
const apiToken = request.headers['x-api-token']; | |
// set user on-success | |
request.user = await request.db.users.findByApiKey(apiToken); | |
// always continue to next middleware | |
next(); | |
} |
// dummy middleware for db (set's request.db) | |
export default function loadDb(request, _response, next) { | |
// dummy db | |
request.db = { | |
users: { | |
findByApiKey: async token => { | |
switch { | |
case (token == '1234') { | |
return {role: 'manager', id: 1234}; | |
case (token == '5678') { | |
return {role: 'employee', id: 5678}; | |
default: | |
return null; // no user | |
} | |
} | |
} | |
}; | |
next(); | |
} |
...allowed can you explain this to me i am new at this
@HamzaKazmi43 f(...args)
is called "rest parameters". It allows the function to consume the parameters as if it was an array.
For more info, see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
very useful, thank you!
Thank you @joshnuss, this is brilliant!
Can I see some example usage of this code?
I also tried to replace 'api' with app and I get some unexpected circular error of some kind. I am not using router directly. I am only using app=express();
Thanks man, this just saved me hours of work today!
Ditto on this being very helpful. And I learned about rest parameters so that was a big bonus for me.
Thanks for sharing.
Thank you for sharing.
Thank you! This was extremely helpful for me.
thanks! save me"
This is helpful. I have adapted mine based on your work. Thanks!
Thank
Just here to Thank... awsome buddy thanks 👊️😎️
Here to thank you too ! :)
This is great, was looking for something similar.
Thanks man
I looked at other implementations but this is the most simple and useful one so far
Extremely Useful. Works like a charm.
Nice, Thank you
By using 'owner' role I would expect the user who created(own) the doc is trying to access, otherwise it is confusing and misleading.
I would suggest to rename 'owner' role to something else, because 'owner' in this pattern is not what you expect.
Excellent design - simple, beautiful and powerful. Thank you very much for sharing!
@sergey-shpak yeh me too, I think it's just an unfortunately named role?
Very helpful. Thanks for sharing.
This is perfect, thank you a ton.
thank you bro..
I got an error. Please advice.
import authenticate from "./authentication.js"; // middleware for doing authentication
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Object.compileFunction (vm.js:344:18)
I got an error. Please advice.
import authenticate from "./authentication.js"; // middleware for doing authentication ^^^^^^
SyntaxError: Cannot use import statement outside a module at Object.compileFunction (vm.js:344:18)
Take a look at https://stackoverflow.com/questions/58384179/syntaxerror-cannot-use-import-statement-outside-a-module or update your syntax to use require. For example, const {authorize} = require('./authentication.js')
I got an error. Please advice.
import authenticate from "./authentication.js"; // middleware for doing authentication ^^^^^^
SyntaxError: Cannot use import statement outside a module at Object.compileFunction (vm.js:344:18)Take a look at https://stackoverflow.com/questions/58384179/syntaxerror-cannot-use-import-statement-outside-a-module or update your syntax to use require. For example, const {authorize} = require('./authentication.js')
Thank you.
Thank you , this is very helpful
Thanks.. it's simple but powerful! 👍