✅ Implemented: - Password hashing with bcrypt (salt rounds = 10) - JWT token generation (access 15m, refresh 7d) - Updated login endpoint to return access + refresh tokens - Added refresh and logout endpoints - Updated seed script with hashed passwords - Added test users for all roles (OWNER, MANAGER, GROWER, STAFF) 📝 Files Added/Modified: - backend/src/utils/password.ts (NEW) - backend/src/utils/jwt.ts (NEW) - backend/src/controllers/auth.controller.ts (UPDATED) - backend/src/routes/auth.routes.ts (UPDATED) - backend/prisma/seed.js (UPDATED - now hashes passwords) - CREDENTIALS.md (UPDATED - all test users documented) 🔐 Test Users: - admin@runfoo.run (OWNER) - manager@runfoo.run (MANAGER) - grower@runfoo.run (GROWER) - staff@runfoo.run (STAFF) All passwords: password123 ⏭️ Next: Auth middleware + RBAC
38 lines
834 B
TypeScript
38 lines
834 B
TypeScript
import jwt from 'jsonwebtoken';
|
|
|
|
const JWT_SECRET = process.env.JWT_SECRET || 'supersecret';
|
|
|
|
export interface TokenPayload {
|
|
userId: string;
|
|
email: string;
|
|
role: string;
|
|
}
|
|
|
|
/**
|
|
* Generate an access token (short-lived)
|
|
*/
|
|
export function generateAccessToken(payload: TokenPayload): string {
|
|
return jwt.sign(payload, JWT_SECRET, {
|
|
expiresIn: '15m',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Generate a refresh token (long-lived)
|
|
*/
|
|
export function generateRefreshToken(payload: TokenPayload): string {
|
|
return jwt.sign(payload, JWT_SECRET, {
|
|
expiresIn: '7d',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Verify and decode a token
|
|
*/
|
|
export function verifyToken(token: string): TokenPayload {
|
|
try {
|
|
return jwt.verify(token, JWT_SECRET) as TokenPayload;
|
|
} catch (error) {
|
|
throw new Error('Invalid or expired token');
|
|
}
|
|
}
|