harmadik gyakorlat
This commit is contained in:
@@ -0,0 +1,658 @@
|
||||
# Backend Fejlesztés Gyakorló Feladat
|
||||
## Authentication & Authorization Implementáció
|
||||
|
||||
---
|
||||
|
||||
## 📋 Tartalom
|
||||
|
||||
1. [Projekt Áttekintés](#projekt-áttekintés)
|
||||
2. [Architektúra](#architektúra)
|
||||
3. [Előkészületek](#előkészületek)
|
||||
4. [A Feladat](#a-feladat)
|
||||
5. [Implementációs Útmutató](#implementációs-útmutató)
|
||||
6. [Tesztelés](#tesztelés)
|
||||
7. [Hasznos Források](#hasznos-források)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Projekt Áttekintés
|
||||
|
||||
Ez egy gyakorló projekt backend fejlesztők számára, amely az **Authentication** és **Authorization** implementálására fókuszál. A projekt egy blog platformot szimulál, ahol a felhasználók regisztrálhatnak, bejelentkezhetnek, és blogokat írhatnak.
|
||||
|
||||
### Technológiai Stack
|
||||
|
||||
- **Node.js** + **Express.js** - Backend framework
|
||||
- **Prisma ORM** - Database ORM
|
||||
- **PostgreSQL** - Relációs adatbázis
|
||||
- **Redis** - Cache és session management
|
||||
- **JWT** - Token-based authentication
|
||||
- **bcrypt** - Jelszó hash-elés
|
||||
- **Cookie-parser** - Cookie kezelés
|
||||
- **Docker** - Konténerizáció
|
||||
|
||||
### Amit MEG KELL implementálni (FELADAT):
|
||||
|
||||
✅ Authentication (Hitelesítés)
|
||||
- Regisztráció
|
||||
- Bejelentkezés
|
||||
- Kijelentkezés
|
||||
- Token refresh
|
||||
- Current user lekérés
|
||||
|
||||
✅ Authorization (Jogosultság kezelés)
|
||||
- Authentication middleware
|
||||
- Role-based access control (RBAC)
|
||||
- Resource ownership ellenőrzés
|
||||
|
||||
### Amit NEM kell implementálni (már kész):
|
||||
|
||||
✅ Prisma schema és migrációk
|
||||
✅ Repository pattern implementáció
|
||||
✅ CQRS command/query handlers
|
||||
✅ Blog CRUD műveletek
|
||||
✅ Docker konfiguráció
|
||||
✅ Projekt struktúra
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architektúra
|
||||
|
||||
A projekt **Clean Architecture** és **CQRS** mintákat követ:
|
||||
|
||||
```
|
||||
src/
|
||||
├── domain/ # Domain réteg (business logic)
|
||||
│ ├── models/ # Domain modellek
|
||||
│ │ ├── User.js
|
||||
│ │ └── Blog.js
|
||||
│ └── repositories/ # Repository interfészek
|
||||
│ ├── IUserRepository.js
|
||||
│ └── IBlogRepository.js
|
||||
│
|
||||
├── application/ # Application réteg (use cases)
|
||||
│ ├── commands/ # Command objektumok
|
||||
│ │ ├── CreateBlogCommand.js
|
||||
│ │ ├── UpdateBlogCommand.js
|
||||
│ │ └── DeleteBlogCommand.js
|
||||
│ ├── queries/ # Query objektumok
|
||||
│ │ └── BlogQueries.js
|
||||
│ └── handlers/ # Command/Query handlerek
|
||||
│ ├── CreateBlogHandler.js
|
||||
│ ├── UpdateBlogHandler.js
|
||||
│ ├── DeleteBlogHandler.js
|
||||
│ └── BlogQueryHandler.js
|
||||
│
|
||||
├── infrastructure/ # Infrastructure réteg (külső függőségek)
|
||||
│ ├── database/ # Database kapcsolatok
|
||||
│ │ ├── prisma.js
|
||||
│ │ └── redis.js
|
||||
│ ├── repositories/ # Repository implementációk
|
||||
│ │ ├── UserRepository.js
|
||||
│ │ └── BlogRepository.js
|
||||
│ └── config/ # Konfigurációk
|
||||
│ └── index.js
|
||||
│
|
||||
├── api/ # API réteg (HTTP)
|
||||
│ ├── controllers/ # Controller-ek
|
||||
│ │ ├── AuthController.js # ⚠️ IMPLEMENTÁLANDÓ
|
||||
│ │ └── BlogController.js
|
||||
│ ├── routes/ # Route definíciók
|
||||
│ │ ├── authRoutes.js
|
||||
│ │ ├── blogRoutes.js
|
||||
│ │ └── userRoutes.js
|
||||
│ └── middlewares/ # Middleware-ek
|
||||
│ ├── authMiddleware.js # ⚠️ IMPLEMENTÁLANDÓ
|
||||
│ └── errorHandler.js
|
||||
│
|
||||
└── index.js # Alkalmazás belépési pont
|
||||
```
|
||||
|
||||
### Rétegek Felelősségei
|
||||
|
||||
**Domain réteg:**
|
||||
- Domain modellek és üzleti logika
|
||||
- Repository interfészek (dependency inversion)
|
||||
|
||||
**Application réteg:**
|
||||
- Use case-ek implementációja
|
||||
- Command/Query objektumok és handlerek
|
||||
- Validációs logika
|
||||
|
||||
**Infrastructure réteg:**
|
||||
- Külső rendszerek integrációja (DB, Redis)
|
||||
- Repository implementációk
|
||||
- Konfigurációk
|
||||
|
||||
**API réteg:**
|
||||
- HTTP kérések kezelése
|
||||
- Routing
|
||||
- Middleware-ek
|
||||
- Authentication & Authorization ⚠️
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Előkészületek
|
||||
|
||||
### 1. Függőségek telepítése
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Környezeti változók beállítása
|
||||
|
||||
Másold le a `.env.example` fájlt `.env` néven:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Állítsd be a környezeti változókat `.env` fájlban:
|
||||
|
||||
```env
|
||||
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/blog_db?schema=public"
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
|
||||
JWT_SECRET=valami-nagyon-titkos-kulcs-ide
|
||||
JWT_EXPIRES_IN=7d
|
||||
JWT_REFRESH_SECRET=masik-nagyon-titkos-kulcs-ide
|
||||
JWT_REFRESH_EXPIRES_IN=30d
|
||||
|
||||
PORT=3000
|
||||
NODE_ENV=development
|
||||
|
||||
COOKIE_SECRET=cookie-titkos-kulcs-ide
|
||||
```
|
||||
|
||||
⚠️ **FONTOS:** Production környezetben használj erős, random generált kulcsokat!
|
||||
|
||||
### 3. Docker konténerek indítása
|
||||
|
||||
```bash
|
||||
npm run docker:up
|
||||
```
|
||||
|
||||
Ez elindítja a PostgreSQL és Redis konténereket.
|
||||
|
||||
### 4. Adatbázis migráció
|
||||
|
||||
```bash
|
||||
npm run prisma:migrate
|
||||
npm run prisma:generate
|
||||
```
|
||||
|
||||
### 5. Projekt indítása (development)
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
A szerver elindul a `http://localhost:3000` címen.
|
||||
|
||||
Ellenőrizd a health endpoint-ot:
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 A Feladat
|
||||
|
||||
A feladatod **három fő komponens** implementálása:
|
||||
|
||||
### 1️⃣ AuthController implementálása
|
||||
|
||||
**Fájl:** `src/api/controllers/AuthController.js`
|
||||
|
||||
Implementálandó metódusok:
|
||||
|
||||
#### `register(req, res)`
|
||||
- Új felhasználó regisztrációja
|
||||
- Input validáció (email, username, password)
|
||||
- Uniqueness ellenőrzés (email és username)
|
||||
- Jelszó hash-elés `bcrypt`-tel
|
||||
- User létrehozása repository-n keresztül
|
||||
- JWT token generálás
|
||||
- HTTP-only cookie beállítás
|
||||
- User publikus adatainak visszaadása (jelszó nélkül!)
|
||||
|
||||
#### `login(req, res)`
|
||||
- Bejelentkezés email vagy username alapján
|
||||
- User keresése repository-val
|
||||
- Jelszó ellenőrzés `bcrypt.compare()`-val
|
||||
- Access és refresh token generálás
|
||||
- Cookie-k beállítása (httpOnly, secure, sameSite)
|
||||
- Opcionális: Session tárolás Redis-ben
|
||||
- Sikeres bejelentkezés esetén user adatok és tokenek visszaadása
|
||||
|
||||
#### `logout(req, res)`
|
||||
- Cookie-k törlése
|
||||
- Redis session törlése (ha van)
|
||||
- Refresh token invalidálás
|
||||
|
||||
#### `refreshToken(req, res)`
|
||||
- Refresh token kiolvasása cookie-ból
|
||||
- Token validálás
|
||||
- Új access token generálás
|
||||
- Új cookie beállítás
|
||||
|
||||
#### `getCurrentUser(req, res)`
|
||||
- Bejelentkezett user adatainak visszaadása
|
||||
- `req.user` alapján (amit az auth middleware állít be)
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ AuthMiddleware-ek implementálása
|
||||
|
||||
**Fájl:** `src/api/middlewares/authMiddleware.js`
|
||||
|
||||
#### `authenticateToken(req, res, next)`
|
||||
|
||||
Ez a middleware **minden védett route előtt** fut.
|
||||
|
||||
**Feladatai:**
|
||||
1. JWT token kiolvasása:
|
||||
- Cookie-ból: `req.cookies.accessToken`
|
||||
- VAGY Authorization header-ből: `Bearer <token>`
|
||||
2. Token validálás `jwt.verify()`-val
|
||||
3. User ID kinyerése a token payload-ból
|
||||
4. User betöltése repository-val
|
||||
5. `req.user` beállítása a user objektummal
|
||||
6. `next()` hívása
|
||||
|
||||
**Hibakezelés:**
|
||||
- Ha nincs token → 401 Unauthorized
|
||||
- Ha érvénytelen token → 401 Unauthorized
|
||||
- Ha user nem létezik → 401 Unauthorized
|
||||
|
||||
#### `requireRole(allowedRoles)`
|
||||
|
||||
Ez egy **higher-order middleware**, ami role-based access control-t implementál.
|
||||
|
||||
**Feladatai:**
|
||||
1. Visszaad egy middleware függvényt
|
||||
2. Ellenőrzi, hogy `req.user` létezik (az `authenticateToken` után fut!)
|
||||
3. Ellenőrzi, hogy `req.user.role` benne van-e az `allowedRoles` tömbben
|
||||
4. Ha nincs jogosultság → 403 Forbidden
|
||||
5. Ha van jogosultság → `next()`
|
||||
|
||||
**Példa használat:**
|
||||
```javascript
|
||||
router.delete('/admin/users/:id',
|
||||
authenticateToken,
|
||||
requireRole(['ADMIN']),
|
||||
deleteUserController
|
||||
);
|
||||
```
|
||||
|
||||
#### `checkOwnership(getResourceOwnerId)`
|
||||
|
||||
Ez a middleware **resource ownership** ellenőrzést implementál.
|
||||
|
||||
**Feladatai:**
|
||||
1. Visszaad egy middleware függvényt
|
||||
2. Meghívja a `getResourceOwnerId` függvényt, hogy megszerezze a resource tulajdonos ID-ját
|
||||
3. Ellenőrzi, hogy:
|
||||
- `req.user.id === ownerId` (a user a tulajdonos)
|
||||
- VAGY `req.user.role === 'ADMIN'` (ADMIN mindent módosíthat)
|
||||
4. Ha egyik sem teljesül → 403 Forbidden
|
||||
5. Ha OK → `next()`
|
||||
|
||||
**Példa használat:**
|
||||
```javascript
|
||||
router.put('/blogs/:id',
|
||||
authenticateToken,
|
||||
checkOwnership(async (req) => {
|
||||
const blog = await blogRepository.findById(req.params.id);
|
||||
return blog.authorId;
|
||||
}),
|
||||
(req, res) => blogController.updateBlog(req, res)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ Middleware-ek integrálása a route-okba
|
||||
|
||||
**Fájlok:**
|
||||
- `src/api/routes/authRoutes.js`
|
||||
- `src/api/routes/blogRoutes.js`
|
||||
|
||||
Add hozzá az `authenticateToken` middleware-t a védett endpoint-okhoz:
|
||||
|
||||
**authRoutes.js:**
|
||||
```javascript
|
||||
router.post('/logout', authenticateToken, (req, res) => authController.logout(req, res));
|
||||
router.get('/me', authenticateToken, (req, res) => authController.getCurrentUser(req, res));
|
||||
```
|
||||
|
||||
**blogRoutes.js:**
|
||||
```javascript
|
||||
router.post('/', authenticateToken, (req, res) => blogController.createBlog(req, res));
|
||||
router.put('/:id', authenticateToken, checkOwnership(...), (req, res) => blogController.updateBlog(req, res));
|
||||
router.delete('/:id', authenticateToken, checkOwnership(...), (req, res) => blogController.deleteBlog(req, res));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Implementációs Útmutató
|
||||
|
||||
### JWT Token Generálás
|
||||
|
||||
```javascript
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
// Access token generálás
|
||||
const accessToken = jwt.sign(
|
||||
{
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
role: user.role
|
||||
},
|
||||
process.env.JWT_SECRET,
|
||||
{ expiresIn: process.env.JWT_EXPIRES_IN }
|
||||
);
|
||||
|
||||
// Refresh token generálás
|
||||
const refreshToken = jwt.sign(
|
||||
{ userId: user.id },
|
||||
process.env.JWT_REFRESH_SECRET,
|
||||
{ expiresIn: process.env.JWT_REFRESH_EXPIRES_IN }
|
||||
);
|
||||
```
|
||||
|
||||
### JWT Token Validálás
|
||||
|
||||
```javascript
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
// decoded.userId, decoded.email, decoded.role
|
||||
} catch (error) {
|
||||
// Token érvénytelen vagy lejárt
|
||||
throw new Error('Invalid token');
|
||||
}
|
||||
```
|
||||
|
||||
### Jelszó Hash-elés
|
||||
|
||||
```javascript
|
||||
import bcrypt from 'bcrypt';
|
||||
|
||||
// Hash-elés (regisztrációnál)
|
||||
const saltRounds = 10;
|
||||
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
||||
|
||||
// Ellenőrzés (bejelentkezésnél)
|
||||
const isValid = await bcrypt.compare(password, user.password);
|
||||
```
|
||||
|
||||
### Cookie Beállítás
|
||||
|
||||
```javascript
|
||||
// Access token cookie
|
||||
res.cookie('accessToken', accessToken, {
|
||||
httpOnly: true, // JavaScript nem férhet hozzá
|
||||
secure: process.env.NODE_ENV === 'production', // Csak HTTPS-en
|
||||
sameSite: 'strict', // CSRF védelem
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 nap
|
||||
});
|
||||
|
||||
// Refresh token cookie
|
||||
res.cookie('refreshToken', refreshToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'strict',
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 nap
|
||||
});
|
||||
```
|
||||
|
||||
### Cookie Törlés
|
||||
|
||||
```javascript
|
||||
res.clearCookie('accessToken');
|
||||
res.clearCookie('refreshToken');
|
||||
```
|
||||
|
||||
### Redis Session Tárolás (Opcionális)
|
||||
|
||||
```javascript
|
||||
import { redis } from '../infrastructure/database/redis.js';
|
||||
|
||||
// Session mentése
|
||||
await redis.set(
|
||||
`session:${userId}`,
|
||||
JSON.stringify({ userId, email, loginTime: new Date() }),
|
||||
'EX',
|
||||
60 * 60 * 24 * 7 // 7 nap TTL
|
||||
);
|
||||
|
||||
// Session lekérése
|
||||
const session = await redis.get(`session:${userId}`);
|
||||
const sessionData = JSON.parse(session);
|
||||
|
||||
// Session törlése
|
||||
await redis.del(`session:${userId}`);
|
||||
```
|
||||
|
||||
### Token Kiolvasás Cookie-ból vagy Header-ből
|
||||
|
||||
```javascript
|
||||
function getTokenFromRequest(req) {
|
||||
// Cookie-ból
|
||||
if (req.cookies && req.cookies.accessToken) {
|
||||
return req.cookies.accessToken;
|
||||
}
|
||||
|
||||
// Authorization header-ből
|
||||
const authHeader = req.headers.authorization;
|
||||
if (authHeader && authHeader.startsWith('Bearer ')) {
|
||||
return authHeader.substring(7);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Tesztelés
|
||||
|
||||
### 1. Regisztráció
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/auth/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "test@example.com",
|
||||
"username": "testuser",
|
||||
"password": "SecurePassword123"
|
||||
}'
|
||||
```
|
||||
|
||||
**Elvárt válasz:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"user": {
|
||||
"id": "uuid...",
|
||||
"email": "test@example.com",
|
||||
"username": "testuser",
|
||||
"role": "USER"
|
||||
},
|
||||
"accessToken": "eyJhbGc...",
|
||||
"refreshToken": "eyJhbGc..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Bejelentkezés
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "test@example.com",
|
||||
"password": "SecurePassword123"
|
||||
}'
|
||||
```
|
||||
|
||||
### 3. Current User
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:3000/api/auth/me \
|
||||
-H "Authorization: Bearer <access_token>"
|
||||
```
|
||||
|
||||
VAGY cookie-val:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:3000/api/auth/me \
|
||||
--cookie "accessToken=<token>"
|
||||
```
|
||||
|
||||
### 4. Blog Létrehozás (Védett endpoint)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/blogs \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer <access_token>" \
|
||||
-d '{
|
||||
"title": "My First Blog",
|
||||
"content": "This is awesome!",
|
||||
"published": true
|
||||
}'
|
||||
```
|
||||
|
||||
### 5. Blog Módosítás (Ownership ellenőrzéssel)
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:3000/api/blogs/<blog_id> \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer <access_token>" \
|
||||
-d '{
|
||||
"title": "Updated Title"
|
||||
}'
|
||||
```
|
||||
|
||||
### 6. Kijelentkezés
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/auth/logout \
|
||||
-H "Authorization: Bearer <access_token>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Ellenőrző Lista
|
||||
|
||||
Implementációd akkor teljes, ha:
|
||||
|
||||
- [ ] ✅ Sikeres regisztráció email + username + password-dal
|
||||
- [ ] ✅ Email és username uniqueness ellenőrzés működik
|
||||
- [ ] ✅ Jelszó hash-elve van tárolva (bcrypt)
|
||||
- [ ] ✅ Sikeres bejelentkezés
|
||||
- [ ] ✅ Rossz jelszóval nem lehet bejelentkezni
|
||||
- [ ] ✅ JWT token generálódik és cookie-ban tárolódik
|
||||
- [ ] ✅ AuthMiddleware validálja a tokent
|
||||
- [ ] ✅ Védett endpoint-ok csak token-nal elérhetők
|
||||
- [ ] ✅ `/api/auth/me` visszaadja a bejelentkezett user adatait
|
||||
- [ ] ✅ Kijelentkezés törli a cookie-kat
|
||||
- [ ] ✅ Token refresh működik
|
||||
- [ ] ✅ Role-based access control működik (ADMIN vs USER)
|
||||
- [ ] ✅ Ownership check működik (csak saját blog módosítható)
|
||||
- [ ] ✅ Hibakezelés 401/403 válaszokkal
|
||||
|
||||
---
|
||||
|
||||
## 📚 Hasznos Források
|
||||
|
||||
### Dokumentációk
|
||||
|
||||
- [JWT](https://jwt.io/) - JSON Web Token
|
||||
- [bcrypt](https://www.npmjs.com/package/bcrypt) - Password hashing
|
||||
- [Prisma](https://www.prisma.io/docs) - ORM dokumentáció
|
||||
- [Express](https://expressjs.com/) - Web framework
|
||||
- [cookie-parser](https://www.npmjs.com/package/cookie-parser) - Cookie middleware
|
||||
|
||||
### Tananyagok
|
||||
|
||||
- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
|
||||
- [JWT Best Practices](https://blog.logrocket.com/jwt-authentication-best-practices/)
|
||||
- [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
|
||||
- [CQRS Pattern](https://martinfowler.com/bliki/CQRS.html)
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Gyakori Hibák és Megoldások
|
||||
|
||||
### "JWT must be provided"
|
||||
- Ellenőrizd, hogy a token szerepel-e a cookie-ban vagy Authorization header-ben
|
||||
- Ellenőrizd a cookie nevét (`accessToken`)
|
||||
|
||||
### "Invalid token"
|
||||
- Ellenőrizd a JWT_SECRET változót
|
||||
- Lehet, hogy a token lejárt - próbálj újra bejelentkezni
|
||||
|
||||
### "User already exists"
|
||||
- Email vagy username már foglalt
|
||||
- Használj egyedi értékeket
|
||||
|
||||
### "Incorrect password"
|
||||
- Ellenőrizd a bcrypt.compare() használatát
|
||||
- A paraméterek sorrendje: `bcrypt.compare(plainPassword, hashedPassword)`
|
||||
|
||||
### "403 Forbidden"
|
||||
- Nincs jogosultságod az adott művelethez
|
||||
- Ellenőrizd a role-t vagy az ownership-et
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Értékelési Szempontok
|
||||
|
||||
A feladat sikeres megoldása:
|
||||
|
||||
1. **Működőképesség (40%)**
|
||||
- Regisztráció működik
|
||||
- Bejelentkezés/kijelentkezés működik
|
||||
- Védett endpoint-ok hozzáférés-védelme
|
||||
|
||||
2. **Biztonság (30%)**
|
||||
- Jelszavak hash-elve vannak
|
||||
- HTTP-only cookie-k használata
|
||||
- JWT token biztonságos kezelése
|
||||
- Input validáció
|
||||
|
||||
3. **Kódminőség (20%)**
|
||||
- Letisztult, olvasható kód
|
||||
- Megfelelő error handling
|
||||
- Architektúra követése
|
||||
|
||||
4. **Extra funkciók (10%)**
|
||||
- Redis session management
|
||||
- Token refresh flow
|
||||
- Role-based access control
|
||||
- Ownership validation
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tippek
|
||||
|
||||
1. **Kezdd a legegyszerűbbel:** Először implementáld a regisztrációt, aztán a logint.
|
||||
|
||||
2. **Tesztelj folyamatosan:** Minden metódus után tesztelj curl-lel vagy Postman-nel.
|
||||
|
||||
3. **Nézd meg a meglévő kódot:** A BlogController egy jó példa, hogyan kell használni a repository-kat és handler-eket.
|
||||
|
||||
4. **Debug logging:** Használj `console.log()`-ot fejlesztés közben, hogy lásd mi történik.
|
||||
|
||||
5. **Hibakezelés:** Minden async művelet legyen try-catch blokkban.
|
||||
|
||||
6. **Token lejárat:** Fejlesztés közben használj rövid lejárati időt (pl. 15 perc), hogy tesztelhesd a refresh flow-t.
|
||||
|
||||
---
|
||||
|
||||
**Jó munkát és kellemes kódolást! 🚀**
|
||||
Reference in New Issue
Block a user