[[:oktatas:web:back-end_framework:express|< Express]]
====== Express - Admin ======
* **Szerző:** Sallai András
* Copyright (c) 2025, Sallai András
* Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC Attribution-Share Alike 4.0 International]]
* Web: https://szit.hu
===== Bevezetés =====
Szeretnénk vizsgálni az egyes végpontoknál, hogy egy bejelentkezett felhasználó admin vagy nem.
Amikor felveszünk egy felhasználót egy role nevű mezőben megadhatjuk a szerepet. A 0 normál felhasználó, az 1 admin felhasználó. A role mezőt nem kötelező megadni, de az alapértelmezés 0.
A regisztráció során a /register végponton lehet beállítani, hogy egy felhasználó admin vagy nem.
===== Előkészületek =====
A modellben fel kell venni egy új mezőt. Lehet a neve például **role**, vagy **user_type** vagy hasonlók. 1-es szám esetén admin felhasználóról beszélünk, egyébként normál felhasználó.
role: { type: DataTypes.INTEGER, defaultValue: 0 },
A modell teeljes kódja:
import { DataTypes } from 'sequelize'
import sequelize from '../database/database.js'
const User = sequelize.define('user', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: { type: DataTypes.STRING, allowNull: false },
email: { type: DataTypes.STRING, allowNull: true },
password: { type: DataTypes.STRING , allowNull: false },
role: { type: DataTypes.INTEGER, defaultValue: 0 },
})
sequelize.sync({
force: false
})
export default User
===== AuthController =====
A kontrollerben be kell állítani a szerepet, ha az szerepel a body-ban, egyébként 0 kell legyen.
role: req.body.role ? req.body.role : 0
Token előállítása:
const payload = {
id: user.id,
role: user.role
}
var token = jwt.sign(payload, config.app.key, {
expiresIn: 86400 //24 óra
})
A tokenben elhelyezzük a szerepet is.
Teljes kontroller:
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import User from '../models/user.js'
import config from '../../config/default.json' assert { type: 'json' }
const AuthController = {
async register(req, res) {
var clientError = false;
try {
if(!req.body.name ||
!req.body.email ||
!req.body.password ||
!req.body.password_confirmation) {
clientError = true
throw new Error('Error! Bad request data!')
}
if(req.body.password != req.body.password_confirmation) {
clientError = true
throw new Error('Error! The two password is not same!')
}
const user = await User.findOne({
where: { name: req.body.name }
})
if(user) {
clientError = true
throw new Error('Error! User already exists: ' + user.name)
}
AuthController.tryRegister(req, res)
} catch (error) {
if (clientError) {
res.status(400)
}else {
res.status(500)
}
await res.json({
success: false,
message: 'Error! User creation failed!',
error: error.message
})
}
},
async tryRegister(req, res) {
const user = {
name: req.body.name,
email: req.body.email,
password: bcrypt.hashSync(req.body.password),
role: req.body.role ? req.body.role : 0
}
await User.create(user)
.then( result => {
res.status(201)
res.json({
succes: true,
data: result
})
})
},
async login(req, res) {
try {
if(!req.body.name || !req.body.password) {
res.status(400)
throw new Error('Error! Bad name or password!')
}
const user = await User.findOne({
where: { name: req.body.name }
})
if(!user) {
res.status(404)
throw new Error('Error! User not found!')
}
var passwordIsValid = await bcrypt.compare(
req.body.password,
user.dataValues.password
);
if(!passwordIsValid) {
res.status(401)
throw new Error('Error! Password is not valid!')
}
AuthController.tryLogin(req, res, user)
} catch (error) {
res.json({
success: false,
message: 'Error! The login is failed!',
error: error.message
})
}
},
async tryLogin(req, res, user) {
const payload = {
id: user.id,
role: user.role
}
var token = jwt.sign(payload, config.app.key, {
expiresIn: 86400 //24 óra
})
res.status(200).json({
id: user.id,
name: user.name,
email: user.email,
accessToken: token
})
}
}
export default AuthController
===== A middleware újraírása =====
Az isAdmin() függvény egyszerre ellenőriz tokent és az admin-t is ellenőrzi.
import jwt from 'jsonwebtoken';
import config from '../../config/default.json' assert { type: 'json' };
const verifyTokenAndDecoded = (req, res, next) => {
const authData = req.headers.authorization;
if(!authData) {
return res.status(403).json({
message: 'No token provided!'
})
}
const token = authData.split(' ')[1];
jwt.verify(token, config.app.key, (err, decoded) => {
if(err) {
return res.status(401).json({
message: "Unauthorized!"
})
}
req.userId = decoded.id;
req.role = decoded.role;
next()
})
}
const verifyToken = (req, res, next) => {
verifyTokenAndDecoded(req, res, next)
}
const isAdmin = (req, res, next) => {
verifyTokenAndDecoded(req, res, (err) => {
if (err) return next(err)
if (req.role == 1) {
next()
} else {
return res.status(403).json({
message: "Require admin role!"
})
}
})
}
export { verifyToken, isAdmin}
===== Felhasználás a routingban =====
Az egyes middleware függvények:
* isAdmin
* verifyToken
A kettőt nincs értelme egyszerre használni, mivel az isAdmin egyben a token
jelenlétét is ellenőrzi. A verifyToken önmagában csak azonosítást végez.
A példánkban a /users végponton használjuk a middleware programokat.
import { isAdmin } from '../middlewares/authjwt.js';
router.get('/users', [isAdmin], UserController.index)
import { verifyToken } from '../middlewares/authjwt.js';
router.get('/users', [verifyToken], UserController.index)
===== Lásd még =====
* https://www.npmjs.com/package/@adminjs/express (2025)