diff --git a/src/app/index.coffee b/src/app/index.coffee index dd5a25a80b..6276f8ff01 100644 --- a/src/app/index.coffee +++ b/src/app/index.coffee @@ -10,8 +10,8 @@ content = require './content' scoring = require './scoring' schema = require './schema' helpers = require './helpers' -helpers.viewHelpers view browser = require './browser' +helpers.viewHelpers view _ = require('underscore') setupListReferences = (model) -> @@ -65,9 +65,9 @@ get '/', (page, model, next) -> setupModelFns(model) # Subscribe to friends - if !_.isEmpty(obj.party) - model.subscribe model.query('users').party(obj.party), (err, party) -> - model.ref '_party', party +# if obj.party?.current? +# model.subscribe model.query('users').party(obj.party), (err, party) -> +# model.ref '_party', party page.render() @@ -96,6 +96,8 @@ ready (model) -> browser.setupTour(model) browser.setupGrowlNotifications(model) unless model.get('_view.mobileDevice') + require('./party')(exports, model) + require('../server/private').app(exports, model) user.on 'set', 'tasks.*.completed', (i, completed, previous, isLocal, passed) -> @@ -282,34 +284,16 @@ ready (model) -> batch.commit() resetDom(model) - exports.closeKickstarterNofitication = (e, el) -> - user.set('flags.kickstarter', 'hide') + exports.closeKickstarterNofitication = (e, el) -> user.set('flags.kickstarter', 'hide') exports.setMale = -> user.set('preferences.gender', 'm') exports.setFemale = -> user.set('preferences.gender', 'f') exports.setArmorsetV1 = -> user.set('preferences.armorSet', 'v1') exports.setArmorsetV2 = -> user.set('preferences.armorSet', 'v2') - exports.addParty = -> - id = model.get('_newPartyMember').replace(/[\s"]/g, '') - debugger - return if _.isEmpty(id) - if user.get('party').indexOf(id) != -1 - model.set "_view.addPartyError", "#{id} already in party." - return - query = model.query('users').party([id]) - model.fetch query, (err, users) -> - partyMember = users.at(0).get() - if partyMember?.id? - user.push('party', id) - $('#add-party-modal').modal('hide') - window.location.reload() #TODO break old subscription, setup new subscript, remove this reload - model.set '_newPartyMember', '' - else - model.set "_view.addPartyError", "User with id #{id} not found." - exports.emulateNextDay = -> yesterday = +moment().subtract('days', 1).toDate() user.set 'lastCron', yesterday window.location.reload() + diff --git a/src/app/party.coffee b/src/app/party.coffee new file mode 100644 index 0000000000..7beba07e1b --- /dev/null +++ b/src/app/party.coffee @@ -0,0 +1,55 @@ +_ = require('underscore') + +module.exports = (appExports, model) -> + user = model.at('_user') + + appExports.partyCreate = -> + newParty = model.get("_newParty") + id = model.add 'parties', { name: newParty, leader: user.get('id'), members: [], invites: [] } + user.set 'party', {current: id, invitation: null, leader: true} + + appExports.partyInvite = -> + id = model.get('_newPartyMember').replace(/[\s"]/g, '') + return if _.isEmpty(id) + + obj = user.get() + query = model.query('users').party([id]) + model.fetch query, (err, users) -> + partyMember = users.at(0).get() + if !partyMember?.id? + model.set "_view.partyError", "User with id #{id} not found." + return + else if partyMember.party.current?.id? or partyMember.party.invitation? + model.set "_view.partyError", "User already in a party or pending invitation." + return + else + model.push "parties.#{obj.party.current}.invites", id + model.set "users.#{id}.party.invitation", obj.party.current + $.bootstrapGrowl "Invitation Sent." + $('#party-modal').modal('hide') + #model.set '_newPartyMember', '' + #window.location.reload() #TODO break old subscription, setup new subscript, remove this reload + + appExports.partyAccept = -> + invitation = user.get('party.invitation') + user.set 'party.current', invitation + user.set 'party.invitation', null + model.push "parties.#{invitation}.members", user.get('id') + window.location.reload() + + appExports.partyReject = -> + user.set 'party.invitation', null + # TODO notify sender + + appExports.partyLeave = -> + id = user.get('party.current') + user.set 'party.current', null + members = model.get ("parties.#{id}.members") + index = members.indexOf(user.get('id')) + model.set "parties.#{id}.members", members.slice(index) + window.location.reload() + + appExports.partyDisband = -> + + + user.on 'set', 'parties.invitation', (after, before) -> diff --git a/src/server/index.coffee b/src/server/index.coffee index e7a4e5de14..1afc7864b6 100644 --- a/src/server/index.coffee +++ b/src/server/index.coffee @@ -8,6 +8,7 @@ serverError = require './serverError' MongoStore = require('connect-mongo')(express) auth = require 'derby-auth' priv = require './private' +habitrpgStore = require('./store') ## Run server cron ## require('./cron').deleteStaleAccounts() @@ -31,7 +32,6 @@ derby.use(require 'racer-db-mongo') store = derby.createStore db: {type: 'Mongo', uri: process.env.NODE_DB_URI, safe:true} listen: server -require('./store')(store) #setup custom accessControl ONE_YEAR = 1000 * 60 * 60 * 24 * 365 root = path.dirname path.dirname __dirname @@ -48,6 +48,7 @@ options = domain: process.env.BASE_URL || 'http://localhost:3000' allowPurl: true schema: require('../app/schema').newUserObject() + customAccessControl: habitrpgStore.customAccessControl mongo_store = new MongoStore {url: process.env.NODE_DB_URI}, -> expressApp diff --git a/src/server/store.coffee b/src/server/store.coffee index d071a2a37e..e36aaa3442 100644 --- a/src/server/store.coffee +++ b/src/server/store.coffee @@ -2,7 +2,41 @@ Setup read / write access @param store ### -module.exports = (store) -> + +module.exports.customAccessControl = (store) -> + +# store.readPathAccess "users.*", () -> # captures, next +# next = arguments[arguments.length-1] +# return unless @session and @session.userId # https://github.com/codeparty/racer/issues/37 +# return next(true) + + store.readPathAccess "users.*", -> # captures, next) -> + return unless @session and @session.userId # https://github.com/codeparty/racer/issues/37 + console.log arguments + captures = arguments[0] + next = arguments[arguments.length - 1] + sameSession = captures is @session.userId + isServer = false #!this.req.socket; //TODO how to determine if request came from server, as in REST? + next sameSession or isServer + + store.writeAccess "*", "users.*", -> # captures, value, next) -> + return unless @session and @session.userId # https://github.com/codeparty/racer/issues/37 + [captures, next] = [arguments[0].split('.'), arguments[arguments.length-1]] + uid = captures.shift() + attrPath = captures.join('.') # new array shifted left, after shift() was run + + # TODO the server can write to anything - aka, REST + #return next(true) if !this.req.socket; + + # public access to users.*.party.invitation (TODO, lock down a bit more) + console.log attrPath + return next(true) if (attrPath == 'party.invitation') + + # Same session (user.id = this.session.userId) + return next(true) if uid is @session.userId + + next(false) + # store.writeAccess "*", "users.*.balance", (id, newBalance, next) -> # return unless @session and @session.userId # https://github.com/codeparty/racer/issues/37 @@ -34,7 +68,19 @@ module.exports = (store) -> ### store.query.expose "users", "party", (ids) -> @where("id").within(ids) - .only('stats', 'preferences.gender', 'preferences.armorSet', 'items', 'auth.local.username', 'auth.facebook.displayName') + .only('stats', + 'items', + 'party', + 'preferences.gender', + 'preferences.armorSet', + 'auth.local.username', + 'auth.facebook.displayName') store.queryAccess "users", "party", (ids, next) -> next(true) # no harm in public user stats + + store.readPathAccess "parties.*", -> + arguments[arguments.length-1](true) + + store.writeAccess "*", "parties.*", -> + arguments[arguments.length-1](true) diff --git a/views/app/index.html b/views/app/index.html index e6539cf291..53a9113506 100644 --- a/views/app/index.html +++ b/views/app/index.html @@ -40,6 +40,9 @@ {/} +
+ Reset + <@footer> @@ -108,14 +111,47 @@ - -
- {#if _view.addPartyError} -
{_view.addPartyError}
+ +

+ {#if _user.party.current}Invite Member To "{_user.party.current}" + {else if _user.party.invitation}You're Invited To A Party + {else}Create A Party{/} +

+ + {#if _user.party.current} + + {#each _party as :member} + {:member.id} + {/} + + {#if _view.partyError} +
{_view.partyError}
{/} - + + Leave + + {else} + + + {#if _user.party.invitation} + + Accept + Reject + {else} + +
+ {#if _view.partyError} +
{_view.partyError}
+ {/} + + +
+ {/} + {/} + +
@@ -142,13 +178,16 @@ Login / Register {else}
- +
@@ -200,7 +239,6 @@
Lvl {:member.stats.lvl}
{/} - {/}