From 3759851621e2767a9ec56b44c831c561ddb19bc8 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Tue, 8 Nov 2016 12:37:06 -0500 Subject: [PATCH 1/5] fix access#access route (#926) --- app/controllers/access_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/access_controller.rb b/app/controllers/access_controller.rb index 302e9385..c48ac418 100644 --- a/app/controllers/access_controller.rb +++ b/app/controllers/access_controller.rb @@ -32,7 +32,7 @@ class AccessController < ApplicationController # POST maps/:id/access def access - user_ids = params[:access] || [] + user_ids = params[:access].to_a.map(&:to_i) || [] @map.add_new_collaborators(user_ids).each do |user_id| # add_new_collaborators returns array of added users, From 83b58d43d5db78657d6c65f7d8c87aba72170ca7 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Tue, 8 Nov 2016 19:42:22 +0000 Subject: [PATCH 2/5] only remove user once they've left all maps --- realtime/realtime-server.js | 2 +- realtime/reducer.js | 29 ++++++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/realtime/realtime-server.js b/realtime/realtime-server.js index 9b07cfc3..72037eb7 100644 --- a/realtime/realtime-server.js +++ b/realtime/realtime-server.js @@ -16,4 +16,4 @@ signalling(io, stunservers, store) junto(io, store) map(io, store) -io.listen(5001) +io.listen(8081) diff --git a/realtime/reducer.js b/realtime/reducer.js index 183ee081..7146667f 100644 --- a/realtime/reducer.js +++ b/realtime/reducer.js @@ -1,4 +1,4 @@ -const { omit, omitBy, isNil, mapValues } = require('lodash') +const { find, omit, isNil, mapValues, values } = require('lodash') const { JOIN_MAP, LEAVE_MAP, @@ -9,7 +9,16 @@ const { const NOT_IN_CONVERSATION = 0 const IN_CONVERSATION = 1 -const addMapperToMap = (map, userId) => { return Object.assign({}, map, { [userId]: NOT_IN_CONVERSATION })} +const addMapperToMap = (map, userId) => Object.assign({}, map, { [userId]: NOT_IN_CONVERSATION }) +const userStillPresent = (userId, liveMaps) => { + if (!userId) return false + let stillPresent = false + const userIdString = userId.toString() + values(liveMaps).forEach(presentUsers => { + if (find(Object.keys(presentUsers), id => id === userIdString)) stillPresent = true + }) + return stillPresent +} const reducer = (state = { connectedPeople: {}, liveMaps: {} }, action) => { const { type, payload } = action @@ -37,10 +46,13 @@ const reducer = (state = { connectedPeople: {}, liveMaps: {} }, action) => { const newLiveMaps = mapWillEmpty ? omit(liveMaps, payload.mapid) : Object.assign({}, liveMaps, { [payload.mapid]: omit(map, payload.userid) }) + delete newLiveMaps[undefined] + delete newLiveMaps[null] + const updateConnectedPeople = userStillPresent(payload.userid, newLiveMaps) ? connectedPeople : omit(connectedPeople, payload.userid) return { - connectedPeople: omit(connectedPeople, payload.userid), - liveMaps: omitBy(newLiveMaps, isNil) + connectedPeople: updateConnectedPeople, + liveMaps: newLiveMaps } case JOIN_CALL: // update the user (payload.id is user id) in the given map to be marked in the conversation @@ -57,15 +69,18 @@ const reducer = (state = { connectedPeople: {}, liveMaps: {} }, action) => { : Object.assign({}, map, { [payload.userid]: NOT_IN_CONVERSATION }) return Object.assign({}, state, { - liveMaps: Object.assign({}, liveMaps, { map: newMap }) + liveMaps: Object.assign({}, liveMaps, { [payload.mapid]: newMap }) }) case 'DISCONNECT': const mapWithoutUser = omit(map, payload.userid) const newMapWithoutUser = callWillFinish ? mapValues(mapWithoutUser, () => NOT_IN_CONVERSATION) : mapWithoutUser const newLiveMapsWithoutUser = mapWillEmpty ? omit(liveMaps, payload.mapid) : Object.assign({}, liveMaps, { [payload.mapid]: newMapWithoutUser }) + delete newLiveMapsWithoutUser[undefined] + delete newLiveMapsWithoutUser[null] + const newConnectedPeople = userStillPresent(payload.userid, newLiveMapsWithoutUser) ? connectedPeople : omit(connectedPeople, payload.userid) return { - connectedPeople: omit(connectedPeople, payload.userid), - liveMaps: omitBy(newLiveMapsWithoutUser, isNil) + connectedPeople: newConnectedPeople, + liveMaps: newLiveMapsWithoutUser } default: return state From d1f75c8c246bc0aa3935710dd657c575256e2d1f Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Tue, 8 Nov 2016 19:45:51 +0000 Subject: [PATCH 3/5] oops! don't change rt server port --- realtime/realtime-server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/realtime/realtime-server.js b/realtime/realtime-server.js index 72037eb7..9b07cfc3 100644 --- a/realtime/realtime-server.js +++ b/realtime/realtime-server.js @@ -16,4 +16,4 @@ signalling(io, stunservers, store) junto(io, store) map(io, store) -io.listen(8081) +io.listen(5001) From e1441acde03d655212dab0ecb0a5548698ac64e8 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Tue, 8 Nov 2016 19:50:08 +0000 Subject: [PATCH 4/5] synapse wasn't updating calculated_permission --- frontend/src/Metamaps/Backbone/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/Metamaps/Backbone/index.js b/frontend/src/Metamaps/Backbone/index.js index ff4c48b9..1547e145 100644 --- a/frontend/src/Metamaps/Backbone/index.js +++ b/frontend/src/Metamaps/Backbone/index.js @@ -270,8 +270,8 @@ _Backbone.init = function () { newOptions.success = function (model, response, opt) { if (s) s(model, response, opt) - model.trigger('saved') model.set('calculated_permission', model.get('permission')) + model.trigger('saved') if (permBefore === 'private' && model.get('permission') !== 'private') { model.trigger('noLongerPrivate') @@ -436,6 +436,7 @@ _Backbone.init = function () { newOptions.success = function (model, response, opt) { if (s) s(model, response, opt) + model.set('calculated_permission', model.get('permission')) model.trigger('saved') if (permBefore === 'private' && model.get('permission') !== 'private') { From ce2d462578f842985db36df659f521aa4747b394 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Tue, 8 Nov 2016 15:51:39 -0500 Subject: [PATCH 5/5] fix bugs on develop branch --- .example-env | 6 +++++- app/controllers/hacks_controller.rb | 11 +++++++++-- doc/production/first-deploy.md | 4 ++-- frontend/src/Metamaps/Import.js | 1 + frontend/src/Metamaps/PasteInput.js | 2 +- frontend/src/Metamaps/Realtime/index.js | 6 +++++- frontend/src/Metamaps/Views/ChatView.js | 4 ++-- frontend/src/Metamaps/Views/Room.js | 5 +++-- realtime/realtime-server.js | 2 +- 9 files changed, 29 insertions(+), 12 deletions(-) diff --git a/.example-env b/.example-env index 1afb010b..96b60f55 100644 --- a/.example-env +++ b/.example-env @@ -1,10 +1,14 @@ +# Node JS env +export NODE_REALTIME_PORT='5000' # should match REALTIME_SERVER, below + +# Rails env export DB_USERNAME='postgres' export DB_PASSWORD='3112' export DB_HOST='localhost' export DB_PORT='5432' export DB_NAME='metamap002' -export REALTIME_SERVER='http://localhost:5001' +export REALTIME_SERVER='http://localhost:5000' export MAILER_DEFAULT_URL='localhost:3000' export DEVISE_MAILER_SENDER='team@metamaps.cc' diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb index 1abe3e60..22df9cbb 100644 --- a/app/controllers/hacks_controller.rb +++ b/app/controllers/hacks_controller.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # bad code that should be checked over before entering one of the # nice files from the right side of this repo class HacksController < ApplicationController @@ -11,7 +12,7 @@ class HacksController < ApplicationController response, url = get_with_redirects(url) title = get_encoded_title(response) render json: { success: true, title: title, url: url } - rescue StandardError => e + rescue StandardError render json: { success: false } end @@ -28,7 +29,13 @@ class HacksController < ApplicationController end def get_encoded_title(http_response) - title = http_response.body.sub(/.*(.*)<\/title>.*/m, '\1') + # ensure there's actually an html title tag + title = http_response.body.sub(%r{.*(<title>.*).*}m, '\1') + return '' unless title.starts_with?('') + return '' unless title.ends_with?('') + title = title.sub('', '').sub(%r{$}, '') + + # encode and trim the title to 140 usable characters charset = http_response['content-type'].sub(/.*charset=(.*);?.*/, '\1') charset = nil if charset == 'text/html' title = title.force_encoding(charset) if charset diff --git a/doc/production/first-deploy.md b/doc/production/first-deploy.md index 413717dd..994e68c2 100644 --- a/doc/production/first-deploy.md +++ b/doc/production/first-deploy.md @@ -93,10 +93,10 @@ server to see what problems show up: #### Realtime server: sudo npm install -g forever - (crontab -u metamaps -l 2>/dev/null; echo "@reboot $(which forever) --append -l /home/metamaps/logs/forever.realtime.log start /home/metamaps/metamaps/realtime/realtime-server.js") | crontab -u metamaps - + (crontab -u metamaps -l 2>/dev/null; echo "@reboot env NODE_REALTIME_PORT=5000 $(which forever) --append -l /home/metamaps/logs/forever.realtime.log start /home/metamaps/metamaps/realtime/realtime-server.js") | crontab -u metamaps - mkdir -p /home/metamaps/logs - forever --append \ + env NODE_REALTIME_PORT=5000 forever --append \ -c /home/metamaps/metamaps/node_modules/.bin/babel-node \ -l /home/metamaps/logs/forever.realtime.log \ start /home/metamaps/metamaps/realtime/realtime-server.js diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index cde37a73..7d1b3aa3 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -375,6 +375,7 @@ const Import = { $.get('/hacks/load_url_title', { url }, function success(data, textStatus) { + if (data.trim() === '') return var selector = '#showcard #topic_' + topic.get('id') + ' .best_in_place' if ($(selector).find('form').length > 0) { $(selector).find('textarea, input').val(data.title) diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index f8c93c3f..6227b23b 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -25,7 +25,7 @@ const PasteInput = { self.handleFile(e.dataTransfer.files[0], coords) } // OMG import bookmarks 😍 - if (e.dataTransfer.items.length > 0) { + if (e.dataTransfer.items && e.dataTransfer.items.length > 0) { e.dataTransfer.items[0].getAsString(function(text) { if (text.match(self.URL_REGEX)) { self.handle(text, coords) diff --git a/frontend/src/Metamaps/Realtime/index.js b/frontend/src/Metamaps/Realtime/index.js index db1334de..952b835c 100644 --- a/frontend/src/Metamaps/Realtime/index.js +++ b/frontend/src/Metamaps/Realtime/index.js @@ -172,7 +172,11 @@ let Realtime = { room: 'global', $video: self.localVideo.$video, myVideoView: self.localVideo.view, - config: { DOUBLE_CLICK_TOLERANCE: 200 } + config: { DOUBLE_CLICK_TOLERANCE: 200 }, + soundUrls: [ + serverData['sounds/MM_sounds.mp3'], + serverData['sounds/MM_sounds.ogg'] + ] }) self.room.videoAdded(self.handleVideoAdded) diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js index 4a549648..fd77864f 100644 --- a/frontend/src/Metamaps/Views/ChatView.js +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -226,7 +226,7 @@ var Handlers = { } } -const ChatView = function(messages, mapper, room) { +const ChatView = function(messages, mapper, room, opts = {}) { this.room = room this.mapper = mapper this.messages = messages // backbone collection @@ -243,7 +243,7 @@ const ChatView = function(messages, mapper, room) { Private.attachElements.call(this) Private.addEventListeners.call(this) Private.initialMessages.call(this) - Private.initializeSounds.call(this, room.soundUrls) + Private.initializeSounds.call(this, opts.soundUrls) this.$container.css({ right: '-300px' }) diff --git a/frontend/src/Metamaps/Views/Room.js b/frontend/src/Metamaps/Views/Room.js index f3327c6d..a3a79cc8 100644 --- a/frontend/src/Metamaps/Views/Room.js +++ b/frontend/src/Metamaps/Views/Room.js @@ -26,10 +26,11 @@ const Room = function(opts = {}) { this.messages = new Backbone.Collection() this.currentMapper = new Backbone.Model({ name: opts.username, image: opts.image }) - this.chat = new ChatView(this.messages, this.currentMapper, this.room) + this.chat = new ChatView(this.messages, this.currentMapper, this.room, { + soundUrls: opts.soundUrls + }) this.videos = {} - this.soundUrls = opts.soundUrls this.init() } diff --git a/realtime/realtime-server.js b/realtime/realtime-server.js index ad5a1900..0150e84d 100644 --- a/realtime/realtime-server.js +++ b/realtime/realtime-server.js @@ -15,4 +15,4 @@ signalling(io, stunservers, store) junto(io, store) map(io, store) -io.listen(5001) +io.listen(parseInt(process.env.NODE_REALTIME_PORT) || 5000)