浏览代码

[tmp] WIP login

B Thibault 8 年之前
父节点
当前提交
f494792faa
共有 9 个文件被更改,包括 299 次插入36 次删除
  1. 1 0
      .gitignore
  2. 7 3
      srv/main.js
  3. 12 1
      srv/sessions.json
  4. 111 5
      srv/src/accounts.js
  5. 115 0
      srv/src/database.js
  6. 18 12
      srv/src/session.js
  7. 2 2
      srv/src/slack.js
  8. 1 1
      srv/src/url.js
  9. 32 12
      srv/template/login.js

+ 1 - 0
.gitignore

@@ -2,6 +2,7 @@
 *.bak
 cli/closure-compiler-v*.jar
 /srv/config.js
+/srv/database.sqlite
 
 # cache
 store.json

+ 7 - 3
srv/main.js

@@ -1,8 +1,12 @@
-var Server = require("./src/httpServ.js").HttpServ;
-
 process.on("uncaughtException", function (err) {
     console.error('err uncaught Exception  : ', err);
 });
 
-var server = new Server(3002);
+require('./src/database.js').database.initDb((err) => {
+    if (err) {
+        console.error("FATAL: cannot init database ", err);
+    } else {
+        var server = new (require("./src/httpServ.js").HttpServ)(3002);
+    }
+});
 

+ 12 - 1
srv/sessions.json

@@ -1,3 +1,14 @@
 {
-  "index": []
+  "index": [
+    {
+      "key": "d2f3a7159804e6f6f5f9eb830c672730",
+      "val": {
+        "sessId": "d2f3a7159804e6f6f5f9eb830c672730",
+        "accountId": 1,
+        "modifiedAt": 1498151437428
+      },
+      "life": 1498237838587,
+      "tags": []
+    }
+  ]
 }

+ 111 - 5
srv/src/accounts.js

@@ -1,17 +1,123 @@
-const sqlite = require('sqlite3');
+const db = require('./database.js');
+
+const TABLE_NAME = "accounts";
 
 function AccountManager() {
 }
 
-AccountManager.prototype.fromSlackEmail = function(slackEmail) {
-    return null;
+AccountManager.prototype.fromGoogleIdAuth = function(id, cb) {
+    var self = this;
+    db.database.queryFirst(TABLE_NAME, { authGoogleUserId: id }, (err, result) => {
+        cb(self.fromDb(result));
+    });
+};
+
+AccountManager.prototype.fromFacebookIdAuth = function(id, cb) {
+    var self = this;
+    db.database.queryFirst(TABLE_NAME, { authFacebookUserId: id }, (err, result) => {
+        cb(self.fromDb(result));
+    });
+};
+
+AccountManager.prototype.fromSlackIdAuth = function(id, cb) {
+    var self = this;
+    db.database.queryFirst(TABLE_NAME, { authSlackUserEmailAndTeam: id }, (err, result) => {
+        cb(self.fromDb(result));
+    });
+};
+
+AccountManager.prototype.fromDb = function(dbResult) {
+    if (!dbResult)
+        return null;
+    return new Account(dbResult);
 };
 
-function Account() {
+function Account(dbResult) {
+    this.id;
+
+    this.authGoogleUserId;
+    this.authFacebookUserId;
+    this.authSlackUserEmailAndTeam;
+
+    this.certificates;
+    this.cguReadAndAccepted;
+    this.dirty;
+
+
+    if (dbResult) {
+        this.id = dbResult.id;
+
+        this.authSlackUserEmailAndTeam = dbResult.authSlackUserEmailAndTeam;
+        this.authGoogleUserId = dbResult.authGoogleUserId;
+        this.authFacebookUserId = dbResult.authFacebookUserId;
+
+        this.certificates = dbResult.certificates;
+        this.cguReadAndAccepted = !!dbResult.cguReadAndAccepted;
+        this.dirty = false;
+    } else {
+        this.id = null;
+
+        this.authSlackUserEmailAndTeam = null;
+        this.authGoogleUserId = null;
+        this.authFacebookUserId = null;
+
+        this.createCertificate();
+        this.cguReadAndAccepted = false;
+        this.dirty = true;
+    }
 }
 
-AccountManager.prototype.save = function(account) {
+Account.prototype.toDb = function() {
+    return {
+        authGoogleUserId: this.authGoogleUserId
+        ,authFacebookUserId: this.authFacebookUserId
+        ,authSlackUserEmailAndTeam: this.authSlackUserEmailAndTeam
+        ,certificates: this.certificates
+        ,cguReadAndAccepted: this.cguReadAndAccepted ? 1 : 0
+    };
+};
+
+Account.prototype.createCertificate = function() {
+    //TODO
+    this.certificates = null;
+};
+
+AccountManager.prototype.createAccount = function() {
+    return new Account();
+};
+
+AccountManager.prototype.save = function(account, cb) {
+    if (!account.id) {
+        // insert and save id
+        var data = account.toDb();
+        data.id = null;
+        db.database.insert(TABLE_NAME, data, (newId) => {
+            account.id = newId;
+            account.dirty = false;
+            cb(account);
+        });
+    } else if (account.dirty) {
+        // update
+        db.database.update(TABLE_NAME, this.id, account.toDb(), () => {
+            account.dirty = false;
+            cb(account);
+        });
+    } else {
+        cb(account);
+    }
 };
 
 module.exports.accountManager = new AccountManager();
 
+module.exports.createTable = function(dbObject, cb) {
+    console.info("Creating table " +TABLE_NAME);
+    dbObject.run('CREATE TABLE IF NOT EXISTS `' +TABLE_NAME +'` ('
+        +"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+        +"`authGoogleUserId` STRING UNIQUE,"
+        +"`authFacebookUserId` STRING UNIQUE,"
+        +"`authSlackUserEmailAndTeam` STRING UNIQUE,"
+        +"`certificates` STRING,"
+        +"`cguReadAndAccepted` BOOLEAN NOT NULL DEFAULT FALSE"
+        +')', cb);
+};
+

+ 115 - 0
srv/src/database.js

@@ -0,0 +1,115 @@
+const sqlite3 = require('sqlite3')
+    ,createAccountTable = require('./accounts.js').createTable;
+
+const DB_PATH = __dirname +"/../database.sqlite";
+
+function Database() {
+    this.db = null;
+};
+
+Database.prototype.initDb = function(cb) {
+    var self = this;
+    if (self.db) {
+        cb(null);
+    } else {
+        self.db = new sqlite3.Database(DB_PATH, sqlite3.OPEN_READWRITE, (err) => {
+            if (err) {
+                if (err.code === "SQLITE_CANTOPEN") {
+                    self.db = new sqlite3.Database(DB_PATH, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
+                        if (!err) {
+                            self.createAllTables([
+                                createAccountTable
+                            ], 0, cb);
+                        } else {
+                            cb(err);
+                        }
+                    });
+                } else {
+                    cb(err);
+                }
+            } else {
+                cb(null);
+            }
+        });
+    }
+};
+
+Database.prototype.createAllTables = function(factories, i, cb) {
+    var self = this;
+
+    if (factories[i]) {
+        factories[i](self.db, (err) => {
+            if (!err)
+                self.createAllTables(factories, ++i, cb);
+            else
+                cb(err);
+        });
+    } else {
+        cb(null);
+    }
+};
+
+Database.prototype.query = function(table, fields, cb) {
+    var args = [];
+    for (var i in fields)
+        args.push(fields[i]);
+    this.db.all("SELECT * FROM `" +table +"` WHERE `" +Object.keys(fields).join("`=? AND") +"`=?", args, (err, rows) => {
+        if (err) {
+            console.warn(err);
+            cb(err, null);
+        } else {
+            cb(null, rows);
+        }
+    });
+};
+
+Database.prototype.queryFirst = function(table, fields, cb) {
+    var args = [];
+    for (var i in fields)
+        args.push(fields[i]);
+    this.db.get("SELECT * FROM `" +table +"` WHERE `" +Object.keys(fields).join("`=? AND") +"`=?", args, (err, row) => {
+        if (err) {
+            console.warn(err);
+            cb(err, null);
+        } else {
+            cb(null, row || null);
+        }
+    });
+};
+
+Database.prototype.insert = function(table, data, cb) {
+    var args = []
+        ,keys = []
+        ,templateArgs = [];
+    for (var i in data) {
+        keys.push('`' +i +'`');
+        args.push(data[i]);
+        templateArgs.push('?');
+    }
+
+    this.db.run("INSERT INTO " +table +" ("+ keys.join(",") +") VALUES(" +templateArgs.join(', ') +")", args, function(err) {
+        if (err) {
+            console.error(err);
+            cb(null);
+        }
+        cb(this.lastID);
+    });
+};
+
+Database.prototype.update = function(table, id, data, cb) {
+    var args = [];
+    for (var i in fields)
+        args.push(fields[i]);
+    args.push(id);
+    this.db.run("UPDATE " +table +" SET `" +Object.keys(data).join("`=?,") +"`=? WHERE id=?", args, (err) => {
+        if (err) {
+            console.error(err);
+        }
+        cb();
+    });
+};
+
+const singleton = new Database();
+
+module.exports.database = singleton;
+

+ 18 - 12
srv/src/session.js

@@ -7,12 +7,11 @@ function SessionManager() {
     });
 }
 
-SessionManager.defaultTtl = 60 * 60 * 24; // keep sessions 24h
+const DEFAULT_TTL = 60 * 60 * 24; // keep sessions 24h
 
-function Session(reqT, sessId, accountId) {
+function Session(reqT, sessId) {
     this.sessId = sessId;
-    this.accountId = accountId;
-    this.slackToken = null;
+    this.accountId = null;
     this.modifiedAt = reqT;
 }
 
@@ -23,7 +22,13 @@ SessionManager.createSessionId = function(req) {
 
 SessionManager.prototype.forRequest = function(request) {
     if (request.cookies && request.cookies.sessID) {
-        return this.sessions.get(request.cookies.sessID);
+        var sess = new Session()
+            ,cachedSession = this.sessions.get(request.cookies.sessID);
+        sess.sessId = request.cookies.sessID;
+        for (var i in cachedSession)
+            if (cachedSession.hasOwnProperty(i))
+                sess[i] = cachedSession[i];
+        return sess;
     }
     return null;
 };
@@ -40,17 +45,18 @@ SessionManager.prototype.lazyForRequest = function(request) {
 
 SessionManager.prototype.saveSession = function(session) {
     if (session) {
-        this.sessions.set(session.sessId, session, {
-            life: SessionManager.defaultTtl
+        var sessionData = {};
+        for (var i in session)
+            if (session.hasOwnProperty(i))
+                sessionData[i] = session[i];
+        this.sessions.set(session.sessId, sessionData, {
+            life: DEFAULT_TTL
         });
     }
 };
 
-Session.prototype.setSlackToken = function(reqT, slackToken) {
-    this.slackUserId = slackToken["user_id"];
-    this.slackTeamName = slackToken["team_name"];
-    this.slackTeamId = slackToken["team_name"];
-    this.slackToken = slackToken["access_token"];
+Session.prototype.setAccountId = function(reqT, accountId) {
+    this.accountId = accountId;
     this.modifiedAt = reqT;
 };
 

+ 2 - 2
srv/src/slack.js

@@ -290,13 +290,13 @@ Slack.prototype.close = function() {
     }
 };
 
-Slack.getUserMail = function(code, redirectUri, cb) {
+Slack.getUserId = function(code, redirectUri, cb) {
     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);
+                    cb(resp.user.id +'_' +resp.team.id);
                 } else {
                     cb(null);
                 }

+ 1 - 1
srv/src/url.js

@@ -69,7 +69,7 @@ function tryLoadTemplateFile(fileName) {
 function tryLoadTemplate() {
     var template;
 
-    if (!this.urlParts.length) {
+    if (!this.urlParts[0]) {
         template = tryLoadTemplateFile(__dirname +'/../template/index.js');
     } else if (this.urlParts[0][0] !== '_') {
         template = tryLoadTemplateFile(__dirname +'/../template/' +this.urlParts[0] +'.js');

+ 32 - 12
srv/template/login.js

@@ -5,17 +5,24 @@ const config = require("../config.js")
     ,FacebookOAuth = require("../src/facebookOAuth.js").FacebookOAuth
     ,slackManager = require("../src/slackManager.js").SlackManager
     ,accountManager = require("../src/accounts.js").accountManager
+    ,sessionManager = require("../src/session.js").SessionManager
     ,templates = require('./_templates.js');
 
 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) => {
-                    if (email) {
-                        console.log("from slack email " +email);
-                        var account = accountManager.fromSlackEmailAuth(email);
-                        cb(account);
+                Slack.getUserId(req.urlObj.queryTokens.code, config.login.slack.redirect_uri, (id) => {
+                    if (id) {
+                        accountManager.fromSlackIdAuth(id, (account) => {
+                            if (account) {
+                                cb(account);
+                            } else {
+                                var account = accountManager.createAccount();
+                                account.authSlackUserEmailAndTeam = id;
+                                accountManager.save(account, () => { cb(account); });
+                            }
+                        });
                     } else {
                         cb(null);
                     }
@@ -29,9 +36,16 @@ function checkTokens(service, req, cb) {
             if (req.urlObj.queryTokens.code) {
                 GoogleOAuth.getUserId(req.urlObj.queryTokens.code, (id) => {
                     if (id) {
-                        console.log("from google id " +id);
-                        var account = accountManager.fromGoogleIdAuth(id);
-                        cb(account);
+                        accountManager.fromGoogleIdAuth(id, (account) => {
+                            if (account) {
+                                cb(account);
+                            } else {
+                                var account = accountManager.createAccount();
+                                account.authGoogleUserId = id;
+                                accountManager.save(account);
+                                accountManager.save(account, () => { cb(account); });
+                            }
+                        });
                     } else {
                         cb(null);
                     }
@@ -45,9 +59,15 @@ function checkTokens(service, req, cb) {
             if (req.urlObj.queryTokens.code) {
                 FacebookOAuth.getUserId(req.urlObj.queryTokens.code[0], (id) => {
                     if (id) {
-                        console.log("from facebook id " +id);
-                        var account = accountManager.fromFacebookIdAuth(id);
-                        cb(account);
+                        accountManager.fromFacebookIdAuth(id, (account) => {
+                            if (account) {
+                                cb(account);
+                            } else {
+                                var account = accountManager.createAccount();
+                                account.authFacebookUserId = id;
+                                accountManager.save(account, () => { cb(account); });
+                            }
+                        });
                     } else {
                         cb(null);
                     }
@@ -104,7 +124,7 @@ module.exports.exec = function(req, res) {
             if (account) {
                 req.account = account;
                 req.session = sessionManager.lazyForRequest(req);
-                req.session.setSlackToken(req.reqT, token);
+                req.session.setAccountId(req.reqT, account.id);
                 res.writeHeader("302", {
                     Location: config.rootUrl
                 ,"Set-Cookie": "sessID="+req.session.sessId