Browse Source

[add] templates files
[add] abstract slack logger
[add] slack logger

B Thibault 8 years ago
parent
commit
371dd03fc0

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "http",
     "client-sessions",
     "crypto",
+    "sqlite3",
     "node-file-cache",
     "memory-cache",
     "sleep",

+ 3 - 0
srv/public/login.css

@@ -0,0 +1,3 @@
+body { text-align: center; display: flex; }
+.services h1 { font-family: Lato; }
+.services { display: inline-block; border: 1px solid #e0e1e2; width: 250px; margin: auto; padding: 14px; }

+ 1 - 12
srv/sessions.json

@@ -1,14 +1,3 @@
 {
-  "index": [
-    {
-      "key": "1607ea15395e788e07dc10694cb25b52",
-      "val": {
-        "sessId": "1607ea15395e788e07dc10694cb25b52",
-        "slackToken": "xoxp-148001785602-147323841537-164283409479-40059e7d86535cbb48c695c5a588fb67",
-        "modifiedAt": 1497910040041
-      },
-      "life": 1497996450677,
-      "tags": []
-    }
-  ]
+  "index": []
 }

+ 5 - 1
srv/src/accounts.js

@@ -3,11 +3,15 @@ const sqlite = require('sqlite3');
 function AccountManager() {
 }
 
+AccountManager.prototype.fromSlackEmail = function(slackEmail) {
+    return null;
+};
+
 function Account() {
 }
 
 AccountManager.prototype.save = function(account) {
 };
 
-module.exports.SessionManager = new SessionManager();
+module.exports.accountManager = new AccountManager();
 

+ 16 - 43
srv/src/httpServ.js

@@ -5,7 +5,6 @@ var http = require("http")
     ,Url = require("./url.js").Url
     ,config = require("../config.js")
     ,sessionManager = require("./session.js").SessionManager
-    ,Slack = require("./slack.js").Slack
     ,slackManager = require("./slackManager.js").SlackManager
     ,FaviconWriter = require("./faviconWriter.js").FaviconWriter;
 
@@ -62,56 +61,25 @@ Server.prototype.onListen = function() {
     console.log("onListen");
 };
 
-function redirectToSlackAuth(res) {
-    res.writeHeader("302", {
-        Location: "https://slack.com/oauth/authorize"
-        +"?client_id=" +config.login.slack.clientId
-        +"&scope=" +slackManager.getScope().join(",")
-        +"&redirect_uri=" +config.rootUrl
-    });
-    res.end();
-}
+Server.prototype.execTemplate = function(template, req, res) {
+    var resp = template.exec(req, res);
+    if (resp && resp.body) {
+        if (resp.status)
+            res.writeHeader(resp.status);
+        res.end(resp.body);
+    }
+    // else something is running asynchronously, let template close request later..
+};
 
 Server.prototype.onRequest = function(req, res) {
     req.reqT = Date.now();
     req.cookies = Server.parseCookies(req);
     req.session = sessionManager.forRequest(req);
-    req.account = req.session ? AccountManager.forId(req.session.accountId);
+    //TODO req.account = req.session ? AccountManager.forId(req.session.accountId);
     req.urlObj = new Url(req.url);
 
     if (req.urlObj.isTemplate() && req.urlObj.template.needLogin === false) {
-        var resp = req.urlObj.template.exec(req, res);
-        res.writeHeader(resp.status || 200);
-        res.end(resp.body);
-        return;
-    } else if (!req.session || !req.session.slackToken) {
-        if (req.urlObj.queryTokens.code) {
-            Slack.getUserMail(req.urlObj.queryTokens.code, config.rootUrl, (token) => {
-                if (token) {
-                    req.account = AccountManager.fromSlackEmail()
-                    req.session = sessionManager.lazyForRequest(req);
-                    req.session.setSlackToken(req.reqT, token);
-                    res.writeHeader("302", {
-                        Location: config.rootUrl
-                    ,"Set-Cookie": "sessID="+req.session.sessId
-                    });
-                    sessionManager.saveSession(req.session);
-                    res.end();
-                } else {
-                    redirectToSlackAuth(res);
-                }
-            });
-        } else {
-            res.writeHeader("302", {
-                Location: "login"
-            });
-            res.end();
-        }
-    } else if (req.urlObj.isTemplate()) {
-        var resp = req.urlObj.template.exec(req, res);
-        res.writeHeader(resp.status || 200);
-        res.end(resp.body);
-        return;
+        return this.execTemplate(req.urlObj.template, req, res);
     } else if (req.urlObj.isPublic()) {
         if (!config.isDebug)
             res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);
@@ -120,6 +88,11 @@ Server.prototype.onRequest = function(req, res) {
         req.urlObj.getReadStream().pipe(res, { end: true });
         sessionManager.saveSession(req.session);
         return; // async pipe will close when finished
+    } else if (!req.session) {
+        res.writeHeader("302", { Location: "login" });
+        res.end();
+    } else if (req.urlObj.isTemplate()) {
+        return this.execTemplate(req.urlObj.template, req, res);
     } else if (req.urlObj.match(["favicon.png"])) {
         if (!config.isDebug)
             res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);

+ 12 - 9
srv/src/slack.js

@@ -15,6 +15,7 @@ const SLACK_ENDPOINT = "https://slack.com/api/"
     ,GETAPI = {
         rtmStart: "rtm.start"
         ,oauth: "oauth.access"
+        ,identityEmail: "users.identity"
         ,channelHistory: "channels.history"
         ,directHistory: "im.history"
         ,groupHistory: "groups.history"
@@ -314,14 +315,16 @@ Slack.prototype.close = function() {
 };
 
 Slack.getUserMail = function(code, redirectUri, cb) {
-    httpsRequest(SLACK_ENDPOINT+GETAPI.oauth
-        +"?client_id=" +config.services.Slack.clientId
-        +"&client_secret=" +config.services.Slack.clientSecret
-        +"&redirect_uri=" +redirectUri
-        +"&code=" +code,
-    (status, resp) => {
-        if (status === 200 && resp.ok) {
-            cb(resp);
+    Slack.getOauthToken(code, redirectUri, (token) => {
+        if (token) {
+            httpsRequest(SLACK_ENDPOINT+GETAPI.identityEmail +"?token="+token,
+            (status, resp) => {
+                if (status === 200 && resp.ok && resp.user && resp.user.email) {
+                    cb(resp.user.email);
+                } else {
+                    cb(null);
+                }
+            });
         } else {
             cb(null);
         }
@@ -336,7 +339,7 @@ Slack.getOauthToken = function(code, redirectUri, cb) {
         +"&code=" +code,
     (status, resp) => {
         if (status === 200 && resp.ok) {
-            cb(resp);
+            cb(resp["access_token"]);
         } else {
             cb(null);
         }

+ 7 - 0
srv/src/slackManager.js

@@ -17,6 +17,13 @@ setInterval(function() {
     });
 }, PING_DELAY);
 
+SlackManager.prototype.getAuthScope = function() {
+    return [
+        "identity.basic",
+        "identity.email"
+    ];
+};
+
 SlackManager.prototype.getScope = function() {
     return [
         "client"

+ 20 - 11
srv/src/url.js

@@ -56,20 +56,29 @@ function tryLoadPublic() {
     return false;
 }
 
-function tryLoadTemplate(Url) {
+function tryLoadTemplateFile(fileName) {
     try{
-        if (!this.urlParts.length) {
-            this.template = require('../template/index.js');
-        } else if (this.urlParts.length == 1 && this.urlParts[0][0] !== '_') {
-            this.template = require('../template/' +this.urlParts[0] +'.js');
-        }
-        return true;
+        fs.statSync(fileName);
     } catch (e) {
-        if (e.code !== "MODULE_NOT_FOUND")
-            throw e;
-        // Not a template
+        // Not a template file
+        return null;
     }
-    return false;
+    return require(fileName);
+}
+
+function tryLoadTemplate() {
+    var template;
+
+    if (!this.urlParts.length) {
+        template = tryLoadTemplateFile(__dirname +'/../template/index.js');
+    } else if (this.urlParts[0][0] !== '_') {
+        template = tryLoadTemplateFile(__dirname +'/../template/' +this.urlParts[0] +'.js');
+    }
+    if (!template || (template.match && !template.match(this)) || (!template.match && this.urlParts[0].length > 1)) {
+        return false;
+    }
+    this.template = template;
+    return true;
 }
 
 Url.prototype.isPublic = function() {

+ 1 - 1
srv/template/_model.js

@@ -5,7 +5,7 @@ module.exports.exec = function() {
     return {
         status: 200
         ,body:
-            templates.header(["login.css"])
+            templates.header("title", ["login.css"])
             +``
             +templates.footer(["emojione.sprites.js", "openpgp.min.js", "slack.min.js"])
     };

+ 2 - 2
srv/template/_templates.js

@@ -1,7 +1,7 @@
 
 module.exports = {
-    header: function(cssFiles, moreHeader) {
-        var res = `<html><head><link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet" />`;
+    header: function(title, cssFiles, moreHeader) {
+        var res = `<html><head><title>${title}</title><link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet" />`;
         (cssFiles || []).forEach(function(i) {
             res += '<link href="' +i +'" rel="stylesheet"/>';
         });

+ 1 - 1
srv/template/index.js

@@ -4,7 +4,7 @@ const templates = require('./_templates.js');
 module.exports.exec = function() {
     return {
         status: 200
-        ,body: templates.header(["style.css", "emojione.sprites.css"], ['<link href="favicon_err.png" type="image/png" rel="icon" id="linkFavicon" />'])
+        ,body: templates.header("Mimou", ["style.css", "emojione.sprites.css"], ['<link href="favicon_err.png" type="image/png" rel="icon" id="linkFavicon" />'])
         +`<aside class="slack-context" id="slackCtx">
                     <nav class="slack-context-menu"></nav>
                     <div class="slack-context-rooms" id="chatList">

+ 60 - 11
srv/template/login.js

@@ -1,21 +1,70 @@
 
 const config = require("../config.js")
+    ,Slack = require("../src/slack.js").Slack
     ,slackManager = require("../src/slackManager.js").SlackManager
+    ,accountManager = require("../src/accounts.js").accountManager
     ,templates = require('./_templates.js');
 
-module.exports.exec = function() {
+function checkTokens(service, req, cb) {
+    switch (service) {
+        case "slack":
+            if (req.urlObj.queryTokens.code) {
+                Slack.getUserMail(req.urlObj.queryTokens.code, config.login.slack.redirect_uri, (email) => {
+                    cb(email);
+                });
+            } else {
+                cb(null);
+            }
+        break;
+
+        default:
+            cb(null);
+        break;
+    }
+}
+
+function makeLoginPage() {
     var slackUri = "https://slack.com/oauth/authorize"
         +"?client_id=" +config.login.slack.clientId
-        +"&scope=identity.basic"
-        +"&redirect_uri=" +config.rootUrl;
-
-    return {
-        status: 200
-        ,body:
-            templates.header(["login.css"])
-            +`<a href="${slackUri}">Slack login</a>`
-            +templates.footer()
-    };
+        +"&scope=" +slackManager.getAuthScope().join(',')
+        +"&redirect_uri=" +config.login.slack.redirect_uri;
+
+    return templates.header("Mimou - login", ["login.css"])
+        +`<div class="services"><h1>Login</h1>`
+        +`<a href="${slackUri}"><img src="https://platform.slack-edge.com/img/sign_in_with_slack.png" srcset="https://platform.slack-edge.com/img/sign_in_with_slack.png 1x, https://platform.slack-edge.com/img/sign_in_with_slack@2x.png 2x" /></a>`
+        +`</div>`
+        +templates.footer();
+}
+
+module.exports.match = function(url) {
+    if (url.urlParts.length === 1) {
+        return true;
+    } else if (url.urlParts.length === 2 && Object.keys(config.login).indexOf(url.urlParts[1]) >= 0) {
+        return true;
+    }
+    return false;
+};
+
+module.exports.exec = function(req, res) {
+    if (!req.urlObj.urlParts[1]) {
+        res.end(makeLoginPage());
+    } else {
+        checkTokens(req.urlObj.urlParts[1], req, (email) => {
+            if (email) {
+                req.account = accountManager.fromSlackEmail(email)
+                req.session = sessionManager.lazyForRequest(req);
+                req.session.setSlackToken(req.reqT, token);
+                res.writeHeader("302", {
+                    Location: config.rootUrl
+                ,"Set-Cookie": "sessID="+req.session.sessId
+                });
+                sessionManager.saveSession(req.session);
+                res.end();
+            } else {
+                res.end(makeLoginPage());
+            }
+        });
+    }
 };
 
 module.exports.needLogin = false;