Skip to main content
added 140 characters in body
Source Link

After a few hours of research for a good logical and semantic prototype, i found a good solution.

router.put('/:articleId', AuthGuard([{ role: 'user', when: isOwner }, { role: 'admin' }]), async (req, res) => {

});

A predicate function can be added to a specific role for more flexibility. In this example, the user can only update an item "when" it owns it.

The little module :

import passport from 'passport';
import { Request, Response, NextFunction } from 'express';

export const AuthenticateGuard = passport.authenticate('jwt', { session: false });

export interface IAuthorizeItem {
  role: string;
  when?: (req: Request) => boolean;
};

export default function AuthGuard(items?: IAuthorizeItem[]) {
  return [AuthenticateGuard, AuthorizeGuard(items)];
};

export function AuthorizeGuard(items?: IAuthorizeItem[]) {
  return async function (req: Request, res: Response, next: NextFunction) {
    let user = req.user;
    if (!user) {
      return res.status(500).send('Access not allowed !');
    }

    if (typeof req.user.hasRole !== 'function') {
      throw new Error('User object must have hasRole method');
    }

    if (!items || items.length == 0) {
      return next();
    }

    for (let item of items) {
      if (req.user.hasRole(item.role)) {
        if (!item.when) {
          return next();
        }
        else {
          if (item.when(req)) {
            return next();
          }
        }
      }
    }

    res.status(500).send('Access not allowed !');
  }
};

Note: I avoid any dynamic types checking because i used typescript and this module must be used only with static object.

After a few hours of research for a good logical and semantic prototype, i found a good solution.

router.put('/:articleId', AuthGuard([{ role: 'user', when: isOwner }, { role: 'admin' }]), async (req, res) => {

});

A predicate function can be added to a specific role for more flexibility. In this example, the user can only update an item "when" it owns it.

The little module :

import passport from 'passport';
import { Request, Response, NextFunction } from 'express';

export const AuthenticateGuard = passport.authenticate('jwt', { session: false });

export interface IAuthorizeItem {
  role: string;
  when?: (req: Request) => boolean;
};

export default function AuthGuard(items?: IAuthorizeItem[]) {
  return [AuthenticateGuard, AuthorizeGuard(items)];
};

export function AuthorizeGuard(items?: IAuthorizeItem[]) {
  return async function (req: Request, res: Response, next: NextFunction) {
    let user = req.user;
    if (!user) {
      return res.status(500).send('Access not allowed !');
    }

    if (!items || items.length == 0) {
      return next();
    }

    for (let item of items) {
      if (req.user.hasRole(item.role)) {
        if (!item.when) {
          return next();
        }
        else {
          if (item.when(req)) {
            return next();
          }
        }
      }
    }

    res.status(500).send('Access not allowed !');
  }
};

Note: I avoid any dynamic types checking because i used typescript and this module must be used only with static object.

After a few hours of research for a good logical and semantic prototype, i found a good solution.

router.put('/:articleId', AuthGuard([{ role: 'user', when: isOwner }, { role: 'admin' }]), async (req, res) => {

});

A predicate function can be added to a specific role for more flexibility. In this example, the user can only update an item "when" it owns it.

The little module :

import passport from 'passport';
import { Request, Response, NextFunction } from 'express';

export const AuthenticateGuard = passport.authenticate('jwt', { session: false });

export interface IAuthorizeItem {
  role: string;
  when?: (req: Request) => boolean;
};

export default function AuthGuard(items?: IAuthorizeItem[]) {
  return [AuthenticateGuard, AuthorizeGuard(items)];
};

export function AuthorizeGuard(items?: IAuthorizeItem[]) {
  return async function (req: Request, res: Response, next: NextFunction) {
    let user = req.user;
    if (!user) {
      return res.status(500).send('Access not allowed !');
    }

    if (typeof req.user.hasRole !== 'function') {
      throw new Error('User object must have hasRole method');
    }

    if (!items || items.length == 0) {
      return next();
    }

    for (let item of items) {
      if (req.user.hasRole(item.role)) {
        if (!item.when) {
          return next();
        }
        else {
          if (item.when(req)) {
            return next();
          }
        }
      }
    }

    res.status(500).send('Access not allowed !');
  }
};

Note: I avoid any dynamic types checking because i used typescript and this module must be used only with static object.

Source Link

After a few hours of research for a good logical and semantic prototype, i found a good solution.

router.put('/:articleId', AuthGuard([{ role: 'user', when: isOwner }, { role: 'admin' }]), async (req, res) => {

});

A predicate function can be added to a specific role for more flexibility. In this example, the user can only update an item "when" it owns it.

The little module :

import passport from 'passport';
import { Request, Response, NextFunction } from 'express';

export const AuthenticateGuard = passport.authenticate('jwt', { session: false });

export interface IAuthorizeItem {
  role: string;
  when?: (req: Request) => boolean;
};

export default function AuthGuard(items?: IAuthorizeItem[]) {
  return [AuthenticateGuard, AuthorizeGuard(items)];
};

export function AuthorizeGuard(items?: IAuthorizeItem[]) {
  return async function (req: Request, res: Response, next: NextFunction) {
    let user = req.user;
    if (!user) {
      return res.status(500).send('Access not allowed !');
    }

    if (!items || items.length == 0) {
      return next();
    }

    for (let item of items) {
      if (req.user.hasRole(item.role)) {
        if (!item.when) {
          return next();
        }
        else {
          if (item.when(req)) {
            return next();
          }
        }
      }
    }

    res.status(500).send('Access not allowed !');
  }
};

Note: I avoid any dynamic types checking because i used typescript and this module must be used only with static object.