From c3cf74f1265bf53a384f3e31f5c397a4b3c793aa Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Wed, 28 Dec 2016 16:06:55 +0000 Subject: [PATCH] add framework --- app/assets/javascripts/application.js | 1 + app/channels/application_cable/channel.rb | 4 ++ app/channels/application_cable/connection.rb | 20 ++++++++++ app/models/synapse.rb | 9 +++++ app/models/topic.rb | 9 +++++ config/initializers/warden_hooks.rb | 10 +++++ config/routes.rb | 1 + frontend/src/Metamaps/Cable.js | 39 ++++++++++++++++++++ frontend/src/Metamaps/DataModel/Synapse.js | 4 ++ frontend/src/Metamaps/DataModel/Topic.js | 4 ++ frontend/src/Metamaps/index.js | 6 ++- 11 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 config/initializers/warden_hooks.rb create mode 100644 frontend/src/Metamaps/Cable.js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 11633bea..6af52fbd 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,6 +14,7 @@ //= require jquery //= require jquery-ui //= require jquery_ujs +//= require action_cable //= require_directory ./lib //= require ./webpacked/metamaps.bundle //= require ./Metamaps.ServerData diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 00000000..d6726972 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 00000000..8eb318cd --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,20 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + identified_by :current_user + + def connect + self.current_user = find_verified_user + logger.add_tags 'ActionCable', current_user.name + end + + protected + def find_verified_user + verified_user = User.find_by(id: cookies.signed['user.id']) + if verified_user && cookies.signed['user.expires_at'] > Time.now + verified_user + else + reject_unauthorized_connection + end + end + end +end diff --git a/app/models/synapse.rb b/app/models/synapse.rb index d14a18f4..4f55fb51 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -38,6 +38,15 @@ class Synapse < ApplicationRecord end end + def filtered + { + id: id, + permission: permission, + user_id: user_id, + collaborator_ids: collaborator_ids + } + end + def as_json(_options = {}) super(methods: [:user_name, :user_image, :collaborator_ids]) end diff --git a/app/models/topic.rb b/app/models/topic.rb index e5ea90ee..af88f342 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -90,6 +90,15 @@ class Topic < ApplicationRecord end end + def filtered + { + id: id, + permission: permission, + user_id: user_id, + collaborator_ids: collaborator_ids + } + end + # TODO: move to a decorator? def synapses_csv(output_format = 'array') output = [] diff --git a/config/initializers/warden_hooks.rb b/config/initializers/warden_hooks.rb new file mode 100644 index 00000000..da983955 --- /dev/null +++ b/config/initializers/warden_hooks.rb @@ -0,0 +1,10 @@ +Warden::Manager.after_set_user do |user,auth,opts| + scope = opts[:scope] + auth.cookies.signed["#{scope}.id"] = user.id + auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now +end +Warden::Manager.before_logout do |user, auth, opts| + scope = opts[:scope] + auth.cookies.signed["#{scope}.id"] = nil + auth.cookies.signed["#{scope}.expires_at"] = nil +end diff --git a/config/routes.rb b/config/routes.rb index 000784f6..4dc44c91 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true Metamaps::Application.routes.draw do use_doorkeeper + mount ActionCable.server => '/cable' root to: 'main#home', via: :get get 'request', to: 'main#requestinvite', as: :request diff --git a/frontend/src/Metamaps/Cable.js b/frontend/src/Metamaps/Cable.js new file mode 100644 index 00000000..ee279865 --- /dev/null +++ b/frontend/src/Metamaps/Cable.js @@ -0,0 +1,39 @@ +/* global $, ActionCable */ + +import Active from './Active' +import DataModel from './DataModel' +import Topic from './Topic' + +const Cable = { + init: () => { + let self = Cable + self.cable = ActionCable.createConsumer() + }, + subTopic: id => { + let self = Cable + self.topicSubs[id] = self.cable.subscriptions.create({ + channel: 'TopicChannel', + id: id + }, { + received: event => self[event.type](event.data) + }) + }, + unsubAllTopics: () => { + let self = Cable + Object.keys(self.topicSubs).forEach(id => { + self.topicSubs[id].unsubscribe() + }) + self.topicSubs = {} + }, + newSynapse: data => { + const m = Active.Mapper + const s = new DataModel.Synapse(data.synapse) + const t1 = new DataModel.Topic(data.topic1) + const t2 = new DataModel.Topic(data.topic2) + if (t1.authorizeToShow(m) && t2.authorizeToShow(m) && s.authorizeToShow(m)) { + Topic.fetchForTopicView(data.synapse.id) + } + } +} + +export default Cable diff --git a/frontend/src/Metamaps/DataModel/Synapse.js b/frontend/src/Metamaps/DataModel/Synapse.js index e6a7f1c7..be37e095 100644 --- a/frontend/src/Metamaps/DataModel/Synapse.js +++ b/frontend/src/Metamaps/DataModel/Synapse.js @@ -87,6 +87,10 @@ const Synapse = Backbone.Model.extend({ if (mapper && (this.get('permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true else return false }, + authorizeToShow: function(mapper) { + if (this.get('permission') !== 'private' || (mapper && this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true + else return false + }, authorizePermissionChange: function(mapper) { if (mapper && this.get('user_id') === mapper.get('id')) return true else return false diff --git a/frontend/src/Metamaps/DataModel/Topic.js b/frontend/src/Metamaps/DataModel/Topic.js index 0d71c973..aaf0937b 100644 --- a/frontend/src/Metamaps/DataModel/Topic.js +++ b/frontend/src/Metamaps/DataModel/Topic.js @@ -88,6 +88,10 @@ const Topic = Backbone.Model.extend({ return false } }, + authorizeToShow: function(mapper) { + if (this.get('permission') !== 'private' || (mapper && this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true + else return false + }, authorizePermissionChange: function(mapper) { if (mapper && this.get('user_id') === mapper.get('id')) return true else return false diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index be218aff..61f5e18a 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -2,9 +2,10 @@ import Account from './Account' import Active from './Active' import Admin from './Admin' import AutoLayout from './AutoLayout' -import DataModel from './DataModel' +import Cable from './Cable' import Control from './Control' import Create from './Create' +import DataModel from './DataModel' import Debug from './Debug' import Filter from './Filter' import GlobalUI, { @@ -38,9 +39,10 @@ Metamaps.Account = Account Metamaps.Active = Active Metamaps.Admin = Admin Metamaps.AutoLayout = AutoLayout -Metamaps.DataModel = DataModel +Metamaps.Cable = Cable Metamaps.Control = Control Metamaps.Create = Create +Metamaps.DataModel = DataModel Metamaps.Debug = Debug Metamaps.Filter = Filter Metamaps.GlobalUI = GlobalUI