Explorar o código

Creation class pour gérer le serveur

Loquicom %!s(int64=5) %!d(string=hai) anos
pai
achega
48582a4795
Modificáronse 4 ficheiros con 319 adicións e 272 borrados
  1. 21 38
      node/main.js
  2. 0 234
      node/src/route.js
  3. 250 0
      node/src/router.js
  4. 48 0
      node/src/server.js

+ 21 - 38
node/main.js

@@ -37,12 +37,7 @@ const argv = require('yargs')
 // Chargement fichier config
 const config = require('./src/config');
 
-// Bibliotheques
-const express = require('express');
-const portfinder = require('portfinder');
-
 // Creation variable globale
-global.app = express();
 if (!config.auth) {
     global.auth = false;
 } else {
@@ -52,40 +47,28 @@ global.storage = config.storage;
 global.verbose = argv.verbose >= 1;
 global.sqlVerbose = argv.sql >= 1;
 
-// Configuration server
-app.use(express.json());
-require('./src/route');
-
-// Lancement serveur sur le port demandé
-portfinder.basePort = argv.port;
-portfinder.highestPort = argv.port;
-portfinder.getPortPromise()
-    .then((port) => {
-        app.listen(argv.port, () => {
+// Lancement du serveur
+const server = require('./src/server');
+server.route(require('./src/router'));
+server.start(argv.port).then((port) => {
+    console.info(`Server starting on port ${port} (http://localhost:${port})`);
+}).catch((err) => {
+    // Si erreur port deja utilisé et option recherche de port ouvert activée
+    if (err.toString().includes('Error: No open ports') && config.findPort) {
+        console.info(`Port ${argv.port} not available, search for a new available port`);
+        server.start(config.basePort, config.highestPort).then((port) => {
+            console.info(`New available port found: ${port}`);
             console.info(`Server starting on port ${port} (http://localhost:${port})`);
-        });
-    })
-    .catch((err) => {
-        if (err.toString().includes('Error: No open ports') && config.findPort) {
-            console.info(`Port ${argv.port} not available, search for a new available port`);
-            // Recherche d'un port ouvert
-            portfinder.basePort = config.basePort;
-            portfinder.highestPort = config.highestPort;
-            portfinder.getPortPromise()
-                .then((port) => {
-                    app.listen(port, () => {
-                        console.info(`New available port found: ${port}`);
-                        console.info(`Server starting on port ${port} (http://localhost:${port})`);
-                    });
-                })
-                .catch((err) => {
-                    console.err(err);
-                    console.info('Unable to start the server, end of execution');
-                    process.exit();
-                });
-        } else {
+        }).catch((err) => {
             console.error(err.toString());
             console.info('Unable to start the server, end of execution');
             process.exit();
-        }
-    });
+        });
+    }
+    // Sinon erreur
+    else {
+        console.error(err.toString());
+        console.info('Unable to start the server, end of execution');
+        process.exit();
+    }
+});

+ 0 - 234
node/src/route.js

@@ -1,234 +0,0 @@
-const fs = require('fs');
-const crypto = require('crypto');
-const auth = require('./auth');
-const db = require('./db');
-
-// Constante d'erreur
-const ERR_REQUEST = 1;
-const ERR_AUTH = 2;
-const ERR_UNKNOW = 3;
-const ERR_TOKEN = 4;
-const ERR_SERV = 5;
-const ERR_FILE = 6;
-
-// Fonctions de traitement pour les routes
-function verifyAuth(req, res, next) {
-    if (req.body.user === undefined || req.body.token === undefined) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    if (auth.isActivated() && !auth.verify(req.body.user, req.body.token)) {
-        res.json(error(ERR_TOKEN));
-        return;
-    }
-    next();
-}
-
-function verbose(req, res, next) {
-    if (global.verbose) {
-        const nbProp = Object.keys(req.body);
-        console.log(`\nCall ${req.route.path} with ${nbProp.length} parameter(s)`);
-        if (nbProp.length > 0) {
-            for (prop in req.body) {
-                console.log(`   ${prop}: ${req.body[prop]}`);
-            }
-        }
-    }
-    next();
-}
-
-// Fonctions reponses
-function error(code) {
-    let answer = {
-        success: false,
-        code: code
-    };
-    switch (code) {
-        case ERR_REQUEST:
-            answer.message = 'Bad request';
-            break;
-        case ERR_AUTH:
-            answer.message = 'Bad authentication';
-            break;
-        case ERR_UNKNOW:
-            answer.message = 'Unknow user';
-            break;
-        case ERR_TOKEN:
-            answer.message = 'Invalid token';
-            break;
-        case ERR_SERV:
-            answer.message = 'Server error';
-            break;
-        case ERR_FILE:
-            answer.message = 'File not found';
-            break;
-        default:
-            answer.message = 'Unknow error';
-    }
-    return answer;
-}
-
-function success(data) {
-    if (data === undefined || data === null) {
-        return {success: true};
-    } else if (typeof data !== 'object') {
-        return {success: true, data: data};
-    } else {
-        data.success = true;
-        return data;
-    }
-}
-
-// Definition des routes
-app.get('/authentication', [verbose, (req, res) => {
-    res.json(success({authentication: auth.isActivated()}));
-}]);
-
-app.post('/register', [verbose, (req, res) => {
-    if (req.body.user === undefined || req.body.password === undefined) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    const passHash = auth.passwordHash(req.body.password);
-    db.addUser(req.body.user, passHash);
-    return res.json(success());
-}]);
-
-app.post('/login', [verbose, (req, res) => {
-    if (req.body.user === undefined || req.body.password === undefined) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    const promise = db.getUser(req.body.user);
-    if (promise === false) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    promise.then((user) => {
-        if (user === undefined) {
-            res.json(error(ERR_UNKNOW));
-        } else {
-            if (auth.passwordVerify(req.body.password, user.pass)) {
-                res.json(success({token: auth.generateToken(req.body.user)}));
-            } else {
-                res.json(error(ERR_AUTH));
-            }
-        }
-    });
-}]);
-
-app.post('/token', [verbose, (req, res) => {
-    if (req.body.user === undefined || req.body.token === undefined) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    res.json(success({valid: auth.verify(req.body.user, req.body.token)}));
-}]);
-
-app.post('/list', [verbose, verifyAuth, (req, res) => {
-    const promise = db.listFile(req.body.user);
-    if (promise === false) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    promise.then((list) => {
-        if (list === false) {
-            res.json(error(ERR_SERV));
-        } else {
-            res.json(success({
-                total: list.length,
-                list: list
-            }));
-        }
-    });
-}]);
-
-app.post('/get/:file', [verbose, verifyAuth, (req, res) => {
-    const promise = db.getFile(req.body.user, req.params.file);
-    if (promise === false) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    promise.then((file) => {
-        // Erreur
-        if (file === false) {
-            res.json(error(ERR_SERV));
-        } else // Le fichier n'existe pas
-        if (file === null) {
-            res.json(error(ERR_FILE));
-        }
-        // Création reponse commune
-        else {
-            let result = {
-                fileid: file.fi_hash,
-                filename: file.fi_name
-            };
-            // Recupération données fichier
-            if (global.storage === 'database') {
-                result.data = file.data;
-                res.json(success(result));
-            } else {
-                if (!fs.existsSync(file.data)) {
-                    res.json(error(ERR_FILE));
-                }
-                fs.readFile(file.data, (err, data) => {
-                    result.data = data.toString();
-                    res.json(success(result));
-                });
-            }
-        }
-    });
-}]);
-
-app.post('/save/:file', [verbose, verifyAuth, (req, res) => {
-    //Si on sauvegarde les données dans des fichiers, generation du chemin
-    let data = req.body.data;
-    if (global.storage === 'file') {
-        let hash = Date.now() + '-' + req.body.user + '-' + req.params.file;
-        hash = crypto.createHash('md5').update(hash).digest('base64');
-        hash = hash.replace(/=/g, '').replace(/\//g, '');
-        data = './data/' + hash + '.fdata';
-    }
-    const promise = db.addFile(req.body.user, req.params.file, data);
-    if (promise === false) {
-        res.json(error(ERR_REQUEST));
-        return;
-    }
-    promise.then((fileId) => {
-        if (fileId === false) {
-            res.json(ERR_SERV);
-        } else {
-            // Si en mode fichier stockage dans un fichier
-            if ((global.storage === 'file')) {
-                fs.writeFile(data, req.body.data, (err) => {
-                    if (err) {
-                        if (global.verbose) {
-                            console.error(err);
-                        }
-                        res.json(error(ERR_SERV));
-                    } else {
-                        res.json(success({fileId: fileId, fileName: req.params.file}));
-                    }
-                });
-            }
-            // Le fichier est directement sauvegarder en base
-            else {
-                res.json(success({fileId: fileId, fileName: req.params.file}));
-            }
-        }
-    });
-}]);
-
-/*
-app.get('/', function (req, res) {
-    res.send('Hello World!');
-});
-
-app.get('/test/:val?', function (req, res) {
-    res.send('Val = ' + req.params.val);
-});
-
-app.get(/.*aze$/, function (req, res) {
-    res.send('URL end with aze');
-})
-*/

+ 250 - 0
node/src/router.js

@@ -0,0 +1,250 @@
+const fs = require('fs');
+const crypto = require('crypto');
+const auth = require('./auth');
+const db = require('./db');
+
+// Constante d'erreur
+const ERR_REQUEST = 1;
+const ERR_AUTH = 2;
+const ERR_UNKNOW = 3;
+const ERR_TOKEN = 4;
+const ERR_SERV = 5;
+const ERR_FILE = 6;
+
+// Fonctions reponses
+function error(code) {
+    let answer = {
+        success: false,
+        code: code
+    };
+    switch (code) {
+        case ERR_REQUEST:
+            answer.message = 'Bad request';
+            break;
+        case ERR_AUTH:
+            answer.message = 'Bad authentication';
+            break;
+        case ERR_UNKNOW:
+            answer.message = 'Unknow user';
+            break;
+        case ERR_TOKEN:
+            answer.message = 'Invalid token';
+            break;
+        case ERR_SERV:
+            answer.message = 'Server error';
+            break;
+        case ERR_FILE:
+            answer.message = 'File not found';
+            break;
+        default:
+            answer.message = 'Unknow error';
+    }
+    return answer;
+}
+
+function success(data) {
+    if (data === undefined || data === null) {
+        return {success: true};
+    } else if (typeof data !== 'object') {
+        return {success: true, data: data};
+    } else {
+        data.success = true;
+        return data;
+    }
+}
+
+const router = class Router {
+
+    constructor(app) {
+        this.app = app;
+    }
+
+    /* --- Helper function --- */
+
+    // Fonctions de traitement pour les routes
+    verifyAuth(req, res, next) {
+        if (req.body.user === undefined || req.body.token === undefined) {
+            res.json(error(ERR_REQUEST));
+            return;
+        }
+        if (auth.isActivated() && !auth.verify(req.body.user, req.body.token)) {
+            res.json(error(ERR_TOKEN));
+            return;
+        }
+        next();
+    }
+
+    verbose(req, res, next) {
+        if (global.verbose) {
+            const nbProp = Object.keys(req.body);
+            console.log(`\nCall ${req.route.path} with ${nbProp.length} parameter(s)`);
+            if (nbProp.length > 0) {
+                for (let prop in req.body) {
+                    console.log(`   ${prop}: ${req.body[prop]}`);
+                }
+            }
+        }
+        next();
+    }
+
+    /* --- Definitions des routes --- */
+
+    route() {
+        this.app.get('/authentication', [this.verbose, (req, res) => {
+            res.json(success({authentication: auth.isActivated()}));
+        }]);
+
+        this.app.post('/register', [this.verbose, (req, res) => {
+            if (req.body.user === undefined || req.body.password === undefined) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            const passHash = auth.passwordHash(req.body.password);
+            db.addUser(req.body.user, passHash);
+            return res.json(success());
+        }]);
+
+        this.app.post('/login', [this.verbose, (req, res) => {
+            if (req.body.user === undefined || req.body.password === undefined) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            const promise = db.getUser(req.body.user);
+            if (promise === false) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            promise.then((user) => {
+                if (user === undefined) {
+                    res.json(error(ERR_UNKNOW));
+                } else {
+                    if (auth.passwordVerify(req.body.password, user.pass)) {
+                        res.json(success({token: auth.generateToken(req.body.user)}));
+                    } else {
+                        res.json(error(ERR_AUTH));
+                    }
+                }
+            });
+        }]);
+
+        this.app.post('/token', [this.verbose, (req, res) => {
+            if (req.body.user === undefined || req.body.token === undefined) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            res.json(success({valid: auth.verify(req.body.user, req.body.token)}));
+        }]);
+
+        this.app.post('/list', [this.verbose, this.verifyAuth, (req, res) => {
+            const promise = db.listFile(req.body.user);
+            if (promise === false) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            promise.then((list) => {
+                if (list === false) {
+                    res.json(error(ERR_SERV));
+                } else {
+                    res.json(success({
+                        total: list.length,
+                        list: list
+                    }));
+                }
+            });
+        }]);
+
+        this.app.post('/get/:file', [this.verbose, this.verifyAuth, (req, res) => {
+            const promise = db.getFile(req.body.user, req.params.file);
+            if (promise === false) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            promise.then((file) => {
+                // Erreur
+                if (file === false) {
+                    res.json(error(ERR_SERV));
+                } else // Le fichier n'existe pas
+                if (file === null) {
+                    res.json(error(ERR_FILE));
+                }
+                // Création reponse commune
+                else {
+                    let result = {
+                        fileid: file.fi_hash,
+                        filename: file.fi_name
+                    };
+                    // Recupération données fichier
+                    if (global.storage === 'database') {
+                        result.data = file.data;
+                        res.json(success(result));
+                    } else {
+                        if (!fs.existsSync(file.data)) {
+                            res.json(error(ERR_FILE));
+                        }
+                        fs.readFile(file.data, (err, data) => {
+                            result.data = data.toString();
+                            res.json(success(result));
+                        });
+                    }
+                }
+            });
+        }]);
+
+        this.app.post('/save/:file', [this.verbose, this.verifyAuth, (req, res) => {
+            //Si on sauvegarde les données dans des fichiers, generation du chemin
+            let data = req.body.data;
+            if (global.storage === 'file') {
+                let hash = Date.now() + '-' + req.body.user + '-' + req.params.file;
+                hash = crypto.createHash('md5').update(hash).digest('base64');
+                hash = hash.replace(/=/g, '').replace(/\//g, '');
+                data = './data/' + hash + '.fdata';
+            }
+            const promise = db.addFile(req.body.user, req.params.file, data);
+            if (promise === false) {
+                res.json(error(ERR_REQUEST));
+                return;
+            }
+            promise.then((fileId) => {
+                if (fileId === false) {
+                    res.json(ERR_SERV);
+                } else {
+                    // Si en mode fichier stockage dans un fichier
+                    if ((global.storage === 'file')) {
+                        fs.writeFile(data, req.body.data, (err) => {
+                            if (err) {
+                                if (global.verbose) {
+                                    console.error(err);
+                                }
+                                res.json(error(ERR_SERV));
+                            } else {
+                                res.json(success({fileId: fileId, fileName: req.params.file}));
+                            }
+                        });
+                    }
+                    // Le fichier est directement sauvegarder en base
+                    else {
+                        res.json(success({fileId: fileId, fileName: req.params.file}));
+                    }
+                }
+            });
+        }]);
+    }
+
+};
+
+module.exports = router;
+
+
+/*
+app.get('/', function (req, res) {
+    res.send('Hello World!');
+});
+
+app.get('/test/:val?', function (req, res) {
+    res.send('Val = ' + req.params.val);
+});
+
+app.get(/.*aze$/, function (req, res) {
+    res.send('URL end with aze');
+})
+*/

+ 48 - 0
node/src/server.js

@@ -0,0 +1,48 @@
+const fs = require('fs');
+const https = require('https');
+const express = require('express');
+const portfinder = require('portfinder');
+
+class Server {
+
+    constructor(useHttps = false) {
+        this.https = false;
+        this.app = express();
+        this.app.use(express.json());
+    }
+
+    route(router) {
+        this.router = new router(this.app);
+        this.router.route();
+    }
+
+    start(port, highestPort = null) {
+        portfinder.basePort = port;
+        portfinder.highestPort = (highestPort === null) ? port : highestPort;
+        return new Promise((resolve, reject) => {
+            // Tentative de demarrage du serveur sur la plage de port definit
+            portfinder.getPortPromise().then((serverPort) => {
+                if (this.https) {
+
+                } else {
+                    this.httpServer(serverPort);
+                }
+                resolve(serverPort);
+            }).catch((err) => {
+                reject(err);
+            });
+        });
+    }
+
+    httpServer(port) {
+        this.app.listen(port);
+    }
+
+    httpsServer() {
+
+    }
+
+}
+
+// Export
+module.exports = new Server();