mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
Pull in a bunch of changes from private branch, initial everyauth code
This commit is contained in:
@@ -27,30 +27,6 @@ get('/:uidParam?', function(page, model, _arg, next) {
|
|||||||
}
|
}
|
||||||
userId = model.get('_userId');
|
userId = model.get('_userId');
|
||||||
return model.subscribe("users." + userId, function(err, user) {
|
return model.subscribe("users." + userId, function(err, user) {
|
||||||
var guid, newUser, task, _i, _len, _ref1;
|
|
||||||
if (!user.get('id')) {
|
|
||||||
newUser = require('node.extend')(true, {}, schema.userSchema);
|
|
||||||
_ref1 = content.defaultTasks;
|
|
||||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
|
||||||
task = _ref1[_i];
|
|
||||||
guid = task.id = require('derby/node_modules/racer').uuid();
|
|
||||||
newUser.tasks[guid] = task;
|
|
||||||
switch (task.type) {
|
|
||||||
case 'habit':
|
|
||||||
newUser.habitIds.push(guid);
|
|
||||||
break;
|
|
||||||
case 'daily':
|
|
||||||
newUser.dailyIds.push(guid);
|
|
||||||
break;
|
|
||||||
case 'todo':
|
|
||||||
newUser.todoIds.push(guid);
|
|
||||||
break;
|
|
||||||
case 'reward':
|
|
||||||
newUser.rewardIds.push(guid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model.set("users." + userId, newUser);
|
|
||||||
}
|
|
||||||
model.ref('_user', user);
|
model.ref('_user', user);
|
||||||
model.set('_items', {
|
model.set('_items', {
|
||||||
armor: content.items.armor[parseInt(user.get('items.armor')) + 1],
|
armor: content.items.armor[parseInt(user.get('items.armor')) + 1],
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ module.exports.userSchema = userSchema = {
|
|||||||
items: {
|
items: {
|
||||||
itemsEnabled: false,
|
itemsEnabled: false,
|
||||||
armor: 0,
|
armor: 0,
|
||||||
weapon: 0
|
weapon: 0,
|
||||||
|
rerollsRemaining: 5
|
||||||
},
|
},
|
||||||
tasks: {},
|
tasks: {},
|
||||||
habitIds: [],
|
habitIds: [],
|
||||||
|
|||||||
125
lib/server/auth.js
Normal file
125
lib/server/auth.js
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
// Generated by CoffeeScript 1.3.3
|
||||||
|
var conf, derby, model, sess;
|
||||||
|
|
||||||
|
conf = require("./conf");
|
||||||
|
|
||||||
|
derby = require('derby');
|
||||||
|
|
||||||
|
model = void 0;
|
||||||
|
|
||||||
|
sess = void 0;
|
||||||
|
|
||||||
|
module.exports.setupPurlAuth = function(req) {
|
||||||
|
var acceptableUid, uidParam;
|
||||||
|
model = req.getModel();
|
||||||
|
sess = req.session;
|
||||||
|
sess.userId || (sess.userId = derby.uuid());
|
||||||
|
sess.auth || (sess.auth = {
|
||||||
|
userId: sess.userId
|
||||||
|
});
|
||||||
|
uidParam = req.url.split('/')[1];
|
||||||
|
acceptableUid = require('guid').isGuid(uidParam) || (uidParam === '3' || uidParam === '9');
|
||||||
|
if (acceptableUid && sess.userId !== uidParam) {
|
||||||
|
sess.userId = uidParam;
|
||||||
|
}
|
||||||
|
return model.set('_userId', sess.userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.setupEveryauth = function(everyauth) {
|
||||||
|
everyauth.debug = true;
|
||||||
|
everyauth.everymodule.findUserById(function(id, callback) {
|
||||||
|
return model.fetch("users." + id, function(err, user) {
|
||||||
|
var content, guid, newUser, schema, task, _i, _len, _ref;
|
||||||
|
if (user && user.get('id')) {
|
||||||
|
return callback(null, user.get());
|
||||||
|
} else {
|
||||||
|
schema = require('../app/schema');
|
||||||
|
content = require('../app/content');
|
||||||
|
newUser = require('node.extend')(true, {}, schema.userSchema);
|
||||||
|
_ref = content.defaultTasks;
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
task = _ref[_i];
|
||||||
|
guid = task.id = require('derby/node_modules/racer').uuid();
|
||||||
|
newUser.tasks[guid] = task;
|
||||||
|
switch (task.type) {
|
||||||
|
case 'habit':
|
||||||
|
newUser.habitIds.push(guid);
|
||||||
|
break;
|
||||||
|
case 'daily':
|
||||||
|
newUser.dailyIds.push(guid);
|
||||||
|
break;
|
||||||
|
case 'todo':
|
||||||
|
newUser.todoIds.push(guid);
|
||||||
|
break;
|
||||||
|
case 'reward':
|
||||||
|
newUser.rewardIds.push(guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.set("users." + id, newUser);
|
||||||
|
return callback(null, newUser);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return everyauth.facebook.appId(process.env.FACEBOOK_KEY).appSecret(process.env.FACEBOOK_SECRET).findOrCreateUser(function(session, accessToken, accessTokenExtra, fbUserMetadata) {
|
||||||
|
var q;
|
||||||
|
q = model.query('users').withEveryauth('facebook', fbUserMetadata.id);
|
||||||
|
model.fetch(q, function(err, user) {
|
||||||
|
console.log({
|
||||||
|
err: err,
|
||||||
|
user: user
|
||||||
|
});
|
||||||
|
if (user.get('id')) {
|
||||||
|
return sess.userId = user.get('id');
|
||||||
|
} else {
|
||||||
|
model.setNull("users." + sess.userId + ".auth", {
|
||||||
|
'facebook': {}
|
||||||
|
});
|
||||||
|
return model.set("users." + sess.userId + ".auth.facebook", fbUserMetadata);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fbUserMetadata;
|
||||||
|
}).redirectPath("/");
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.setupQueries = function(store) {
|
||||||
|
store.query.expose('users', 'withId', function(id) {
|
||||||
|
return this.byId(id);
|
||||||
|
});
|
||||||
|
store.query.expose('users', 'withEveryauth', function(provider, id) {
|
||||||
|
console.log({
|
||||||
|
withEveryauth: {
|
||||||
|
provider: provider,
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this.where("auth." + provider + ".id").equals(id);
|
||||||
|
});
|
||||||
|
return store.queryAccess('users', 'withEveryauth', function(methodArgs) {
|
||||||
|
var accept;
|
||||||
|
accept = arguments[arguments.length - 1];
|
||||||
|
return accept(true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.setupAccessControl = function(store) {
|
||||||
|
store.accessControl = true;
|
||||||
|
store.readPathAccess('users.*', function() {
|
||||||
|
var captures, next;
|
||||||
|
if (!(this.session && this.session.userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
captures = arguments[0];
|
||||||
|
next = arguments[arguments.length - 1];
|
||||||
|
return next(captures === this.session.userId);
|
||||||
|
});
|
||||||
|
return store.writeAccess('*', 'users.*', function() {
|
||||||
|
var captures, next, pathArray;
|
||||||
|
if (!(this.session && this.session.userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
captures = arguments[0];
|
||||||
|
next = arguments[arguments.length - 1];
|
||||||
|
pathArray = captures.split('.');
|
||||||
|
return next(pathArray[0] === this.session.userId);
|
||||||
|
});
|
||||||
|
};
|
||||||
121
lib/server/conf.js
Normal file
121
lib/server/conf.js
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// Generated by CoffeeScript 1.3.3
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fb: {
|
||||||
|
appId: "439694562721556",
|
||||||
|
appSecret: "d34327a67e32fe7936ababb72fa9639e"
|
||||||
|
},
|
||||||
|
twit: {
|
||||||
|
consumerKey: "JLCGyLzuOK1BjnKPKGyQ",
|
||||||
|
consumerSecret: "GNqKfPqtzOcsCtFbGTMqinoATHvBcy1nzCTimeA9M0"
|
||||||
|
},
|
||||||
|
github: {
|
||||||
|
appId: "11932f2b6d05d2a5fa18",
|
||||||
|
appSecret: "2603d1bc663b74d6732500c1e9ad05b0f4013593"
|
||||||
|
},
|
||||||
|
instagram: {
|
||||||
|
clientId: "be147b077ddf49368d6fb5cf3112b9e0",
|
||||||
|
clientSecret: "b65ad83daed242c0aa059ffae42feddd"
|
||||||
|
},
|
||||||
|
foursquare: {
|
||||||
|
clientId: "VUGE4VHJMKWALKDKIOH1HLD1OQNHTC0PBZZBUQSHJ3WKW04K",
|
||||||
|
clientSecret: "0LVAGARGUN05DEDDRVWNIMH4RFIHEFV0CERU3OITAZW1CXGX"
|
||||||
|
},
|
||||||
|
gowalla: {
|
||||||
|
apiKey: "11cf666912004d709fa4bbf21718a82e",
|
||||||
|
apiSecret: "e1e23f135776452898a6d268129bf153"
|
||||||
|
},
|
||||||
|
linkedin: {
|
||||||
|
apiKey: "pv6AWspODUeHIPNZfA531OYcFyB1v23u3y-KIADJdpyw54BXh-ciiQnduWf6FNRH",
|
||||||
|
apiSecret: "Pdx7DCoJRdAk0ai3joXsslZvK1DPCQwsLn-T17Opkae22ZYDP5R7gmAoFes9TNHy"
|
||||||
|
},
|
||||||
|
google: {
|
||||||
|
clientId: "3335216477.apps.googleusercontent.com",
|
||||||
|
clientSecret: "PJMW_uP39nogdu0WpBuqMhtB"
|
||||||
|
},
|
||||||
|
googlehybrid: {
|
||||||
|
consumerKey: "YOUR CONSUMER KEY HERE",
|
||||||
|
consumerSecret: "YOUR CONSUMER SECRET HERE"
|
||||||
|
},
|
||||||
|
_37signals: {
|
||||||
|
clientId: "cd4bf9cd9ed828b6bed8b67e6b314cf8b90c8de5",
|
||||||
|
clientSecret: "07883c36b4f4493b70f31872ed8fbdb099ff1cef"
|
||||||
|
},
|
||||||
|
angellist: {
|
||||||
|
clientId: "e5feda9308f55f16b0ef0e848f5b1e41",
|
||||||
|
clientSecret: "e0ec367efb9d59fa10bdd53ba268b81f"
|
||||||
|
},
|
||||||
|
yahoo: {
|
||||||
|
consumerKey: "dj0yJmk9RVExRlhPRE9rV1hSJmQ9WVdrOWEyRTBVMUJoTm1zbWNHbzlNVE13TURFeU9UTTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1iYg--",
|
||||||
|
consumerSecret: "efe6ae4982217630fe3aebf6e6fa1e82c02eba0b"
|
||||||
|
},
|
||||||
|
readability: {
|
||||||
|
consumerKey: "Alfrednerstu",
|
||||||
|
consumerSecret: "MXGftcxrRNMYn66CVmADR3KRnygCdYSk"
|
||||||
|
},
|
||||||
|
justintv: {
|
||||||
|
consumerKey: "enter your consumer key here",
|
||||||
|
consumerSecret: "enter your consumer secret here"
|
||||||
|
},
|
||||||
|
tumblr: {
|
||||||
|
consumerKey: "TAofjqRz9iKiAjtPMnXzHELIeQAw8cqKCZVXaEFSAxBrrvV99f",
|
||||||
|
consumerSecret: "s8ldFtirtsnWGSiBjwpUwMct8Yh4sliS9Uiocqsv3bw0ovMtlR"
|
||||||
|
},
|
||||||
|
dropbox: {
|
||||||
|
consumerKey: "uhfqnbely5stdtm",
|
||||||
|
consumerSecret: "jr7ofuwo32l7vkd"
|
||||||
|
},
|
||||||
|
vimeo: {
|
||||||
|
consumerKey: "Enter your consumer key here",
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
},
|
||||||
|
box: {
|
||||||
|
apiKey: "5hl66lbfy0quj8qhhzcn57dflb55y4rg"
|
||||||
|
},
|
||||||
|
dwolla: {
|
||||||
|
clientId: "Enter your consumer key here",
|
||||||
|
clientSecret: "Enter your consumer secret here"
|
||||||
|
},
|
||||||
|
vkontakte: {
|
||||||
|
appId: "Enter your app id here",
|
||||||
|
appSecret: "Enter your app secret here"
|
||||||
|
},
|
||||||
|
mailru: {
|
||||||
|
appId: "Enter your app id here",
|
||||||
|
appSecret: "Enter your app secret here"
|
||||||
|
},
|
||||||
|
skyrock: {
|
||||||
|
consumerKey: "a0ae943e20c5af88",
|
||||||
|
consumerSecret: "cjucy86r0fg4uxx3"
|
||||||
|
},
|
||||||
|
evernote: {
|
||||||
|
oauthHost: "https://www.evernote.com",
|
||||||
|
consumerKey: "Enter your consumer key here",
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
},
|
||||||
|
tripit: {
|
||||||
|
consumerKey: "a59bb58479f80e24dc6da1b1e61a107db743bc4c",
|
||||||
|
consumerSecret: "41dc4c0c39ac3ab162269a79f399eb180f753c66"
|
||||||
|
},
|
||||||
|
_500px: {
|
||||||
|
consumerKey: "Enter your consumer key here",
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
},
|
||||||
|
soundcloud: {
|
||||||
|
appId: "79dcfcb876e71dc18c1767b9ebe96298",
|
||||||
|
appSecret: "6f828028dab96838d07b2407cd5f80cd"
|
||||||
|
},
|
||||||
|
mixi: {
|
||||||
|
consumerKey: "Enter your consumer key here",
|
||||||
|
consumerSecret: "Enter your consumer secret here",
|
||||||
|
scope: "r_profile"
|
||||||
|
},
|
||||||
|
mailchimp: {
|
||||||
|
appId: "Enter your client/app id here",
|
||||||
|
appSecret: "Enter your client/app secret here"
|
||||||
|
},
|
||||||
|
mendeley: {
|
||||||
|
consumerKey: "Enter your consumer key here",
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Generated by CoffeeScript 1.3.3
|
// Generated by CoffeeScript 1.3.3
|
||||||
var MongoStore, ONE_YEAR, app, derby, express, expressApp, gzippo, habitrpgMiddleware, http, path, publicPath, racer, root, server, serverError, store;
|
var MongoStore, ONE_YEAR, app, auth, derby, everyauth, express, expressApp, gzippo, habitrpgMiddleware, http, path, publicPath, racer, root, server, serverError, store;
|
||||||
|
|
||||||
http = require('http');
|
http = require('http');
|
||||||
|
|
||||||
@@ -13,10 +13,14 @@ derby = require('derby');
|
|||||||
|
|
||||||
app = require('../app');
|
app = require('../app');
|
||||||
|
|
||||||
|
everyauth = require('everyauth');
|
||||||
|
|
||||||
serverError = require('./serverError');
|
serverError = require('./serverError');
|
||||||
|
|
||||||
MongoStore = require('connect-mongo')(express);
|
MongoStore = require('connect-mongo')(express);
|
||||||
|
|
||||||
|
auth = require('./auth');
|
||||||
|
|
||||||
racer = require('derby/node_modules/racer');
|
racer = require('derby/node_modules/racer');
|
||||||
|
|
||||||
racer.io.set('transports', ['xhr-polling']);
|
racer.io.set('transports', ['xhr-polling']);
|
||||||
@@ -42,6 +46,10 @@ store = derby.createStore({
|
|||||||
listen: server
|
listen: server
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auth.setupQueries(store);
|
||||||
|
|
||||||
|
auth.setupEveryauth(everyauth);
|
||||||
|
|
||||||
ONE_YEAR = 1000 * 60 * 60 * 24 * 365;
|
ONE_YEAR = 1000 * 60 * 60 * 24 * 365;
|
||||||
|
|
||||||
root = path.dirname(path.dirname(__dirname));
|
root = path.dirname(path.dirname(__dirname));
|
||||||
@@ -49,24 +57,19 @@ root = path.dirname(path.dirname(__dirname));
|
|||||||
publicPath = path.join(root, 'public');
|
publicPath = path.join(root, 'public');
|
||||||
|
|
||||||
habitrpgMiddleware = function(req, res, next) {
|
habitrpgMiddleware = function(req, res, next) {
|
||||||
var acceptableUid, model, uidParam, _base;
|
var model;
|
||||||
model = req.getModel();
|
model = req.getModel();
|
||||||
(_base = req.session).userId || (_base.userId = derby.uuid());
|
auth.setupPurlAuth(req);
|
||||||
uidParam = req.url.split('/')[1];
|
auth.setupAccessControl(store);
|
||||||
acceptableUid = require('guid').isGuid(uidParam) || (uidParam === '3' || uidParam === '9');
|
model.set('_stripePubKey', process.env.STRIPE_PUB_KEY);
|
||||||
if (acceptableUid && req.session.userId !== uidParam) {
|
|
||||||
req.session.userId = uidParam;
|
|
||||||
}
|
|
||||||
model.set('_userId', req.session.userId);
|
|
||||||
model.set('_mobileDevice', /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')));
|
|
||||||
model.set('_nodeEnv', process.env.NODE_ENV);
|
model.set('_nodeEnv', process.env.NODE_ENV);
|
||||||
require('./setupStore').accessControl(store);
|
model.set('_mobileDevice', /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')));
|
||||||
return next();
|
return next();
|
||||||
};
|
};
|
||||||
|
|
||||||
expressApp.use(express.favicon()).use(gzippo.staticGzip(publicPath, {
|
expressApp.use(express.favicon()).use(gzippo.staticGzip(publicPath, {
|
||||||
maxAge: ONE_YEAR
|
maxAge: ONE_YEAR
|
||||||
})).use(express.compress()).use(express.bodyParser()).use(express.cookieParser()).use(store.sessionMiddleware({
|
})).use(express.compress()).use(express.bodyParser()).use(express.methodOverride()).use(express.cookieParser()).use(store.sessionMiddleware({
|
||||||
secret: process.env.SESSION_SECRET || 'YOUR SECRET HERE',
|
secret: process.env.SESSION_SECRET || 'YOUR SECRET HERE',
|
||||||
cookie: {
|
cookie: {
|
||||||
maxAge: ONE_YEAR
|
maxAge: ONE_YEAR
|
||||||
@@ -74,26 +77,6 @@ expressApp.use(express.favicon()).use(gzippo.staticGzip(publicPath, {
|
|||||||
store: new MongoStore({
|
store: new MongoStore({
|
||||||
url: process.env.NODE_DB_URI
|
url: process.env.NODE_DB_URI
|
||||||
})
|
})
|
||||||
})).use(store.modelMiddleware()).use(habitrpgMiddleware).use(app.router()).use(expressApp.router).use(serverError(root));
|
})).use(store.modelMiddleware()).use(habitrpgMiddleware).use(everyauth.middleware()).use(app.router()).use(expressApp.router).use(serverError(root));
|
||||||
|
|
||||||
require('./api')(expressApp);
|
require('./serverRoutes')(expressApp);
|
||||||
|
|
||||||
expressApp.post('/', function(req) {
|
|
||||||
return require('../app/reroll').stripeResponse(req);
|
|
||||||
});
|
|
||||||
|
|
||||||
expressApp.get('/privacy', function(req, res) {
|
|
||||||
var staticPages;
|
|
||||||
staticPages = derby.createStatic(root);
|
|
||||||
return staticPages.render('privacy', res);
|
|
||||||
});
|
|
||||||
|
|
||||||
expressApp.get('/terms', function(req, res) {
|
|
||||||
var staticPages;
|
|
||||||
staticPages = derby.createStatic(root);
|
|
||||||
return staticPages.render('terms', res);
|
|
||||||
});
|
|
||||||
|
|
||||||
expressApp.all('*', function(req) {
|
|
||||||
throw "404: " + req.url;
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ module.exports = function(expressApp) {
|
|||||||
});
|
});
|
||||||
return res.send(200);
|
return res.send(200);
|
||||||
});
|
});
|
||||||
return expressApp.get('/:uid/down/:score?', function(req, res) {
|
expressApp.get('/:uid/down/:score?', function(req, res) {
|
||||||
var model, score;
|
var model, score;
|
||||||
score = parseInt(req.params.score) || 1;
|
score = parseInt(req.params.score) || 1;
|
||||||
console.log({
|
console.log({
|
||||||
@@ -40,4 +40,20 @@ module.exports = function(expressApp) {
|
|||||||
});
|
});
|
||||||
return res.send(200);
|
return res.send(200);
|
||||||
});
|
});
|
||||||
|
expressApp.get('/privacy', function(req, res) {
|
||||||
|
var staticPages;
|
||||||
|
staticPages = derby.createStatic(root);
|
||||||
|
return staticPages.render('privacy', res);
|
||||||
|
});
|
||||||
|
expressApp.get('/terms', function(req, res) {
|
||||||
|
var staticPages;
|
||||||
|
staticPages = derby.createStatic(root);
|
||||||
|
return staticPages.render('terms', res);
|
||||||
|
});
|
||||||
|
expressApp.all('*', function(req) {
|
||||||
|
throw "404: " + req.url;
|
||||||
|
});
|
||||||
|
return expressApp.post('/', function(req) {
|
||||||
|
return require('../app/reroll').stripeResponse(req);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// Generated by CoffeeScript 1.3.3
|
|
||||||
|
|
||||||
module.exports.queries = function(store) {
|
|
||||||
return store.query.expose('users', 'withId', function(id) {
|
|
||||||
return this.byId(id);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.accessControl = function(store) {
|
|
||||||
store.accessControl = true;
|
|
||||||
store.readPathAccess('users.*', function() {
|
|
||||||
var captures, next;
|
|
||||||
if (!(this.session && this.session.userId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
captures = arguments[0];
|
|
||||||
next = arguments[arguments.length - 1];
|
|
||||||
return next(captures === this.session.userId);
|
|
||||||
});
|
|
||||||
return store.writeAccess('*', 'users.*', function() {
|
|
||||||
var captures, next, pathArray;
|
|
||||||
if (!(this.session && this.session.userId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
captures = arguments[0];
|
|
||||||
next = arguments[arguments.length - 1];
|
|
||||||
pathArray = captures.split('.');
|
|
||||||
return next(pathArray[0] === this.session.userId);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
10
package.json
10
package.json
@@ -1,18 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "habitrpg",
|
"name": "habitrpg",
|
||||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||||
"version": "0.0.0-101",
|
"version": "0.0.0-106",
|
||||||
"main": "./server.js",
|
"main": "./server.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"derby": "0.3.13",
|
"derby": "0.3.13",
|
||||||
"racer-db-mongo": "0.3.13",
|
"racer-db-mongo": "0.3.13",
|
||||||
"express": "3.0.0beta4",
|
"express": "*",
|
||||||
"gzippo": ">=0.1.7",
|
"gzippo": "git://github.com/dbashford/gzippo.git",
|
||||||
"connect-mongo": ">=0.1.9",
|
"connect-mongo": ">=0.1.9",
|
||||||
|
"everyauth": "git://github.com/bnoguchi/everyauth#express3",
|
||||||
"derby-ui-boot": "*",
|
"derby-ui-boot": "*",
|
||||||
"guid": "*",
|
"guid": "*",
|
||||||
"node.extend": "*",
|
"node.extend": "*",
|
||||||
"moment": "*"
|
"moment": "*",
|
||||||
|
"stripe": "*"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -22,21 +22,6 @@ get '/:uidParam?', (page, model, {uidParam}, next) ->
|
|||||||
|
|
||||||
model.subscribe "users.#{userId}", (err, user) ->
|
model.subscribe "users.#{userId}", (err, user) ->
|
||||||
|
|
||||||
# Create new user if none exists
|
|
||||||
unless user.get('id')
|
|
||||||
# deep clone, else further new users get duplicate objects
|
|
||||||
newUser = require('node.extend')(true, {}, schema.userSchema)
|
|
||||||
for task in content.defaultTasks
|
|
||||||
guid = task.id = require('derby/node_modules/racer').uuid()
|
|
||||||
newUser.tasks[guid] = task
|
|
||||||
switch task.type
|
|
||||||
when 'habit' then newUser.habitIds.push guid
|
|
||||||
when 'daily' then newUser.dailyIds.push guid
|
|
||||||
when 'todo' then newUser.todoIds.push guid
|
|
||||||
when 'reward' then newUser.rewardIds.push guid
|
|
||||||
model.set "users.#{userId}", newUser
|
|
||||||
# /end create new user
|
|
||||||
|
|
||||||
model.ref '_user', user
|
model.ref '_user', user
|
||||||
|
|
||||||
# Store
|
# Store
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
module.exports.userSchema = userSchema = {
|
module.exports.userSchema = userSchema = {
|
||||||
stats: { money: 0, exp: 0, lvl: 1, hp: 50 }
|
stats: { money: 0, exp: 0, lvl: 1, hp: 50 }
|
||||||
items: { itemsEnabled: false, armor: 0, weapon: 0 }
|
items: { itemsEnabled: false, armor: 0, weapon: 0, rerollsRemaining: 5 }
|
||||||
tasks: {}
|
tasks: {}
|
||||||
habitIds: []
|
habitIds: []
|
||||||
dailyIds: []
|
dailyIds: []
|
||||||
|
|||||||
116
src/server/auth.coffee
Normal file
116
src/server/auth.coffee
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
conf = require("./conf")
|
||||||
|
derby = require('derby')
|
||||||
|
|
||||||
|
# FIXME I need access to model in everyauth, so that I can test whether a user exists in the database or
|
||||||
|
# create a new one otherwise. Everyauth configs must be declared before expressApp.use(...); howeve,r model is
|
||||||
|
# setup during expresApp.use(...). So my hack is - declare model here, define everyauth configs early in the server (like
|
||||||
|
# we should), then use our own middleware (habitrpgMiddleware) to model during expresApp.use(...)
|
||||||
|
model = undefined
|
||||||
|
sess = undefined
|
||||||
|
|
||||||
|
# Ultimate goal: set `sess.auth.userId`
|
||||||
|
|
||||||
|
## PURL authentication
|
||||||
|
# This is temporary and will go away when everyauth is setup. It tests to see if
|
||||||
|
# a UUID was used (bookmarked private url), and restores the user session if so
|
||||||
|
module.exports.setupPurlAuth = (req) ->
|
||||||
|
model = req.getModel()
|
||||||
|
sess = req.session
|
||||||
|
|
||||||
|
# Setup userId for new users
|
||||||
|
sess.userId ||= derby.uuid()
|
||||||
|
sess.auth ||= {userId: sess.userId} # prepare for everyauth
|
||||||
|
# Previously saved session (eg, http://localhost/{guid}) (temporary solution until authentication built)
|
||||||
|
uidParam = req.url.split('/')[1]
|
||||||
|
acceptableUid = require('guid').isGuid(uidParam) or (uidParam in ['3','9'])
|
||||||
|
if acceptableUid && sess.userId!=uidParam
|
||||||
|
# TODO test whether user exists: ```model.fetch("users.#{uidParam}", function(err,user){if(user.get(..){})}})```, but doesn't seem to work
|
||||||
|
sess.userId = uidParam
|
||||||
|
model.set '_userId', sess.userId
|
||||||
|
|
||||||
|
## Setup callbacks for serializing/deserializing users to/from model.
|
||||||
|
module.exports.setupEveryauth = (everyauth) ->
|
||||||
|
|
||||||
|
everyauth.debug = true
|
||||||
|
|
||||||
|
everyauth.everymodule.findUserById (id, callback) ->
|
||||||
|
model.fetch "users.#{id}", (err, user) ->
|
||||||
|
if user && user.get('id')
|
||||||
|
callback null, user.get() # FIXME what format are we supposed to return user?
|
||||||
|
else
|
||||||
|
# Create new user if none exists
|
||||||
|
# deep clone, else further new users get duplicate objects
|
||||||
|
schema = require('../app/schema')
|
||||||
|
content = require('../app/content')
|
||||||
|
newUser = require('node.extend')(true, {}, schema.userSchema)
|
||||||
|
for task in content.defaultTasks
|
||||||
|
guid = task.id = require('derby/node_modules/racer').uuid()
|
||||||
|
newUser.tasks[guid] = task
|
||||||
|
switch task.type
|
||||||
|
when 'habit' then newUser.habitIds.push guid
|
||||||
|
when 'daily' then newUser.dailyIds.push guid
|
||||||
|
when 'todo' then newUser.todoIds.push guid
|
||||||
|
when 'reward' then newUser.rewardIds.push guid
|
||||||
|
model.set "users.#{id}", newUser
|
||||||
|
callback null, newUser
|
||||||
|
|
||||||
|
# Facebook Authentication Logic
|
||||||
|
everyauth
|
||||||
|
.facebook
|
||||||
|
.appId(process.env.FACEBOOK_KEY)
|
||||||
|
.appSecret(process.env.FACEBOOK_SECRET)
|
||||||
|
.findOrCreateUser( (session, accessToken, accessTokenExtra, fbUserMetadata) ->
|
||||||
|
# usersByFbId[fbUserMetadata.id] or (usersByFbId[fbUserMetadata.id] = addUser("facebook", fbUserMetadata))
|
||||||
|
q = model.query('users').withEveryauth('facebook', fbUserMetadata.id)
|
||||||
|
model.fetch q, (err,user) ->
|
||||||
|
console.log {err:err,user:user} #FIXME this is always returning user:null, however; this runs fine on the client
|
||||||
|
if user.get('id')
|
||||||
|
sess.userId = user.get('id') # is necessary?
|
||||||
|
else
|
||||||
|
model.setNull "users.#{sess.userId}.auth", {'facebook':{}}
|
||||||
|
model.set "users.#{sess.userId}.auth.facebook", fbUserMetadata
|
||||||
|
fbUserMetadata
|
||||||
|
).redirectPath "/"
|
||||||
|
|
||||||
|
# addUser = (source, sourceUser) ->
|
||||||
|
# user = undefined
|
||||||
|
# if arguments.length is 1 # password-based
|
||||||
|
# user = sourceUser = source
|
||||||
|
# user.id = ++nextUserId
|
||||||
|
# return usersById[nextUserId] = user
|
||||||
|
# else # non-password-based
|
||||||
|
# user = usersById[++nextUserId] = id: nextUserId
|
||||||
|
# user[source] = sourceUser
|
||||||
|
# user
|
||||||
|
|
||||||
|
module.exports.setupQueries = (store) ->
|
||||||
|
## Setup Queries
|
||||||
|
store.query.expose 'users', 'withId', (id) ->
|
||||||
|
@byId(id)
|
||||||
|
store.query.expose 'users', 'withEveryauth', (provider, id) ->
|
||||||
|
console.log {withEveryauth:{provider:provider,id:id}}
|
||||||
|
@where("auth.#{provider}.id").equals(id)
|
||||||
|
store.queryAccess 'users', 'withEveryauth', (methodArgs) ->
|
||||||
|
accept = arguments[arguments.length-1]
|
||||||
|
accept(true) #for now
|
||||||
|
|
||||||
|
module.exports.setupAccessControl = (store) ->
|
||||||
|
store.accessControl = true
|
||||||
|
|
||||||
|
# Callback signatures here have variable length, eg `callback(captures..., next)`
|
||||||
|
# Is using arguments[n] the correct way to handle this?
|
||||||
|
|
||||||
|
store.readPathAccess 'users.*', () -> #captures, next) ->
|
||||||
|
return unless @session && @session.userId # https://github.com/codeparty/racer/issues/37
|
||||||
|
captures = arguments[0]
|
||||||
|
next = arguments[arguments.length-1]
|
||||||
|
# console.log { readPathAccess: {captures:captures, sessionUserId:@session.userId, next:next} }
|
||||||
|
next(captures == @session.userId)
|
||||||
|
|
||||||
|
store.writeAccess '*', 'users.*', () -> #captures, value, next) ->
|
||||||
|
return unless @session && @session.userId
|
||||||
|
captures = arguments[0]
|
||||||
|
next = arguments[arguments.length-1]
|
||||||
|
pathArray = captures.split('.')
|
||||||
|
# console.log { writeAccess: {captures:captures, next:next, pathArray:pathArray, arguments:arguments} }
|
||||||
|
next(pathArray[0] == @session.userId)
|
||||||
117
src/server/conf.coffee
Normal file
117
src/server/conf.coffee
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
module.exports =
|
||||||
|
fb:
|
||||||
|
appId: "439694562721556"
|
||||||
|
appSecret: "d34327a67e32fe7936ababb72fa9639e"
|
||||||
|
|
||||||
|
twit:
|
||||||
|
consumerKey: "JLCGyLzuOK1BjnKPKGyQ"
|
||||||
|
consumerSecret: "GNqKfPqtzOcsCtFbGTMqinoATHvBcy1nzCTimeA9M0"
|
||||||
|
|
||||||
|
github:
|
||||||
|
appId: "11932f2b6d05d2a5fa18"
|
||||||
|
appSecret: "2603d1bc663b74d6732500c1e9ad05b0f4013593"
|
||||||
|
|
||||||
|
instagram:
|
||||||
|
clientId: "be147b077ddf49368d6fb5cf3112b9e0"
|
||||||
|
clientSecret: "b65ad83daed242c0aa059ffae42feddd"
|
||||||
|
|
||||||
|
foursquare:
|
||||||
|
clientId: "VUGE4VHJMKWALKDKIOH1HLD1OQNHTC0PBZZBUQSHJ3WKW04K"
|
||||||
|
clientSecret: "0LVAGARGUN05DEDDRVWNIMH4RFIHEFV0CERU3OITAZW1CXGX"
|
||||||
|
|
||||||
|
gowalla:
|
||||||
|
apiKey: "11cf666912004d709fa4bbf21718a82e"
|
||||||
|
apiSecret: "e1e23f135776452898a6d268129bf153"
|
||||||
|
|
||||||
|
linkedin:
|
||||||
|
apiKey: "pv6AWspODUeHIPNZfA531OYcFyB1v23u3y-KIADJdpyw54BXh-ciiQnduWf6FNRH"
|
||||||
|
apiSecret: "Pdx7DCoJRdAk0ai3joXsslZvK1DPCQwsLn-T17Opkae22ZYDP5R7gmAoFes9TNHy"
|
||||||
|
|
||||||
|
google:
|
||||||
|
clientId: "3335216477.apps.googleusercontent.com"
|
||||||
|
clientSecret: "PJMW_uP39nogdu0WpBuqMhtB"
|
||||||
|
|
||||||
|
googlehybrid:
|
||||||
|
consumerKey: "YOUR CONSUMER KEY HERE"
|
||||||
|
consumerSecret: "YOUR CONSUMER SECRET HERE"
|
||||||
|
|
||||||
|
_37signals:
|
||||||
|
clientId: "cd4bf9cd9ed828b6bed8b67e6b314cf8b90c8de5"
|
||||||
|
clientSecret: "07883c36b4f4493b70f31872ed8fbdb099ff1cef"
|
||||||
|
|
||||||
|
angellist:
|
||||||
|
clientId: "e5feda9308f55f16b0ef0e848f5b1e41"
|
||||||
|
clientSecret: "e0ec367efb9d59fa10bdd53ba268b81f"
|
||||||
|
|
||||||
|
yahoo:
|
||||||
|
consumerKey: "dj0yJmk9RVExRlhPRE9rV1hSJmQ9WVdrOWEyRTBVMUJoTm1zbWNHbzlNVE13TURFeU9UTTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1iYg--"
|
||||||
|
consumerSecret: "efe6ae4982217630fe3aebf6e6fa1e82c02eba0b"
|
||||||
|
|
||||||
|
readability:
|
||||||
|
consumerKey: "Alfrednerstu"
|
||||||
|
consumerSecret: "MXGftcxrRNMYn66CVmADR3KRnygCdYSk"
|
||||||
|
|
||||||
|
justintv:
|
||||||
|
consumerKey: "enter your consumer key here"
|
||||||
|
consumerSecret: "enter your consumer secret here"
|
||||||
|
|
||||||
|
tumblr:
|
||||||
|
consumerKey: "TAofjqRz9iKiAjtPMnXzHELIeQAw8cqKCZVXaEFSAxBrrvV99f"
|
||||||
|
consumerSecret: "s8ldFtirtsnWGSiBjwpUwMct8Yh4sliS9Uiocqsv3bw0ovMtlR"
|
||||||
|
|
||||||
|
dropbox:
|
||||||
|
consumerKey: "uhfqnbely5stdtm"
|
||||||
|
consumerSecret: "jr7ofuwo32l7vkd"
|
||||||
|
|
||||||
|
vimeo:
|
||||||
|
consumerKey: "Enter your consumer key here"
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
|
||||||
|
box:
|
||||||
|
apiKey: "5hl66lbfy0quj8qhhzcn57dflb55y4rg"
|
||||||
|
|
||||||
|
dwolla:
|
||||||
|
clientId: "Enter your consumer key here"
|
||||||
|
clientSecret: "Enter your consumer secret here"
|
||||||
|
|
||||||
|
vkontakte:
|
||||||
|
appId: "Enter your app id here"
|
||||||
|
appSecret: "Enter your app secret here"
|
||||||
|
|
||||||
|
mailru:
|
||||||
|
appId: "Enter your app id here"
|
||||||
|
appSecret: "Enter your app secret here"
|
||||||
|
|
||||||
|
skyrock:
|
||||||
|
consumerKey: "a0ae943e20c5af88"
|
||||||
|
consumerSecret: "cjucy86r0fg4uxx3"
|
||||||
|
|
||||||
|
evernote:
|
||||||
|
oauthHost: "https://www.evernote.com"
|
||||||
|
consumerKey: "Enter your consumer key here"
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
|
||||||
|
tripit:
|
||||||
|
consumerKey: "a59bb58479f80e24dc6da1b1e61a107db743bc4c"
|
||||||
|
consumerSecret: "41dc4c0c39ac3ab162269a79f399eb180f753c66"
|
||||||
|
|
||||||
|
_500px:
|
||||||
|
consumerKey: "Enter your consumer key here"
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
|
||||||
|
soundcloud:
|
||||||
|
appId: "79dcfcb876e71dc18c1767b9ebe96298"
|
||||||
|
appSecret: "6f828028dab96838d07b2407cd5f80cd"
|
||||||
|
|
||||||
|
mixi:
|
||||||
|
consumerKey: "Enter your consumer key here"
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
|
scope: "r_profile"
|
||||||
|
|
||||||
|
mailchimp:
|
||||||
|
appId: "Enter your client/app id here"
|
||||||
|
appSecret: "Enter your client/app secret here"
|
||||||
|
|
||||||
|
mendeley:
|
||||||
|
consumerKey: "Enter your consumer key here"
|
||||||
|
consumerSecret: "Enter your consumer secret here"
|
||||||
@@ -4,8 +4,10 @@ express = require 'express'
|
|||||||
gzippo = require 'gzippo'
|
gzippo = require 'gzippo'
|
||||||
derby = require 'derby'
|
derby = require 'derby'
|
||||||
app = require '../app'
|
app = require '../app'
|
||||||
|
everyauth = require('everyauth')
|
||||||
serverError = require './serverError'
|
serverError = require './serverError'
|
||||||
MongoStore = require('connect-mongo')(express)
|
MongoStore = require('connect-mongo')(express)
|
||||||
|
auth = require('./auth')
|
||||||
|
|
||||||
## RACER CONFIGURATION ##
|
## RACER CONFIGURATION ##
|
||||||
|
|
||||||
@@ -25,6 +27,8 @@ derby.use(require 'racer-db-mongo')
|
|||||||
store = derby.createStore
|
store = derby.createStore
|
||||||
db: {type: 'Mongo', uri: process.env.NODE_DB_URI}
|
db: {type: 'Mongo', uri: process.env.NODE_DB_URI}
|
||||||
listen: server
|
listen: server
|
||||||
|
auth.setupQueries(store)
|
||||||
|
auth.setupEveryauth(everyauth)
|
||||||
|
|
||||||
ONE_YEAR = 1000 * 60 * 60 * 24 * 365
|
ONE_YEAR = 1000 * 60 * 60 * 24 * 365
|
||||||
root = path.dirname path.dirname __dirname
|
root = path.dirname path.dirname __dirname
|
||||||
@@ -33,26 +37,15 @@ publicPath = path.join root, 'public'
|
|||||||
habitrpgMiddleware = (req, res, next) ->
|
habitrpgMiddleware = (req, res, next) ->
|
||||||
model = req.getModel()
|
model = req.getModel()
|
||||||
|
|
||||||
## PURL authentication
|
auth.setupPurlAuth(req)
|
||||||
# Setup userId for new users
|
auth.setupAccessControl(store)
|
||||||
req.session.userId ||= derby.uuid()
|
|
||||||
# Previously saved session (eg, http://localhost/{guid}) (temporary solution until authentication built)
|
model.set '_stripePubKey', process.env.STRIPE_PUB_KEY
|
||||||
uidParam = req.url.split('/')[1]
|
model.set '_nodeEnv', process.env.NODE_ENV
|
||||||
acceptableUid = require('guid').isGuid(uidParam) or (uidParam in ['3','9'])
|
|
||||||
if acceptableUid && req.session.userId!=uidParam
|
|
||||||
# TODO test whether user exists: ```model.fetch("users.#{uidParam}", function(err,user){if(user.get(..){})}})```, but doesn't seem to work
|
|
||||||
req.session.userId = uidParam
|
|
||||||
model.set '_userId', req.session.userId
|
|
||||||
|
|
||||||
## Set _mobileDevice to true or false so view can exclude portions from mobile device
|
## Set _mobileDevice to true or false so view can exclude portions from mobile device
|
||||||
model.set '_mobileDevice', /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header 'User-Agent')
|
model.set '_mobileDevice', /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header 'User-Agent')
|
||||||
|
|
||||||
## Same for production/development
|
|
||||||
model.set '_nodeEnv', process.env.NODE_ENV
|
|
||||||
|
|
||||||
## Setup access control
|
|
||||||
require('./setupStore').accessControl(store)
|
|
||||||
|
|
||||||
next()
|
next()
|
||||||
|
|
||||||
expressApp
|
expressApp
|
||||||
@@ -64,7 +57,7 @@ expressApp
|
|||||||
|
|
||||||
# Uncomment to add form data parsing support
|
# Uncomment to add form data parsing support
|
||||||
.use(express.bodyParser())
|
.use(express.bodyParser())
|
||||||
# .use(express.methodOverride())
|
.use(express.methodOverride())
|
||||||
|
|
||||||
# Uncomment and supply secret to add Derby session handling
|
# Uncomment and supply secret to add Derby session handling
|
||||||
# Derby session middleware creates req.session and socket.io sessions
|
# Derby session middleware creates req.session and socket.io sessions
|
||||||
@@ -80,26 +73,10 @@ expressApp
|
|||||||
# Middelware can be inserted after the modelMiddleware and before
|
# Middelware can be inserted after the modelMiddleware and before
|
||||||
# the app router to pass server accessible data to a model
|
# the app router to pass server accessible data to a model
|
||||||
.use(habitrpgMiddleware)
|
.use(habitrpgMiddleware)
|
||||||
|
.use(everyauth.middleware())
|
||||||
# Creates an express middleware from the app's routes
|
# Creates an express middleware from the app's routes
|
||||||
.use(app.router())
|
.use(app.router())
|
||||||
.use(expressApp.router)
|
.use(expressApp.router)
|
||||||
.use(serverError root)
|
.use(serverError root)
|
||||||
|
|
||||||
## SERVER ONLY ROUTES ##
|
require('./serverRoutes')(expressApp)
|
||||||
|
|
||||||
require('./api')(expressApp)
|
|
||||||
|
|
||||||
expressApp.post '/', (req) ->
|
|
||||||
require('../app/reroll').stripeResponse(req)
|
|
||||||
|
|
||||||
expressApp.get '/privacy', (req, res) ->
|
|
||||||
staticPages = derby.createStatic root
|
|
||||||
staticPages.render 'privacy', res
|
|
||||||
|
|
||||||
expressApp.get '/terms', (req, res) ->
|
|
||||||
staticPages = derby.createStatic root
|
|
||||||
staticPages.render 'terms', res
|
|
||||||
|
|
||||||
expressApp.all '*', (req) ->
|
|
||||||
throw "404: #{req.url}"
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
scoring = require('../app/scoring')
|
scoring = require('../app/scoring')
|
||||||
|
|
||||||
module.exports = (expressApp) ->
|
module.exports = (expressApp) ->
|
||||||
|
|
||||||
expressApp.get '/:uid/up/:score?', (req, res) ->
|
expressApp.get '/:uid/up/:score?', (req, res) ->
|
||||||
score = parseInt(req.params.score) || 1
|
score = parseInt(req.params.score) || 1
|
||||||
console.log {score:score}
|
console.log {score:score}
|
||||||
@@ -18,3 +19,17 @@ module.exports = (expressApp) ->
|
|||||||
return if err || !user.get()
|
return if err || !user.get()
|
||||||
scoring.score({user:user, direction:'down'})
|
scoring.score({user:user, direction:'down'})
|
||||||
res.send(200)
|
res.send(200)
|
||||||
|
|
||||||
|
expressApp.get '/privacy', (req, res) ->
|
||||||
|
staticPages = derby.createStatic root
|
||||||
|
staticPages.render 'privacy', res
|
||||||
|
|
||||||
|
expressApp.get '/terms', (req, res) ->
|
||||||
|
staticPages = derby.createStatic root
|
||||||
|
staticPages.render 'terms', res
|
||||||
|
|
||||||
|
expressApp.all '*', (req) ->
|
||||||
|
throw "404: #{req.url}"
|
||||||
|
|
||||||
|
expressApp.post '/', (req) ->
|
||||||
|
require('../app/reroll').stripeResponse(req)
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
module.exports.queries = (store) ->
|
|
||||||
store.query.expose 'users', 'withId', (id) ->
|
|
||||||
@byId(id)
|
|
||||||
|
|
||||||
module.exports.accessControl = (store) ->
|
|
||||||
store.accessControl = true
|
|
||||||
|
|
||||||
# FIXME callback signatures here have variable length, eg `callback(captures..., next)`
|
|
||||||
# Is using arguments[n] the correct way to handle this?
|
|
||||||
|
|
||||||
store.readPathAccess 'users.*', () -> #captures, next) ->
|
|
||||||
return unless @session && @session.userId # https://github.com/codeparty/racer/issues/37
|
|
||||||
captures = arguments[0]
|
|
||||||
next = arguments[arguments.length-1]
|
|
||||||
# console.log { readPathAccess: {captures:captures, sessionUserId:@session.userId, next:next} }
|
|
||||||
next(captures == @session.userId)
|
|
||||||
|
|
||||||
store.writeAccess '*', 'users.*', () -> #captures, value, next) ->
|
|
||||||
return unless @session && @session.userId
|
|
||||||
captures = arguments[0]
|
|
||||||
next = arguments[arguments.length-1]
|
|
||||||
pathArray = captures.split('.')
|
|
||||||
# console.log { writeAccess: {captures:captures, next:next, pathArray:pathArray, arguments:arguments} }
|
|
||||||
next(pathArray[0] == @session.userId)
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<ui:connectionAlert>
|
<ui:connectionAlert>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<div class='pulle-right'>
|
<div class='pull-right'>
|
||||||
<a class='btn btn-small pull-right' onClick="$('#copy-link-section').toggle();"><i class=icon-bookmark></i></a><br/>
|
<a class='btn btn-small pull-right' onClick="$('#copy-link-section').toggle();"><i class=icon-bookmark></i></a><br/>
|
||||||
<div id=copy-link-section style='display:none;' class=well>
|
<div id=copy-link-section style='display:none;' class=well>
|
||||||
<h3>Secret Link</h3>
|
<h3>Secret Link</h3>
|
||||||
|
|||||||
Reference in New Issue
Block a user