-
Star
(450)
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(); | |
| } |
@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
Thank you man!!!
...allowed can you explain this to me i am new at this