mirror of
https://github.com/itsnaveenk/bazar3.git
synced 2025-12-19 21:27:05 +00:00
Merge branch 'main' of https://github.com/itsnaveenk/bazar3
This commit is contained in:
commit
a501ddf0d6
30
nginx.conf
Normal file
30
nginx.conf
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
user nginx;
|
||||||
|
worker_processes auto;
|
||||||
|
|
||||||
|
http {
|
||||||
|
# ...existing code...
|
||||||
|
|
||||||
|
server {
|
||||||
|
server_name kings.com;
|
||||||
|
root /var/www/kings-frontend; # Path to your built frontend files
|
||||||
|
index index.html;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
# ...existing code...
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
server_name backend.kings.com;
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3000; // Forward to your Node.js backend
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
# ...existing code...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ...existing code...
|
||||||
|
}
|
||||||
@ -27,15 +27,17 @@ exports.publishResult = async (data, authorization) => {
|
|||||||
const [admin] = await db.query('SELECT id FROM admins WHERE session_token = ?', [token]);
|
const [admin] = await db.query('SELECT id FROM admins WHERE session_token = ?', [token]);
|
||||||
if (!admin) throw { status: 401, message: 'Unauthorized' };
|
if (!admin) throw { status: 401, message: 'Unauthorized' };
|
||||||
|
|
||||||
const { team, date, result } = data;
|
const { team, date, result, announcement_time } = data; // renamed draw_time
|
||||||
// validate if the team exists
|
// validate if the team exists
|
||||||
const teams = await db.query('SELECT id FROM teams WHERE name = ?', [team.toUpperCase()]);
|
const teams = await db.query('SELECT id FROM teams WHERE name = ?', [team.toUpperCase()]);
|
||||||
if (!teams.length) throw { status: 400, message: 'Team does not exist. Create team first.' };
|
if (!teams.length) throw { status: 400, message: 'Team does not exist. Create team first.' };
|
||||||
|
|
||||||
// publish result using team id
|
// publish result using team id
|
||||||
await db.query(`
|
await db.query(`
|
||||||
INSERT INTO results (team_id, result_date, result)
|
INSERT INTO results (team_id, result_date, result, announcement_time)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?, COALESCE(?, '00:00:00'))
|
||||||
ON DUPLICATE KEY UPDATE result = VALUES(result)
|
ON DUPLICATE KEY UPDATE
|
||||||
`, [teams[0].id, date, result]);
|
result = VALUES(result),
|
||||||
|
announcement_time = VALUES(announcement_time)
|
||||||
|
`, [teams[0].id, date, result, announcement_time]);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,7 +7,7 @@ exports.getMonthlyResults = async (req, res) => {
|
|||||||
return res.status(400).json({ error: 'Team and month are required.' });
|
return res.status(400).json({ error: 'Team and month are required.' });
|
||||||
}
|
}
|
||||||
const results = await db.query(`
|
const results = await db.query(`
|
||||||
SELECT r.result, r.result_date
|
SELECT r.result, r.result_date, r.announcement_time
|
||||||
FROM results r
|
FROM results r
|
||||||
JOIN teams t ON r.team_id = t.id
|
JOIN teams t ON r.team_id = t.id
|
||||||
WHERE t.name = ? AND DATE_FORMAT(r.result_date, '%Y-%m') = ?
|
WHERE t.name = ? AND DATE_FORMAT(r.result_date, '%Y-%m') = ?
|
||||||
@ -28,7 +28,7 @@ exports.getDailyResults = async (req, res) => {
|
|||||||
return res.status(400).json({ error: 'Date query parameter is required.' });
|
return res.status(400).json({ error: 'Date query parameter is required.' });
|
||||||
}
|
}
|
||||||
const results = await db.query(`
|
const results = await db.query(`
|
||||||
SELECT t.name as team, r.result, r.result_date
|
SELECT t.name as team, r.result, r.result_date, r.announcement_time
|
||||||
FROM results r
|
FROM results r
|
||||||
JOIN teams t ON r.team_id = t.id
|
JOIN teams t ON r.team_id = t.id
|
||||||
WHERE r.result_date = ?
|
WHERE r.result_date = ?
|
||||||
|
|||||||
@ -12,15 +12,15 @@ exports.getAllTeams = async (req, res) => {
|
|||||||
|
|
||||||
exports.createTeam = async (req, res) => {
|
exports.createTeam = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { name, announcement_time } = req.body;
|
const { name } = req.body;
|
||||||
|
|
||||||
if (!name || !announcement_time) {
|
if (!name) {
|
||||||
return res.status(400).json({ error: 'Name and announcement time are required' });
|
return res.status(400).json({ error: 'Name is required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.query(
|
await db.query(
|
||||||
'INSERT INTO teams (name, announcement_time) VALUES (?, ?)',
|
'INSERT INTO teams (name) VALUES (?)',
|
||||||
[name.toUpperCase(), announcement_time]
|
[name.toUpperCase()]
|
||||||
);
|
);
|
||||||
|
|
||||||
res.status(201).json({ success: true, message: 'Team created successfully' });
|
res.status(201).json({ success: true, message: 'Team created successfully' });
|
||||||
@ -33,26 +33,14 @@ exports.createTeam = async (req, res) => {
|
|||||||
exports.updateTeam = async (req, res) => {
|
exports.updateTeam = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const { name, announcement_time } = req.body;
|
const { name } = req.body;
|
||||||
|
|
||||||
if (!name && !announcement_time) {
|
if (!name) {
|
||||||
return res.status(400).json({ error: 'At least one field (name or announcement time) is required' });
|
return res.status(400).json({ error: 'At least name is required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields = [];
|
const fields = ['name = ?'];
|
||||||
const values = [];
|
const values = [name.toUpperCase(), id];
|
||||||
|
|
||||||
if (name) {
|
|
||||||
fields.push('name = ?');
|
|
||||||
values.push(name.toUpperCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (announcement_time) {
|
|
||||||
fields.push('announcement_time = ?');
|
|
||||||
values.push(announcement_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
values.push(id);
|
|
||||||
|
|
||||||
await db.query(`UPDATE teams SET ${fields.join(', ')} WHERE id = ?`, values);
|
await db.query(`UPDATE teams SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,7 @@ const Joi = require('joi');
|
|||||||
|
|
||||||
exports.validateTeam = (req, res, next) => {
|
exports.validateTeam = (req, res, next) => {
|
||||||
const schema = Joi.object({
|
const schema = Joi.object({
|
||||||
name: Joi.string().max(100).required(),
|
name: Joi.string().max(100).required()
|
||||||
announcement_time: Joi.string().pattern(/^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/).required()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { error } = schema.validate(req.body);
|
const { error } = schema.validate(req.body);
|
||||||
|
|||||||
@ -44,7 +44,7 @@
|
|||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"team\": \"BIKANER SUPER\",\n \"date\": \"2025-03-12\",\n \"result\": \"45\"\n}"
|
"raw": "{\n \"team\": \"BIKANER SUPER\",\n \"date\": \"2025-03-12\",\n \"result\": \"45\",\n \"announcement_time\": \"02:30:00\"\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "http://localhost:3000/admin/results",
|
"raw": "http://localhost:3000/admin/results",
|
||||||
@ -77,11 +77,15 @@
|
|||||||
{
|
{
|
||||||
"key": "Content-Type",
|
"key": "Content-Type",
|
||||||
"value": "application/json"
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer <SESSION_TOKEN>"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"name\": \"NEW TEAM\",\n \"announcement_time\": \"02:30:00\"\n}"
|
"raw": "{\n \"name\": \"NEW TEAM\"\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "http://localhost:3000/api/teams",
|
"raw": "http://localhost:3000/api/teams",
|
||||||
@ -100,11 +104,15 @@
|
|||||||
{
|
{
|
||||||
"key": "Content-Type",
|
"key": "Content-Type",
|
||||||
"value": "application/json"
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer <SESSION_TOKEN>"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"name\": \"UPDATED TEAM\",\n \"announcement_time\": \"03:00:00\"\n}"
|
"raw": "{\n \"name\": \"UPDATED TEAM\"\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "http://localhost:3000/api/teams/1",
|
"raw": "http://localhost:3000/api/teams/1",
|
||||||
@ -119,7 +127,12 @@
|
|||||||
"name": "Delete Team",
|
"name": "Delete Team",
|
||||||
"request": {
|
"request": {
|
||||||
"method": "DELETE",
|
"method": "DELETE",
|
||||||
"header": [],
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Authorization",
|
||||||
|
"value": "Bearer <SESSION_TOKEN>"
|
||||||
|
}
|
||||||
|
],
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "http://localhost:3000/api/teams/1",
|
"raw": "http://localhost:3000/api/teams/1",
|
||||||
"protocol": "http",
|
"protocol": "http",
|
||||||
@ -169,7 +182,7 @@
|
|||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"name\": \"<script>alert('xss');</script>\",\n \"announcement_time\": \"02:30:00\"\n}"
|
"raw": "{\n \"name\": \"<script>alert('xss');</script>\"\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "http://localhost:3000/api/teams",
|
"raw": "http://localhost:3000/api/teams",
|
||||||
|
|||||||
@ -106,27 +106,27 @@ The server will listen on the port specified in your `.env` file (default is 300
|
|||||||
|
|
||||||
### Team Endpoints
|
### Team Endpoints
|
||||||
- **GET /api/teams**
|
- **GET /api/teams**
|
||||||
Retrieve all teams.
|
Retrieve all teams (public).
|
||||||
|
|
||||||
- **POST /api/teams**
|
- **POST /api/teams**
|
||||||
Create a new team. Requires `name` and `announcement_time` in the body.
|
Create a new team (admin only).
|
||||||
_Request Body Example:_
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "NEW TEAM",
|
"name": "NEW TEAM"
|
||||||
"announcement_time": "02:30:00"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- **PUT /api/teams/:id**
|
- **PUT /api/teams/:id**
|
||||||
Update a team.
|
Update a team (admin only, requires Bearer token).
|
||||||
|
|
||||||
- **DELETE /api/teams/:id**
|
- **DELETE /api/teams/:id**
|
||||||
Delete a team.
|
Delete a team (admin only, requires Bearer token).
|
||||||
|
|
||||||
### Testing Sanitization
|
### Testing Sanitization
|
||||||
A sample endpoint (POST /api/teams) will sanitize HTML input. For example, sending:
|
A sample endpoint (POST /api/teams) will sanitize HTML input. For example, sending:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "<script>alert('xss');</script>",
|
"name": "<script>alert('xss');</script>"
|
||||||
"announcement_time": "02:30:00"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
will have the `<` and `>` characters escaped to protect against XSS.
|
will have the `<` and `>` characters escaped to protect against XSS.
|
||||||
|
|||||||
@ -14,7 +14,7 @@ router.get('/results', async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [result] = await db.query(`
|
const [result] = await db.query(`
|
||||||
SELECT r.result, r.result_date, t.name AS team
|
SELECT r.result, r.result_date, r.announcement_time, t.name AS team
|
||||||
FROM results r
|
FROM results r
|
||||||
JOIN teams t ON r.team_id = t.id
|
JOIN teams t ON r.team_id = t.id
|
||||||
WHERE t.name = ? AND r.result_date = ?
|
WHERE t.name = ? AND r.result_date = ?
|
||||||
@ -39,7 +39,7 @@ router.get('/today', async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const results = await db.query(`
|
const results = await db.query(`
|
||||||
SELECT t.name AS team, r.result, r.result_date
|
SELECT t.name AS team, r.result, r.result_date, r.announcement_time
|
||||||
FROM results r
|
FROM results r
|
||||||
JOIN teams t ON r.team_id = t.id
|
JOIN teams t ON r.team_id = t.id
|
||||||
WHERE r.result_date = ?
|
WHERE r.result_date = ?
|
||||||
|
|||||||
@ -2,13 +2,26 @@ const express = require('express');
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const teamController = require('../controllers/teamController');
|
const teamController = require('../controllers/teamController');
|
||||||
const { validateTeam } = require('../middlewares/validation');
|
const { validateTeam } = require('../middlewares/validation');
|
||||||
|
const db = require('../db');
|
||||||
|
|
||||||
|
async function requireAdmin(req, res, next) {
|
||||||
|
try {
|
||||||
|
const token = req.headers.authorization?.split(' ')[1];
|
||||||
|
if (!token) return res.status(401).json({ error: 'Unauthorized' });
|
||||||
|
const [admin] = await db.query('SELECT id FROM admins WHERE session_token = ?', [token]);
|
||||||
|
if (!admin) return res.status(401).json({ error: 'Unauthorized' });
|
||||||
|
next();
|
||||||
|
} catch {
|
||||||
|
res.status(401).json({ error: 'Unauthorized' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
router.get('/', teamController.getAllTeams);
|
router.get('/', teamController.getAllTeams);
|
||||||
|
|
||||||
router.post('/', validateTeam, teamController.createTeam);
|
router.post('/', requireAdmin, validateTeam, teamController.createTeam);
|
||||||
|
|
||||||
router.put('/:id', validateTeam, teamController.updateTeam);
|
router.put('/:id', requireAdmin, validateTeam, teamController.updateTeam);
|
||||||
|
|
||||||
router.delete('/:id', teamController.deleteTeam);
|
router.delete('/:id', requireAdmin, teamController.deleteTeam);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ USE kingdb_prod;
|
|||||||
CREATE TABLE teams (
|
CREATE TABLE teams (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
name VARCHAR(100) NOT NULL UNIQUE,
|
name VARCHAR(100) NOT NULL UNIQUE,
|
||||||
announcement_time TIME NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -12,6 +11,7 @@ CREATE TABLE results (
|
|||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
team_id INT NOT NULL,
|
team_id INT NOT NULL,
|
||||||
result_date DATE NOT NULL,
|
result_date DATE NOT NULL,
|
||||||
|
announcement_time TIME NOT NULL,
|
||||||
result VARCHAR(10) NOT NULL,
|
result VARCHAR(10) NOT NULL,
|
||||||
FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE,
|
FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE,
|
||||||
UNIQUE KEY uniq_team_date (team_id, result_date)
|
UNIQUE KEY uniq_team_date (team_id, result_date)
|
||||||
|
|||||||
@ -17,8 +17,7 @@ const BASE_URL = 'http://localhost:3000';
|
|||||||
const createTeamResponse = await axios.post(
|
const createTeamResponse = await axios.post(
|
||||||
`${BASE_URL}/api/teams`,
|
`${BASE_URL}/api/teams`,
|
||||||
{
|
{
|
||||||
name: 'NEW TEAM',
|
name: 'NEW TEAM'
|
||||||
announcement_time: '02:30:00'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: { Authorization: `Bearer ${sessionToken}` }
|
headers: { Authorization: `Bearer ${sessionToken}` }
|
||||||
@ -35,8 +34,7 @@ const BASE_URL = 'http://localhost:3000';
|
|||||||
const updateTeamResponse = await axios.put(
|
const updateTeamResponse = await axios.put(
|
||||||
`${BASE_URL}/api/teams/1`,
|
`${BASE_URL}/api/teams/1`,
|
||||||
{
|
{
|
||||||
name: 'UPDATED TEAM',
|
name: 'UPDATED TEAM'
|
||||||
announcement_time: '03:00:00'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: { Authorization: `Bearer ${sessionToken}` }
|
headers: { Authorization: `Bearer ${sessionToken}` }
|
||||||
|
|||||||
@ -10,7 +10,7 @@ const teamRoutes = require('./routes/team');
|
|||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
app.use(cors({ origin: ['http://localhost:3000', 'https://your-production-domain.com'] }));
|
app.use(cors({ origin: ['http://localhost:3000', '*', 'https://your-production-domain.com'] }));
|
||||||
app.use(express.json({ limit: '10kb' }));
|
app.use(express.json({ limit: '10kb' }));
|
||||||
app.use(security.anonymizeIP);
|
app.use(security.anonymizeIP);
|
||||||
app.use(security.sanitizeInput);
|
app.use(security.sanitizeInput);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user