mirror of
https://github.com/moparisthebest/kaiwa
synced 2025-02-16 07:00:09 -05:00
All the things
This commit is contained in:
parent
f1bad70a14
commit
c54bb6f7fe
@ -13,48 +13,64 @@ var xmppEventHandlers = require('./helpers/xmppEventHandlers');
|
||||
|
||||
module.exports = {
|
||||
launch: function () {
|
||||
var self = this;
|
||||
var self = window.app = this;
|
||||
var config = localStorage.config;
|
||||
|
||||
if (!config) {
|
||||
console.log('missing config');
|
||||
window.location = '/login';
|
||||
}
|
||||
|
||||
config = JSON.parse(config);
|
||||
|
||||
_.extend(this, Backbone.Events);
|
||||
|
||||
var app = window.app = this;
|
||||
|
||||
$(function () {
|
||||
async.series([
|
||||
function (cb) {
|
||||
app.storage = new Storage();
|
||||
app.storage.open(cb);
|
||||
},
|
||||
function (cb) {
|
||||
var me = window.me = new MeModel();
|
||||
|
||||
new Router();
|
||||
app.history = Backbone.history;
|
||||
|
||||
app.view = new MainView({
|
||||
model: me,
|
||||
el: document.body
|
||||
});
|
||||
app.view.render();
|
||||
|
||||
var client = window.client = app.client = XMPP.createClient({
|
||||
rosterVer: localStorage.rosterVersion || undefined
|
||||
});
|
||||
xmppEventHandlers(client, app);
|
||||
|
||||
// we have what we need, we can now start our router and show the appropriate page
|
||||
app.history.start({pushState: true, root: '/'});
|
||||
|
||||
async.series([
|
||||
function (cb) {
|
||||
app.storage = new Storage();
|
||||
app.storage.open(cb);
|
||||
},
|
||||
function (cb) {
|
||||
app.storage.rosterver.get(config.jid, function (err, ver) {
|
||||
if (ver) {
|
||||
config.rosterVer = ver;
|
||||
}
|
||||
cb();
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
},
|
||||
function (cb) {
|
||||
window.me = new MeModel();
|
||||
|
||||
self.api = window.client = XMPP.createClient(config);
|
||||
xmppEventHandlers(self.api, self);
|
||||
|
||||
self.api.connect();
|
||||
|
||||
self.api.once('session:started', function () {
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function (cb) {
|
||||
new Router();
|
||||
app.history = Backbone.history;
|
||||
|
||||
self.view = new MainView({
|
||||
model: me,
|
||||
el: document.body
|
||||
});
|
||||
self.view.render();
|
||||
|
||||
// we have what we need, we can now start our router and show the appropriate page
|
||||
app.history.start({pushState: true, root: '/'});
|
||||
cb();
|
||||
}
|
||||
]);
|
||||
},
|
||||
whenConnected: function (func) {
|
||||
if (client.sessionStarted) {
|
||||
if (app.api.sessionStarted) {
|
||||
func();
|
||||
} else {
|
||||
client.once('session:started', func);
|
||||
app.api.once('session:started', func);
|
||||
}
|
||||
},
|
||||
navigate: function (page) {
|
||||
|
@ -16,13 +16,42 @@ module.exports = function (client, app) {
|
||||
log.debug(name, data);
|
||||
});
|
||||
|
||||
client.on('credentials:update', function (creds) {
|
||||
client.config.credentials = creds;
|
||||
|
||||
if (creds.clientKey && creds.serverKey) {
|
||||
delete creds.password;
|
||||
delete creds.saltedPassword;
|
||||
} else if (creds.saltedPassword) {
|
||||
delete creds.password;
|
||||
}
|
||||
|
||||
localStorage.config = JSON.stringify({
|
||||
jid: client.config.jid,
|
||||
server: client.config.server,
|
||||
wsURL: client.config.wsURL,
|
||||
credentials: creds
|
||||
});
|
||||
});
|
||||
|
||||
client.on('disconnected', function () {
|
||||
me.connectionStatus = 'disconnected';
|
||||
});
|
||||
|
||||
client.on('auth:failed', function () {
|
||||
console.log('auth failed');
|
||||
window.location = '/login';
|
||||
});
|
||||
|
||||
client.on('session:started', function (jid) {
|
||||
me.jid = jid;
|
||||
|
||||
me.connectionStatus = 'connected';
|
||||
|
||||
client.getRoster(function (err, resp) {
|
||||
resp = resp.toJSON();
|
||||
|
||||
localStorage.rosterVersion = resp.roster.ver;
|
||||
app.storage.rosterver.set(me.barejid, resp.roster.ver);
|
||||
|
||||
_.each(resp.roster.items, function (item) {
|
||||
console.log(item);
|
||||
@ -41,7 +70,7 @@ module.exports = function (client, app) {
|
||||
iq = iq.toJSON();
|
||||
var items = iq.roster.items;
|
||||
|
||||
localStorage.rosterVersion = iq.roster.ver;
|
||||
app.storage.rosterver.set(me.barejid, iq.roster.ver);
|
||||
|
||||
_.each(items, function (item) {
|
||||
var contact = me.getContact(item.jid);
|
||||
|
@ -127,6 +127,14 @@ function Client(opts) {
|
||||
self.send(new SASL.Response({
|
||||
value: mech.response(self.getCredentials())
|
||||
}));
|
||||
|
||||
if (mech.cache) {
|
||||
_.each(mech.cache, function (val, key) {
|
||||
self.config.credentials[key] = btoa(val);
|
||||
});
|
||||
self.emit('credentials:update', self.config.credentials);
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
self.on('sasl:failure', 'sasl', function () {
|
||||
@ -377,7 +385,16 @@ Client.prototype.getCredentials = function () {
|
||||
serviceName: server
|
||||
};
|
||||
|
||||
return _.extend(defaultCreds, creds);
|
||||
var result = _.extend(defaultCreds, creds);
|
||||
|
||||
var cachedBinary = ['saltedPassword', 'clientKey', 'serverKey'];
|
||||
cachedBinary.forEach(function (key) {
|
||||
if (result[key]) {
|
||||
result[key] = atob(result[key]);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Client.prototype.connect = function (opts) {
|
||||
@ -4480,8 +4497,6 @@ EntityTime.prototype = {
|
||||
toString: stanza.toString,
|
||||
toJSON: stanza.toJSON,
|
||||
get tzo() {
|
||||
console.log(this.toString());
|
||||
console.log(this.parent.toString());
|
||||
var split, hrs, min;
|
||||
var sign = -1;
|
||||
var formatted = stanza.getSubText(this.xml, this.NS, 'tzo');
|
||||
@ -4491,14 +4506,11 @@ EntityTime.prototype = {
|
||||
}
|
||||
if (formatted.charAt(0) === '-') {
|
||||
sign = 1;
|
||||
formatted = formatted.slice(1);
|
||||
formatted.slice(1);
|
||||
}
|
||||
split = formatted.split(':');
|
||||
console.log(split);
|
||||
hrs = parseInt(split[0], 10);
|
||||
min = parseInt(split[1], 10);
|
||||
console.log('hrs', hrs);
|
||||
console.log('min', min);
|
||||
return (hrs * 60 + min) * sign;
|
||||
},
|
||||
set tzo(value) {
|
||||
@ -14405,8 +14417,16 @@ var Buffer=require("__browserify_Buffer").Buffer;// uuid.js
|
||||
|
||||
mech._clientFinalMessageWithoutProof = 'c=' + gs2Header + ',r=' + mech._nonce;
|
||||
|
||||
var saltedPassword = Hi(cred.password, mech._salt, mech._iterationCount);
|
||||
var clientKey = HMAC(saltedPassword, 'Client Key');
|
||||
var saltedPassword, clientKey, serverKey;
|
||||
if (cred.clientKey && cred.serverKey) {
|
||||
clientKey = cred.clientKey;
|
||||
serverKey = cred.serverKey;
|
||||
} else {
|
||||
saltedPassword = cred.saltedPassword || Hi(cred.password, mech._salt, mech._iterationCount);
|
||||
clientKey = HMAC(saltedPassword, 'Client Key');
|
||||
serverKey = HMAC(saltedPassword, 'Server Key');
|
||||
}
|
||||
|
||||
var storedKey = H(clientKey);
|
||||
var authMessage = mech._clientFirstMessageBare + ',' +
|
||||
mech._challenge + ',' +
|
||||
@ -14416,7 +14436,6 @@ var Buffer=require("__browserify_Buffer").Buffer;// uuid.js
|
||||
var xorstuff = XOR(clientKey, clientSignature);
|
||||
|
||||
var clientProof = new Buffer(xorstuff, 'binary').toString('base64');
|
||||
var serverKey = HMAC(saltedPassword, 'Server Key');
|
||||
|
||||
mech._serverSignature = HMAC(serverKey, authMessage);
|
||||
|
||||
@ -14424,6 +14443,12 @@ var Buffer=require("__browserify_Buffer").Buffer;// uuid.js
|
||||
|
||||
mech._stage = 2;
|
||||
|
||||
mech.cache = {
|
||||
saltedPassword: saltedPassword,
|
||||
clientKey: clientKey,
|
||||
serverKey: serverKey
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
responses[2] = function (mech, cred) {
|
||||
@ -14832,4 +14857,4 @@ I(m)):b&&y(m);return h});f.assign=x;f.createCallback=function(a,d,b){if(null==a)
|
||||
ja;f.forIn=W;f.keys=K;f.uniq=p;f.each=ja;f.extend=x;f.unique=p;f.identity=X;f.indexOf=ka;f.isArguments=v;f.isArray=T;f.isEqual=w;f.isFunction=D;f.isObject=ia;f.isString=ca;f.sortedIndex=la;f.VERSION="1.3.1";typeof define=="function"&&typeof define.amd=="object"&&define.amd?(G._=f, define(function(){return f})):N&&!N.nodeType?ma?(ma.exports=f)._=f:N._=f:G._=f})(this);
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
;
|
||||
;
|
@ -1,5 +1,5 @@
|
||||
/*global XMPP, app, me, client*/
|
||||
"use strict";
|
||||
//"use strict";
|
||||
|
||||
var async = require('async');
|
||||
var HumanModel = require('human-model');
|
||||
@ -9,7 +9,7 @@ var Message = require('./message');
|
||||
var crypto = XMPP.crypto;
|
||||
|
||||
|
||||
module.exports = HumanModel.extend({
|
||||
module.exports = HumanModel.define({
|
||||
initialize: function (attrs) {
|
||||
if (attrs.jid) {
|
||||
this.cid = attrs.jid;
|
||||
@ -20,6 +20,7 @@ module.exports = HumanModel.extend({
|
||||
this.resources.bind('add remove reset change', this.resourceChange, this);
|
||||
this.bind('change:lockedResource', this.fetchTimezone, this);
|
||||
},
|
||||
seal: true,
|
||||
type: 'contact',
|
||||
props: {
|
||||
jid: ['string', true],
|
||||
|
@ -6,7 +6,7 @@ var Contacts = require('./contacts');
|
||||
var Contact = require('./contact');
|
||||
|
||||
|
||||
module.exports = HumanModel.extend({
|
||||
module.exports = HumanModel.define({
|
||||
session: {
|
||||
jid: ['string', true, ''],
|
||||
status: ['string', true, ''],
|
||||
|
@ -4,7 +4,7 @@
|
||||
var HumanModel = require('human-model');
|
||||
|
||||
|
||||
module.exports = HumanModel.extend({
|
||||
module.exports = HumanModel.define({
|
||||
initialize: function (attrs) {
|
||||
this._created = Date.now();
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
var HumanModel = require('human-model');
|
||||
|
||||
|
||||
module.exports = HumanModel.extend({
|
||||
module.exports = HumanModel.define({
|
||||
initialize: function () {},
|
||||
type: 'resource',
|
||||
session: {
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*global app, client*/
|
||||
"use strict";
|
||||
|
||||
var BasePage = require('./base');
|
||||
var templates = require('../templates');
|
||||
|
||||
|
||||
module.exports = BasePage.extend({
|
||||
template: templates.pages.signin,
|
||||
events: {
|
||||
'submit #loginForm form': 'login'
|
||||
},
|
||||
initialize: function (spec) {
|
||||
this.renderAndBind();
|
||||
},
|
||||
login: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var jid = this.$('#jid').val();
|
||||
var password = this.$('#password').val();
|
||||
var wsURL = this.$('#wsURL').val();
|
||||
|
||||
client.connect({
|
||||
jid: jid,
|
||||
server: jid.slice(jid.indexOf('@') + 1),
|
||||
wsURL: wsURL,
|
||||
credentials: {
|
||||
password: password
|
||||
}
|
||||
});
|
||||
|
||||
client.once('auth:success', 'signin', function () {
|
||||
client.releaseGroup('signin');
|
||||
app.navigate('/');
|
||||
});
|
||||
|
||||
client.once('auth:failed', 'signin', function () {
|
||||
client.releaseGroup('signin');
|
||||
console.log('Failed Auth');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
@ -2,7 +2,6 @@
|
||||
"use strict";
|
||||
|
||||
var Backbone = require('backbone');
|
||||
var SigninPage = require('./pages/signin');
|
||||
var MainPage = require('./pages/main');
|
||||
var ChatPage = require('./pages/chat');
|
||||
|
||||
@ -10,15 +9,10 @@ var ChatPage = require('./pages/chat');
|
||||
module.exports = Backbone.Router.extend({
|
||||
routes: {
|
||||
'': 'main',
|
||||
'signin': 'signin',
|
||||
'chat/:jid': 'chat'
|
||||
'chat/:jid': 'chat',
|
||||
'logout': 'logout'
|
||||
},
|
||||
// ------- ROUTE HANDLERS ---------
|
||||
signin: function () {
|
||||
app.renderPage(new SigninPage({
|
||||
model: me
|
||||
}));
|
||||
},
|
||||
main: function () {
|
||||
app.renderPage(new MainPage({
|
||||
model: me
|
||||
@ -33,5 +27,9 @@ module.exports = Backbone.Router.extend({
|
||||
} else {
|
||||
app.navigate('/');
|
||||
}
|
||||
},
|
||||
logout: function () {
|
||||
localStorage.clear();
|
||||
window.location = '/login';
|
||||
}
|
||||
});
|
||||
|
@ -5,6 +5,7 @@ var AvatarStorage = require('./avatars');
|
||||
var RosterStorage = require('./roster');
|
||||
var DiscoStorage = require('./disco');
|
||||
var ArchiveStorage = require('./archive');
|
||||
var RosterVerStorage = require('./rosterver');
|
||||
|
||||
|
||||
function Storage() {
|
||||
@ -15,6 +16,7 @@ function Storage() {
|
||||
this.roster = new RosterStorage(this);
|
||||
this.disco = new DiscoStorage(this);
|
||||
this.archive = new ArchiveStorage(this);
|
||||
this.rosterver = new RosterVerStorage(this);
|
||||
}
|
||||
Storage.prototype = {
|
||||
constructor: {
|
||||
@ -36,6 +38,7 @@ Storage.prototype = {
|
||||
self.roster.setup(db);
|
||||
self.disco.setup(db);
|
||||
self.archive.setup(db);
|
||||
self.rosterver.setup(db);
|
||||
};
|
||||
request.onerror = cb;
|
||||
}
|
||||
|
63
clientapp/storage/rosterver.js
Normal file
63
clientapp/storage/rosterver.js
Normal file
@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
|
||||
// SCHEMA
|
||||
// jid: 'string',
|
||||
// ver: 'string'
|
||||
|
||||
|
||||
function RosterVerStorage(storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
RosterVerStorage.prototype = {
|
||||
constructor: {
|
||||
value: RosterVerStorage
|
||||
},
|
||||
setup: function (db) {
|
||||
db.createObjectStore('rosterver', {
|
||||
keyPath: 'jid'
|
||||
});
|
||||
},
|
||||
transaction: function (mode) {
|
||||
var trans = this.storage.db.transaction('rosterver', mode);
|
||||
return trans.objectStore('rosterver');
|
||||
},
|
||||
set: function (jid, ver, cb) {
|
||||
cb = cb || function () {};
|
||||
var data = {
|
||||
jid: jid,
|
||||
ver: ver
|
||||
};
|
||||
var request = this.transaction('readwrite').put(data);
|
||||
request.onsuccess = function () {
|
||||
cb(false, data);
|
||||
};
|
||||
request.onerror = cb;
|
||||
},
|
||||
get: function (jid, cb) {
|
||||
cb = cb || function () {};
|
||||
if (!jid) {
|
||||
return cb('not-found');
|
||||
}
|
||||
var request = this.transaction('readonly').get(jid);
|
||||
request.onsuccess = function (e) {
|
||||
var res = request.result;
|
||||
if (res === undefined) {
|
||||
return cb('not-found');
|
||||
}
|
||||
cb(false, request.result);
|
||||
};
|
||||
request.onerror = cb;
|
||||
},
|
||||
remove: function (jid, cb) {
|
||||
cb = cb || function () {};
|
||||
var request = this.transaction('readwrite')['delete'](id);
|
||||
request.onsuccess = function (e) {
|
||||
cb(false, request.result);
|
||||
};
|
||||
request.onerror = cb;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = RosterVerStorage;
|
@ -18,7 +18,6 @@ module.exports = HumanView.extend({
|
||||
return this;
|
||||
},
|
||||
handleLinkClick: function (e) {
|
||||
console.log(e);
|
||||
var t = $(e.target);
|
||||
var aEl = t.is('a') ? t[0] : t.closest('a')[0];
|
||||
var local = window.location.host === aEl.host;
|
||||
|
@ -2,7 +2,9 @@
|
||||
"isDev": true,
|
||||
"http": {
|
||||
"baseUrl": "https://localhost:8000",
|
||||
"port": 8000
|
||||
"port": 8000,
|
||||
"key": "./fakekeys/privatekey.pem",
|
||||
"cert": "./fakekeys/certificate.pem"
|
||||
},
|
||||
"session": {
|
||||
"secret": "shhhhhh don't tell anyone ok?"
|
||||
|
@ -18,8 +18,8 @@
|
||||
"node-uuid": "1.4.1",
|
||||
"semi-static": "0.0.4",
|
||||
"sound-effect-manager": "0.0.5",
|
||||
"human-model": "0.3.0",
|
||||
"human-view": "1.1.0",
|
||||
"human-model": "1.0.0",
|
||||
"human-view": "1.1.2",
|
||||
"templatizer": "0.1.2",
|
||||
"underscore": "1.5.1"
|
||||
},
|
||||
|
19
public/login.js
Normal file
19
public/login.js
Normal file
@ -0,0 +1,19 @@
|
||||
$('#loginbox form').on('submit', function (e) {
|
||||
var jid = $('#jid').val();
|
||||
var password = $('#password').val();
|
||||
var wsURL = $('#wsURL').val();
|
||||
|
||||
localStorage.config = JSON.stringify({
|
||||
jid: jid,
|
||||
server: jid.slice(jid.indexOf('@') + 1),
|
||||
wsURL: wsURL,
|
||||
credentials: {
|
||||
password: password
|
||||
}
|
||||
});
|
||||
|
||||
window.location = '/';
|
||||
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
4
public/logout.js
Normal file
4
public/logout.js
Normal file
@ -0,0 +1,4 @@
|
||||
$(function () {
|
||||
localStorage.clear();
|
||||
window.location = '/login';
|
||||
});
|
1565
public/zepto.js
Normal file
1565
public/zepto.js
Normal file
File diff suppressed because it is too large
Load Diff
15
server.js
15
server.js
@ -1,3 +1,5 @@
|
||||
var fs = require('fs');
|
||||
var https = require('https');
|
||||
var express = require('express');
|
||||
var helmet = require('helmet');
|
||||
var Moonboots = require('moonboots');
|
||||
@ -36,10 +38,21 @@ var clientApp = new Moonboots({
|
||||
}
|
||||
});
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.get('/login', function (req, res) {
|
||||
res.render('login');
|
||||
});
|
||||
app.get('/logout', function (req, res) {
|
||||
res.render('logout');
|
||||
});
|
||||
|
||||
// serves app on every other url
|
||||
app.get('*', clientApp.html());
|
||||
|
||||
|
||||
app.listen(config.http.port);
|
||||
https.createServer({
|
||||
key: fs.readFileSync(config.http.key),
|
||||
cert: fs.readFileSync(config.http.cert)
|
||||
}, app).listen(config.http.port);
|
||||
console.log('demo.stanza.io running at: ' + config.http.baseUrl);
|
||||
|
14
views/layout.jade
Normal file
14
views/layout.jade
Normal file
@ -0,0 +1,14 @@
|
||||
!!!5
|
||||
html
|
||||
head
|
||||
title OTalk
|
||||
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1, user-scalable=no")
|
||||
|
||||
link(rel="stylesheet", href="/styles.css")
|
||||
block head
|
||||
body
|
||||
block content
|
||||
|
||||
script(src='/zepto.js')
|
||||
block scripts
|
20
views/login.jade
Normal file
20
views/login.jade
Normal file
@ -0,0 +1,20 @@
|
||||
extends layout
|
||||
|
||||
block content
|
||||
section#loginbox.content
|
||||
h2 Log in
|
||||
form
|
||||
.fieldContainer
|
||||
label(for='username') JID
|
||||
input(type='text', id='jid', name='jid', placeholder='you@aweso.me', tabindex='1', autofocus)
|
||||
.fieldContainer
|
||||
label(for='password') Password
|
||||
input(type='password', id='password', name='password', placeholder='•••••••••••••', tabindex='2')
|
||||
.fieldContainer
|
||||
label(for='wsURL') WebSocket URL
|
||||
input(type='text', id='wsURL', name='wsURL', placeholder='wss://aweso.me:5281/xmpp-websocket', tabindex='3')
|
||||
|
||||
button(type='submit', tabindex='3') Go!
|
||||
|
||||
block scripts
|
||||
script(src="/login.js")
|
4
views/logout.jade
Normal file
4
views/logout.jade
Normal file
@ -0,0 +1,4 @@
|
||||
extends layout
|
||||
|
||||
block scripts
|
||||
script(src="/logout.js")
|
Loading…
Reference in New Issue
Block a user