[[: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)