Added jwt authenticaation
This commit is contained in:
@@ -13,10 +13,12 @@
|
||||
"dotenv": "^17.2.3",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^5.1.0",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"sqlite3": "^5.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^5.0.3",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/node": "^24.6.1",
|
||||
"@types/sqlite3": "^3.1.11",
|
||||
"nodemon": "^3.1.10",
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'dotenv/config';
|
||||
import {TournamentService} from './services/tournament-service';
|
||||
import {UserService} from './services/user-service';
|
||||
import {TeamService} from './services/team-service';
|
||||
import {authMiddleware} from './middlewares/auth-middleware';
|
||||
import router from './middlewares/logger';
|
||||
import {Database} from 'sqlite3';
|
||||
import fs from "fs";
|
||||
@@ -38,7 +39,7 @@ app.get('/tournaments/:id', async (req: Request, res: Response) => {
|
||||
res.send(tournament);
|
||||
});
|
||||
|
||||
app.post('/tournaments', async (req: Request, res: Response) => {
|
||||
app.post('/tournaments', authMiddleware, async (req: Request, res: Response) => {
|
||||
try {
|
||||
await tournamentService.addTournament(req.body);
|
||||
res.status(201).send();
|
||||
@@ -48,7 +49,7 @@ app.post('/tournaments', async (req: Request, res: Response) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.put('/tournaments/:id', async (req: Request, res: Response) => {
|
||||
app.put('/tournaments/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||
try {
|
||||
await tournamentService.updateTournament(+req.params.id, req.body);
|
||||
} catch (err) {
|
||||
@@ -57,7 +58,7 @@ app.put('/tournaments/:id', async (req: Request, res: Response) => {
|
||||
res.status(200).send({message: 'Tournament updated successfully'});
|
||||
});
|
||||
|
||||
app.delete('/tournaments/:id', async (req: Request, res: Response) => {
|
||||
app.delete('/tournaments/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||
try {
|
||||
await tournamentService.deleteTournament(+req.params.id);
|
||||
} catch (err) {
|
||||
@@ -79,7 +80,7 @@ app.get('/teams/:id', async (req: Request, res: Response) => {
|
||||
res.send(team);
|
||||
});
|
||||
|
||||
app.post('/teams', async (req: Request, res: Response) => {
|
||||
app.post('/teams', authMiddleware, async (req: Request, res: Response) => {
|
||||
const {name, tag, description} = req.body;
|
||||
if (!name || !tag) {
|
||||
return res.status(400).send({error: 'name and tag are required'});
|
||||
@@ -93,7 +94,7 @@ app.post('/teams', async (req: Request, res: Response) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.put('/teams/:id', async (req: Request, res: Response) => {
|
||||
app.put('/teams/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||
try {
|
||||
await teamService.updateTeam(+req.params.id, req.body);
|
||||
} catch (err) {
|
||||
@@ -102,7 +103,7 @@ app.put('/teams/:id', async (req: Request, res: Response) => {
|
||||
res.status(200).send({message: 'Team updated successfully'});
|
||||
});
|
||||
|
||||
app.delete('/teams/:id', async (req: Request, res: Response) => {
|
||||
app.delete('/teams/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||
try {
|
||||
await teamService.deleteTeam(+req.params.id);
|
||||
} catch (err) {
|
||||
@@ -116,7 +117,7 @@ app.get('/tournaments/:id/teams', async (req: Request, res: Response) => {
|
||||
res.send(teams);
|
||||
});
|
||||
|
||||
app.post('/tournaments/:id/teams', async (req: Request, res: Response) => {
|
||||
app.post('/tournaments/:id/teams', authMiddleware, async (req: Request, res: Response) => {
|
||||
const {teamId} = req.body;
|
||||
if (!teamId) {
|
||||
return res.status(400).send({error: 'teamId is required'});
|
||||
@@ -132,7 +133,7 @@ app.post('/tournaments/:id/teams', async (req: Request, res: Response) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.delete('/tournaments/:id/teams/:teamId', async (req: Request, res: Response) => {
|
||||
app.delete('/tournaments/:id/teams/:teamId', authMiddleware, async (req: Request, res: Response) => {
|
||||
try {
|
||||
await teamService.removeTeamFromTournament(+req.params.id, +req.params.teamId);
|
||||
} catch (err) {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || "key"
|
||||
|
||||
export const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).send({ error: 'Unauthorized: No token provided' });
|
||||
}
|
||||
const token = authHeader.split(' ')[1];
|
||||
try {
|
||||
const decoded = jwt.verify(token, JWT_SECRET);
|
||||
// @ts-ignore
|
||||
req.user = decoded;
|
||||
|
||||
next();
|
||||
} catch (err) {
|
||||
return res.status(401).send({ error: 'Unauthorized: Invalid token' });
|
||||
}
|
||||
};
|
||||
@@ -1,9 +1,12 @@
|
||||
import { User } from '../models/user';
|
||||
import { Database } from 'sqlite3';
|
||||
import * as argon2 from 'argon2';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || "key";
|
||||
|
||||
export class UserService {
|
||||
private csvFilename = 'csv/users.csv';
|
||||
private db: Database;
|
||||
@@ -40,7 +43,7 @@ export class UserService {
|
||||
});
|
||||
}
|
||||
|
||||
register(username: string, password: string): Promise<{ id: number; username: string }> {
|
||||
register(username: string, password: string): Promise<{ id: number; username: string; token: string }> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const hash = await argon2.hash(password);
|
||||
@@ -51,7 +54,8 @@ export class UserService {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve({ id: this.lastID, username });
|
||||
const token = jwt.sign({ id: this.lastID, username }, JWT_SECRET, { expiresIn: '7d' });
|
||||
resolve({ id: this.lastID, username, token });
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -60,7 +64,7 @@ export class UserService {
|
||||
});
|
||||
}
|
||||
|
||||
login(username: string, password: string): Promise<{ id: number; username: string }> {
|
||||
login(username: string, password: string): Promise<{ id: number; username: string; token: string }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db.get(
|
||||
'SELECT * FROM Users WHERE username = ?',
|
||||
@@ -77,7 +81,8 @@ export class UserService {
|
||||
if (!valid) {
|
||||
return reject(new Error('Invalid password'));
|
||||
}
|
||||
resolve({ id: user.id, username: user.username });
|
||||
const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '7d' });
|
||||
resolve({ id: user.id, username: user.username, token });
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
@@ -86,5 +91,3 @@ export class UserService {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user