exports.index = function(req, res){ console.log("Client " + req.ip + ": connected..."); if(typeof req.signedCookies[config.loginCKey] !== 'undefined'){ console.log("Client " + req.ip + ": cookies:"); console.log(prettyjson.render(req.signedCookies)); redisClient.hgetall(req.signedCookies[config.loginCKey], function(err, obj){ if(err){ console.log(err); console.log(obj); } else if(obj !== null){ req.session.address = obj.address; req.session.username = obj.username; // console.log(prettyjson.render(req.session)); } res.render('index', {title: 'Watcher'}); }); } else{ res.render('index', {title: 'Watcher'}); } }; exports.servers = function(req, res){ console.log("Client " + req.ip + ": REQUEST - server data"); // console.log(prettyjson.render(req.session.address)); // console.log(prettyjson.render(req.session.username)); if(typeof req.signedCookies[config.loginCKey] == 'undefined'){ console.log('Client ' + req.ip + ': RESPONSE - invalid login session'); res.send(401, {error: 'Valid login session is required.'}); } else{ var p4CmdParams = 'p4 -z tag -p ' + (config.masterAddr || req.session.address) + ' -u ' + (config.masterUser || req.session.username), getServerList = p4CmdParams + ' servers', getServerConf = p4CmdParams + ' configure show allservers'; execute(getServerList, function(error, stdout, stderr){ if(error){ res.send("ERROR: " + error); } var servers = {}; var currentID = ""; var currentServer; var lines = stdout.split('\n'); for(line in lines){ var key = (/\b\w*\b/).exec(lines[line]); if(key == null){ continue; } var value = lines[line].substring(key.index + key[0].length + 1); if(key == 'ServerID'){ currentServer = value; servers[currentServer] = { attr: {} }; } else{ servers[currentServer].attr[key[0]] = value; } } execute(getServerConf, function(error, stdout, stderr){ var lines = stdout.split('\n'); var server = ''; for(line in lines){ var key = (/\b\w*\b\w*/).exec(lines[line]); // Ignore empty lines. if(key == null || key == 'Type'){ continue; } if(key == 'ServerName'){ var server = lines[line].substring(key.index + key[0].length + 1); continue; } // switch (key){ // case null: // break; // case 'Type': // break; // case 'ServerName': // var server = lines[line].substring(key.index + key[0].length + 1); // break; // } // Ignore generic params if(server == 'any'){ continue; } if(key[0] == 'Name'){ var keyValue = lines[line].substring(key.index + key[0].length + 1); key = (/\b\w*\b/).exec(lines[line++]); var valValue = lines[line].substring(key.index + key[0].length + 1); servers[server].attr[keyValue] = valValue.trim(); } } for(server in servers){ if(!servers[server].attr.hasOwnProperty('P4TARGET')){ servers[server].attr.master = true; } } console.log('Client ' + req.ip + ': RESPONSE - server data'); res.json(servers); }); }); } }; exports.connect = function(req, res){ //res.clearCookie('connect.sid', {path: '/'}); console.log("Client " + req.ip + ": logging in..."); console.log(prettyjson.render(req.body.address)); console.log(prettyjson.render(req.body.username)); var address = req.body.address, username = req.body.username, password = req.body.password; /* * Expected cases: * - p4 login to invalid address * - p4 login w/ invalid user * - p4 login w/ pass; pass required * - p4 login w/ pass; pass not required * - p4 login w/o pass; pass required * - p4 login w/o pass; pass not required */ execute('p4 -u ' + username + ' -p ' + address + ' changes -m 1', function(error, stdout, stderr){ if(error){ console.log(stderr); var invalidAddr = /\.*Connect to server failed.*/; var invalidUser = /\.*User.*doesn't exist.*/; var invalidPass = /\.*password.*invalid or unset.*/; if(invalidAddr.exec(stderr)){ res.send('invalid'); // alt: res.send('invAddr'); } if(invalidUser.exec(stderr)){ res.send('invalid'); // alt: res.send('invUser'); } if(invalidPass.exec(stderr) && password == ""){ res.send('invalid'); // alt: res.send('invPass'); } } var loginCommand = "p4 -u " + username + " -p " + address + " login"; if(password != ""){ loginCommand = "echo " + password + " | " + loginCommand; } execute(loginCommand, function(error, stdout, stderr){ if(error){ res.send('invalid'); // alt: res.send('invPass'); }else{ var salt = bcrypt.genSaltSync(12, 20); // (10, 20) => default; NOTE: cost = 2^n (n = default 10) var hash = bcrypt.hashSync((Date() + '///' + address + '///' + username), salt); // console.log('SALT: ' + salt); // console.log('HASH: ' + hash); redisClient.hmset(hash, { 'address': address, 'username': username }, redis.print); redisClient.expire(hash, config.cookieLife / 1000); req.session.address = address; req.session.username = username; res.cookie(config.loginCKey, hash, {maxAge: config.cookieLife, secure: true, signed: true, path: '/', httpOnly: true}); res.send('valid'); } }); }); } exports.disconnect = function(req, res){ var logoutCommand = "p4 -u " + req.session.username + " -p " + req.session.address + " logout"; execute(logoutCommand, function(error, stdout, stderr){ console.log('ERROR: ' + error); console.log('STDOUT: ' + stdout); console.log('STDERR: ' + stderr); if(error == null){ req.session.address = ""; req.session.username = ""; //req.session = null; redisClient.del(req.signedCookies[config.loginCKey]); res.clearCookie(config.loginCKey, {path: '/'}); res.send('success'); } else{ res.send('failure'); } }); } exports.sessionInfo = function(req, res){ var sessionInfo = { address: req.session.address, username: req.session.username, requestTime: config.requestTime, requestTimeMin: config.requestTimeMin, requestTimeMax: config.requestTimeMax } res.json(sessionInfo); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#6 | 8378 | Joe Robinson |
- Server modal working. - Simplified backbone data fetching. - Log out of perforce now and not just empty session. - TODO: - Prettier/different icons for each server type. - Modal image and parent/child list. |
||
#5 | 8373 | Joe Robinson |
- Moved to d3 to handle image drawing (SVG). - Proper sessions (logging in/out) implemented. - TODO: Fix server modal style/formatting & populate with data. |
||
#4 | 8371 | Joe Robinson |
Implemented cookies/sessions (still need logout functionality). Cleaned up logging window; delete older messages so new ones do not break the page. |
||
#3 | 8367 | Joe Robinson |
Improve backbone data retrieval functionality (for building canvas nodes). Connect/login modal working almost as desired. Draw basic things on canvas. Preliminary implementation of Redis DB/cookie saving. |
||
#2 | 8362 | Joe Robinson |
Basic backbone functionality. Removed user routes. |
||
#1 | 8356 | Joe Robinson |
Refactored files, old service version can be deleted. Improved base service structure. |