Abstraction of middleware functions

After reviewing my middleware Express functions, I realized that there is repeated code.

The first function is as follows:

const isAdmin = async (req, res, next) => {
  try {
    const requestingUser = await knex('users')
                                  .first('current_role')
                                  .where('id','=',req.user.id)

    requestingUser.current_role !== 'admin' ? res.sendStatus(403) : next()

  } catch (error) {
    res.send({error})
  }
}

The second function is:

const isAdminOrRecruiter = async (req, res, next) => {
  try {
    const requestingUser = await knex('users')
                                  .first('current_role')
                                  .where('id','=',req.user.id)
    const isNotAllowed = requestingUser.current_role !== 'admin' && requestingUser.current_role !==  'recruiter'
    isNotAllowed ? res.sendStatus(403) : next()

  } catch (error) {
    res.send({error})
  }
}

I am now considering how to create a single abstract function like isAllowed(['admin]) for only allowing admin access, or isAllowed(['admin','recruiter']) for permitting admins and recruiters to pass through. How can I achieve this efficiently?

The issue I face currently pertains to the arguments - there are already three of them, leaving me uncertain about where to add a fourth one.

Answer №1

One way to enhance your existing functions is by incorporating higher order functions. By creating a function that takes a list of roles as input and returns another function that utilizes this list to verify if the current user is assigned to any of them, you can streamline your access control logic:

const checkRole = (...roles) => async (req, res, next) => {
  try {
    const currentUser = await knex('users').first('current_role').where('id','=',req.user.id);
    const isAuthorized = roles.some(role => role === currentUser.current_role);
    isAuthorized ? next() : res.sendStatus(403);

  } catch (error) {
    res.send({error});
  }
}

const isAdmin = checkRole("admin");
const isAdminOrRecruiter = checkRole("admin", "recruiter");

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

At the ready stance for a particular grade of students attending a class

I have created a page with a navigation menu that can be scrolled using the wheel mouse. My goal is to ensure that the li item with the 'selected' class is always positioned in the first position on the left. Is there a way to achieve this using ...

What is the best way to save a current HTML element for later use?

Here is a simple HTML code that I would like to save the entire div with the class test_area and then replicate it when needed. Currently, my goal is to duplicate this div and place the clone underneath the original element. How can I achieve this? Unfortu ...

Enhancing user experience with jquery autocomplete matching

Currently utilizing the JQuery Autocomplete plugin. It seems that the default behavior is to match from the start, so "foo" matches "fool", but not "bufoon". I am seeking a way for matching to happen anywhere in the text and also in a case-insensitive man ...

The Node.js server refuses to start due to an error that is preventing it

I'm encountering an error while trying to run a node.js server for CRUD operations using Mongoose and Express dependencies. Below is the error message I receive when running the server with the command `node server.js`: ---------- Server.js Code ...

The code for accessing files in MongoDB using this.db.collection appears to be malfunctioning

I am facing an issue while trying to retrieve a file from MongoDB Atlas using gridfsstream and multer. The error that keeps popping up is: TypeError: this.db.collection is not a function Although I can successfully upload files, the retrieval process i ...

Exploring AngularJS 1.x: Understanding the differences between isolated scope and using require with ngModel

Throughout my experience with Angular 1.x, I have always used isolated scope in my directives. However, recently I encountered a directive that solely utilized ngModel. This made me curious about the differences and potential issues when using both methods ...

What is the procedure for deactivating a plugin within the replace feature of CkEditor?

Is there a way to disable image-upload on specific CKEditor textareas without affecting all of them through the config.js file? I'm wondering if it's possible to achieve this using the .replace method. For example: CKEDITOR.replace("meTextarea" ...

Setting default parameters for TypeScript generics

Let's say I define a function like this: const myFunc = <T, > (data: T) => { return data?.map((d) => ({name: d.name}) } The TypeScript compiler throws an error saying: Property 'name' does not exist on type 'T', whic ...

What is the best way to ensure that the content container's max-width for a split tier is the same as the width of a full-width tier?

My goal is to create a split tier on a webpage with a 60/40 layout. The size of this tier should be calculated based on the maximum width of the container above it. Using JavaScript and jQuery, I managed to derive the max-width value of the full-width-tier ...

How to Detect Font Resizing in Google Web Toolkit (GWT)

I am trying to find a way in GWT to capture the font resize event that occurs when the user changes the size of the font by using Ctrl-Mouse Scroll or going to View -> Zoom. I have searched on Google and looked on StackOverflow but haven't found any i ...

How to use AJAX to retrieve the text content of an HTML option value?

I have a script that displays a list of values, which I want to write: <option th:each = "iName : ${iNames}" th:value = "${iName}" th:text = "${iName}" th:selected="${selectedIName == iName}" In addition, I have the function setSelectedName in my .j ...

The loader fails to disappear even after the AJAX response has been received

I am currently working on a page that utilizes AJAX to display data. While the data is being fetched, I want to show a loading animation, and once the data has been retrieved, I want the loader to disappear. Below is a snippet of the code where I am attemp ...

Sharing Pictures (Using Express, Node, and MongoDB)

Seeking advice on the best method to create an upload feature for a web gallery application. After researching, I've come across different approaches like storing image data in Mongo: https://gist.github.com/aheckmann/2408370 Alternatively, saving ...

Can the recently introduced renderToNodeStream be utilized?

Recently, I upgraded my project to use server side rendering with React 16. The current technology stack includes: Node 8.4 Express React 16 Redux Webpack Pug for static content (such as header and footer) I am curious if it is possible to implement the ...

Struggling to find multiline content in a SWIFT message using regex

Looking into a SWIFT message using RegEx, here is an excerpt: :16R:FIN :35B:ISIN CH0117044708 ANTEILE -DT USD- SWISSCANTO (CH) INDEX EQUITY FUND USA :16R:FIA The goal is to extract information in group 3: ISIN CH0117044708 ANTEILE -DT USD- SWISSCANTO (C ...

employing HTTP.request within ejs rendering

When working with Express, I have a route that is connected to my ejs middleware. Snippet 1: app.all("/sample", function(req,res,next){ ejs.renderFile("./sample.ejs", {req,res,next,require,module:require("module")} {}, function(e, dt){ res. ...

Improving List performance with React.cloneElement

I am uncertain about the usage of React.cloneElement within a List component. Is it recommended to avoid using it, especially when dealing with a large number of elements in the list? Does React.cloneElement cause unnecessary re-renders that can be optimal ...

Using React hook form to create a Field Array within a Dialog component in Material UI

I have a form with custom fields added via Field Array from react-hook-form, and everything is functioning properly. However, I recently implemented drag and drop functionality for the property items to allow reordering them. Due to the large number of fie ...

What is the best way to display an image and text side by side within a single row in react-table?

I am trying to display an image and text side by side within a single column in a React table. I have successfully added two texts together in a single column using the code below: Header: "Name", id: "User", accessor: (d) => ...

Retrieve an array from the success function of a jQuery AJAX call

After successfully reading an rss file using the jQuery ajax function, I created the array function mycarousel_itemList in which I stored items by pushing them. However, when I tried to use this array in another function that I had created, I encountered t ...