UNPKG

scalra

Version:

node.js framework to prototype and scale rapidly

813 lines (688 loc) 22.3 kB
// // login.js // // login/account related message handlers // // include access to user API (/extension/user.js) //var l_users = SR.Require.ext('user.js'); // a pool for all message handlers var l_handlers = exports.handlers = {}; var l_checkers = exports.checkers = {}; // loginID to account mapping var l_loginID = {}; var groupPermissionDB = 'groupPermission'; SR.DB.useCollections([groupPermissionDB]); // // helpers // // perform remote login (at cloud server) of accounts at local servers var l_login_local_accounts = function (account) { // get all local accounts & perform login var onDone = function (err, data) { if (err) { LOG.warn(err.toString()); } else { for (var server in data.accounts) { LOG.warn('local server: ' + server); var user_list = data.accounts[server]; for (var uid in user_list) { var token = user_list[uid]; LOG.warn('local uid: ' + uid + ' token: ' + token); l_send_remote_login(server, uid, token); } } } }; SR.User.getUser(account, onDone); } // send login info for local server var l_send_remote_login = function (server, uid, token) { try { // convert uid to number if not already if (typeof uid === 'string') uid = parseInt(uid); } catch (e) { LOG.error('uid cannot be parsed as integer...', 'login.send_remote_login'); return false; } SR.User.loginLocal(server, uid, token, function (result) { // NOTE: if local server is not registered, will return 'undefined' as result if (result) { // NOTE: result has U and P fields LOG.warn('local login result for [' + uid + ']: ' + (result.code === 0)); } else LOG.warn('local login result for [' + uid + ']: remote server not online'); }); return true; } //----------------------------------------- // define handlers (format checkers and event handlers) // //----------------------------------------- // // Login System // // set the upper limit of the message queue's size l_checkers.SR_LOGIN_QUERY_ACCOUNT = { //login_id: 'string' }; l_handlers.SR_LOGIN_QUERY_ACCOUNT = function (event) { LOG.warn('SR_LOGIN_QUERY_ACCOUNT called, session:'); LOG.warn(event.session); console.log(event.session); if (event.session['_account']) { // get email var account = event.session['_account']; //var email = SR.User.getEmail(account); event.done('SR_LOGIN_RESPONSE', {code: 0, msg: account, session: event.session}); } else event.done('SR_LOGIN_RESPONSE', {code: 1, msg: 'account not logined'}); /* var login_id = event.data.login_id; if (l_loginID.hasOwnProperty(login_id)) event.done('SR_LOGIN_RESPONSE', {code: 0, msg: l_loginID[login_id]}); else event.done('SR_LOGIN_RESPONSE', {code: 1, msg: 'no account found for login_id: ' + login_id}); */ } // retrieve a given user's data l_checkers.SR_QUERY_USERDATA = { }; l_handlers.SR_QUERY_USERDATA = function (event) { LOG.warn(event); var account = event.session['_account']; if (typeof account === 'undefined') { event.done('SR_QUERY_USERDATA', {code: 1, msg: 'account not logined'}); return; } var getEmailDone = function (getEmail_err, email) { if (getEmail_err) { LOG.warn(getEmail_err.toString()); event.done("SR_QUERY_USERDATA", {code: 1, msg: "account email does not exist"}); } else { var getUserDone = function (err, data) { console.log("SR_QUERY_USERDATA"); console.log(data); if (err) { LOG.warn(err.toString()); event.done('SR_QUERY_USERDATA', {code: 1, msg: 'cannot query user data for: ' + account}); } else { event.done('SR_QUERY_USERDATA', {code: 0, msg: 'query user data success for: ' + account, data: {account: account, email: email, data: data}, lastStatus: event.session['lastStatus']}); } }; SR.User.getUser(account, getUserDone); } }; SR.User.getEmail(account, getEmailDone); /* sample for query an array of user accounts SR.User.getUser(['tt', account, 'abc'], function (data) { LOG.warn(data); if (data === undefined) { return event.done('SR_QUERY_USERDATA', {code: 1, msg: 'cannot query user data for: ' + account}); } event.done('SR_QUERY_USERDATA', {code: 0, msg: 'query user data success for: ' + account, data: {account: account, email: email, data: data[account]}}); }); */ } // retrieve a given user's data l_checkers.SR_UPDATE_USERDATA = { }; l_handlers.SR_UPDATE_USERDATA = function (event) { var account = event.session['_account']; if (typeof account === 'undefined') { return event.done('SR_UPDATE_USERDATA', {code: 1, msg: 'account not logined'}); } // store back var onDone = function (err) { if (err) { LOG.warn(err.toString()); event.done('SR_UPDATE_USERDATA', {code: 1, msg: 'user data update failed'}); } else { event.done('SR_UPDATE_USERDATA', {code: 0, msg: 'user data updated'}); } }; SR.User.setUser(account, event.data, onDone); } // initialize session content based on registered or logined user data var l_initSession = function (login_id, session, data) { // acknowledge as 'logined' l_loginID[login_id] = data.account; // init session session['_account'] = data.account; // TODO: needs to fix this, should read "groups" from DB session['_groups'] = data.groups; session['_permissions'] = data.permissions; session['lastStatus'] = data.lastStatus; // TODO: centralize handling of logined users? //SR.User.addGroup(user_data.account, ['user', 'admin']); } l_handlers.SR_LOGIN_FB = function (event) { SR.SNS.login(event.data.login_id, 'FB', event.data.app_name, function (result) { LOG.warn(result); event.done(result); }) } // NOTE: // if testing SR_LOGIN_REGISTER by URL in browser, need to put parameters into following format: // ex. // http://src.scalra.com:37194/event/SR_LOGIN_REGISTER?_data={"login_id": "xxx", "data": {"account": "syhu", "password": "abc", "email": "jjj"}} // register l_checkers.SR_LOGIN_REGISTER = { login_id: 'string', data: 'object' }; l_handlers.SR_LOGIN_REGISTER = function (event) { //var data = event.data; var user_data = UTIL.clone(event.data.data); //var account = user_data.account; //var password = user_data.password; //var email = user_data.email; //var groups = user_data.groups; delete user_data.account; delete user_data.password; delete user_data.email; delete user_data.groups; //console.log(data); //LOG.warn('register new user: '); //LOG.warn(user_data); // try to register new account var reg = { account: event.data.data.account, password: event.data.data.password, email: event.data.data.email, groups: event.data.data.groups || [], // by default there's no specific group permissions: [], data: user_data, lastStatus: {loginIP: event.conn.host, time: event.conn.time, loginCount: 1}, onDone: function (err, result) { if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } else { // if success, record login_id to account mapping if (result.code === 0) { l_initSession(event.data.login_id, event.session, reg); } } event.done('SR_LOGIN_RESPONSE', result); } }; // special handling (by default 'admin' account is special and will be part of the 'admin' group by default if (reg.account === 'admin') { reg.groups.push('admin'); } SR.User.register(reg); } // login /* data: {account: 'string', password: 'string', server: 'string' } */ l_checkers.SR_LOGIN_ACCOUNT = { login_id: 'string', data: 'object' }; l_handlers.SR_LOGIN_ACCOUNT = function (event) { //console.log(event); var data = event.data; var user_data = data.data; user_data.lastStatus = {loginIP: event.conn.host, time: event.conn.time, loginCount: 1}; LOG.warn(data, 'SR_LOGIN_ACCOUNT'); var server_name = event.data.data.server; LOG.sys(server_name); // if a local server is specified if (server_name && server_name !== '') { LOG.warn('check login with local server [' + server_name + ']'); // TODO: cloud processing // if this is a remotely executable event, then stop execution from now // NOTE: if server is not registered, will also return true, event will be handled within SR.RPC if (SR.RPC.relayEvent(server_name, 'SR_LOGIN_ACCOUNT', event) === true) return; } // otherwise perform local login var loginDone = function (err, result) { // if login is successful, we record the user's account in cache if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } else { if (result.code === 0) { LOG.warn('login success, result: '); LOG.warn(result); var data = { account: user_data.account, groups: result.data.groups, lastStatus: result.data.lastStatus, permissions: [] } l_initSession(event.data.login_id, event.session, data); /* // todo: read permssion from DB //event.session['_permissions'] = result.data.permissions; var xx = []; var onSuccess = function(dat){ //console.log(dat.permission); if (dat === null) { console.log("no permission"); } else { for (var i in dat.permission) { //console.log("pushing: " + dat.permission[i]); xx.push(dat.permission[i]); } } //event.done("get group", {"status": "success", "data": data}); }; var onFail = function(dat){ //event.done("get group", {"status": "failure", "data": data}); }; for (var i in event.session['_groups']) { //console.log("getting: " + event.session['_groups'][i]); SR.DB.getData(groupPermissionDB, {"group": event.session['_groups'][i], part: "group"}, onSuccess, onFail); } */ // TODO: login at once to all local accounts // NOTE: need to query all local login account name & password, then perform individual logins l_login_local_accounts(user_data.account); } } //LOG.warn('event before sending login response:'); //LOG.warn(event); //if (result.data) delete result.data; // return response regardless success or fail event.done('SR_LOGIN_RESPONSE', result); }; SR.User.login(user_data.account, user_data.password, loginDone, user_data.requester, event.conn); } l_checkers.SR_LOGIN_TOKEN = { login_id: 'string', data: 'object' }; l_handlers.SR_LOGIN_TOKEN = function (event) { var data = event.data; var user_data = data.data; var token = data.token; event.done('SR_LOGIN_RESPONSE', result); } // login by guest l_checkers.SR_LOGIN_GUEST = { login_id: 'string' }; l_handlers.SR_LOGIN_GUEST = function (event) { var data = event.data; var user_data = data; var onDone = function (err, result) { if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } else { if (result.code === 0) { l_loginID[data.login_id] = data.login_id; } } event.done('SR_LOGIN_RESPONSE', result); }; SR.User.loginByID(data.login_id, user_data, onDone, event.conn); } // get password l_checkers.SR_LOGIN_GETPASS = { email: 'string', }; l_handlers.SR_LOGIN_GETPASS = function (event) { //var data = extractJSONPara(event.data); var data = event.data; var onDone = function (err, result) { if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } else { } event.done('SR_LOGIN_RESPONSE', result); }; SR.User.getPass('email', data.email, onDone); } // set password l_checkers.SR_LOGIN_SETPASS = { password: 'string', token: 'string' }; l_handlers.SR_LOGIN_SETPASS = function (event) { var data = event.data; console.log("---------------------"); console.log(event.data); var onDone = function (err, result) { if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } else { } event.done('SR_LOGIN_RESPONSE', result); }; SR.User.setPass(data.password, data.token, onDone); } // get password l_checkers.SR_LOGOUT = { //_group: ['user', 'admin'], account: 'string', }; l_handlers.SR_LOGOUT = function (event) { var onDone = function (err, result) { if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } // remove session // TODO: remove at one place only delete event.session['_account']; delete event.session['_groups']; delete event.session['_permissions']; event.done('SR_LOGOUT_RESPONSE', result); }; SR.User.logout(event.data.account, onDone); } // add an account to local system l_checkers.SR_ADDLOCAL = { account: 'string', local_account: 'object' }; // TODO: can event perhaps directly call API? (for example, calling SR.User functions directly) l_handlers.SR_ADDLOCAL = function (event) { LOG.warn(event.data); // store this to local user's account profile var onDone = function (err, result) { if (err) { LOG.warn(err.toString()); result = {code: err.code, msg: err.message}; } event.done('SR_LOGIN_RESPONSE', result); }; SR.User.addLocal(event.data.account, event.data.local_account, onDone); } // revoke a token l_checkers.SR_REVOKETOKEN = { token: 'string' }; // TODO: can event perhaps directly call API? (for example, calling SR.User functions directly) l_handlers.SR_REVOKETOKEN = function (event) { LOG.warn(event.data); var uid = (typeof event.data.uid === 'string' ? parseInt(event.data.uid) : event.data.uid); // store this to local user's account profile var onDone = function (err, result) { if (err) { event.done('SR_LOGIN_RESPONSE', {code: 1, msg: 'revokeToken fail: ' + event.data.token}); } else { event.done('SR_LOGIN_RESPONSE', {code: 0, msg: 'revokeToken success: ' + event.data.token}); } }; SR.User.revokeToken(uid, event.data.token, onDone); } // update user's email l_checkers.SR_UPDATE_EMAIL = { account: 'string', email: 'string' }; // TODO: can event perhaps directly call API? (for example, calling SR.User functions directly) l_handlers.SR_UPDATE_EMAIL = function (event) { LOG.warn(event.data); // store this to local user's account profile var onDone = function (err, result) { if (err) { event.done('SR_LOGIN_RESPONSE', {code: 1, msg: 'update email failed: ' + event.data.account}); } else { event.done('SR_LOGIN_RESPONSE', {code: 0, msg: 'update email success: ' + event.data.account}); } }; SR.User.setEmail(event.data.account, event.data.email, onDone); } ///////////////////////////////////////// // extensions for group and permission // // ///////////////////////////////////////// l_handlers.SR_GROUP_PERMISSION = function (event) { console.log(event.data); switch (event.data.action) { case 'setGroup': SR.DB.getData(groupPermissionDB, {"group": event.data.group, part: "group"}, function(data){ if (data) { //console.log("appending permission(s)"); var appendPermission = function (arg) { if ( ! arg.permission ){ console.log("error: no permission assigned"); return; } var exist = false; for (var i in data.permission) { if (data.permission[i] === arg.permission) { //console.log("existing: " + arg.permission); exist = true; } } if ( exist === false ) { //console.log("adding: " + arg.permission); data.permission[data.permission.length] = arg.permission; } } switch (typeof event.data.permission) { case 'string': appendPermission({permission: event.data.permission}); break; case 'object': for (var i in event.data.permission) { appendPermission({permission: event.data.permission[i]}); } break; default: console.log("error: 729ff39587 please debug."); break; } } else { // does not exist, create a new one var data = {group: event.data.group}; switch (typeof event.data.permission) { case 'string': data.permission = [event.data.permission]; break; case 'object': data.permission = event.data.permission; break; } } console.log(data); SR.DB.updateData(groupPermissionDB, {"group": event.data.group, part: "group"}, data, function(dat){ event.done("set group", {"status": "success", detail: dat}); }, function(dat){ event.done("set group", {"status": "failure", detail: dat}); }); }, function(data){ event.done("set group stage1", {"status": "failure", "detail": data}); }); break; case 'getGroup': SR.DB.getData(groupPermissionDB, {"group": event.data.group, part: "group"}, function(data){ event.done("get group", {"status": "success", "data": data}); }, function(data){ event.done("get group", {"status": "failure", "data": data}); }); break; case 'listGroup': SR.DB.getArray(groupPermissionDB, function(data){ event.done("list group", {"status": "success", "data": data}); }, function(data) { event.done("list group", {"status": "failure", "data": data}); }, {part: "group"}); break; case 'deleteGroup': SR.DB.getData(groupPermissionDB, {"group": event.data.group, part: "group"}, function(data){ if (typeof data.permission === 'object') { for (var i in data.permission) { switch (typeof event.data.permission) { case 'string': if (data.permission[i] === event.data.permission) { delete data.permission[i]; } break; case 'object': for (var j in event.data.permission) { if (data.permission[i] === event.data.permission[j]) delete data.permission[i]; } break; default: break; } } } data.permission = UTIL.cleanArray(data.permission); console.log(data); if ( data && data.permission.length > 0 ) { SR.DB.updateData(groupPermissionDB,{"group": event.data.group, part: "group"}, data, function(dat){ event.done("delete group", {"status": "success", "data": dat}); }, function(dat){ event.done("delete group", {"status": "failure", "data": dat}); }, {"group": event.data.group, part: "group"}); } else { SR.DB.deleteData(groupPermissionDB, function(data){ event.done("delete event level", {"status": "success", "data": data}); }, function(data){ event.done("delete event level", {"status": "failure", "data": data}); }, {group: event.data.group, part: "group"}); } }, function(data){ event.done("get group", {"status": "failure", "data": data}); }); break; /////////////////////////////////////////////// case 'setPermission': SR.DB.getData(groupPermissionDB, {"permission": event.data.permission, part: "permission"}, function(data){ if (data) { // level exists, to modify this level var appendAllow = function (arg) { if ( ! arg.allow ){ return; } var exist = false; for (var i in data.allow) { if (data.allow[i] === arg.allow) { exist = true; } } if ( exist === false ) { data.allow[data.allow.length] = arg.allow; } } switch (typeof event.data.allow) { case 'string': appendAllow({allow: event.data.allow}); break; case 'object': for (var i in event.data.allow) { appendAllow({allow: event.data.allow[i]}); } break; default: console.log("error: 72939587 please debug."); break; } } else { // does not exist, create a new one var data = {permission: event.data.permission}; switch (typeof event.data.allow) { case 'string': data.allow = [event.data.allow]; break; case 'object': data.allow = event.data.allow; break; } } SR.DB.updateData(groupPermissionDB, {"permission": event.data.permission, part: "permission"}, data, function(dat){ event.done("set permission", {"status": "success"}); }, function(dat){ event.done("set permission", {"status": "failure"}); }); }, function(data){ event.done("set permission stage1", {"status": "failure", "data": data}); }); break; case 'getPermission': SR.DB.getData(groupPermissionDB, {"permission": event.data.permission, part: "permission"}, function(data){ event.done("get permission", {"status": "success", "data": data}); }, function(data){ event.done("get permission", {"status": "failure", "data": data}); }); break; case 'listPermission': SR.DB.getArray(groupPermissionDB, function(data){ event.done("list permission", {"status": "success", "data": data}); }, function(data) { event.done("list permission", {"status": "failure", "data": data}); }, {part: "permission"}); break; case 'deletePermission': SR.DB.getData(groupPermissionDB, {"permission": event.data.permission, part: "permission"}, function(data){ if (typeof data.allow === 'object') { for (var i in data.allow) { switch (typeof event.data.allow) { case 'string': if (data.allow[i] === event.data.allow) { delete data.allow[i]; } break; case 'object': for (var j in event.data.allow) { if (data.allow[i] === event.data.allow[j]) delete data.allow[i]; } break; default: break; } } } data.allow = UTIL.cleanArray(data.allow); console.log(data); if ( data && data.allow.length > 0 ) { SR.DB.updateData(groupPermissionDB,{"permission": event.data.permission, part: "permission"}, data, function(dat){ event.done("delete permission", {"status": "success", "data": dat}); }, function(dat){ event.done("delete permission", {"status": "failure", "data": dat}); }, {permission: event.data.permission, part: "permission"}); } else { SR.DB.deleteData(groupPermissionDB, function(data){ event.done("delete event level", {"status": "success", "data": data}); }, function(data){ event.done("delete event level", {"status": "failure", "data": data}); }, {permission: event.data.permission, part: "permission"}); } }, function(data){ event.done("get permission", {"status": "failure", "data": data}); }); break; case 'deleteLevel': break; default: event.done("no action"); break; } }