CoolFace
Apppublic

Reality123b/RelayServer

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
server.js326 linesDownload Raw Back to root
1const fs = require('fs');2const path = require('path');3['data', 'datasets'].forEach(dir => {4  const fullPath = path.join(__dirname, dir);5  if (!fs.existsSync(fullPath)) {6    fs.mkdirSync(fullPath, { recursive: true });7  }8});9const express = require('express');10const sqlite3 = require('sqlite3').verbose();11const bcrypt = require('bcryptjs');12const jwt = require('jsonwebtoken');13const multer = require('multer');14const cors = require('cors');15const helmet = require('helmet');16const rateLimit = require('express-rate-limit');17const archiver = require('archiver');18const { parse } = require('csv-parse');19const app = express();20const PORT = process.env.PORT || 3000;21const JWT_SECRET = process.env.JWT_SECRET || 'your-super-secret-jwt-key-change-this-in-production';22const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'DataMaster2024!';23app.use(helmet());24app.use(cors());25app.use(express.json({ limit: '50mb' }));26app.use(express.urlencoded({ extended: true, limit: '50mb' }));27const limiter = rateLimit({28  windowMs: 15 * 60 * 1000,29  max: 10030});31app.use(limiter);32const storage = multer.diskStorage({33  destination: (req, file, cb) => {34    const uploadPath = path.join(__dirname, 'datasets');35    if (!fs.existsSync(uploadPath)) {36      fs.mkdirSync(uploadPath, { recursive: true });37    }38    cb(null, uploadPath);39  },40  filename: (req, file, cb) => {41    cb(null, `${Date.now()}-${file.originalname}`);42  }43});44const upload = multer({45  storage: storage,46  limits: { fileSize: 100 * 1024 * 1024 }47});48const userDb = new sqlite3.Database('./data/users.db');49const datasetDb = new sqlite3.Database('./data/datasets.db');50userDb.serialize(() => {51  userDb.run(`CREATE TABLE IF NOT EXISTS users (52    id INTEGER PRIMARY KEY AUTOINCREMENT,53    username TEXT UNIQUE NOT NULL,54    password TEXT NOT NULL,55    role TEXT DEFAULT 'user',56    created_at DATETIME DEFAULT CURRENT_TIMESTAMP57  )`);58});59datasetDb.serialize(() => {60  datasetDb.run(`CREATE TABLE IF NOT EXISTS datasets (61    id INTEGER PRIMARY KEY AUTOINCREMENT,62    name TEXT UNIQUE NOT NULL,63    description TEXT,64    file_path TEXT,65    file_type TEXT,66    size INTEGER,67    created_by TEXT,68    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,69    download_count INTEGER DEFAULT 070  )`);71});72const authenticateToken = (req, res, next) => {73  const authHeader = req.headers['authorization'];74  const token = authHeader && authHeader.split(' ')[1];75  if (!token) {76    return res.status(401).json({ error: 'Access token required' });77  }78  jwt.verify(token, JWT_SECRET, (err, user) => {79    if (err) {80      return res.status(403).json({ error: 'Invalid token' });81    }82    req.user = user;83    next();84  });85};86app.get('/health', (req, res) => {87  res.json({ status: 'OK', timestamp: new Date().toISOString() });88});89app.post('/api/register', async (req, res) => {90  try {91    const { username, password } = req.body;92    if (!username || !password) {93      return res.status(400).json({ error: 'Username and password required' });94    }95    const hashedPassword = await bcrypt.hash(password, 10);96    userDb.run(97      'INSERT INTO users (username, password) VALUES (?, ?)',98      [username, hashedPassword],99      function(err) {100        if (err) {101          if (err.message.includes('UNIQUE constraint failed')) {102            return res.status(409).json({ error: 'Username already exists' });103          }104          return res.status(500).json({ error: 'Database error' });105        }106        const token = jwt.sign({ id: this.lastID, username }, JWT_SECRET, { expiresIn: '24h' });107        res.status(201).json({108          message: 'User created successfully',109          token,110          user: { id: this.lastID, username }111        });112      }113    );114  } catch (error) {115    res.status(500).json({ error: 'Server error' });116  }117});118app.post('/api/login', (req, res) => {119  const { username, password } = req.body;120  if (!username || !password) {121    return res.status(400).json({ error: 'Username and password required' });122  }123  userDb.get(124    'SELECT * FROM users WHERE username = ?',125    [username],126    async (err, user) => {127      if (err) {128        return res.status(500).json({ error: 'Database error' });129      }130      if (!user) {131        return res.status(401).json({ error: 'Invalid credentials' });132      }133      const validPassword = await bcrypt.compare(password, user.password);134      if (!validPassword) {135        return res.status(401).json({ error: 'Invalid credentials' });136      }137      const token = jwt.sign(138        { id: user.id, username: user.username, role: user.role },139        JWT_SECRET,140        { expiresIn: '24h' }141      );142      res.json({143        message: 'Login successful',144        token,145        user: { id: user.id, username: user.username, role: user.role }146      });147    }148  );149});150app.get('/api/datasets', authenticateToken, (req, res) => {151  datasetDb.all(152    'SELECT id, name, description, file_type, size, created_by, created_at, download_count FROM datasets ORDER BY created_at DESC',153    (err, datasets) => {154      if (err) {155        return res.status(500).json({ error: 'Database error' });156      }157      res.json(datasets);158    }159  );160});161app.post('/api/datasets/upload', authenticateToken, upload.single('file'), (req, res) => {162  if (!req.file) {163    return res.status(400).json({ error: 'No file uploaded' });164  }165  const { name, description } = req.body;166  if (!name) {167    return res.status(400).json({ error: 'Dataset name required' });168  }169  datasetDb.run(170    'INSERT INTO datasets (name, description, file_path, file_type, size, created_by) VALUES (?, ?, ?, ?, ?, ?)',171    [name, description || '', req.file.path, req.file.mimetype, req.file.size, req.user.username],172    function(err) {173      if (err) {174        if (err.message.includes('UNIQUE constraint failed')) {175          return res.status(409).json({ error: 'Dataset name already exists' });176        }177        return res.status(500).json({ error: 'Database error' });178      }179      res.status(201).json({180        id: this.lastID,181        name,182        description,183        file_type: req.file.mimetype,184        size: req.file.size,185        message: 'Dataset uploaded successfully'186      });187    }188  );189});190app.get('/api/datasets/:id/download', authenticateToken, (req, res) => {191  const datasetId = req.params.id;192  datasetDb.get(193    'SELECT * FROM datasets WHERE id = ?',194    [datasetId],195    (err, dataset) => {196      if (err) {197        return res.status(500).json({ error: 'Database error' });198      }199      if (!dataset) {200        return res.status(404).json({ error: 'Dataset not found' });201      }202      if (!fs.existsSync(dataset.file_path)) {203        return res.status(404).json({ error: 'File not found on server' });204      }205      datasetDb.run(206        'UPDATE datasets SET download_count = download_count + 1 WHERE id = ?',207        [datasetId]208      );209      res.download(dataset.file_path, dataset.name);210    }211  );212});213app.post('/api/datasets/create', authenticateToken, (req, res) => {214  const { name, description, data } = req.body;215  if (!name || !data) {216    return res.status(400).json({ error: 'Name and data required' });217  }218  const fileName = `${Date.now()}-${name.replace(/[^a-zA-Z0-9]/g, '_')}.json`;219  const filePath = path.join(__dirname, 'datasets', fileName);220  fs.writeFile(filePath, JSON.stringify(data, null, 2), (err) => {221    if (err) {222      return res.status(500).json({ error: 'Failed to create file' });223    }224    const fileSize = fs.statSync(filePath).size;225    datasetDb.run(226      'INSERT INTO datasets (name, description, file_path, file_type, size, created_by) VALUES (?, ?, ?, ?, ?, ?)',227      [name, description || '', filePath, 'application/json', fileSize, req.user.username],228      function(err) {229        if (err) {230          fs.unlinkSync(filePath);231          if (err.message.includes('UNIQUE constraint failed')) {232            return res.status(409).json({ error: 'Dataset name already exists' });233          }234          return res.status(500).json({ error: 'Database error' });235        }236        res.status(201).json({237          id: this.lastID,238          name,239          description,240          file_type: 'application/json',241          size: fileSize,242          message: 'Dataset created successfully'243        });244      }245    );246  });247});248app.delete('/api/datasets/:id', authenticateToken, (req, res) => {249  const datasetId = req.params.id;250  datasetDb.get(251    'SELECT * FROM datasets WHERE id = ?',252    [datasetId],253    (err, dataset) => {254      if (err) {255        return res.status(500).json({ error: 'Database error' });256      }257      if (!dataset) {258        return res.status(404).json({ error: 'Dataset not found' });259      }260      if (dataset.created_by !== req.user.username && req.user.role !== 'admin') {261        return res.status(403).json({ error: 'Not authorized to delete this dataset' });262      }263      if (fs.existsSync(dataset.file_path)) {264        fs.unlinkSync(dataset.file_path);265      }266      datasetDb.run(267        'DELETE FROM datasets WHERE id = ?',268        [datasetId],269        (err) => {270          if (err) {271            return res.status(500).json({ error: 'Database error' });272          }273          res.json({ message: 'Dataset deleted successfully' });274        }275      );276    }277  );278});279app.get('/api/datasets/:id', authenticateToken, (req, res) => {280  const datasetId = req.params.id;281  datasetDb.get(282    'SELECT * FROM datasets WHERE id = ?',283    [datasetId],284    (err, dataset) => {285      if (err) {286        return res.status(500).json({ error: 'Database error' });287      }288      if (!dataset) {289        return res.status(404).json({ error: 'Dataset not found' });290      }291      res.json(dataset);292    }293  );294});295app.post('/api/datasets/bulk-download', authenticateToken, (req, res) => {296  const { datasetIds } = req.body;297  if (!datasetIds || !Array.isArray(datasetIds)) {298    return res.status(400).json({ error: 'Dataset IDs array required' });299  }300  const placeholders = datasetIds.map(() => '?').join(',');301  datasetDb.all(302    `SELECT * FROM datasets WHERE id IN (${placeholders})`,303    datasetIds,304    (err, datasets) => {305      if (err) {306        return res.status(500).json({ error: 'Database error' });307      }308      if (datasets.length === 0) {309        return res.status(404).json({ error: 'No datasets found' });310      }311      const archive = archiver('zip', { zlib: { level: 9 } });312      res.attachment('datasets.zip');313      archive.pipe(res);314      datasets.forEach(dataset => {315        if (fs.existsSync(dataset.file_path)) {316          archive.file(dataset.file_path, { name: dataset.name });317        }318      });319      archive.finalize();320    }321  );322});323app.use((err, req, res, next) => {324  res.status(500).json({ error: 'Something went wrong!' });325});326app.listen(PORT, () => {});