3
0
mirror of https://github.com/reality/dbot.git synced 2024-12-24 11:42:36 +01:00

Merge pull request #541 from reality/weblogin

Weblogin
This commit is contained in:
Luke Slater 2013-08-05 10:34:59 -07:00
commit 30a371d4d5
16 changed files with 218 additions and 26 deletions

View File

@ -30,7 +30,11 @@ var pages = function(dbot) {
/* TODO: merge back into github module */
var milestones;
request({"url":"https://api.github.com/repos/" + dbot.config.modules.github.defaultrepo + "/milestones?state=open","headers":{"User-Agent":"reality/depressionbot (project module)"}}, function(error, response, body){
try {
milestones = JSON.parse(body);
} catch(err) {
milestones = {};
}
});

View File

@ -2,5 +2,7 @@
"ignorable": true,
"notifyVoice": false,
"dependencies": [ "users" ],
"dbType": "redis"
"dbType": "redis",
"requireWebLogin": true,
"webAccess": "power_users"
}

View File

@ -2,14 +2,14 @@ var _ = require('underscore')._;
var pages = function(dbot) {
return {
'/notify': function(req, res) {
'/report': function(req, res) {
res.render('servers', {
'name': dbot.config.name,
'servers': _.keys(dbot.config.servers)
});
},
'/notify/:server': function(req, res) {
'/report/:server': function(req, res) {
var server = req.params.server;
res.render('channels', {
'name': dbot.config.name,
@ -18,7 +18,7 @@ var pages = function(dbot) {
});
},
'/notify/:server/:channel': function(req, res) {
'/report/:server/:channel': function(req, res) {
var server = req.params.server,
channel = req.params.channel,
notifies = [];

View File

@ -50,10 +50,21 @@ var report = function(dbot) {
this.listener = function(event) {
if(_.has(this.pending, event.rUser.id)) {
_.each(this.pending[event.rUser.id], function(message) {
dbot.say(event.server, event.rUser.currentNick, message);
});
var i=0,
pending = this.pending[event.rUser.id];
var notifyUser = function(pending) {
if(i >= msg.length) {
delete this.pending[event.rUser.id];
return;
}
dbot.say(event.server, pending[i], message);
setTimeout(function() {
i++; notifyUser(pending);
}, 1000);
}.bind(this);
notifyUser(pending);
}
}.bind(this);
this.on = 'JOIN';

View File

@ -1,4 +1,6 @@
{
"dependencies": [ "report", "users", "web" ],
"dbType": "redis"
"dbType": "redis",
"requireWebLogin": true,
"webAccess": "power_users"
}

View File

@ -35,9 +35,9 @@ var pages = function(dbot) {
});
},
'/warning/:server/:user': function(req, res) {
'/warning/:server/:uid': function(req, res) {
var server = req.params.server,
user = req.params.user;
user = req.params.uid;
dbot.api.users.resolveUser(server, user, function(user) {
var warnings = [];
@ -47,16 +47,18 @@ var pages = function(dbot) {
}, function(warning) {
warnings.push(warning);
}, function(err) {
console.log(warnings);
async.eachSeries(warnings, function(warning, callback) {
dbot.api.users.getUser(warning.warner, function(user) {
warning.warner = user.primaryNick;
callback(false);
});
}, function(err) {
console.log(warnings);
res.render('warnings', {
'name': dbot.config.name,
'server': server,
'warnings': warnings
'warns': warnings
});
});
});

View File

@ -1,5 +1,6 @@
{
"webHost": "nourishedcloud.com",
"webPort": 8080,
"externalPath": false
"externalPath": false,
"dbType": "redis"
}

5
modules/web/strings.json Normal file
View File

@ -0,0 +1,5 @@
{
"web_pass_set": {
"en": "Congratulations, your account is now set up to log into the web interface!"
}
}

View File

@ -1,6 +1,10 @@
var express = require('express'),
passport = require('passport'),
passHash = require('password-hash'),
flash = require('connect-flash'),
_ = require('underscore')._,
fs = require('fs');
fs = require('fs'),
LocalStrategy = require('passport-local').Strategy;
var webInterface = function(dbot) {
this.config = dbot.config.modules.web;
@ -9,6 +13,52 @@ var webInterface = function(dbot) {
this.app.use(express.static(this.pub));
this.app.set('view engine', 'jade');
this.app.use(express.cookieParser());
this.app.use(express.bodyParser());
this.app.use(express.methodOverride());
this.app.use(express.session({ 'secret': 'wat' }));
this.app.use(flash());
this.app.use(passport.initialize());
this.app.use(passport.session());
this.app.use(this.app.router);
passport.serializeUser(function(user, done) {
console.log('serialising ' + user);
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
dbot.api.users.getUser(id, function(user) {
console.log(id);
console.log(user);
done(null, user);
});
});
passport.use(new LocalStrategy(function(username, password, callback) {
var splitUser = username.split('@'),
server = splitUser[1],
username = splitUser[0];
dbot.api.users.resolveUser(server, username, function(user) {
if(user) {
this.api.getWebUser(user.id, function(webUser) {
if(webUser) {
if(passHash.verify(password, webUser.password)) {
return callback(null, user);
} else {
return callback(null, false, { 'message': 'Incorrect password.' });
}
} else {
return callback(null, false, { 'message': 'Use ~setwebpass to set up your account for web login.' });
}
});
} else {
return callback(null, false, { 'message': 'Unknown user' });
}
}.bind(this));
}.bind(this)));
var server = this.app.listen(this.config.webPort);
@ -18,11 +68,15 @@ var webInterface = function(dbot) {
if(_.has(pages, p)) {
var func = pages[p];
var mod = func.module;
this.app.get(p, (function(req, resp) {
this.app.get(p, this.api.hasAccess, (function(req, resp) {
// Crazy shim to seperate module views.
var shim = Object.create(resp);
shim.render = (function(view, one, two) {
// Render with express.js
_.extend(one, {
'name': dbot.config.name,
'user': req.user
});
resp.render(this.module + '/' + view, one, two);
}).bind(this);
shim.render_core = resp.render;
@ -37,6 +91,7 @@ var webInterface = function(dbot) {
var moduleNames = _.keys(dbot.modules);
var indexModules = [];
// fix the thingy
_.each(moduleNames, function(moduleName) {
var modulePath = '/' + moduleName;
if(_.include(routes, modulePath)) {
@ -44,15 +99,36 @@ var webInterface = function(dbot) {
}
});
console.log(indexModules);
// TODO: get list of loaded modules
this.app.get('/', function(req, res) {
res.render('index', {
'name': dbot.config.name,
'user': req.user,
'routes': indexModules
});
});
this.app.get('/login', function(req, res) {
res.render('login', {
'user': req.user,
'message': req.flash('error')
});
});
this.app.post('/login', passport.authenticate('local', {
'failureRedirect': '/login',
'failureFlash': true
}), function(req, res) {
if(req.body.redirect) {
res.redirect(req.body.redirect);
} else {
res.redirect('/');
}
});
this.app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
}.bind(this);
this.onDestroy = function() {
@ -67,8 +143,70 @@ var webInterface = function(dbot) {
} else {
return 'http://' + this.config.webHost + ':' + this.config.webPort + '/' + path;
}
},
'getWebUser': function(id, callback) {
this.db.read('web_users', id, function(err, webUser) {
callback(webUser);
});
},
'hasAccess': function(req, res, next) {
var module = req.route.path.split('/')[1];
module = dbot.modules[module];
if(module.config.requireWebLogin == true) {
if(req.isAuthenticated()) {
if(!_.isUndefined(module.config.webAccess)) {
var allowedUsers = dbot.config.admins;
if(module.config.webAccess == 'moderators') {
allowedUsers = _.union(allowedUsers, dbot.config.moderators);
}
if(module.config.webAccess == 'power_users') {
allowedUsers = _.union(allowedUsers, dbot.config.moderators);
allowedUsers = _.union(allowedUsers, dbot.config.power_users);
}
if(_.include(allowedUsers, req.user.primaryNick)) {
return next();
} else {
res.redirect('/');
}
} else {
return next();
}
} else {
res.render('login', {
'message': 'You need to log in to access this module.',
'redirect': module
});
}
} else {
return next();
}
}
};
this.commands = {
'~setwebpass': function(event) {
var newPass = event.input[1];
console.log(newPass);
this.api.getWebUser(event.rUser.id, function(webUser) {
if(!webUser) {
webUser = {
'id': event.rUser.id,
'password': false
}
}
webUser.password = passHash.generate(newPass);
this.db.save('web_users', webUser.id, webUser, function(result) {
event.reply(dbot.t('web_pass_set'));
});
}.bind(this));
}
};
this.commands['~setwebpass'].regex = [/^~setwebpass ([^ ]+)$/, 2]
};
exports.fetch = function(dbot) {

View File

@ -230,8 +230,10 @@ div.imgwrap > img {
margin-right:10px;
margin-left:10px;
}
#footer a {
#bread {
float:right;
margin-left: 2px;
margin-right: 2px;
padding-left:2px;
padding-right:2px;
background-color:#f5f5f5;

View File

@ -16,7 +16,12 @@ html(lang='en')
div.container#main
block content
div#footer
a#project(href='/project') About
p#project
a#bread(href='/project') About
if user
span#bread Logged in as #{user.primaryNick}
else
a#bread(href='/login') Login
script(type="text/javascript", src="/bootstrap/js/bootstrap.min.js")
script(type="text/javascript", src="/d3/d3.v3.min.js")

20
views/login.jade Normal file
View File

@ -0,0 +1,20 @@
extends layout
block content
div#backlink
a(href='/') « Home
br
if message
p #{message}
div#login
form(action='/login', method='post')
input(type="hidden", name="redirect", value=redirect)
p
key Username
input(type="text", name="username")
p
key Password
input(type="password", name="password")
p
input(type="submit", value="Log In")

View File

@ -3,8 +3,8 @@ extends ../layout
block content
h3 Channels on #{server}
div#backlink
a(href='/warning') « Server List
a(href='/report') « Server List
ul#quotelist
-each channel in channels
a(href='/notify/'+server+'/'+encodeURIComponent(channel))
a(href='/report/'+server+'/'+encodeURIComponent(channel))
li.quotes #{channel}

View File

@ -2,7 +2,7 @@ extends ../layout
block content
div#backlink
a(href='/notify/'+server) « Server Channels
a(href='/report/'+server) « Server Channels
p
div#profile_datatable
table.table.table-hover.data

View File

@ -6,5 +6,5 @@ block content
a(href='/') « Home
ul#quotelist
-each server in servers
a(href='/notify/'+server)
a(href='/report/'+server)
li.quotes #{server}

View File

@ -12,7 +12,7 @@ block content
th Warner
th Reason
tbody
for warning, key in warnings
each warning, key in warns
tr
td #{new Date(warning.time)}
td #{warning.warner}