Skip to content

Commit

Permalink
Add validation for user role
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasgehl3n committed Aug 7, 2023
1 parent 6219647 commit f00fccf
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 26 deletions.
36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
"dependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/connect-flash": "^0.0.37",
"@types/cors": "^2.8.13",
"@types/express-session": "^1.17.7",
"@types/passport": "^1.0.12",
"@types/passport-local": "^1.0.35",
"accesscontrol": "^2.2.1",
"bcrypt": "^5.1.0",
"bcryptjs": "^2.4.3",
"connect-flash": "^0.1.1",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-session": "^1.17.3",
Expand Down
33 changes: 15 additions & 18 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import flash from 'connect-flash';
import expressSession from 'express-session';
import PassportManager from './middlewares/authentication/PassportManager';
import AuthenticationValidator from './middlewares/authentication/AuthenticationValidator';

import cors from 'cors';
class Application {
server: http.Server;
express: express.Application;
Expand All @@ -19,13 +19,25 @@ class Application {
this.server = http.createServer(this.express);

this._setSession();
//this._setAclExpress();
this._setMiddlewares();
this._setRoutes();
databaseSync();
}

private _setMiddlewares(): void {
this.express.use(cors({ origin: true, credentials: true }));

this.express.use(function (req: any, res: any, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Origin, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Response-Time, X-PINGOTHER, X-CSRF-Token,Authorization');
if (req.method === "OPTIONS") {
return res.status(200).end();
} else {
next();
}
});
this.express.use(express.json());
this.express.use(bodyParser.urlencoded({ extended: true }));
this.express.use(AuthenticationValidator);
Expand All @@ -48,23 +60,8 @@ class Application {
this.express.use(flash())
this.express.use(passport.initialize());
this.express.use(passport.session());
PassportManager.InitAuthenticateMethods();
PassportManager.InitAuthenticateMethods();
}

// private _setAclExpress(): void {
// acl.config({
// rules: aclRules,
// baseUrl: '/',
// decodedObjectName: 'user',
// roleSearchPath: 'session.user.role',
// defaultRole: Perfil[Perfil.deslogado],
// });


// }



}

export default new Application().server;
4 changes: 4 additions & 0 deletions src/database/entities.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Animal from "./models/Animal";
import Institution from "./models/Institution";
import User from "./models/User";
import UserRole from "./models/UserRole";
export const entities: any[] = [
User,
Institution,
UserRole,
Animal,
]
59 changes: 59 additions & 0 deletions src/database/models/Institution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Model, DataTypes } from 'sequelize';
import database from '../database';

class Institution extends Model {
public id!: number;
public name!: string;
public cnpj?: string;
public description!: string;
public phone?: string;
public site?: string;
public email?: string;
public image?: string;
public receive_volunteers!: string;
}

Institution.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
cnpj:{
type: DataTypes.STRING,
allowNull: true,
},
description:{
type: DataTypes.STRING,
allowNull: false,
},
phone:{
type: DataTypes.STRING,
allowNull: true,
},
site:{
type: DataTypes.STRING,
allowNull: true,
},
image:{
type: DataTypes.BLOB,
allowNull: true,
},
receive_volunteers:{
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
},
},
{
tableName: 'institution',
sequelize: database.connection,
}
);

export default Institution;
2 changes: 2 additions & 0 deletions src/database/models/User.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Model, DataTypes } from 'sequelize';
import database from '../database';
import UserRole from './UserRole';

class User extends Model {
public id!: number;
public name?: string;
public email!: string;
public encriptedPassword!: string;
public userRoles!: UserRole[];
}

User.init(
Expand Down
49 changes: 49 additions & 0 deletions src/database/models/UserRole.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Model, DataTypes } from 'sequelize';
import database from '../database';
import User from './User';
import Institution from './Institution';

class UserRole extends Model {
public id!: number;
public idUser!: number;
public idInstitution?: number;
public idRole?: number;
}

UserRole.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
idUser:{
type: DataTypes.INTEGER,
allowNull: false,
},
idInstitution:{
type: DataTypes.INTEGER,
allowNull: true,
},
idRole:{
type: DataTypes.INTEGER,
allowNull: false,
}
},
{
tableName: 'user_role',
sequelize: database.connection,
}
);

User.hasMany(UserRole, {
foreignKey:'idUser',
as: 'userRoles'
});

Institution.hasMany(UserRole, {
foreignKey:'idInstitution',
});


export default UserRole;
5 changes: 5 additions & 0 deletions src/enums/Roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum Roles {
User = 1,
Volunteer = 2,
Administrator = 3,
}
18 changes: 18 additions & 0 deletions src/middlewares/acl/CheckAclPermission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { NextFunction } from "express";
import { AuthenticatedRequest } from "../../..";
import { Request, Response } from 'express';
import { Roles } from "../../enums/Roles";

export default function CheckAclPermission(role: Roles) {
return function (req: Request, res: Response, next: NextFunction) {
const authenticatedRequest = req as unknown as AuthenticatedRequest;
const { userRoles } = authenticatedRequest.user!;

if (userRoles.some(x => x.idRole === role)) {
return next();
}

return res.status(403).json({ message: 'Perfil sem permissão!' });
}
};

4 changes: 2 additions & 2 deletions src/middlewares/authentication/PassportManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export default class PassportManager {
}

static DeserializeUser() {
passport.deserializeUser(async (id: string, done) => {
const user = await UserService.GetById(id);
passport.deserializeUser(async (id: number, done) => {
const user = await UserService.GetByIdWithRoles(id);
done(null, user);
});
}
Expand Down
11 changes: 6 additions & 5 deletions src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Router } from "express";
import passport from "passport";
import { AuthenticatedRequest } from "..";
import { Response, Request } from "express";
import CheckUserPermission from "./middlewares/acl/CheckAclPermission";
import { Roles } from "./enums/Roles";

const routes = Router();
routes.post(
Expand All @@ -16,9 +18,8 @@ routes.post(
}
);

routes.get('/testingRoute', (req: Request, res: Response) => {
const foo = req as unknown as AuthenticatedRequest;
return res.status(200).send(foo.user?.email);
});

routes.get('/testingRoute', CheckUserPermission(Roles.User), (req, res) => {
res.json({ message: 'Usuário encontrado!' });
});

export default routes;
13 changes: 12 additions & 1 deletion src/services/UserService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import User from "../database/models/User";
import UserRole from "../database/models/UserRole";
import BaseService from "./BaseService";

class UserService extends BaseService<User>{
Expand All @@ -10,7 +11,17 @@ class UserService extends BaseService<User>{
return await User.findOne({
where: {
email: email
}
},
include: 'userRoles'
});
}

static async GetByIdWithRoles(id: number) {
return await User.findOne({
where: {
id: id
},
include: 'userRoles'
});
}
}
Expand Down

0 comments on commit f00fccf

Please sign in to comment.