From 66f1d2ec0b8cb3387c9760707df614d25021ae92 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 13 Feb 2016 17:28:09 +0800 Subject: [PATCH 01/67] install pundit --- Gemfile | 2 +- Gemfile.lock | 5 ++- app/controllers/application_controller.rb | 1 + app/policies/application_policy.rb | 53 +++++++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 app/policies/application_policy.rb diff --git a/Gemfile b/Gemfile index 8379a7db..eec31832 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ gem 'rails', '4.2.4' gem 'devise' gem 'redis' gem 'pg' -gem 'cancancan' +gem 'pundit' gem 'formula' gem 'formtastic' gem 'json' diff --git a/Gemfile.lock b/Gemfile.lock index eb8edec5..2f10214a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -56,7 +56,6 @@ GEM builder (3.2.2) byebug (5.0.0) columnize (= 0.9.0) - cancancan (1.13.1) climate_control (0.0.3) activesupport (>= 3.0) cocaine (0.5.7) @@ -141,6 +140,8 @@ GEM pry (~> 0.10) pry-rails (0.3.4) pry (>= 0.9.10) + pundit (1.1.0) + activesupport (>= 3.0.0) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) rack (1.6.4) @@ -243,7 +244,6 @@ DEPENDENCIES best_in_place better_errors binding_of_caller - cancancan coffee-rails devise dotenv @@ -260,6 +260,7 @@ DEPENDENCIES pg pry-byebug pry-rails + pundit quiet_assets rails (= 4.2.4) rails3-jquery-autocomplete diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 71d3d6ea..c380f96c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,5 @@ class ApplicationController < ActionController::Base + include Pundit protect_from_forgery before_filter :get_invite_link diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb new file mode 100644 index 00000000..2a0bbc52 --- /dev/null +++ b/app/policies/application_policy.rb @@ -0,0 +1,53 @@ +class ApplicationPolicy + attr_reader :user, :record + + def initialize(user, record) + @user = user + @record = record + end + + def index? + false + end + + def show? + scope.where(:id => record.id).exists? + end + + def create? + false + end + + def new? + create? + end + + def update? + false + end + + def edit? + update? + end + + def destroy? + false + end + + def scope + Pundit.policy_scope!(user, record.class) + end + + class Scope + attr_reader :user, :scope + + def initialize(user, scope) + @user = user + @scope = scope + end + + def resolve + scope + end + end +end From 52facb9c1da665e36ea6f81b9a712fa6e1f1a361 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 13 Feb 2016 17:28:16 +0800 Subject: [PATCH 02/67] topic policy --- app/policies/topic_policy.rb | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 app/policies/topic_policy.rb diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb new file mode 100644 index 00000000..55e79c2d --- /dev/null +++ b/app/policies/topic_policy.rb @@ -0,0 +1,40 @@ +class TopicPolicy < ApplicationPolicy + class Scope < Scope + def resolve + scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + end + end + + def create? + user.present? + end + + def show? + record.permission == 'commons' || record.permission == 'public' || record.user == user + end + + def update? + # user.present? && (record.permission == 'commons' || record.user == user) + true + end + + def destroy? + record.user == user || user.admin + end + + def autocomplete_topic? + user.present? + end + + def network? + show? + end + + def relative_numbers? + show? + end + + def relatives? + show? + end +end From baca4aac83f08fe26d3f4f078ba745310bca8385 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 13 Feb 2016 17:28:21 +0800 Subject: [PATCH 03/67] synapse policy --- app/policies/synapse_policy.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 app/policies/synapse_policy.rb diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb new file mode 100644 index 00000000..7cd305bf --- /dev/null +++ b/app/policies/synapse_policy.rb @@ -0,0 +1,25 @@ +class SynapsePolicy < ApplicationPolicy + class Scope < Scope + def resolve + scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + end + end + + def create? + user.present? + end + + def show? + #record.permission == 'commons' || record.permission == 'public' || record.user == user + true + end + + def update? + #user.present? && (record.permission == 'commons' || record.user == user) + true + end + + def destroy? + record.user == user || user.admin + end +end From 8ef847bd6d374daecf2a98f1adda9a9dca91f67b Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 13 Feb 2016 17:42:36 +0800 Subject: [PATCH 04/67] factor maps#index into 4 separate functions --- app/controllers/maps_controller.rb | 80 ++++++++++++++++++------------ config/routes.rb | 11 ++-- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 9ad05810..80568b90 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -6,47 +6,66 @@ class MapsController < ApplicationController autocomplete :map, :name, :full => true, :extra_data => [:user_id] # GET /explore/active - # GET /explore/featured - # GET /explore/mapper/:id - def index - return redirect_to activemaps_url if request.path == "/explore" - + def activemaps @current = current_user - @maps = [] page = params[:page].present? ? params[:page] : 1 + @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) + @request = "active" - if request.path.index("/explore/active") != nil - @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) - @request = "active" - elsif request.path.index("/explore/featured") != nil - @maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private").order("updated_at DESC").page(page).per(20) - @request = "featured" - elsif request.path.index('/explore/mine') != nil # looking for maps by me - return redirect_to activemaps_url if !authenticated? - - # don't need to exclude private maps because they all belong to you - @maps = Map.where("maps.user_id = ?", @current.id).order("updated_at DESC").page(page).per(20) - @request = "you" - elsif request.path.index('/explore/mapper/') != nil # looking for maps by a mapper - @user = User.find(params[:id]) - @maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20) - @request = "mapper" - end + redirect_to root_url and return if authenticated? respond_to do |format| - format.html { - if @request == "active" && authenticated? - redirect_to root_url and return - end - respond_with(@maps, @request, @user) - } + format.html { respond_with(@maps, @request, @user) } + format.json { render json: @maps } + end + end + + # GET /explore/featured + def featuredmaps + @current = current_user + page = params[:page].present? ? params[:page] : 1 + @maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private") + .order("updated_at DESC").page(page).per(20) + @request = "featured" + + respond_to do |format| + format.html { respond_with(@maps, @request, @user) } + format.json { render json: @maps } + end + end + + # GET /explore/mine + def mymaps + return redirect_to activemaps_url if !authenticated? + + @current = current_user + page = params[:page].present? ? params[:page] : 1 + # don't need to exclude private maps because they all belong to you + @maps = Map.where("maps.user_id = ?", @current.id).order("updated_at DESC").page(page).per(20) + @request = "you" + + respond_to do |format| + format.html { respond_with(@maps, @request, @user) } + format.json { render json: @maps } + end + end + + # GET /explore/mapper/:id + def usermaps + @current = current_user + page = params[:page].present? ? params[:page] : 1 + @user = User.find(params[:id]) + @maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20) + @request = "mapper" + + respond_to do |format| + format.html { respond_with(@maps, @request, @user) } format.json { render json: @maps } end end # GET maps/:id def show - @current = current_user @map = Map.find(params[:id]).authorize_to_show(@current) @@ -72,7 +91,6 @@ class MapsController < ApplicationController # GET maps/:id/contains def contains - @current = current_user @map = Map.find(params[:id]).authorize_to_show(@current) diff --git a/config/routes.rb b/config/routes.rb index a3ab6e3a..76d281ce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,11 +20,12 @@ Metamaps::Application.routes.draw do get 'topics/:id/relative_numbers', to: 'topics#relative_numbers', as: :relative_numbers get 'topics/:id/relatives', to: 'topics#relatives', as: :relatives - get 'explore/active', to: 'maps#index', as: :activemaps - get 'explore/featured', to: 'maps#index', as: :featuredmaps - get 'explore/mine', to: 'maps#index', as: :mymaps - get 'explore/mapper/:id', to: 'maps#index', as: :usermaps - resources :maps, except: [:new, :edit] + resources :maps, except: [:index, :new, :edit] + get 'explore/active', to: 'maps#activemaps' + get 'explore/featured', to: 'maps#featuredmaps' + get 'explore/mine', to: 'maps#mymaps' + get 'explore/mapper/:id', to: 'maps#usermaps' + get 'maps/:id/contains', to: 'maps#contains', as: :contains post 'maps/:id/upload_screenshot', to: 'maps#screenshot', as: :screenshot From bbc36de62830166df0b023bd1092416efab416ea Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 13 Feb 2016 17:44:11 +0800 Subject: [PATCH 05/67] update maps spec --- spec/controllers/maps_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/maps_controller_spec.rb b/spec/controllers/maps_controller_spec.rb index b2f0abec..67950d75 100644 --- a/spec/controllers/maps_controller_spec.rb +++ b/spec/controllers/maps_controller_spec.rb @@ -10,7 +10,7 @@ RSpec.describe MapsController, type: :controller do describe 'GET #index' do it 'viewable maps as @maps' do - get :index, {} + get :activemaps expect(assigns(:maps)).to eq([map]) end end From bc7db85c8c354aca9de9157f9f28ccc775075a75 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 13:13:44 +0800 Subject: [PATCH 06/67] update map index views --- app/controllers/maps_controller.rb | 12 +++------ app/views/maps/activemaps.html.erb | 15 +++++++++++ app/views/maps/featuredmaps.html.erb | 15 +++++++++++ app/views/maps/index.html.erb | 38 ---------------------------- app/views/maps/mymaps.html.erb | 15 +++++++++++ app/views/maps/usermaps.html.erb | 18 +++++++++++++ 6 files changed, 67 insertions(+), 46 deletions(-) create mode 100644 app/views/maps/activemaps.html.erb create mode 100644 app/views/maps/featuredmaps.html.erb delete mode 100644 app/views/maps/index.html.erb create mode 100644 app/views/maps/mymaps.html.erb create mode 100644 app/views/maps/usermaps.html.erb diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 80568b90..cad6d8f6 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -10,12 +10,11 @@ class MapsController < ApplicationController @current = current_user page = params[:page].present? ? params[:page] : 1 @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) - @request = "active" redirect_to root_url and return if authenticated? respond_to do |format| - format.html { respond_with(@maps, @request, @user) } + format.html { respond_with(@maps, @user) } format.json { render json: @maps } end end @@ -26,10 +25,9 @@ class MapsController < ApplicationController page = params[:page].present? ? params[:page] : 1 @maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private") .order("updated_at DESC").page(page).per(20) - @request = "featured" respond_to do |format| - format.html { respond_with(@maps, @request, @user) } + format.html { respond_with(@maps, @user) } format.json { render json: @maps } end end @@ -42,10 +40,9 @@ class MapsController < ApplicationController page = params[:page].present? ? params[:page] : 1 # don't need to exclude private maps because they all belong to you @maps = Map.where("maps.user_id = ?", @current.id).order("updated_at DESC").page(page).per(20) - @request = "you" respond_to do |format| - format.html { respond_with(@maps, @request, @user) } + format.html { respond_with(@maps, @user) } format.json { render json: @maps } end end @@ -56,10 +53,9 @@ class MapsController < ApplicationController page = params[:page].present? ? params[:page] : 1 @user = User.find(params[:id]) @maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20) - @request = "mapper" respond_to do |format| - format.html { respond_with(@maps, @request, @user) } + format.html { respond_with(@maps, @user) } format.json { render json: @maps } end end diff --git a/app/views/maps/activemaps.html.erb b/app/views/maps/activemaps.html.erb new file mode 100644 index 00000000..90156321 --- /dev/null +++ b/app/views/maps/activemaps.html.erb @@ -0,0 +1,15 @@ +<% # + # @file + # Shows a list of recently active maps + # GET /explore/active(.:format) + # %> + + diff --git a/app/views/maps/featuredmaps.html.erb b/app/views/maps/featuredmaps.html.erb new file mode 100644 index 00000000..048d23a4 --- /dev/null +++ b/app/views/maps/featuredmaps.html.erb @@ -0,0 +1,15 @@ +<% # + # @file + # Shows a list of featured maps + # GET /explore/featured(.:format) + # %> + + diff --git a/app/views/maps/index.html.erb b/app/views/maps/index.html.erb deleted file mode 100644 index 0e067a63..00000000 --- a/app/views/maps/index.html.erb +++ /dev/null @@ -1,38 +0,0 @@ -<% # - # @file - # Shows a list of all maps, or just a user's maps. - # GET /explore/active(.:format) - # GET /explore/featured(.:format) - # GET /explore/mine(.:format) - # GET /explore/mapper/:id(.:format) - # GET /maps(.:format) - # %> - - diff --git a/app/views/maps/mymaps.html.erb b/app/views/maps/mymaps.html.erb new file mode 100644 index 00000000..76a96ec1 --- /dev/null +++ b/app/views/maps/mymaps.html.erb @@ -0,0 +1,15 @@ +<% # + # @file + # Shows a list of current user's maps + # GET /explore/mine(.:format) + # %> + + diff --git a/app/views/maps/usermaps.html.erb b/app/views/maps/usermaps.html.erb new file mode 100644 index 00000000..4107fbb7 --- /dev/null +++ b/app/views/maps/usermaps.html.erb @@ -0,0 +1,18 @@ +<% # + # @file + # Shows a list of a user's maps + # GET /explore/mapper/:id(.:format) + # %> + + From cec6d3bfcd3776f23bb2d3472554763c1a442ac5 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 13:24:55 +0800 Subject: [PATCH 07/67] handle pundit errors with http 403 --- config/application.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/application.rb b/config/application.rb index 399b32c9..658a4203 100644 --- a/config/application.rb +++ b/config/application.rb @@ -53,5 +53,8 @@ module Metamaps g.test_framework :rspec end config.active_record.raise_in_transactional_callbacks = true + + # pundit errors return 403 FORBIDDEN + config.action_dispatch.rescue_responses["Pundit::NotAuthorizedError"] = :forbidden end end From 1e01ff8bc976fe5e2b5ccd1f8b53419631f247e6 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 13:28:28 +0800 Subject: [PATCH 08/67] map policy --- app/policies/map_policy.rb | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 app/policies/map_policy.rb diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb new file mode 100644 index 00000000..96a0b724 --- /dev/null +++ b/app/policies/map_policy.rb @@ -0,0 +1,48 @@ +class MapPolicy < ApplicationPolicy + class Scope < Scope + def resolve + scope.where('permission IN ("public", "commons") OR user_id = ?', @user.id) + end + end + + def activemaps? + @user.blank? # redirect to root url if authenticated for some reason + end + + def featuredmaps? + true + end + + def mymaps? + @user.present? + end + + def usermaps? + true + end + + def show? + @record.permission == 'commons' || @record.permission == 'public' || @record.user == @user + end + + def contains? + show? + end + + def create? + @user.present? + end + + def update? + @user.present? && (@record.permission == 'commons' || @record.user == @user) + true + end + + def screenshot? + update? + end + + def destroy? + @record.user == @user || @user.admin + end +end From 3ed6ffbdba12fac5d031c5bfafb95de7d5212ef0 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 13:29:33 +0800 Subject: [PATCH 09/67] @record/@user in topic/synapse policy --- app/policies/synapse_policy.rb | 10 +++++----- app/policies/topic_policy.rb | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 7cd305bf..f7db11ed 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,25 +1,25 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('permission IN ("public", "commons") OR user_id = ?', @user.id) end end def create? - user.present? + @user.present? end def show? - #record.permission == 'commons' || record.permission == 'public' || record.user == user + # @record.permission == 'commons' || @record.permission == 'public' || @record.user == @user true end def update? - #user.present? && (record.permission == 'commons' || record.user == user) + # @user.present? && (@record.permission == 'commons' || @record.user == @user) true end def destroy? - record.user == user || user.admin + @record.user == @user || @user.admin end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 55e79c2d..2978cb13 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,29 +1,29 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('permission IN ("public", "commons") OR user_id = ?', @user.id) end end def create? - user.present? + @user.present? end def show? - record.permission == 'commons' || record.permission == 'public' || record.user == user + @record.permission == 'commons' || @record.permission == 'public' || @record.user == @user end def update? - # user.present? && (record.permission == 'commons' || record.user == user) + # @user.present? && (@record.permission == 'commons' || @record.user == @user) true end def destroy? - record.user == user || user.admin + @record.user == @user || @user.admin end def autocomplete_topic? - user.present? + @user.present? end def network? From cbb6b648bee1fd833a29e00d133e08790314465d Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 16:53:59 +0800 Subject: [PATCH 10/67] implement main_policy (headless). also remove all @current references --- app/controllers/main_controller.rb | 9 +++---- app/controllers/maps_controller.rb | 35 ++++++++++---------------- app/controllers/synapses_controller.rb | 2 +- app/controllers/topics_controller.rb | 30 +++++++++------------- app/policies/main_policy.rb | 26 +++++++++++++++++++ 5 files changed, 55 insertions(+), 47 deletions(-) create mode 100644 app/policies/main_policy.rb diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 1cd0f577..31a55abc 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -8,15 +8,13 @@ class MainController < ApplicationController # home page def home - @current = current_user - + @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(1).per(20) respond_to do |format| format.html { if authenticated? - @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(1).per(20) - respond_with(@maps, @current) + render 'main/home' else - respond_with(@current) + render 'maps/activemaps' end } end @@ -213,5 +211,4 @@ class MainController < ApplicationController render json: autocomplete_synapse_array_json(@synapses) end - end diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index cad6d8f6..cb949098 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -7,10 +7,10 @@ class MapsController < ApplicationController # GET /explore/active def activemaps - @current = current_user page = params[:page].present? ? params[:page] : 1 @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) + # root url => main/home. main/home renders maps/activemaps view. redirect_to root_url and return if authenticated? respond_to do |format| @@ -21,7 +21,6 @@ class MapsController < ApplicationController # GET /explore/featured def featuredmaps - @current = current_user page = params[:page].present? ? params[:page] : 1 @maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private") .order("updated_at DESC").page(page).per(20) @@ -36,10 +35,9 @@ class MapsController < ApplicationController def mymaps return redirect_to activemaps_url if !authenticated? - @current = current_user page = params[:page].present? ? params[:page] : 1 # don't need to exclude private maps because they all belong to you - @maps = Map.where("maps.user_id = ?", @current.id).order("updated_at DESC").page(page).per(20) + @maps = Map.where("maps.user_id = ?", current_user.id).order("updated_at DESC").page(page).per(20) respond_to do |format| format.html { respond_with(@maps, @user) } @@ -49,7 +47,6 @@ class MapsController < ApplicationController # GET /explore/mapper/:id def usermaps - @current = current_user page = params[:page].present? ? params[:page] : 1 @user = User.find(params[:id]) @maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20) @@ -62,8 +59,7 @@ class MapsController < ApplicationController # GET maps/:id def show - @current = current_user - @map = Map.find(params[:id]).authorize_to_show(@current) + @map = Map.find(params[:id]).authorize_to_show(current_user) if not @map redirect_to root_url, notice: "Access denied. That map is private." and return @@ -72,11 +68,11 @@ class MapsController < ApplicationController respond_to do |format| format.html { @allmappers = @map.contributors - @alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } - @allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } + @alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } + @allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) } @allmappings = @map.mappings.to_a.delete_if {|m| object = m.mappable - !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))) + !object || (object.permission == "private" && (!authenticated? || (authenticated? && current_user.id != object.user_id))) } respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map) @@ -87,19 +83,18 @@ class MapsController < ApplicationController # GET maps/:id/contains def contains - @current = current_user - @map = Map.find(params[:id]).authorize_to_show(@current) + @map = Map.find(params[:id]).authorize_to_show(current_user) if not @map redirect_to root_url, notice: "Access denied. That map is private." and return end @allmappers = @map.contributors - @alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } - @allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } + @alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } + @allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) } @allmappings = @map.mappings.to_a.delete_if {|m| object = m.mappable - !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))) + !object || (object.permission == "private" && (!authenticated? || (authenticated? && current_user.id != object.user_id))) } @json = Hash.new() @@ -167,8 +162,7 @@ class MapsController < ApplicationController # PUT maps/:id def update - @current = current_user - @map = Map.find(params[:id]).authorize_to_edit(@current) + @map = Map.find(params[:id]).authorize_to_edit(current_user) respond_to do |format| if !@map @@ -183,8 +177,7 @@ class MapsController < ApplicationController # POST maps/:id/upload_screenshot def screenshot - @current = current_user - @map = Map.find(params[:id]).authorize_to_edit(@current) + @map = Map.find(params[:id]).authorize_to_edit(current_user) if @map png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) @@ -207,9 +200,7 @@ class MapsController < ApplicationController # DELETE maps/:id def destroy - @current = current_user - - @map = Map.find(params[:id]).authorize_to_delete(@current) + @map = Map.find(params[:id]).authorize_to_delete(current_user) @map.delete if @map diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index f19dc053..e706aac4 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -9,7 +9,7 @@ class SynapsesController < ApplicationController def show @synapse = Synapse.find(params[:id]) - #.authorize_to_show(@current) + #.authorize_to_show(current_user) #if not @synapse # redirect_to root_url and return diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 19062ba9..47105396 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -7,7 +7,6 @@ class TopicsController < ApplicationController # GET /topics/autocomplete_topic def autocomplete_topic - @current = current_user term = params[:term] if term && !term.empty? @topics = Topic.where('LOWER("name") like ?', term.downcase + '%').order('"name"') @@ -15,7 +14,7 @@ class TopicsController < ApplicationController #read this next line as 'delete a topic if its private and you're either #1. logged out or 2. logged in but not the topic creator @topics.to_a.delete_if {|t| t.permission == "private" && - (!authenticated? || (authenticated? && @current.id != t.user_id)) } + (!authenticated? || (authenticated? && current_user.id != t.user_id)) } else @topics = [] end @@ -24,8 +23,7 @@ class TopicsController < ApplicationController # GET topics/:id def show - @current = current_user - @topic = Topic.find(params[:id]).authorize_to_show(@current) + @topic = Topic.find(params[:id]).authorize_to_show(current_user) if not @topic redirect_to root_url, notice: "Access denied. That topic is private." and return @@ -33,8 +31,8 @@ class TopicsController < ApplicationController respond_to do |format| format.html { - @alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } # should limit to topics visible to user - @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } + @alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } # should limit to topics visible to user + @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) } @allcreators = [] @alltopics.each do |t| @@ -56,15 +54,14 @@ class TopicsController < ApplicationController # GET topics/:id/network def network - @current = current_user - @topic = Topic.find(params[:id]).authorize_to_show(@current) + @topic = Topic.find(params[:id]).authorize_to_show(current_user) if not @topic redirect_to root_url, notice: "Access denied. That topic is private." and return end - @alltopics = @topic.relatives.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } - @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } + @alltopics = @topic.relatives.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } + @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) } @allcreators = [] @allcreators.push(@topic.user) @alltopics.each do |t| @@ -91,8 +88,7 @@ class TopicsController < ApplicationController # GET topics/:id/relative_numbers def relative_numbers - @current = current_user - @topic = Topic.find(params[:id]).authorize_to_show(@current) + @topic = Topic.find(params[:id]).authorize_to_show(current_user) if not @topic redirect_to root_url, notice: "Access denied. That topic is private." and return @@ -102,7 +98,7 @@ class TopicsController < ApplicationController @alltopics = @topic.relatives.to_a.delete_if {|t| @topicsAlreadyHas.index(t.id.to_s) != nil || - (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) + (t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id))) } @alltopics.uniq! @@ -123,8 +119,7 @@ class TopicsController < ApplicationController # GET topics/:id/relatives def relatives - @current = current_user - @topic = Topic.find(params[:id]).authorize_to_show(@current) + @topic = Topic.find(params[:id]).authorize_to_show(current_user) if not @topic redirect_to root_url, notice: "Access denied. That topic is private." and return @@ -135,7 +130,7 @@ class TopicsController < ApplicationController @alltopics = @topic.relatives.to_a.delete_if {|t| @topicsAlreadyHas.index(t.id.to_s) != nil || (params[:metacode] && t.metacode_id.to_s != params[:metacode]) || - (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) + (t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id))) } @alltopics.uniq! @@ -198,8 +193,7 @@ class TopicsController < ApplicationController # DELETE topics/:id def destroy - @current = current_user - @topic = Topic.find(params[:id]).authorize_to_delete(@current) + @topic = Topic.find(params[:id]).authorize_to_delete(current_user) @topic.delete if @topic respond_to do |format| diff --git a/app/policies/main_policy.rb b/app/policies/main_policy.rb new file mode 100644 index 00000000..ee7f9fc9 --- /dev/null +++ b/app/policies/main_policy.rb @@ -0,0 +1,26 @@ +class MainPolicy < ApplicationPolicy + def initialize(user, record) + @user = user + @record = nil + end + + def home? + true + end + + def searchtopics? + true + end + + def searchmaps? + true + end + + def searchmappers? + true + end + + def searchsynapses? + true + end +end From 25774d9f16e04392aec137ed1e42b560e88e4708 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 16:57:25 +0800 Subject: [PATCH 11/67] remove unneeded https stuff --- app/controllers/application_controller.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 71d3d6ea..5266a0f2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,13 +12,7 @@ class ApplicationController < ActionController::Base helper_method :admin? def after_sign_in_path_for(resource) - unsafe_uri = request.env["REQUEST_URI"] - if unsafe_uri.starts_with?('http') && !unsafe_uri.starts_with?('https') - protocol = 'http' - else - protocol = 'https' - end - sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => protocol) + sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'https') if request.referer == sign_in_url super From 895b872bda07e8a1ed38b09b7e337961c0160567 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 16:57:25 +0800 Subject: [PATCH 12/67] remove unneeded https stuff --- app/controllers/application_controller.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c380f96c..d3f14f99 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,13 +13,7 @@ class ApplicationController < ActionController::Base helper_method :admin? def after_sign_in_path_for(resource) - unsafe_uri = request.env["REQUEST_URI"] - if unsafe_uri.starts_with?('http') && !unsafe_uri.starts_with?('https') - protocol = 'http' - else - protocol = 'https' - end - sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => protocol) + sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'https') if request.referer == sign_in_url super From 155eac41d875ff2730f797ef77e27e4f5aa8bf1c Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 17:24:00 +0800 Subject: [PATCH 13/67] @ symbols unneeded --- app/policies/map_policy.rb | 14 +++++++------- app/policies/synapse_policy.rb | 10 +++++----- app/policies/topic_policy.rb | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 96a0b724..2cdbdee2 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -1,12 +1,12 @@ class MapPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', @user.id) + scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) end end def activemaps? - @user.blank? # redirect to root url if authenticated for some reason + user.blank? # redirect to root url if authenticated for some reason end def featuredmaps? @@ -14,7 +14,7 @@ class MapPolicy < ApplicationPolicy end def mymaps? - @user.present? + user.present? end def usermaps? @@ -22,7 +22,7 @@ class MapPolicy < ApplicationPolicy end def show? - @record.permission == 'commons' || @record.permission == 'public' || @record.user == @user + record.permission == 'commons' || record.permission == 'public' || record.user == user end def contains? @@ -30,11 +30,11 @@ class MapPolicy < ApplicationPolicy end def create? - @user.present? + user.present? end def update? - @user.present? && (@record.permission == 'commons' || @record.user == @user) + user.present? && (record.permission == 'commons' || record.user == user) true end @@ -43,6 +43,6 @@ class MapPolicy < ApplicationPolicy end def destroy? - @record.user == @user || @user.admin + record.user == user || user.admin end end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index f7db11ed..6d332fbf 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,25 +1,25 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', @user.id) + scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) end end def create? - @user.present? + user.present? end def show? - # @record.permission == 'commons' || @record.permission == 'public' || @record.user == @user + # record.permission == 'commons' || record.permission == 'public' || record.user == user true end def update? - # @user.present? && (@record.permission == 'commons' || @record.user == @user) + # user.present? && (record.permission == 'commons' || record.user == user) true end def destroy? - @record.user == @user || @user.admin + record.user == user || user.admin end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 2978cb13..55e79c2d 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,29 +1,29 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', @user.id) + scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) end end def create? - @user.present? + user.present? end def show? - @record.permission == 'commons' || @record.permission == 'public' || @record.user == @user + record.permission == 'commons' || record.permission == 'public' || record.user == user end def update? - # @user.present? && (@record.permission == 'commons' || @record.user == @user) + # user.present? && (record.permission == 'commons' || record.user == user) true end def destroy? - @record.user == @user || @user.admin + record.user == user || user.admin end def autocomplete_topic? - @user.present? + user.present? end def network? From 36c5ddab1fae30505097d28effb89df375c7b9ba Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 17:48:18 +0800 Subject: [PATCH 14/67] before_filter => before_action --- app/controllers/application_controller.rb | 2 +- app/controllers/mappings_controller.rb | 2 +- app/controllers/maps_controller.rb | 2 +- app/controllers/metacode_sets_controller.rb | 2 +- app/controllers/metacodes_controller.rb | 2 +- app/controllers/synapses_controller.rb | 2 +- app/controllers/topics_controller.rb | 2 +- app/controllers/users/registrations_controller.rb | 4 ++-- app/controllers/users_controller.rb | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5266a0f2..f9ef3f45 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,7 @@ class ApplicationController < ActionController::Base protect_from_forgery - before_filter :get_invite_link + before_action :get_invite_link after_action :allow_embedding # this is for global login diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index c20b0153..6ce37234 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -1,6 +1,6 @@ class MappingsController < ApplicationController - before_filter :require_user, only: [:create, :update, :destroy] + before_action :require_user, only: [:create, :update, :destroy] respond_to :json diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 9ad05810..f3bdda49 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,5 +1,5 @@ class MapsController < ApplicationController - before_filter :require_user, only: [:create, :update, :screenshot, :destroy] + before_action :require_user, only: [:create, :update, :screenshot, :destroy] respond_to :html, :json diff --git a/app/controllers/metacode_sets_controller.rb b/app/controllers/metacode_sets_controller.rb index 720076c1..e76f4c9a 100644 --- a/app/controllers/metacode_sets_controller.rb +++ b/app/controllers/metacode_sets_controller.rb @@ -1,6 +1,6 @@ class MetacodeSetsController < ApplicationController - before_filter :require_admin + before_action :require_admin # GET /metacode_sets # GET /metacode_sets.json diff --git a/app/controllers/metacodes_controller.rb b/app/controllers/metacodes_controller.rb index 54956c60..77f9ba54 100644 --- a/app/controllers/metacodes_controller.rb +++ b/app/controllers/metacodes_controller.rb @@ -1,5 +1,5 @@ class MetacodesController < ApplicationController - before_filter :require_admin, except: [:index] + before_action :require_admin, except: [:index] # GET /metacodes # GET /metacodes.json diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index f19dc053..4bf7cffb 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -1,7 +1,7 @@ class SynapsesController < ApplicationController include TopicsHelper - before_filter :require_user, only: [:create, :update, :destroy] + before_action :require_user, only: [:create, :update, :destroy] respond_to :json diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 19062ba9..5b9da340 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -1,7 +1,7 @@ class TopicsController < ApplicationController include TopicsHelper - before_filter :require_user, only: [:create, :update, :destroy] + before_action :require_user, only: [:create, :update, :destroy] respond_to :html, :js, :json diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index c77edb50..88474e21 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,6 +1,6 @@ class Users::RegistrationsController < Devise::RegistrationsController - before_filter :configure_sign_up_params, only: [:create] - before_filter :configure_account_update_params, only: [:update] + before_action :configure_sign_up_params, only: [:create] + before_action :configure_account_update_params, only: [:update] protected def after_sign_up_path_for(resource) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 063ab866..f5b0aab9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,5 @@ class UsersController < ApplicationController - before_filter :require_user, only: [:edit, :update, :updatemetacodes] + before_action :require_user, only: [:edit, :update, :updatemetacodes] respond_to :html, :json From ef5d85c2bffc516025d6941073890c46f3bcecf8 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 17:48:18 +0800 Subject: [PATCH 15/67] before_filter => before_action --- app/controllers/application_controller.rb | 2 +- app/controllers/mappings_controller.rb | 2 +- app/controllers/maps_controller.rb | 2 +- app/controllers/metacode_sets_controller.rb | 2 +- app/controllers/metacodes_controller.rb | 2 +- app/controllers/synapses_controller.rb | 2 +- app/controllers/topics_controller.rb | 2 +- app/controllers/users/registrations_controller.rb | 4 ++-- app/controllers/users_controller.rb | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d3f14f99..0e6503ef 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base include Pundit protect_from_forgery - before_filter :get_invite_link + before_action :get_invite_link after_action :allow_embedding # this is for global login diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index c20b0153..6ce37234 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -1,6 +1,6 @@ class MappingsController < ApplicationController - before_filter :require_user, only: [:create, :update, :destroy] + before_action :require_user, only: [:create, :update, :destroy] respond_to :json diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index cb949098..9fbf95e0 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,5 +1,5 @@ class MapsController < ApplicationController - before_filter :require_user, only: [:create, :update, :screenshot, :destroy] + before_action :require_user, only: [:create, :update, :screenshot, :destroy] respond_to :html, :json diff --git a/app/controllers/metacode_sets_controller.rb b/app/controllers/metacode_sets_controller.rb index 720076c1..e76f4c9a 100644 --- a/app/controllers/metacode_sets_controller.rb +++ b/app/controllers/metacode_sets_controller.rb @@ -1,6 +1,6 @@ class MetacodeSetsController < ApplicationController - before_filter :require_admin + before_action :require_admin # GET /metacode_sets # GET /metacode_sets.json diff --git a/app/controllers/metacodes_controller.rb b/app/controllers/metacodes_controller.rb index 54956c60..77f9ba54 100644 --- a/app/controllers/metacodes_controller.rb +++ b/app/controllers/metacodes_controller.rb @@ -1,5 +1,5 @@ class MetacodesController < ApplicationController - before_filter :require_admin, except: [:index] + before_action :require_admin, except: [:index] # GET /metacodes # GET /metacodes.json diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index e706aac4..46592dcc 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -1,7 +1,7 @@ class SynapsesController < ApplicationController include TopicsHelper - before_filter :require_user, only: [:create, :update, :destroy] + before_action :require_user, only: [:create, :update, :destroy] respond_to :json diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 47105396..4d11f8ca 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -1,7 +1,7 @@ class TopicsController < ApplicationController include TopicsHelper - before_filter :require_user, only: [:create, :update, :destroy] + before_action :require_user, only: [:create, :update, :destroy] respond_to :html, :js, :json diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index c77edb50..88474e21 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,6 +1,6 @@ class Users::RegistrationsController < Devise::RegistrationsController - before_filter :configure_sign_up_params, only: [:create] - before_filter :configure_account_update_params, only: [:update] + before_action :configure_sign_up_params, only: [:create] + before_action :configure_account_update_params, only: [:update] protected def after_sign_up_path_for(resource) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 063ab866..f5b0aab9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,5 @@ class UsersController < ApplicationController - before_filter :require_user, only: [:edit, :update, :updatemetacodes] + before_action :require_user, only: [:edit, :update, :updatemetacodes] respond_to :html, :json From e64a16f1b830a3bd327b14566c728d49589858a8 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 28 Feb 2016 18:55:48 +0800 Subject: [PATCH 16/67] main#home view simplify for only unauthenticated users --- app/views/main/home.html.erb | 88 ++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/app/views/main/home.html.erb b/app/views/main/home.html.erb index 3c1319e0..6089b7df 100644 --- a/app/views/main/home.html.erb +++ b/app/views/main/home.html.erb @@ -2,52 +2,42 @@ # @file # Located at / # Shows 3 most recently created topics, synapses, and maps. - #%> - -<% if !authenticated? %> - <% content_for :title, "Home | Metamaps" %> -
-
-
Make Sense with Metamaps
-
- METAMAPS.CC is a free and open source platform that supports real-time sense-making, distributed collaboration, and the creative intelligence of individuals, organizations and communities. We are currently in an invite-only beta. -
-
-
-
- -
-

Who finds it useful?

-

Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!

- - EXPLORE FEATURED MAPS - REQUEST INVITE -
-
-
-
-
-
- <% # our partners %> -
-
-
- - -<% elsif authenticated? %> - <% content_for :title, "Explore Active Maps | Metamaps" %> - -<% end %> + # +%> + +<% content_for :title, "Home | Metamaps" %> +
+
+
Make Sense with Metamaps
+
+ METAMAPS.CC is a free and open source platform that supports real-time sense-making, distributed collaboration, and the creative intelligence of individuals, organizations and communities. We are currently in an invite-only beta. +
+
+
+
+ +
+

Who finds it useful?

+

Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!

+ + EXPLORE FEATURED MAPS + REQUEST INVITE +
+
+
+
+
+
+ <% # our partners %> +
+
+
+ + From ef60aefe882589213e6df2c5a208362a65c8860e Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Mon, 29 Feb 2016 17:05:11 +1300 Subject: [PATCH 17/67] fix js bug --- app/assets/javascripts/src/Metamaps.GlobalUI.js.erb | 1 + app/assets/javascripts/src/Metamaps.js.erb | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb b/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb index 27812c57..00460ad4 100644 --- a/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb +++ b/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb @@ -48,6 +48,7 @@ $(document).ready(function () { // this runs the init function within each sub-object on the Metamaps one if (Metamaps.hasOwnProperty(prop) && + Metamaps[prop] != null && Metamaps[prop].hasOwnProperty('init') && typeof (Metamaps[prop].init) == 'function' ) { diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/app/assets/javascripts/src/Metamaps.js.erb index 5a6c5955..ff6d57e6 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/app/assets/javascripts/src/Metamaps.js.erb @@ -17,12 +17,10 @@ var labelType, useGradients, nativeTextSupport, animate; })(); // TODO eliminate these 4 top-level variables -Metamaps = { - panningInt: null, - tempNode: null, - tempInit: false, - tempNode2: null -} +Metamaps.panningInt = null; +Metamaps.tempNode = null; +Metamaps.tempInit = false; +Metamaps.tempNode2 = null; Metamaps.Settings = { embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages From 059591b78b419ebdfedc79dc721aced625717724 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Fri, 11 Mar 2016 17:16:04 +1100 Subject: [PATCH 18/67] first pass at important API endpoints, token auth --- Gemfile | 2 + Gemfile.lock | 126 +++++++++++---------- app/assets/javascripts/src/Metamaps.js.erb | 4 +- app/controllers/api/mappings_controller.rb | 11 ++ app/controllers/api/maps_controller.rb | 11 ++ app/controllers/api/restful_controller.rb | 29 +++++ app/controllers/api/synapses_controller.rb | 11 ++ app/controllers/api/tokens_controller.rb | 21 ++++ app/controllers/api/topics_controller.rb | 11 ++ app/models/logged_out_user.rb | 7 ++ app/models/mapping.rb | 10 +- app/models/permitted_params.rb | 33 ++++++ app/models/synapse.rb | 2 + app/models/token.rb | 11 ++ app/models/user.rb | 5 + app/serializers/map_serializer.rb | 20 ++++ app/serializers/mapping_serializer.rb | 17 +++ app/serializers/metacode_serializer.rb | 7 ++ app/serializers/synapse_serializer.rb | 19 ++++ app/serializers/token_serializer.rb | 14 +++ app/serializers/topic_serializer.rb | 18 +++ app/serializers/user_serializer.rb | 15 +++ config/routes.rb | 10 ++ db/migrate/20160310200131_create_tokens.rb | 11 ++ db/schema.rb | 13 ++- postatoken.txt | 7 ++ postdata.txt | 1 + postmapping.txt | 1 + postsynapse.txt | 1 + posttopic.txt | 1 + spec/models/token_spec.rb | 5 + 31 files changed, 392 insertions(+), 62 deletions(-) create mode 100644 app/controllers/api/mappings_controller.rb create mode 100644 app/controllers/api/maps_controller.rb create mode 100644 app/controllers/api/restful_controller.rb create mode 100644 app/controllers/api/synapses_controller.rb create mode 100644 app/controllers/api/tokens_controller.rb create mode 100644 app/controllers/api/topics_controller.rb create mode 100644 app/models/logged_out_user.rb create mode 100644 app/models/permitted_params.rb create mode 100644 app/models/token.rb create mode 100644 app/serializers/map_serializer.rb create mode 100644 app/serializers/mapping_serializer.rb create mode 100644 app/serializers/metacode_serializer.rb create mode 100644 app/serializers/synapse_serializer.rb create mode 100644 app/serializers/token_serializer.rb create mode 100644 app/serializers/topic_serializer.rb create mode 100644 app/serializers/user_serializer.rb create mode 100644 db/migrate/20160310200131_create_tokens.rb create mode 100644 postatoken.txt create mode 100644 postdata.txt create mode 100644 postmapping.txt create mode 100644 postsynapse.txt create mode 100644 posttopic.txt create mode 100644 spec/models/token_spec.rb diff --git a/Gemfile b/Gemfile index 8379a7db..6b48c790 100644 --- a/Gemfile +++ b/Gemfile @@ -15,6 +15,8 @@ gem 'best_in_place' #in-place editing gem 'kaminari' # pagination gem 'uservoice-ruby' gem 'dotenv' +gem 'snorlax', '~> 0.1.3' +gem 'active_model_serializers', '~> 0.8.1' gem 'paperclip' gem 'aws-sdk', '< 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index eb8edec5..08c76b66 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,6 +20,8 @@ GEM erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) + active_model_serializers (0.8.3) + activemodel (>= 3.0) activejob (4.2.4) activesupport (= 4.2.4) globalid (>= 0.3.0) @@ -43,8 +45,8 @@ GEM aws-sdk-v1 (1.66.0) json (~> 1.4) nokogiri (>= 1.4.4) - bcrypt (3.1.10) - best_in_place (3.0.3) + bcrypt (3.1.11) + best_in_place (3.1.0) actionpack (>= 3.2) railties (>= 3.2) better_errors (2.1.1) @@ -54,24 +56,23 @@ GEM binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) - byebug (5.0.0) - columnize (= 0.9.0) - cancancan (1.13.1) + byebug (8.2.2) + cancancan (1.10.1) climate_control (0.0.3) activesupport (>= 3.0) - cocaine (0.5.7) + cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) - coderay (1.1.0) - coffee-rails (4.1.0) + coderay (1.1.1) + coffee-rails (4.1.1) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.0) + railties (>= 4.0.0, < 5.1.x) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1.1) - columnize (0.9.0) + coffee-script-source (1.10.0) + concurrent-ruby (1.0.1) debug_inspector (0.0.2) - devise (3.5.2) + devise (3.5.6) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 3.2.6, < 5) @@ -80,13 +81,13 @@ GEM warden (~> 1.2.3) diff-lcs (1.2.5) docile (1.1.5) - dotenv (2.0.2) + dotenv (2.1.0) erubis (2.7.0) execjs (2.6.0) ezcrypto (0.7.2) factory_girl (4.5.0) activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) + factory_girl_rails (4.6.0) factory_girl (~> 4.5.0) railties (>= 3.0.0) formtastic (3.1.3) @@ -96,17 +97,17 @@ GEM globalid (0.3.6) activesupport (>= 4.1.0) i18n (0.7.0) - jbuilder (2.3.2) - activesupport (>= 3.0.0, < 5) + jbuilder (2.4.1) + activesupport (>= 3.0.0, < 5.1) multi_json (~> 1.2) - jquery-rails (4.0.5) - rails-dom-testing (~> 1.0) + jquery-rails (4.1.1) + rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) jquery-ui-rails (5.0.5) railties (>= 3.2.16) json (1.8.3) - json-schema (2.6.0) + json-schema (2.6.1) addressable (~> 2.3.8) kaminari (0.16.3) actionpack (>= 3.0.0) @@ -116,28 +117,28 @@ GEM mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (2.6.2) + mime-types (2.99.1) mimemagic (0.3.0) - mini_portile (0.6.2) - minitest (5.8.2) + mini_portile2 (2.0.0) + minitest (5.8.4) multi_json (1.11.2) - nokogiri (1.6.6.2) - mini_portile (~> 0.6.0) - oauth (0.4.7) + nokogiri (1.6.7.2) + mini_portile2 (~> 2.0.0.rc2) + oauth (0.5.1) orm_adapter (0.5.0) - paperclip (4.3.1) + paperclip (4.3.5) activemodel (>= 3.2.0) activesupport (>= 3.2.0) cocaine (~> 0.5.5) mime-types mimemagic (= 0.3.0) - pg (0.18.3) + pg (0.18.4) pry (0.10.3) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - pry-byebug (3.2.0) - byebug (~> 5.0) + pry-byebug (3.3.0) + byebug (~> 8.0) pry (~> 0.10) pry-rails (0.3.4) pry (>= 0.9.10) @@ -163,66 +164,70 @@ GEM activesupport (>= 4.2.0.beta, < 5.0) nokogiri (~> 1.6.0) rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.2) + rails-html-sanitizer (1.0.3) loofah (~> 2.0) rails3-jquery-autocomplete (1.0.15) rails (>= 3.2) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging - rails_serve_static_assets (0.0.4) + rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.4) railties (4.2.4) actionpack (= 4.2.4) activesupport (= 4.2.4) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (10.4.2) - redis (3.2.1) - responders (2.1.0) - railties (>= 4.2.0, < 5) - rspec-core (3.3.2) - rspec-support (~> 3.3.0) - rspec-expectations (3.3.1) + rake (11.0.1) + redis (3.2.2) + responders (2.1.1) + railties (>= 4.2.0, < 5.1) + rspec-core (3.4.4) + rspec-support (~> 3.4.0) + rspec-expectations (3.4.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-mocks (3.3.2) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-rails (3.3.3) + rspec-support (~> 3.4.0) + rspec-rails (3.4.2) actionpack (>= 3.0, < 4.3) activesupport (>= 3.0, < 4.3) railties (>= 3.0, < 4.3) - rspec-core (~> 3.3.0) - rspec-expectations (~> 3.3.0) - rspec-mocks (~> 3.3.0) - rspec-support (~> 3.3.0) - rspec-support (3.3.0) - sass (3.4.19) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) + rspec-support (~> 3.4.0) + rspec-support (3.4.1) + sass (3.4.21) sass-rails (5.0.4) railties (>= 4.0.0, < 5.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - shoulda-matchers (3.0.1) + shoulda-matchers (3.1.1) activesupport (>= 4.0.0) - simplecov (0.11.1) + simplecov (0.11.2) docile (~> 1.1.0) json (~> 1.8) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) - sprockets (3.4.0) + snorlax (0.1.4) + cancancan (~> 1.10.1) + rails (> 4.1) + sprockets (3.5.2) + concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (2.3.3) - actionpack (>= 3.0) - activesupport (>= 3.0) - sprockets (>= 2.8, < 4.0) + sprockets-rails (3.0.4) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) thor (0.19.1) thread_safe (0.3.5) - tilt (2.0.1) - tunemygc (1.0.61) + tilt (2.0.2) + tunemygc (1.0.65) tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.2) @@ -232,13 +237,14 @@ GEM ezcrypto (>= 0.7.2) json (>= 1.7.5) oauth (>= 0.4.7) - warden (1.2.3) + warden (1.2.6) rack (>= 1.0) PLATFORMS ruby DEPENDENCIES + active_model_serializers (~> 0.8.1) aws-sdk (< 2.0) best_in_place better_errors @@ -269,6 +275,10 @@ DEPENDENCIES sass-rails shoulda-matchers simplecov + snorlax (~> 0.1.3) tunemygc uglifier uservoice-ruby + +BUNDLED WITH + 1.11.2 diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/app/assets/javascripts/src/Metamaps.js.erb index ff6d57e6..95cf7379 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/app/assets/javascripts/src/Metamaps.js.erb @@ -4083,7 +4083,7 @@ Metamaps.Topic = { }; var topicSuccessCallback = function (topicModel, response) { if (Metamaps.Active.Map) { - mapping.save({ mappable_id: topicModel.id }, { + mapping.save({ mappable_id: topicModel.get('topic').id }, { success: mappingSuccessCallback, error: function (model, response) { console.log('error saving mapping to database'); @@ -4254,7 +4254,7 @@ Metamaps.Synapse = { }; var synapseSuccessCallback = function (synapseModel, response) { if (Metamaps.Active.Map) { - mapping.save({ mappable_id: synapseModel.id }, { + mapping.save({ mappable_id: synapseModel.get('synapse').id }, { success: mappingSuccessCallback }); } diff --git a/app/controllers/api/mappings_controller.rb b/app/controllers/api/mappings_controller.rb new file mode 100644 index 00000000..83892b9a --- /dev/null +++ b/app/controllers/api/mappings_controller.rb @@ -0,0 +1,11 @@ +class Api::MappingsController < API::RestfulController + + def create + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + +end diff --git a/app/controllers/api/maps_controller.rb b/app/controllers/api/maps_controller.rb new file mode 100644 index 00000000..2f86d254 --- /dev/null +++ b/app/controllers/api/maps_controller.rb @@ -0,0 +1,11 @@ +class Api::MapsController < API::RestfulController + + def create + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + +end diff --git a/app/controllers/api/restful_controller.rb b/app/controllers/api/restful_controller.rb new file mode 100644 index 00000000..8289583d --- /dev/null +++ b/app/controllers/api/restful_controller.rb @@ -0,0 +1,29 @@ +class API::RestfulController < ActionController::Base + snorlax_used_rest! + + def show + load_resource + raise AccessDenied.new unless resource.authorize_to_show(current_user) + respond_with_resource + end + + private + + def current_user + super || token_user || LoggedOutUser.new + end + + def token_user + authenticate_with_http_token do |token, options| + access_token = Token.find_by_token(token) + if access_token + @token_user ||= access_token.user + end + end + end + + def permitted_params + @permitted_params ||= PermittedParams.new(params) + end + +end diff --git a/app/controllers/api/synapses_controller.rb b/app/controllers/api/synapses_controller.rb new file mode 100644 index 00000000..de435df3 --- /dev/null +++ b/app/controllers/api/synapses_controller.rb @@ -0,0 +1,11 @@ +class Api::SynapsesController < API::RestfulController + + def create + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + +end diff --git a/app/controllers/api/tokens_controller.rb b/app/controllers/api/tokens_controller.rb new file mode 100644 index 00000000..2b2ff8df --- /dev/null +++ b/app/controllers/api/tokens_controller.rb @@ -0,0 +1,21 @@ +class Api::TokensController < API::RestfulController + + def create + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + + def my_tokens + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_collection page_collection: false, timeframe_collection: false + respond_with_collection + end + + def visible_records + current_user.tokens + end + +end diff --git a/app/controllers/api/topics_controller.rb b/app/controllers/api/topics_controller.rb new file mode 100644 index 00000000..ded6a5e6 --- /dev/null +++ b/app/controllers/api/topics_controller.rb @@ -0,0 +1,11 @@ +class Api::TopicsController < API::RestfulController + + def create + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + +end diff --git a/app/models/logged_out_user.rb b/app/models/logged_out_user.rb new file mode 100644 index 00000000..14e0cfb9 --- /dev/null +++ b/app/models/logged_out_user.rb @@ -0,0 +1,7 @@ +class LoggedOutUser + + FALSE_METHODS = [:is_logged_in?] + + FALSE_METHODS.each { |method| define_method(method, -> { false }) } + +end diff --git a/app/models/mapping.rb b/app/models/mapping.rb index d034de1c..8f29ed6a 100644 --- a/app/models/mapping.rb +++ b/app/models/mapping.rb @@ -25,5 +25,13 @@ class Mapping < ActiveRecord::Base def as_json(options={}) super(:methods =>[:user_name, :user_image]) end - + + def authorize_to_show(user) + if ((self.map.permission == "private" && self.map.user != user) || + (self.mappable.permission == "private" && self.mappable.user != user)) + return false + end + return self + end + end diff --git a/app/models/permitted_params.rb b/app/models/permitted_params.rb new file mode 100644 index 00000000..a49ed648 --- /dev/null +++ b/app/models/permitted_params.rb @@ -0,0 +1,33 @@ +class PermittedParams < Struct.new(:params) + + %w[map synapse topic mapping token].each do |kind| + define_method(kind) do + permitted_attributes = self.send("#{kind}_attributes") + params.require(kind).permit(*permitted_attributes) + end + alias_method :"api_#{kind}", kind.to_sym + end + + alias :read_attribute_for_serialization :send + + def token_attributes + [:description] + end + + def map_attributes + [:name, :desc, :permission, :arranged] + end + + def synapse_attributes + [:desc, :category, :weight, :permission, :node1_id, :node2_id] + end + + def topic_attributes + [:name, :desc, :link, :permission, :metacode_id] + end + + def mapping_attributes + [:xloc, :yloc, :map_id, :mappable_type, :mappable_id] + end + +end diff --git a/app/models/synapse.rb b/app/models/synapse.rb index ea5889cc..c766d95c 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -10,6 +10,8 @@ class Synapse < ActiveRecord::Base validates :desc, length: { minimum: 0, allow_nil: false } validates :permission, presence: true + validates :node1_id, presence: true + validates :node2_id, presence: true validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) } validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true } diff --git a/app/models/token.rb b/app/models/token.rb new file mode 100644 index 00000000..15bdca79 --- /dev/null +++ b/app/models/token.rb @@ -0,0 +1,11 @@ +class Token < ActiveRecord::Base + belongs_to :user + + before_create :generate_token + + private + def generate_token + self.token = SecureRandom.uuid.gsub(/\-/,'') + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index bd3bf477..a8fb6e6b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,6 +6,7 @@ class User < ActiveRecord::Base has_many :synapses has_many :maps has_many :mappings + has_many :tokens after_create :generate_code @@ -40,6 +41,10 @@ class User < ActiveRecord::Base # Validate the attached image is image/jpg, image/png, etc validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/ + def is_logged_in? + true + end + # override default as_json def as_json(options={}) { :id => self.id, diff --git a/app/serializers/map_serializer.rb b/app/serializers/map_serializer.rb new file mode 100644 index 00000000..b9839782 --- /dev/null +++ b/app/serializers/map_serializer.rb @@ -0,0 +1,20 @@ +class MapSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :name, + :desc, + :permission, + :screenshot, + :created_at, + :updated_at + + has_many :topics + has_many :synapses + has_many :mappings + has_many :contributors, root: :users + + #def filter(keys) + # keys.delete(:outcome_author) unless object.outcome_author.present? + # keys + #end +end diff --git a/app/serializers/mapping_serializer.rb b/app/serializers/mapping_serializer.rb new file mode 100644 index 00000000..400c35ba --- /dev/null +++ b/app/serializers/mapping_serializer.rb @@ -0,0 +1,17 @@ +class MappingSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :xloc, + :yloc, + :created_at, + :updated_at + has_one :user + has_one :map + has_one :mappable, polymorphic: true + + def filter(keys) + keys.delete(:xloc) unless object.mappable_type == "Topic" + keys.delete(:yloc) unless object.mappable_type == "Topic" + keys + end +end diff --git a/app/serializers/metacode_serializer.rb b/app/serializers/metacode_serializer.rb new file mode 100644 index 00000000..3918d274 --- /dev/null +++ b/app/serializers/metacode_serializer.rb @@ -0,0 +1,7 @@ +class MetacodeSerializer < ActiveModel::Serializer + attributes :id, + :name, + :manual_icon, + :color, + :aws_icon +end diff --git a/app/serializers/synapse_serializer.rb b/app/serializers/synapse_serializer.rb new file mode 100644 index 00000000..77c3a159 --- /dev/null +++ b/app/serializers/synapse_serializer.rb @@ -0,0 +1,19 @@ +class SynapseSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :desc, + :category, + :weight, + :permission, + :created_at, + :updated_at + + has_one :topic1, root: :topics + has_one :topic2, root: :topics + has_one :user + + #def filter(keys) + # keys.delete(:outcome_author) unless object.outcome_author.present? + # keys + #end +end diff --git a/app/serializers/token_serializer.rb b/app/serializers/token_serializer.rb new file mode 100644 index 00000000..777a14c1 --- /dev/null +++ b/app/serializers/token_serializer.rb @@ -0,0 +1,14 @@ +class TokenSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :token, + :description, + :user_id, + :created_at, + :updated_at + + #def filter(keys) + # keys.delete(:outcome_author) unless object.outcome_author.present? + # keys + #end +end diff --git a/app/serializers/topic_serializer.rb b/app/serializers/topic_serializer.rb new file mode 100644 index 00000000..205b8178 --- /dev/null +++ b/app/serializers/topic_serializer.rb @@ -0,0 +1,18 @@ +class TopicSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :name, + :desc, + :link, + :permission, + :created_at, + :updated_at + + has_one :user + has_one :metacode + + #def filter(keys) + # keys.delete(:outcome_author) unless object.outcome_author.present? + # keys + #end +end diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb new file mode 100644 index 00000000..b9a3b416 --- /dev/null +++ b/app/serializers/user_serializer.rb @@ -0,0 +1,15 @@ +class UserSerializer < ActiveModel::Serializer + attributes :id, + :name, + :avatar, + :is_admin, + :generation + + def avatar + object.image.url(:sixtyfour) + end + + def is_admin + object.admin + end +end diff --git a/config/routes.rb b/config/routes.rb index a3ab6e3a..1b0e5295 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,16 @@ Metamaps::Application.routes.draw do get 'search/mappers', to: 'main#searchmappers', as: :searchmappers get 'search/synapses', to: 'main#searchsynapses', as: :searchsynapses + namespace :api, path: '/api/v1', defaults: {format: :json} do + resources :maps, only: [:create, :show, :update, :destroy] + resources :synapses, only: [:create, :show, :update, :destroy] + resources :topics, only: [:create, :show, :update, :destroy] + resources :mappings, only: [:create, :show, :update, :destroy] + resources :tokens, only: [ :create, :destroy] do + get :my_tokens, on: :collection + end + end + resources :mappings, except: [:index, :new, :edit] resources :metacode_sets, :except => [:show] resources :metacodes, :except => [:show, :destroy] diff --git a/db/migrate/20160310200131_create_tokens.rb b/db/migrate/20160310200131_create_tokens.rb new file mode 100644 index 00000000..7b9272a5 --- /dev/null +++ b/db/migrate/20160310200131_create_tokens.rb @@ -0,0 +1,11 @@ +class CreateTokens < ActiveRecord::Migration + def change + create_table :tokens do |t| + t.string :token + t.string :description + t.references :user, index: true, foreign_key: true + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e6a9bd11..334fd4ad 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160223061711) do +ActiveRecord::Schema.define(version: 20160310200131) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -117,6 +117,16 @@ ActiveRecord::Schema.define(version: 20160223061711) do add_index "synapses", ["node2_id"], name: "index_synapses_on_node2_id", using: :btree add_index "synapses", ["user_id"], name: "index_synapses_on_user_id", using: :btree + create_table "tokens", force: :cascade do |t| + t.string "token" + t.string "description" + t.integer "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "tokens", ["user_id"], name: "index_tokens_on_user_id", using: :btree + create_table "topics", force: :cascade do |t| t.text "name" t.text "desc" @@ -171,4 +181,5 @@ ActiveRecord::Schema.define(version: 20160223061711) do add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + add_foreign_key "tokens", "users" end diff --git a/postatoken.txt b/postatoken.txt new file mode 100644 index 00000000..c9d98ff3 --- /dev/null +++ b/postatoken.txt @@ -0,0 +1,7 @@ +$.post('http://localhost:3000/api/v1/tokens', {token: { + description: 'for stuff', + token: '1234', + user_id: 2 +}}) + +curl -X POST -d @postdata.txt http://localhost:3000/api/v1/maps --header "Authorization: Token token=fb5b3db125c94e9fb50f1e42054be856" --header "Content-Type:application/json" diff --git a/postdata.txt b/postdata.txt new file mode 100644 index 00000000..9daaf598 --- /dev/null +++ b/postdata.txt @@ -0,0 +1 @@ +{ "map": { "name":"tree", "desc": "green", "permission": "commons", "arranged": true }} diff --git a/postmapping.txt b/postmapping.txt new file mode 100644 index 00000000..c9463f92 --- /dev/null +++ b/postmapping.txt @@ -0,0 +1 @@ +{ "mapping": { "xloc": 123, "yloc": 123, "map_id": 1, "mappable_type": "Topic", "mappable_id": 2 }} diff --git a/postsynapse.txt b/postsynapse.txt new file mode 100644 index 00000000..da2617d8 --- /dev/null +++ b/postsynapse.txt @@ -0,0 +1 @@ +{ "synapse": { "desc": "link between", "permission": "commons", "node1_id": 1, "node2_id": 2, "category": "from-to" }} diff --git a/posttopic.txt b/posttopic.txt new file mode 100644 index 00000000..e00d797f --- /dev/null +++ b/posttopic.txt @@ -0,0 +1 @@ +{ "topic": { "name":"tree topic", "desc": "so green", "permission": "commons", "metacode_id": 1 }} diff --git a/spec/models/token_spec.rb b/spec/models/token_spec.rb new file mode 100644 index 00000000..18bba17d --- /dev/null +++ b/spec/models/token_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Token, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From ccfba03fdb1ed5a858f3573f84026ee90c0b7c77 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Fri, 11 Mar 2016 17:26:54 +1100 Subject: [PATCH 19/67] clean up duplicate code --- app/controllers/api/mappings_controller.rb | 8 -------- app/controllers/api/maps_controller.rb | 8 -------- app/controllers/api/restful_controller.rb | 8 ++++++++ app/controllers/api/synapses_controller.rb | 8 -------- app/controllers/api/tokens_controller.rb | 10 +--------- app/controllers/api/topics_controller.rb | 8 -------- 6 files changed, 9 insertions(+), 41 deletions(-) diff --git a/app/controllers/api/mappings_controller.rb b/app/controllers/api/mappings_controller.rb index 83892b9a..426c9dbe 100644 --- a/app/controllers/api/mappings_controller.rb +++ b/app/controllers/api/mappings_controller.rb @@ -1,11 +1,3 @@ class Api::MappingsController < API::RestfulController - def create - raise CanCan::AccessDenied.new unless current_user.is_logged_in? - instantiate_resouce - resource.user = current_user - create_action - respond_with_resource - end - end diff --git a/app/controllers/api/maps_controller.rb b/app/controllers/api/maps_controller.rb index 2f86d254..7b805280 100644 --- a/app/controllers/api/maps_controller.rb +++ b/app/controllers/api/maps_controller.rb @@ -1,11 +1,3 @@ class Api::MapsController < API::RestfulController - def create - raise CanCan::AccessDenied.new unless current_user.is_logged_in? - instantiate_resouce - resource.user = current_user - create_action - respond_with_resource - end - end diff --git a/app/controllers/api/restful_controller.rb b/app/controllers/api/restful_controller.rb index 8289583d..d56783a0 100644 --- a/app/controllers/api/restful_controller.rb +++ b/app/controllers/api/restful_controller.rb @@ -1,6 +1,14 @@ class API::RestfulController < ActionController::Base snorlax_used_rest! + def create + raise CanCan::AccessDenied.new unless current_user.is_logged_in? + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + def show load_resource raise AccessDenied.new unless resource.authorize_to_show(current_user) diff --git a/app/controllers/api/synapses_controller.rb b/app/controllers/api/synapses_controller.rb index de435df3..f133ffd0 100644 --- a/app/controllers/api/synapses_controller.rb +++ b/app/controllers/api/synapses_controller.rb @@ -1,11 +1,3 @@ class Api::SynapsesController < API::RestfulController - def create - raise CanCan::AccessDenied.new unless current_user.is_logged_in? - instantiate_resouce - resource.user = current_user - create_action - respond_with_resource - end - end diff --git a/app/controllers/api/tokens_controller.rb b/app/controllers/api/tokens_controller.rb index 2b2ff8df..cc54e531 100644 --- a/app/controllers/api/tokens_controller.rb +++ b/app/controllers/api/tokens_controller.rb @@ -1,13 +1,5 @@ class Api::TokensController < API::RestfulController - - def create - raise CanCan::AccessDenied.new unless current_user.is_logged_in? - instantiate_resouce - resource.user = current_user - create_action - respond_with_resource - end - + def my_tokens raise CanCan::AccessDenied.new unless current_user.is_logged_in? instantiate_collection page_collection: false, timeframe_collection: false diff --git a/app/controllers/api/topics_controller.rb b/app/controllers/api/topics_controller.rb index ded6a5e6..f3633544 100644 --- a/app/controllers/api/topics_controller.rb +++ b/app/controllers/api/topics_controller.rb @@ -1,11 +1,3 @@ class Api::TopicsController < API::RestfulController - def create - raise CanCan::AccessDenied.new unless current_user.is_logged_in? - instantiate_resouce - resource.user = current_user - create_action - respond_with_resource - end - end From d8cc588efb9ea11a43a3a9b6da71471068aff37f Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 11 Mar 2016 21:25:24 +0800 Subject: [PATCH 20/67] basics of admin_override policy function --- app/policies/application_policy.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 2a0bbc52..6bd56c64 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -34,6 +34,14 @@ class ApplicationPolicy false end + # TODO update this function to enable some flag in the interface + # so that admins usually can't do super admin stuff unless they + # explicitly say they want to (E.g. seeing/editing/deleting private + # maps - they should be able to, but not by accident) + def admin_override + user.admin + end + def scope Pundit.policy_scope!(user, record.class) end From 615eaf580eb68a15e195338bf62d11e25f45907b Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 11 Mar 2016 21:30:54 +0800 Subject: [PATCH 21/67] mapping policy --- app/policies/mapping_policy.rb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 app/policies/mapping_policy.rb diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb new file mode 100644 index 00000000..44e7bfd7 --- /dev/null +++ b/app/policies/mapping_policy.rb @@ -0,0 +1,31 @@ +class MappingPolicy < ApplicationPolicy + class Scope < Scope + def resolve + # TODO base this on the map policy + # it would be nice if we could also base this on the mappable, but that + # gets really complicated. Devin thinks it's OK to SHOW a mapping for + # a private topic, since you can't see the private topic anyways + scope.joins(:maps).where('maps.permission IN ("public", "commons") OR user_id = ?', user.id) + end + end + + def show? + map = policy(record.map, user) + mappable = policy(record.mappable, user) + map.show? && mappable.show? + end + + def create? + map = policy(record.map, user) + map.edit? + end + + def update? + map = policy(record.map, user) + map.update? + end + + def destroy? + record.user == user || admin_override + end +end From 73b82801cc8d5712d3b100ac56b195cacd5bd564 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 11 Mar 2016 21:32:18 +0800 Subject: [PATCH 22/67] consistent permissions --- app/policies/map_policy.rb | 2 +- app/policies/synapse_policy.rb | 8 +++----- app/policies/topic_policy.rb | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 2cdbdee2..671eea83 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -43,6 +43,6 @@ class MapPolicy < ApplicationPolicy end def destroy? - record.user == user || user.admin + record.user == user || admin_override end end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 6d332fbf..6763014a 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -10,16 +10,14 @@ class SynapsePolicy < ApplicationPolicy end def show? - # record.permission == 'commons' || record.permission == 'public' || record.user == user - true + record.permission == 'commons' || record.permission == 'public' || record.user == user end def update? - # user.present? && (record.permission == 'commons' || record.user == user) - true + user.present? && (record.permission == 'commons' || record.user == user) end def destroy? - record.user == user || user.admin + record.user == user || admin_override end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 55e79c2d..03b42895 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -14,12 +14,11 @@ class TopicPolicy < ApplicationPolicy end def update? - # user.present? && (record.permission == 'commons' || record.user == user) - true + user.present? && (record.permission == 'commons' || record.user == user) end def destroy? - record.user == user || user.admin + record.user == user || admin_override end def autocomplete_topic? From 7395811ba5cdb23442710d537082d6821558850f Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 11 Mar 2016 21:35:48 +0800 Subject: [PATCH 23/67] handle unauthorized with baaaaad 403 --- app/controllers/application_controller.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0e6503ef..6d10c553 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,6 @@ class ApplicationController < ActionController::Base include Pundit + rescue_from Pundit::NotAuthorizedError, with: :handle_unauthorized protect_from_forgery before_action :get_invite_link @@ -23,6 +24,10 @@ class ApplicationController < ActionController::Base stored_location_for(resource) || request.referer || root_path end end + + def handle_unauthorized + head :forbidden # TODO make this better + end private From eb5675506811266ead0e4a95a914d31ec0fc0011 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 11 Mar 2016 22:10:31 +0800 Subject: [PATCH 24/67] implement five policies into their controllers --- app/controllers/main_controller.rb | 3 + app/controllers/mappings_controller.rb | 8 +- app/controllers/maps_controller.rb | 80 +++++----- app/controllers/synapses_controller.rb | 16 +- app/controllers/topics_controller.rb | 209 ++++++++++--------------- 5 files changed, 142 insertions(+), 174 deletions(-) diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 31a55abc..29c11777 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -3,6 +3,9 @@ class MainController < ApplicationController include MapsHelper include UsersHelper include SynapsesHelper + + after_action :verify_authorized, except: :index + after_action :verify_policy_scoped, only: :index respond_to :html, :json diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index 6ce37234..ea2aaf0e 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -1,12 +1,14 @@ class MappingsController < ApplicationController - before_action :require_user, only: [:create, :update, :destroy] + after_action :verify_authorized, except: :index + after_action :verify_policy_scoped, only: :index respond_to :json # GET /mappings/1.json def show @mapping = Mapping.find(params[:id]) + authorize! @mapping render json: @mapping end @@ -14,6 +16,7 @@ class MappingsController < ApplicationController # POST /mappings.json def create @mapping = Mapping.new(mapping_params) + authorize! @mapping if @mapping.save render json: @mapping, status: :created @@ -25,6 +28,7 @@ class MappingsController < ApplicationController # PUT /mappings/1.json def update @mapping = Mapping.find(params[:id]) + authorize! @mapping if @mapping.update_attributes(mapping_params) head :no_content @@ -36,7 +40,7 @@ class MappingsController < ApplicationController # DELETE /mappings/1.json def destroy @mapping = Mapping.find(params[:id]) - @map = @mapping.map + authorize! @mapping @mapping.destroy diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 9fbf95e0..016ba7b5 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,5 +1,7 @@ class MapsController < ApplicationController before_action :require_user, only: [:create, :update, :screenshot, :destroy] + after_action :verify_authorized, except: :activemaps, :featuredmaps, :mymaps, :usermaps + after_action :verify_policy_scoped, only: :activemaps, :featuredmaps, :mymaps, :usermaps respond_to :html, :json @@ -8,7 +10,8 @@ class MapsController < ApplicationController # GET /explore/active def activemaps page = params[:page].present? ? params[:page] : 1 - @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) + @maps = policy_scope(Map).order("updated_at DESC") + .page(page).per(20) # root url => main/home. main/home renders maps/activemaps view. redirect_to root_url and return if authenticated? @@ -22,8 +25,10 @@ class MapsController < ApplicationController # GET /explore/featured def featuredmaps page = params[:page].present? ? params[:page] : 1 - @maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private") - .order("updated_at DESC").page(page).per(20) + @maps = policy_scope( + Map.where("maps.featured = ? AND maps.permission != ?", + true, "private") + ).order("updated_at DESC").page(page).per(20) respond_to do |format| format.html { respond_with(@maps, @user) } @@ -36,8 +41,9 @@ class MapsController < ApplicationController return redirect_to activemaps_url if !authenticated? page = params[:page].present? ? params[:page] : 1 - # don't need to exclude private maps because they all belong to you - @maps = Map.where("maps.user_id = ?", current_user.id).order("updated_at DESC").page(page).per(20) + @maps = policy_scope( + Map.where("maps.user_id = ?", current_user.id) + ).order("updated_at DESC").page(page).per(20) respond_to do |format| format.html { respond_with(@maps, @user) } @@ -49,7 +55,8 @@ class MapsController < ApplicationController def usermaps page = params[:page].present? ? params[:page] : 1 @user = User.find(params[:id]) - @maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20) + @maps = policy_scope(Map.where(user: @user)) + .order("updated_at DESC").page(page).per(20) respond_to do |format| format.html { respond_with(@maps, @user) } @@ -59,7 +66,8 @@ class MapsController < ApplicationController # GET maps/:id def show - @map = Map.find(params[:id]).authorize_to_show(current_user) + @map = Map.find(params[:id]) + authorize! @map if not @map redirect_to root_url, notice: "Access denied. That map is private." and return @@ -83,7 +91,8 @@ class MapsController < ApplicationController # GET maps/:id/contains def contains - @map = Map.find(params[:id]).authorize_to_show(current_user) + @map = Map.find(params[:id]) + authorize! @map if not @map redirect_to root_url, notice: "Access denied. That map is private." and return @@ -130,6 +139,7 @@ class MapsController < ApplicationController mapping.xloc = topic[1] mapping.yloc = topic[2] @map.topicmappings << mapping + authorize! mapping, :create mapping.save end @@ -142,6 +152,7 @@ class MapsController < ApplicationController mapping.map = @map mapping.mappable = Synapse.find(synapse_id) @map.synapsemappings << mapping + authorize! mapping, :create mapping.save end end @@ -149,6 +160,8 @@ class MapsController < ApplicationController @map.arranged = true end + authorize! @map + if @map.save respond_to do |format| format.json { render :json => @map } @@ -162,7 +175,8 @@ class MapsController < ApplicationController # PUT maps/:id def update - @map = Map.find(params[:id]).authorize_to_edit(current_user) + @map = Map.find(params[:id]) + authorize! @map respond_to do |format| if !@map @@ -177,42 +191,36 @@ class MapsController < ApplicationController # POST maps/:id/upload_screenshot def screenshot - @map = Map.find(params[:id]).authorize_to_edit(current_user) + @map = Map.find(params[:id]) + authorize! @map - if @map - png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) - StringIO.open(png) do |data| - data.class.class_eval { attr_accessor :original_filename, :content_type } - data.original_filename = "map-" + @map.id.to_s + "-screenshot.png" - data.content_type = "image/png" - @map.screenshot = data - end + png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) + StringIO.open(png) do |data| + data.class.class_eval { attr_accessor :original_filename, :content_type } + data.original_filename = "map-" + @map.id.to_s + "-screenshot.png" + data.content_type = "image/png" + @map.screenshot = data + end - if @map.save - render :json => {:message => "Successfully uploaded the map screenshot."} - else - render :json => {:message => "Failed to upload image."} - end - else - render :json => {:message => "Unauthorized to set map screenshot."} - end + if @map.save + render :json => {:message => "Successfully uploaded the map screenshot."} + else + render :json => {:message => "Failed to upload image."} + end end # DELETE maps/:id def destroy - @map = Map.find(params[:id]).authorize_to_delete(current_user) + @map = Map.find(params[:id]) + authorize! @map - @map.delete if @map + @map.delete - respond_to do |format| - format.json { - if @map - render json: "success" - else - render json: "unauthorized" - end - } + respond_to do |format| + format.json do + head :no_content end + end end private diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index 46592dcc..f242ad38 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -2,19 +2,16 @@ class SynapsesController < ApplicationController include TopicsHelper before_action :require_user, only: [:create, :update, :destroy] + after_action :verify_authorized, except: :index + after_action :verify_policy_scoped, only: :index respond_to :json # GET /synapses/1.json def show @synapse = Synapse.find(params[:id]) + authorize! @synapse - #.authorize_to_show(current_user) - - #if not @synapse - # redirect_to root_url and return - #end - render json: @synapse end @@ -23,6 +20,7 @@ class SynapsesController < ApplicationController def create @synapse = Synapse.new(synapse_params) @synapse.desc = "" if @synapse.desc.nil? + authorize! @synapse respond_to do |format| if @synapse.save @@ -38,6 +36,7 @@ class SynapsesController < ApplicationController def update @synapse = Synapse.find(params[:id]) @synapse.desc = "" if @synapse.desc.nil? + authorize! @synapse respond_to do |format| if @synapse.update_attributes(synapse_params) @@ -50,8 +49,9 @@ class SynapsesController < ApplicationController # DELETE synapses/:id def destroy - @synapse = Synapse.find(params[:id]).authorize_to_delete(current_user) - @synapse.delete if @synapse + @synapse = Synapse.find(params[:id]) + authorize! @synapse + @synapse.delete respond_to do |format| format.json { head :no_content } diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 4d11f8ca..125005f9 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -2,19 +2,15 @@ class TopicsController < ApplicationController include TopicsHelper before_action :require_user, only: [:create, :update, :destroy] - + after_action :verify_authorized + respond_to :html, :js, :json # GET /topics/autocomplete_topic def autocomplete_topic term = params[:term] if term && !term.empty? - @topics = Topic.where('LOWER("name") like ?', term.downcase + '%').order('"name"') - - #read this next line as 'delete a topic if its private and you're either - #1. logged out or 2. logged in but not the topic creator - @topics.to_a.delete_if {|t| t.permission == "private" && - (!authenticated? || (authenticated? && current_user.id != t.user_id)) } + @topics = policy_scope(Topic.where('LOWER("name") like ?', term.downcase + '%')).order('"name"') else @topics = [] end @@ -23,28 +19,16 @@ class TopicsController < ApplicationController # GET topics/:id def show - @topic = Topic.find(params[:id]).authorize_to_show(current_user) - - if not @topic - redirect_to root_url, notice: "Access denied. That topic is private." and return - end + @topic = Topic.find(params[:id]) + authorize! @topic respond_to do |format| format.html { - @alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } # should limit to topics visible to user - @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) } + @alltopics = ([@topic] + policy_scope(@topic.relatives) + @allsynapses = policy_scope(@topic.synapses) - @allcreators = [] - @alltopics.each do |t| - if @allcreators.index(t.user) == nil - @allcreators.push(t.user) - end - end - @allsynapses.each do |s| - if @allcreators.index(s.user) == nil - @allcreators.push(s.user) - end - end + @allcreators = @alltopics.map(&:user).uniq + @allcreators += @allsynapses.map(&:user).uniq respond_with(@allsynapses, @alltopics, @allcreators, @topic) } @@ -54,27 +38,15 @@ class TopicsController < ApplicationController # GET topics/:id/network def network - @topic = Topic.find(params[:id]).authorize_to_show(current_user) + @topic = Topic.find(params[:id]) + authorize! @topic - if not @topic - redirect_to root_url, notice: "Access denied. That topic is private." and return - end + @alltopics = [@topic] + policy_scope(@topic.relatives) + @allsynapses = policy_scope(@topic.synapses) + + @allcreators = @alltopics.map(&:user).uniq + @allcreators += @allsynapses.map(&:user).uniq - @alltopics = @topic.relatives.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } - @allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) } - @allcreators = [] - @allcreators.push(@topic.user) - @alltopics.each do |t| - if @allcreators.index(t.user) == nil - @allcreators.push(t.user) - end - end - @allsynapses.each do |s| - if @allcreators.index(s.user) == nil - @allcreators.push(s.user) - end - end - @json = Hash.new() @json['topic'] = @topic @json['creators'] = @allcreators @@ -88,118 +60,99 @@ class TopicsController < ApplicationController # GET topics/:id/relative_numbers def relative_numbers - @topic = Topic.find(params[:id]).authorize_to_show(current_user) + @topic = Topic.find(params[:id]) + authorize @topic - if not @topic - redirect_to root_url, notice: "Access denied. That topic is private." and return + topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : [] + + @alltopics = policy_scope(@topic.relatives).to_a.uniq + @alltopics.delete_if! do |topic| + topicsAlreadyHas.index(topic.id) != nil end - @topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] - - @alltopics = @topic.relatives.to_a.delete_if {|t| - @topicsAlreadyHas.index(t.id.to_s) != nil || - (t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id))) - } - - @alltopics.uniq! - - @json = Hash.new() + @json = Hash.new(0) @alltopics.each do |t| - if @json[t.metacode.id] - @json[t.metacode.id] += 1 - else - @json[t.metacode.id] = 1 - end + @json[t.metacode.id] += 1 end respond_to do |format| - format.json { render json: @json } + format.json { render json: @json } end end # GET topics/:id/relatives def relatives - @topic = Topic.find(params[:id]).authorize_to_show(current_user) + @topic = Topic.find(params[:id]) + authorize! @topic - if not @topic - redirect_to root_url, notice: "Access denied. That topic is private." and return - end + topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : [] - @topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] + alltopics = policy_scope(@topic.relatives).to_a.uniq.delete_if do |topic| + topicsAlreadyHas.index(topic.id.to_s) != nil + end - @alltopics = @topic.relatives.to_a.delete_if {|t| - @topicsAlreadyHas.index(t.id.to_s) != nil || - (params[:metacode] && t.metacode_id.to_s != params[:metacode]) || - (t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id))) - } + #find synapses between topics in alltopics array + allsynapses = policy_scope(@topic.synapses) + synapse_ids = (allsynapses.map(&:topic1_id) + allsynapses.map(&:topic2_id)).uniq + allsynapses.delete_if! do |synapse| + synapse_ids.index(synapse.id) != nil + end - @alltopics.uniq! + creatorsAlreadyHas = params[:creators] ? params[:creators].split(',').map(&:to_i) : [] + allcreators = (alltopics.map(&:user) + allsynapses.map(&:user)).uniq.delete_if do |user| + creatorsAlreadyHas.index(user.id) != nil + end - @allsynapses = @topic.synapses.to_a.delete_if {|s| - (s.topic1 == @topic && @alltopics.index(s.topic2) == nil) || - (s.topic2 == @topic && @alltopics.index(s.topic1) == nil) - } + @json = Hash.new() + @json['topics'] = alltopics + @json['synapses'] = allsynapses + @json['creators'] = allcreators - @creatorsAlreadyHas = params[:creators] ? params[:creators].split(',') : [] - @allcreators = [] - @alltopics.each do |t| - if @allcreators.index(t.user) == nil && @creatorsAlreadyHas.index(t.user_id.to_s) == nil - @allcreators.push(t.user) - end - end - @allsynapses.each do |s| - if @allcreators.index(s.user) == nil && @creatorsAlreadyHas.index(s.user_id.to_s) == nil - @allcreators.push(s.user) - end - end - - @json = Hash.new() - @json['topics'] = @alltopics - @json['synapses'] = @allsynapses - @json['creators'] = @allcreators - - respond_to do |format| - format.json { render json: @json } - end + respond_to do |format| + format.json { render json: @json } + end end - # POST /topics - # POST /topics.json - def create - @topic = Topic.new(topic_params) + # POST /topics + # POST /topics.json + def create + @topic = Topic.new(topic_params) + authorize! @topic - respond_to do |format| - if @topic.save - format.json { render json: @topic, status: :created } - else - format.json { render json: @topic.errors, status: :unprocessable_entity } - end - end + respond_to do |format| + if @topic.save + format.json { render json: @topic, status: :created } + else + format.json { render json: @topic.errors, status: :unprocessable_entity } + end end + end - # PUT /topics/1 - # PUT /topics/1.json - def update - @topic = Topic.find(params[:id]) + # PUT /topics/1 + # PUT /topics/1.json + def update + @topic = Topic.find(params[:id]) + authorize! @topic - respond_to do |format| - if @topic.update_attributes(topic_params) - format.json { head :no_content } - else - format.json { render json: @topic.errors, status: :unprocessable_entity } - end - end + respond_to do |format| + if @topic.update_attributes(topic_params) + format.json { head :no_content } + else + format.json { render json: @topic.errors, status: :unprocessable_entity } + end end + end - # DELETE topics/:id - def destroy - @topic = Topic.find(params[:id]).authorize_to_delete(current_user) - @topic.delete if @topic + # DELETE topics/:id + def destroy + @topic = Topic.find(params[:id]) + authorize! @topic - respond_to do |format| - format.json { head :no_content } - end + @topic.delete + respond_to do |format| + format.json { head :no_content } end + end private From 669b337d04815d136d5b97ee3af638509fcc7a46 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 09:37:18 +1100 Subject: [PATCH 25/67] changes for api --- Gemfile | 2 ++ Gemfile.lock | 10 +++++++--- app/controllers/api/restful_controller.rb | 24 +++++++++++++++-------- app/controllers/api/tokens_controller.rb | 4 +++- app/models/logged_out_user.rb | 7 ------- 5 files changed, 28 insertions(+), 19 deletions(-) delete mode 100644 app/models/logged_out_user.rb diff --git a/Gemfile b/Gemfile index a0600ced..b7ea08e9 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,8 @@ gem 'devise' gem 'redis' gem 'pg' gem 'pundit' +gem 'cancan' +gem 'pundit_extra' gem 'formula' gem 'formtastic' gem 'json' diff --git a/Gemfile.lock b/Gemfile.lock index 9e9731a6..a2a3b031 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -56,8 +56,9 @@ GEM binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) - byebug (5.0.0) - columnize (= 0.9.0) + byebug (8.2.2) + cancan (1.6.10) + cancancan (1.10.1) climate_control (0.0.3) activesupport (>= 3.0) cocaine (0.5.8) @@ -144,6 +145,7 @@ GEM pry (>= 0.9.10) pundit (1.1.0) activesupport (>= 3.0.0) + pundit_extra (0.1.1) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) rack (1.6.4) @@ -180,7 +182,7 @@ GEM activesupport (= 4.2.4) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (11.0.1) + rake (11.1.0) redis (3.2.2) responders (2.1.1) railties (>= 4.2.0, < 5.1) @@ -251,6 +253,7 @@ DEPENDENCIES best_in_place better_errors binding_of_caller + cancan coffee-rails devise dotenv @@ -268,6 +271,7 @@ DEPENDENCIES pry-byebug pry-rails pundit + pundit_extra quiet_assets rails (= 4.2.4) rails3-jquery-autocomplete diff --git a/app/controllers/api/restful_controller.rb b/app/controllers/api/restful_controller.rb index d56783a0..ca7ff481 100644 --- a/app/controllers/api/restful_controller.rb +++ b/app/controllers/api/restful_controller.rb @@ -1,24 +1,32 @@ class API::RestfulController < ActionController::Base + include Pundit + include PunditExtra + snorlax_used_rest! + rescue_from(Pundit::NotAuthorizedError) { |e| respond_with_standard_error e, 403 } + load_and_authorize_resource except: [:index, :create] + def create - raise CanCan::AccessDenied.new unless current_user.is_logged_in? + authorize resource_class instantiate_resouce resource.user = current_user create_action respond_with_resource end - def show - load_resource - raise AccessDenied.new unless resource.authorize_to_show(current_user) - respond_with_resource - end - private + def accessible_records + if current_user + visible_records + else + public_records + end + end + def current_user - super || token_user || LoggedOutUser.new + super || token_user || nil end def token_user diff --git a/app/controllers/api/tokens_controller.rb b/app/controllers/api/tokens_controller.rb index cc54e531..6ef01e69 100644 --- a/app/controllers/api/tokens_controller.rb +++ b/app/controllers/api/tokens_controller.rb @@ -1,7 +1,9 @@ class Api::TokensController < API::RestfulController + + skip_authorization def my_tokens - raise CanCan::AccessDenied.new unless current_user.is_logged_in? + raise Pundit::NotAuthorizedError.new unless current_user.is_logged_in? instantiate_collection page_collection: false, timeframe_collection: false respond_with_collection end diff --git a/app/models/logged_out_user.rb b/app/models/logged_out_user.rb deleted file mode 100644 index 14e0cfb9..00000000 --- a/app/models/logged_out_user.rb +++ /dev/null @@ -1,7 +0,0 @@ -class LoggedOutUser - - FALSE_METHODS = [:is_logged_in?] - - FALSE_METHODS.each { |method| define_method(method, -> { false }) } - -end From 450db5eb8d2e641eefcfa1b9642223108d12a943 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 09:37:32 +1100 Subject: [PATCH 26/67] changes for pundit --- app/controllers/application_controller.rb | 1 + app/controllers/main_controller.rb | 4 +-- app/controllers/maps_controller.rb | 36 ++++++++--------------- app/models/map.rb | 29 ------------------ app/models/synapse.rb | 26 ---------------- app/models/topic.rb | 27 ----------------- app/policies/application_policy.rb | 2 +- app/policies/map_policy.rb | 2 +- app/policies/mapping_policy.rb | 2 +- 9 files changed, 19 insertions(+), 110 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6d10c553..d030c6e6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,6 @@ class ApplicationController < ActionController::Base include Pundit + include PunditExtra rescue_from Pundit::NotAuthorizedError, with: :handle_unauthorized protect_from_forgery diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 29c11777..efebdce7 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -4,8 +4,8 @@ class MainController < ApplicationController include UsersHelper include SynapsesHelper - after_action :verify_authorized, except: :index - after_action :verify_policy_scoped, only: :index +# after_action :verify_authorized, except: :index +# after_action :verify_policy_scoped, only: :index respond_to :html, :json diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index a778de9a..fd169083 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,8 +1,8 @@ class MapsController < ApplicationController before_action :require_user, only: [:create, :update, :screenshot, :destroy] - after_action :verify_authorized, except: :activemaps, :featuredmaps, :mymaps, :usermaps - after_action :verify_policy_scoped, only: :activemaps, :featuredmaps, :mymaps, :usermaps + after_action :verify_authorized, except: [:activemaps, :featuredmaps, :mymaps, :usermaps] + after_action :verify_policy_scoped, only: [:activemaps, :featuredmaps, :mymaps, :usermaps] respond_to :html, :json @@ -68,11 +68,7 @@ class MapsController < ApplicationController # GET maps/:id def show @map = Map.find(params[:id]) - authorize! @map - - if not @map - redirect_to root_url, notice: "Access denied. That map is private." and return - end + authorize @map respond_to do |format| format.html { @@ -86,18 +82,14 @@ class MapsController < ApplicationController respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map) } - format.json { render json: @map } + format.json { render json: @map.as_json } end end # GET maps/:id/contains def contains @map = Map.find(params[:id]) - authorize! @map - - if not @map - redirect_to root_url, notice: "Access denied. That map is private." and return - end + authorize @map @allmappers = @map.contributors @alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } @@ -140,7 +132,7 @@ class MapsController < ApplicationController mapping.xloc = topic[1] mapping.yloc = topic[2] @map.topicmappings << mapping - authorize! mapping, :create + authorize mapping, :create mapping.save end @@ -153,7 +145,7 @@ class MapsController < ApplicationController mapping.map = @map mapping.mappable = Synapse.find(synapse_id) @map.synapsemappings << mapping - authorize! mapping, :create + authorize mapping, :create mapping.save end end @@ -161,7 +153,7 @@ class MapsController < ApplicationController @map.arranged = true end - authorize! @map + authorize @map if @map.save respond_to do |format| @@ -177,12 +169,10 @@ class MapsController < ApplicationController # PUT maps/:id def update @map = Map.find(params[:id]) - authorize! @map + authorize @map respond_to do |format| - if !@map - format.json { render json: "unauthorized" } - elsif @map.update_attributes(map_params) + if @map.update_attributes(map_params) format.json { head :no_content } else format.json { render json: @map.errors, status: :unprocessable_entity } @@ -193,7 +183,7 @@ class MapsController < ApplicationController # POST maps/:id/upload_screenshot def screenshot @map = Map.find(params[:id]) - authorize! @map + authorize @map png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) StringIO.open(png) do |data| @@ -213,7 +203,7 @@ class MapsController < ApplicationController # DELETE maps/:id def destroy @map = Map.find(params[:id]) - authorize! @map + authorize @map @map.delete @@ -228,6 +218,6 @@ class MapsController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def map_params - params.require(:map).permit(:id, :name, :arranged, :desc, :permission, :user_id) + params.require(:map).permit(:id, :name, :arranged, :desc, :permission) end end diff --git a/app/models/map.rb b/app/models/map.rb index 6c2caca2..87c8d641 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -78,36 +78,7 @@ class Map < ActiveRecord::Base json[:updated_at_clean] = updated_at_str json end - - ##### PERMISSIONS ###### - def authorize_to_delete(user) - if (self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'show' Topic, Synapse, or Map - def authorize_to_show(user) - if (self.permission == "private" && self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'edit' Topic, Synapse, or Map - def authorize_to_edit(user) - if !user - return false - elsif (self.permission == "private" && self.user != user) - return false - elsif (self.permission == "public" && self.user != user) - return false - end - return self - end - def decode_base64(imgBase64) decoded_data = Base64.decode64(imgBase64) diff --git a/app/models/synapse.rb b/app/models/synapse.rb index c766d95c..d545a25c 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -34,30 +34,4 @@ class Synapse < ActiveRecord::Base end # :nocov: - ##### PERMISSIONS ###### - - # returns false if user not allowed to 'show' Topic, Synapse, or Map - def authorize_to_show(user) - if (self.permission == "private" && self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'edit' Topic, Synapse, or Map - def authorize_to_edit(user) - if (self.permission == "private" && self.user != user) - return false - elsif (self.permission == "public" && self.user != user) - return false - end - return self - end - - def authorize_to_delete(user) - if (self.user == user || user.admin) - return self - end - return false - end end diff --git a/app/models/topic.rb b/app/models/topic.rb index c528aa6e..0039040e 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -87,31 +87,4 @@ class Topic < ActiveRecord::Base end result end - - ##### PERMISSIONS ###### - - # returns false if user not allowed to 'show' Topic, Synapse, or Map - def authorize_to_show(user) - if (self.permission == "private" && self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'edit' Topic, Synapse, or Map - def authorize_to_edit(user) - if (self.permission == "private" && self.user != user) - return false - elsif (self.permission == "public" && self.user != user) - return false - end - return self - end - - def authorize_to_delete(user) - if (self.user == user || user.admin) - return self - end - return false - end end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 6bd56c64..39b7a961 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -39,7 +39,7 @@ class ApplicationPolicy # explicitly say they want to (E.g. seeing/editing/deleting private # maps - they should be able to, but not by accident) def admin_override - user.admin + user && user.admin end def scope diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 671eea83..5e845d44 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -1,7 +1,7 @@ class MapPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) end end diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 44e7bfd7..49e134ef 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -5,7 +5,7 @@ class MappingPolicy < ApplicationPolicy # it would be nice if we could also base this on the mappable, but that # gets really complicated. Devin thinks it's OK to SHOW a mapping for # a private topic, since you can't see the private topic anyways - scope.joins(:maps).where('maps.permission IN ("public", "commons") OR user_id = ?', user.id) + scope.joins(:maps).where('maps.permission IN ("public", "commons") OR maps.user_id = ?', user.id) end end From 77d39d664999935b6ac112e6e1c2adfcef05e4f9 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 09:48:07 +1100 Subject: [PATCH 27/67] redid so they won't interfere --- .../{map_serializer.rb => new_map_serializer.rb} | 10 +++++----- ...mapping_serializer.rb => new_mapping_serializer.rb} | 8 ++++---- ...tacode_serializer.rb => new_metacode_serializer.rb} | 2 +- ...synapse_serializer.rb => new_synapse_serializer.rb} | 8 ++++---- .../{topic_serializer.rb => new_topic_serializer.rb} | 6 +++--- .../{user_serializer.rb => new_user_serializer.rb} | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) rename app/serializers/{map_serializer.rb => new_map_serializer.rb} (52%) rename app/serializers/{mapping_serializer.rb => new_mapping_serializer.rb} (61%) rename app/serializers/{metacode_serializer.rb => new_metacode_serializer.rb} (67%) rename app/serializers/{synapse_serializer.rb => new_synapse_serializer.rb} (56%) rename app/serializers/{topic_serializer.rb => new_topic_serializer.rb} (66%) rename app/serializers/{user_serializer.rb => new_user_serializer.rb} (80%) diff --git a/app/serializers/map_serializer.rb b/app/serializers/new_map_serializer.rb similarity index 52% rename from app/serializers/map_serializer.rb rename to app/serializers/new_map_serializer.rb index b9839782..1e27420b 100644 --- a/app/serializers/map_serializer.rb +++ b/app/serializers/new_map_serializer.rb @@ -1,4 +1,4 @@ -class MapSerializer < ActiveModel::Serializer +class NewMapSerializer < ActiveModel::Serializer embed :ids, include: true attributes :id, :name, @@ -8,10 +8,10 @@ class MapSerializer < ActiveModel::Serializer :created_at, :updated_at - has_many :topics - has_many :synapses - has_many :mappings - has_many :contributors, root: :users + has_many :topics, serializer: NewTopicSerializer + has_many :synapses, serializer: NewSynapseSerializer + has_many :mappings, serializer: NewMappingSerializer + has_many :contributors, root: :users, serializer: NewUserSerializer #def filter(keys) # keys.delete(:outcome_author) unless object.outcome_author.present? diff --git a/app/serializers/mapping_serializer.rb b/app/serializers/new_mapping_serializer.rb similarity index 61% rename from app/serializers/mapping_serializer.rb rename to app/serializers/new_mapping_serializer.rb index 400c35ba..9241305a 100644 --- a/app/serializers/mapping_serializer.rb +++ b/app/serializers/new_mapping_serializer.rb @@ -1,13 +1,13 @@ -class MappingSerializer < ActiveModel::Serializer +class NewMappingSerializer < ActiveModel::Serializer embed :ids, include: true attributes :id, :xloc, :yloc, :created_at, :updated_at - has_one :user - has_one :map - has_one :mappable, polymorphic: true + has_one :user, serializer: NewUserSerializer + has_one :map, serializer: NewMapSerializer + has_one :mappable, polymorphic: true ##? def filter(keys) keys.delete(:xloc) unless object.mappable_type == "Topic" diff --git a/app/serializers/metacode_serializer.rb b/app/serializers/new_metacode_serializer.rb similarity index 67% rename from app/serializers/metacode_serializer.rb rename to app/serializers/new_metacode_serializer.rb index 3918d274..e664e7ea 100644 --- a/app/serializers/metacode_serializer.rb +++ b/app/serializers/new_metacode_serializer.rb @@ -1,4 +1,4 @@ -class MetacodeSerializer < ActiveModel::Serializer +class NewMetacodeSerializer < ActiveModel::Serializer attributes :id, :name, :manual_icon, diff --git a/app/serializers/synapse_serializer.rb b/app/serializers/new_synapse_serializer.rb similarity index 56% rename from app/serializers/synapse_serializer.rb rename to app/serializers/new_synapse_serializer.rb index 77c3a159..e7cd9fd7 100644 --- a/app/serializers/synapse_serializer.rb +++ b/app/serializers/new_synapse_serializer.rb @@ -1,4 +1,4 @@ -class SynapseSerializer < ActiveModel::Serializer +class NewSynapseSerializer < ActiveModel::Serializer embed :ids, include: true attributes :id, :desc, @@ -8,9 +8,9 @@ class SynapseSerializer < ActiveModel::Serializer :created_at, :updated_at - has_one :topic1, root: :topics - has_one :topic2, root: :topics - has_one :user + has_one :topic1, root: :topics, serializer: NewTopicSerializer + has_one :topic2, root: :topics, serializer: NewTopicSerializer + has_one :user, serializer: NewUserSerializer #def filter(keys) # keys.delete(:outcome_author) unless object.outcome_author.present? diff --git a/app/serializers/topic_serializer.rb b/app/serializers/new_topic_serializer.rb similarity index 66% rename from app/serializers/topic_serializer.rb rename to app/serializers/new_topic_serializer.rb index 205b8178..d36f1db0 100644 --- a/app/serializers/topic_serializer.rb +++ b/app/serializers/new_topic_serializer.rb @@ -1,4 +1,4 @@ -class TopicSerializer < ActiveModel::Serializer +class NewTopicSerializer < ActiveModel::Serializer embed :ids, include: true attributes :id, :name, @@ -8,8 +8,8 @@ class TopicSerializer < ActiveModel::Serializer :created_at, :updated_at - has_one :user - has_one :metacode + has_one :user, serializer: NewUserSerializer + has_one :metacode, serializer: NewMetacodeSerializer #def filter(keys) # keys.delete(:outcome_author) unless object.outcome_author.present? diff --git a/app/serializers/user_serializer.rb b/app/serializers/new_user_serializer.rb similarity index 80% rename from app/serializers/user_serializer.rb rename to app/serializers/new_user_serializer.rb index b9a3b416..45be36b0 100644 --- a/app/serializers/user_serializer.rb +++ b/app/serializers/new_user_serializer.rb @@ -1,4 +1,4 @@ -class UserSerializer < ActiveModel::Serializer +class NewUserSerializer < ActiveModel::Serializer attributes :id, :name, :avatar, From 623b3c7ad7ae2b9c8a4703b812bcbc50e60b2306 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 09:54:23 +1100 Subject: [PATCH 28/67] can load maps --- app/views/layouts/application.html.erb | 2 +- app/views/maps/_mapinfobox.html.erb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index c09d227e..0480cb39 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -81,7 +81,7 @@ classes += controller_name == "maps" && action_name == "index" ? " explorePage" : "" if controller_name == "maps" && action_name == "show" classes += " mapPage" - if @map.authorize_to_edit(current_user) + if policy(@map).update? classes += " canEditMap" end if @map.permission == "commons" diff --git a/app/views/maps/_mapinfobox.html.erb b/app/views/maps/_mapinfobox.html.erb index 1fa6da02..ff90532c 100644 --- a/app/views/maps/_mapinfobox.html.erb +++ b/app/views/maps/_mapinfobox.html.erb @@ -4,7 +4,7 @@ #%>
- <%= @map && @map.authorize_to_edit(user) ? " canEdit" : "" %> + <%= @map && policy(@map).update? ? " canEdit" : "" %> <%= @map && @map.permission != 'private' ? " shareable" : "" %>"> <% if @map %> @@ -41,7 +41,7 @@
- <% if (authenticated? && @map.authorize_to_edit(user)) || (!authenticated? && @map.desc != "" && @map.desc != nil )%> + <% if (authenticated? && policy(@map).update?) || (!authenticated? && @map.desc != "" && @map.desc != nil )%> <%= best_in_place @map, :desc, :activator => "#mapInfoDesc", :as => :textarea, :placeholder => "Click to add description...", :class => 'best_in_place_desc' %> <% end %>
From fc1a7fd23d2e10f6db4f1844694ad0c7114db27d Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:05:42 +1100 Subject: [PATCH 29/67] api: adjust serializers --- app/controllers/api/restful_controller.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/api/restful_controller.rb b/app/controllers/api/restful_controller.rb index ca7ff481..d6c544e2 100644 --- a/app/controllers/api/restful_controller.rb +++ b/app/controllers/api/restful_controller.rb @@ -17,6 +17,10 @@ class API::RestfulController < ActionController::Base private + def resource_serializer + "new_#{resource_name}_serializer".camelize.constantize + end + def accessible_records if current_user visible_records From 0095a8daf42b0b5dbf8a05e6e5ccdc53d4bb8ab0 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:06:00 +1100 Subject: [PATCH 30/67] pundit: syntax error --- app/controllers/topics_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 125005f9..e9239bac 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -24,7 +24,7 @@ class TopicsController < ApplicationController respond_to do |format| format.html { - @alltopics = ([@topic] + policy_scope(@topic.relatives) + @alltopics = ([@topic] + policy_scope(@topic.relatives)) @allsynapses = policy_scope(@topic.synapses) @allcreators = @alltopics.map(&:user).uniq From c7075dab48c80cdfede708d0d95ee7390d366f12 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:10:31 +1100 Subject: [PATCH 31/67] pundit: fix queries --- app/policies/mapping_policy.rb | 3 ++- app/policies/synapse_policy.rb | 2 +- app/policies/topic_policy.rb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 49e134ef..39dbd86a 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -5,7 +5,8 @@ class MappingPolicy < ApplicationPolicy # it would be nice if we could also base this on the mappable, but that # gets really complicated. Devin thinks it's OK to SHOW a mapping for # a private topic, since you can't see the private topic anyways - scope.joins(:maps).where('maps.permission IN ("public", "commons") OR maps.user_id = ?', user.id) + scope.joins(:maps).where('maps.permission IN (?) OR maps.user_id = ?', + ["public", "commons"], user.id) end end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 6763014a..12f9c8ca 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,7 +1,7 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 03b42895..97fefdcc 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,7 +1,7 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) end end From 09a7b336bf1200f4368852dc9e1535cc7c050983 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:13:22 +1100 Subject: [PATCH 32/67] pundit: exclude topic action --- app/controllers/topics_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index e9239bac..0d58d912 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -2,7 +2,7 @@ class TopicsController < ApplicationController include TopicsHelper before_action :require_user, only: [:create, :update, :destroy] - after_action :verify_authorized + after_action :verify_authorized, except: :autocomplete_topic respond_to :html, :js, :json From bef21341c6a1ae7cccd2f89705087661746c9c25 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:10:30 +1100 Subject: [PATCH 33/67] pundit: fixing up topics and synapses --- app/controllers/synapses_controller.rb | 8 ++++---- app/controllers/topics_controller.rb | 16 ++++++++-------- app/models/synapse.rb | 4 ++++ app/models/topic.rb | 7 +++++++ app/policies/synapse_policy.rb | 2 +- app/policies/topic_policy.rb | 2 +- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index f242ad38..4440872f 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -10,7 +10,7 @@ class SynapsesController < ApplicationController # GET /synapses/1.json def show @synapse = Synapse.find(params[:id]) - authorize! @synapse + authorize @synapse render json: @synapse end @@ -20,7 +20,7 @@ class SynapsesController < ApplicationController def create @synapse = Synapse.new(synapse_params) @synapse.desc = "" if @synapse.desc.nil? - authorize! @synapse + authorize @synapse respond_to do |format| if @synapse.save @@ -36,7 +36,7 @@ class SynapsesController < ApplicationController def update @synapse = Synapse.find(params[:id]) @synapse.desc = "" if @synapse.desc.nil? - authorize! @synapse + authorize @synapse respond_to do |format| if @synapse.update_attributes(synapse_params) @@ -50,7 +50,7 @@ class SynapsesController < ApplicationController # DELETE synapses/:id def destroy @synapse = Synapse.find(params[:id]) - authorize! @synapse + authorize @synapse @synapse.delete respond_to do |format| diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 0d58d912..1b1e9b3c 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -20,12 +20,12 @@ class TopicsController < ApplicationController # GET topics/:id def show @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic respond_to do |format| format.html { - @alltopics = ([@topic] + policy_scope(@topic.relatives)) - @allsynapses = policy_scope(@topic.synapses) + @alltopics = ([@topic] + policy_scope(Topic.relatives(@topic.id))) + @allsynapses = policy_scope(Synapse.for_topic(@topic.id)) @allcreators = @alltopics.map(&:user).uniq @allcreators += @allsynapses.map(&:user).uniq @@ -39,7 +39,7 @@ class TopicsController < ApplicationController # GET topics/:id/network def network @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic @alltopics = [@topic] + policy_scope(@topic.relatives) @allsynapses = policy_scope(@topic.synapses) @@ -83,7 +83,7 @@ class TopicsController < ApplicationController # GET topics/:id/relatives def relatives @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : [] @@ -117,7 +117,7 @@ class TopicsController < ApplicationController # POST /topics.json def create @topic = Topic.new(topic_params) - authorize! @topic + authorize @topic respond_to do |format| if @topic.save @@ -132,7 +132,7 @@ class TopicsController < ApplicationController # PUT /topics/1.json def update @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic respond_to do |format| if @topic.update_attributes(topic_params) @@ -146,7 +146,7 @@ class TopicsController < ApplicationController # DELETE topics/:id def destroy @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic @topic.delete respond_to do |format| diff --git a/app/models/synapse.rb b/app/models/synapse.rb index d545a25c..540376bb 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -16,6 +16,10 @@ class Synapse < ActiveRecord::Base validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true } + scope :for_topic, ->(topic_id = nil) { + where("node1_id = ? OR node2_id = ?", topic_id, topic_id) + } + # :nocov: def user_name user.name diff --git a/app/models/topic.rb b/app/models/topic.rb index 0039040e..0f312823 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -41,6 +41,13 @@ class Topic < ActiveRecord::Base belongs_to :metacode + scope :relatives, ->(topic_id = nil) { + includes(:synapses1) + .includes(:synapses2) + .where('synapses.node1_id = ? OR synapses.node2_id = ?', topic_id, topic_id) + .references(:synapses) + } + def user_name user.name end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 12f9c8ca..85de12da 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,7 +1,7 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) + scope.where('synapses.permission IN (?) OR synapses.user_id = ?', ["public", "commons"], user.id) end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 97fefdcc..43d4ec98 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,7 +1,7 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) + scope.where('topics.permission IN (?) OR topics.user_id = ?', ["public", "commons"], user.id) end end From 4ed00240ebff82816943f4fd82e6ce722cd66685 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:15:14 +1100 Subject: [PATCH 34/67] api: revert silly js change --- app/assets/javascripts/src/Metamaps.js.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/app/assets/javascripts/src/Metamaps.js.erb index 95cf7379..ff6d57e6 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/app/assets/javascripts/src/Metamaps.js.erb @@ -4083,7 +4083,7 @@ Metamaps.Topic = { }; var topicSuccessCallback = function (topicModel, response) { if (Metamaps.Active.Map) { - mapping.save({ mappable_id: topicModel.get('topic').id }, { + mapping.save({ mappable_id: topicModel.id }, { success: mappingSuccessCallback, error: function (model, response) { console.log('error saving mapping to database'); @@ -4254,7 +4254,7 @@ Metamaps.Synapse = { }; var synapseSuccessCallback = function (synapseModel, response) { if (Metamaps.Active.Map) { - mapping.save({ mappable_id: synapseModel.get('synapse').id }, { + mapping.save({ mappable_id: synapseModel.id }, { success: mappingSuccessCallback }); } From cb79f2deae4aad86eb2c4b6bd89b02b27b62cc00 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:16:46 +1100 Subject: [PATCH 35/67] pundit: make it work --- app/controllers/mappings_controller.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index 5b64efe1..897d1ee1 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -9,7 +9,7 @@ class MappingsController < ApplicationController # GET /mappings/1.json def show @mapping = Mapping.find(params[:id]) - authorize! @mapping + authorize @mapping render json: @mapping end @@ -17,8 +17,8 @@ class MappingsController < ApplicationController # POST /mappings.json def create @mapping = Mapping.new(mapping_params) - authorize! @mapping - + authorize @mapping + @mapping.user = current_user if @mapping.save render json: @mapping, status: :created else @@ -29,7 +29,7 @@ class MappingsController < ApplicationController # PUT /mappings/1.json def update @mapping = Mapping.find(params[:id]) - authorize! @mapping + authorize @mapping if @mapping.update_attributes(mapping_params) head :no_content @@ -41,7 +41,7 @@ class MappingsController < ApplicationController # DELETE /mappings/1.json def destroy @mapping = Mapping.find(params[:id]) - authorize! @mapping + authorize @mapping @mapping.destroy @@ -51,6 +51,6 @@ class MappingsController < ApplicationController private # Never trust parameters from the scary internet, only allow the white list through. def mapping_params - params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id, :user_id) + params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id) end end From fdd93513785fff6334aaffdac161a2c078a1277a Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:24:49 +1100 Subject: [PATCH 36/67] pundit: policy didn't exist --- app/policies/mapping_policy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 39dbd86a..13ef033e 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -18,7 +18,7 @@ class MappingPolicy < ApplicationPolicy def create? map = policy(record.map, user) - map.edit? + map.update? end def update? From d0fd676aa01db64496d0322923ae0221877430f4 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:35:03 +1100 Subject: [PATCH 37/67] pundit: now updating maps actually works --- app/policies/map_policy.rb | 1 - app/policies/mapping_policy.rb | 10 ++++------ app/policies/synapse_policy.rb | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 5e845d44..50123877 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -35,7 +35,6 @@ class MapPolicy < ApplicationPolicy def update? user.present? && (record.permission == 'commons' || record.user == user) - true end def screenshot? diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 13ef033e..787b5794 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -11,19 +11,17 @@ class MappingPolicy < ApplicationPolicy end def show? - map = policy(record.map, user) - mappable = policy(record.mappable, user) + map = Pundit.policy(user, record.map) + mappable = Pundit.policy(user, record.mappable) map.show? && mappable.show? end def create? - map = policy(record.map, user) - map.update? + Pundit.policy(user, record.map).update? end def update? - map = policy(record.map, user) - map.update? + Pundit.policy(user, record.map).update? end def destroy? diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 85de12da..e8d49548 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -7,6 +7,7 @@ class SynapsePolicy < ApplicationPolicy def create? user.present? + # todo add validation against whether you can see both topics end def show? From d8c328468ed318f38b93f39112276935343fe7c9 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 09:37:32 +1100 Subject: [PATCH 38/67] changess for pundit --- app/controllers/application_controller.rb | 1 + app/controllers/main_controller.rb | 4 +-- app/controllers/maps_controller.rb | 36 ++++++++--------------- app/models/map.rb | 29 ------------------ app/models/synapse.rb | 26 ---------------- app/models/topic.rb | 27 ----------------- app/policies/application_policy.rb | 2 +- app/policies/map_policy.rb | 2 +- app/policies/mapping_policy.rb | 2 +- 9 files changed, 19 insertions(+), 110 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6d10c553..d030c6e6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,6 @@ class ApplicationController < ActionController::Base include Pundit + include PunditExtra rescue_from Pundit::NotAuthorizedError, with: :handle_unauthorized protect_from_forgery diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 29c11777..efebdce7 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -4,8 +4,8 @@ class MainController < ApplicationController include UsersHelper include SynapsesHelper - after_action :verify_authorized, except: :index - after_action :verify_policy_scoped, only: :index +# after_action :verify_authorized, except: :index +# after_action :verify_policy_scoped, only: :index respond_to :html, :json diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 016ba7b5..83f7cb89 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,7 +1,7 @@ class MapsController < ApplicationController before_action :require_user, only: [:create, :update, :screenshot, :destroy] - after_action :verify_authorized, except: :activemaps, :featuredmaps, :mymaps, :usermaps - after_action :verify_policy_scoped, only: :activemaps, :featuredmaps, :mymaps, :usermaps + after_action :verify_authorized, except: [:activemaps, :featuredmaps, :mymaps, :usermaps] + after_action :verify_policy_scoped, only: [:activemaps, :featuredmaps, :mymaps, :usermaps] respond_to :html, :json @@ -67,11 +67,7 @@ class MapsController < ApplicationController # GET maps/:id def show @map = Map.find(params[:id]) - authorize! @map - - if not @map - redirect_to root_url, notice: "Access denied. That map is private." and return - end + authorize @map respond_to do |format| format.html { @@ -85,18 +81,14 @@ class MapsController < ApplicationController respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map) } - format.json { render json: @map } + format.json { render json: @map.as_json } end end # GET maps/:id/contains def contains @map = Map.find(params[:id]) - authorize! @map - - if not @map - redirect_to root_url, notice: "Access denied. That map is private." and return - end + authorize @map @allmappers = @map.contributors @alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } @@ -139,7 +131,7 @@ class MapsController < ApplicationController mapping.xloc = topic[1] mapping.yloc = topic[2] @map.topicmappings << mapping - authorize! mapping, :create + authorize mapping, :create mapping.save end @@ -152,7 +144,7 @@ class MapsController < ApplicationController mapping.map = @map mapping.mappable = Synapse.find(synapse_id) @map.synapsemappings << mapping - authorize! mapping, :create + authorize mapping, :create mapping.save end end @@ -160,7 +152,7 @@ class MapsController < ApplicationController @map.arranged = true end - authorize! @map + authorize @map if @map.save respond_to do |format| @@ -176,12 +168,10 @@ class MapsController < ApplicationController # PUT maps/:id def update @map = Map.find(params[:id]) - authorize! @map + authorize @map respond_to do |format| - if !@map - format.json { render json: "unauthorized" } - elsif @map.update_attributes(map_params) + if @map.update_attributes(map_params) format.json { head :no_content } else format.json { render json: @map.errors, status: :unprocessable_entity } @@ -192,7 +182,7 @@ class MapsController < ApplicationController # POST maps/:id/upload_screenshot def screenshot @map = Map.find(params[:id]) - authorize! @map + authorize @map png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) StringIO.open(png) do |data| @@ -212,7 +202,7 @@ class MapsController < ApplicationController # DELETE maps/:id def destroy @map = Map.find(params[:id]) - authorize! @map + authorize @map @map.delete @@ -227,6 +217,6 @@ class MapsController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def map_params - params.require(:map).permit(:id, :name, :arranged, :desc, :permission, :user_id) + params.require(:map).permit(:id, :name, :arranged, :desc, :permission) end end diff --git a/app/models/map.rb b/app/models/map.rb index 6c2caca2..87c8d641 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -78,36 +78,7 @@ class Map < ActiveRecord::Base json[:updated_at_clean] = updated_at_str json end - - ##### PERMISSIONS ###### - def authorize_to_delete(user) - if (self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'show' Topic, Synapse, or Map - def authorize_to_show(user) - if (self.permission == "private" && self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'edit' Topic, Synapse, or Map - def authorize_to_edit(user) - if !user - return false - elsif (self.permission == "private" && self.user != user) - return false - elsif (self.permission == "public" && self.user != user) - return false - end - return self - end - def decode_base64(imgBase64) decoded_data = Base64.decode64(imgBase64) diff --git a/app/models/synapse.rb b/app/models/synapse.rb index ea5889cc..beda8976 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -32,30 +32,4 @@ class Synapse < ActiveRecord::Base end # :nocov: - ##### PERMISSIONS ###### - - # returns false if user not allowed to 'show' Topic, Synapse, or Map - def authorize_to_show(user) - if (self.permission == "private" && self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'edit' Topic, Synapse, or Map - def authorize_to_edit(user) - if (self.permission == "private" && self.user != user) - return false - elsif (self.permission == "public" && self.user != user) - return false - end - return self - end - - def authorize_to_delete(user) - if (self.user == user || user.admin) - return self - end - return false - end end diff --git a/app/models/topic.rb b/app/models/topic.rb index c528aa6e..0039040e 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -87,31 +87,4 @@ class Topic < ActiveRecord::Base end result end - - ##### PERMISSIONS ###### - - # returns false if user not allowed to 'show' Topic, Synapse, or Map - def authorize_to_show(user) - if (self.permission == "private" && self.user != user) - return false - end - return self - end - - # returns false if user not allowed to 'edit' Topic, Synapse, or Map - def authorize_to_edit(user) - if (self.permission == "private" && self.user != user) - return false - elsif (self.permission == "public" && self.user != user) - return false - end - return self - end - - def authorize_to_delete(user) - if (self.user == user || user.admin) - return self - end - return false - end end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 6bd56c64..39b7a961 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -39,7 +39,7 @@ class ApplicationPolicy # explicitly say they want to (E.g. seeing/editing/deleting private # maps - they should be able to, but not by accident) def admin_override - user.admin + user && user.admin end def scope diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 671eea83..5e845d44 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -1,7 +1,7 @@ class MapPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) end end diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 44e7bfd7..49e134ef 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -5,7 +5,7 @@ class MappingPolicy < ApplicationPolicy # it would be nice if we could also base this on the mappable, but that # gets really complicated. Devin thinks it's OK to SHOW a mapping for # a private topic, since you can't see the private topic anyways - scope.joins(:maps).where('maps.permission IN ("public", "commons") OR user_id = ?', user.id) + scope.joins(:maps).where('maps.permission IN ("public", "commons") OR maps.user_id = ?', user.id) end end From 2d53922f1c4173131f5131ae9687f99b7dd4f988 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 09:54:23 +1100 Subject: [PATCH 39/67] can load maps --- app/views/layouts/application.html.erb | 2 +- app/views/maps/_mapinfobox.html.erb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index c09d227e..0480cb39 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -81,7 +81,7 @@ classes += controller_name == "maps" && action_name == "index" ? " explorePage" : "" if controller_name == "maps" && action_name == "show" classes += " mapPage" - if @map.authorize_to_edit(current_user) + if policy(@map).update? classes += " canEditMap" end if @map.permission == "commons" diff --git a/app/views/maps/_mapinfobox.html.erb b/app/views/maps/_mapinfobox.html.erb index 1fa6da02..ff90532c 100644 --- a/app/views/maps/_mapinfobox.html.erb +++ b/app/views/maps/_mapinfobox.html.erb @@ -4,7 +4,7 @@ #%>
- <%= @map && @map.authorize_to_edit(user) ? " canEdit" : "" %> + <%= @map && policy(@map).update? ? " canEdit" : "" %> <%= @map && @map.permission != 'private' ? " shareable" : "" %>"> <% if @map %> @@ -41,7 +41,7 @@
- <% if (authenticated? && @map.authorize_to_edit(user)) || (!authenticated? && @map.desc != "" && @map.desc != nil )%> + <% if (authenticated? && policy(@map).update?) || (!authenticated? && @map.desc != "" && @map.desc != nil )%> <%= best_in_place @map, :desc, :activator => "#mapInfoDesc", :as => :textarea, :placeholder => "Click to add description...", :class => 'best_in_place_desc' %> <% end %>
From 5f3f5212c5890a14d665c0709f33cfbed988d04b Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:06:00 +1100 Subject: [PATCH 40/67] pundit: syntax error --- app/controllers/topics_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 125005f9..e9239bac 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -24,7 +24,7 @@ class TopicsController < ApplicationController respond_to do |format| format.html { - @alltopics = ([@topic] + policy_scope(@topic.relatives) + @alltopics = ([@topic] + policy_scope(@topic.relatives)) @allsynapses = policy_scope(@topic.synapses) @allcreators = @alltopics.map(&:user).uniq From bd3afff06911576214ff2465bfb02e9e66c05810 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:10:31 +1100 Subject: [PATCH 41/67] pundit: fix queries --- app/policies/mapping_policy.rb | 3 ++- app/policies/synapse_policy.rb | 2 +- app/policies/topic_policy.rb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 49e134ef..39dbd86a 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -5,7 +5,8 @@ class MappingPolicy < ApplicationPolicy # it would be nice if we could also base this on the mappable, but that # gets really complicated. Devin thinks it's OK to SHOW a mapping for # a private topic, since you can't see the private topic anyways - scope.joins(:maps).where('maps.permission IN ("public", "commons") OR maps.user_id = ?', user.id) + scope.joins(:maps).where('maps.permission IN (?) OR maps.user_id = ?', + ["public", "commons"], user.id) end end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 6763014a..12f9c8ca 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,7 +1,7 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 03b42895..97fefdcc 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,7 +1,7 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN ("public", "commons") OR user_id = ?', user.id) + scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) end end From 1cf3182e7555cdb9c75253e1ca54fecbe47f1517 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 10:13:22 +1100 Subject: [PATCH 42/67] pundit: exclude topic action --- app/controllers/topics_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index e9239bac..0d58d912 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -2,7 +2,7 @@ class TopicsController < ApplicationController include TopicsHelper before_action :require_user, only: [:create, :update, :destroy] - after_action :verify_authorized + after_action :verify_authorized, except: :autocomplete_topic respond_to :html, :js, :json From dc6ccd20223709c087d7ef6784772cfd597ee381 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:10:30 +1100 Subject: [PATCH 43/67] pundit: fixing up topics and synapses --- app/controllers/synapses_controller.rb | 8 ++++---- app/controllers/topics_controller.rb | 16 ++++++++-------- app/models/synapse.rb | 4 ++++ app/models/topic.rb | 7 +++++++ app/policies/synapse_policy.rb | 2 +- app/policies/topic_policy.rb | 2 +- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index f242ad38..4440872f 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -10,7 +10,7 @@ class SynapsesController < ApplicationController # GET /synapses/1.json def show @synapse = Synapse.find(params[:id]) - authorize! @synapse + authorize @synapse render json: @synapse end @@ -20,7 +20,7 @@ class SynapsesController < ApplicationController def create @synapse = Synapse.new(synapse_params) @synapse.desc = "" if @synapse.desc.nil? - authorize! @synapse + authorize @synapse respond_to do |format| if @synapse.save @@ -36,7 +36,7 @@ class SynapsesController < ApplicationController def update @synapse = Synapse.find(params[:id]) @synapse.desc = "" if @synapse.desc.nil? - authorize! @synapse + authorize @synapse respond_to do |format| if @synapse.update_attributes(synapse_params) @@ -50,7 +50,7 @@ class SynapsesController < ApplicationController # DELETE synapses/:id def destroy @synapse = Synapse.find(params[:id]) - authorize! @synapse + authorize @synapse @synapse.delete respond_to do |format| diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 0d58d912..1b1e9b3c 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -20,12 +20,12 @@ class TopicsController < ApplicationController # GET topics/:id def show @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic respond_to do |format| format.html { - @alltopics = ([@topic] + policy_scope(@topic.relatives)) - @allsynapses = policy_scope(@topic.synapses) + @alltopics = ([@topic] + policy_scope(Topic.relatives(@topic.id))) + @allsynapses = policy_scope(Synapse.for_topic(@topic.id)) @allcreators = @alltopics.map(&:user).uniq @allcreators += @allsynapses.map(&:user).uniq @@ -39,7 +39,7 @@ class TopicsController < ApplicationController # GET topics/:id/network def network @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic @alltopics = [@topic] + policy_scope(@topic.relatives) @allsynapses = policy_scope(@topic.synapses) @@ -83,7 +83,7 @@ class TopicsController < ApplicationController # GET topics/:id/relatives def relatives @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : [] @@ -117,7 +117,7 @@ class TopicsController < ApplicationController # POST /topics.json def create @topic = Topic.new(topic_params) - authorize! @topic + authorize @topic respond_to do |format| if @topic.save @@ -132,7 +132,7 @@ class TopicsController < ApplicationController # PUT /topics/1.json def update @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic respond_to do |format| if @topic.update_attributes(topic_params) @@ -146,7 +146,7 @@ class TopicsController < ApplicationController # DELETE topics/:id def destroy @topic = Topic.find(params[:id]) - authorize! @topic + authorize @topic @topic.delete respond_to do |format| diff --git a/app/models/synapse.rb b/app/models/synapse.rb index beda8976..4807d7ab 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -14,6 +14,10 @@ class Synapse < ActiveRecord::Base validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true } + scope :for_topic, ->(topic_id = nil) { + where("node1_id = ? OR node2_id = ?", topic_id, topic_id) + } + # :nocov: def user_name user.name diff --git a/app/models/topic.rb b/app/models/topic.rb index 0039040e..0f312823 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -41,6 +41,13 @@ class Topic < ActiveRecord::Base belongs_to :metacode + scope :relatives, ->(topic_id = nil) { + includes(:synapses1) + .includes(:synapses2) + .where('synapses.node1_id = ? OR synapses.node2_id = ?', topic_id, topic_id) + .references(:synapses) + } + def user_name user.name end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 12f9c8ca..85de12da 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,7 +1,7 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) + scope.where('synapses.permission IN (?) OR synapses.user_id = ?', ["public", "commons"], user.id) end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 97fefdcc..43d4ec98 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,7 +1,7 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('permission IN (?) OR user_id = ?', ["public", "commons"], user.id) + scope.where('topics.permission IN (?) OR topics.user_id = ?', ["public", "commons"], user.id) end end From d0aecc0b31cf94217a8930ef3f6839af1f3cc836 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:16:46 +1100 Subject: [PATCH 44/67] pundit: make it work --- app/controllers/mappings_controller.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index ea2aaf0e..cba1cb3f 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -8,7 +8,7 @@ class MappingsController < ApplicationController # GET /mappings/1.json def show @mapping = Mapping.find(params[:id]) - authorize! @mapping + authorize @mapping render json: @mapping end @@ -16,8 +16,8 @@ class MappingsController < ApplicationController # POST /mappings.json def create @mapping = Mapping.new(mapping_params) - authorize! @mapping - + authorize @mapping + @mapping.user = current_user if @mapping.save render json: @mapping, status: :created else @@ -28,7 +28,7 @@ class MappingsController < ApplicationController # PUT /mappings/1.json def update @mapping = Mapping.find(params[:id]) - authorize! @mapping + authorize @mapping if @mapping.update_attributes(mapping_params) head :no_content @@ -40,7 +40,7 @@ class MappingsController < ApplicationController # DELETE /mappings/1.json def destroy @mapping = Mapping.find(params[:id]) - authorize! @mapping + authorize @mapping @mapping.destroy @@ -50,6 +50,6 @@ class MappingsController < ApplicationController private # Never trust parameters from the scary internet, only allow the white list through. def mapping_params - params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id, :user_id) + params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id) end end From 5d179ae5ec822b635804642dd3443d9768f5ea95 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:24:49 +1100 Subject: [PATCH 45/67] pundit: policy didn't exist --- app/policies/mapping_policy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 39dbd86a..13ef033e 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -18,7 +18,7 @@ class MappingPolicy < ApplicationPolicy def create? map = policy(record.map, user) - map.edit? + map.update? end def update? From bc505a13610b0a12a55c85ed0852c1448def7141 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:35:03 +1100 Subject: [PATCH 46/67] pundit: now updating maps actually works --- app/policies/map_policy.rb | 1 - app/policies/mapping_policy.rb | 10 ++++------ app/policies/synapse_policy.rb | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 5e845d44..50123877 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -35,7 +35,6 @@ class MapPolicy < ApplicationPolicy def update? user.present? && (record.permission == 'commons' || record.user == user) - true end def screenshot? diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 13ef033e..787b5794 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -11,19 +11,17 @@ class MappingPolicy < ApplicationPolicy end def show? - map = policy(record.map, user) - mappable = policy(record.mappable, user) + map = Pundit.policy(user, record.map) + mappable = Pundit.policy(user, record.mappable) map.show? && mappable.show? end def create? - map = policy(record.map, user) - map.update? + Pundit.policy(user, record.map).update? end def update? - map = policy(record.map, user) - map.update? + Pundit.policy(user, record.map).update? end def destroy? diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index 85de12da..e8d49548 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -7,6 +7,7 @@ class SynapsePolicy < ApplicationPolicy def create? user.present? + # todo add validation against whether you can see both topics end def show? From 7f86810f625197e240a1ea51f975c767cdc5d03a Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:53:12 +1100 Subject: [PATCH 47/67] remove things again not needed --- app/models/mapping.rb | 8 -------- app/models/user.rb | 4 ---- 2 files changed, 12 deletions(-) diff --git a/app/models/mapping.rb b/app/models/mapping.rb index 8f29ed6a..1a37f490 100644 --- a/app/models/mapping.rb +++ b/app/models/mapping.rb @@ -26,12 +26,4 @@ class Mapping < ActiveRecord::Base super(:methods =>[:user_name, :user_image]) end - def authorize_to_show(user) - if ((self.map.permission == "private" && self.map.user != user) || - (self.mappable.permission == "private" && self.mappable.user != user)) - return false - end - return self - end - end diff --git a/app/models/user.rb b/app/models/user.rb index a8fb6e6b..50493a55 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -41,10 +41,6 @@ class User < ActiveRecord::Base # Validate the attached image is image/jpg, image/png, etc validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/ - def is_logged_in? - true - end - # override default as_json def as_json(options={}) { :id => self.id, From 521aa6b5d00cda63d6b64210cecc861bc52197a4 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 11:58:26 +1100 Subject: [PATCH 48/67] function no longer exists --- app/controllers/api/tokens_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/tokens_controller.rb b/app/controllers/api/tokens_controller.rb index 6ef01e69..481b41ba 100644 --- a/app/controllers/api/tokens_controller.rb +++ b/app/controllers/api/tokens_controller.rb @@ -3,7 +3,7 @@ class Api::TokensController < API::RestfulController skip_authorization def my_tokens - raise Pundit::NotAuthorizedError.new unless current_user.is_logged_in? + raise Pundit::NotAuthorizedError.new unless current_user instantiate_collection page_collection: false, timeframe_collection: false respond_with_collection end From bb03b49d800c7d4b424fdd9b9459d2210326b824 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 12 Mar 2016 09:09:41 +0800 Subject: [PATCH 49/67] update main controller (searching) to use policies --- app/controllers/main_controller.rb | 112 +++++++++---------------- app/controllers/mappings_controller.rb | 1 + 2 files changed, 39 insertions(+), 74 deletions(-) diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index efebdce7..363c9c94 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -4,14 +4,13 @@ class MainController < ApplicationController include UsersHelper include SynapsesHelper -# after_action :verify_authorized, except: :index -# after_action :verify_policy_scoped, only: :index + after_action :verify_policy_scoped respond_to :html, :json # home page def home - @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(1).per(20) + @maps = policy_scope(Map).order("updated_at DESC").page(1).per(20) respond_to do |format| format.html { if authenticated? @@ -60,69 +59,35 @@ class MainController < ApplicationController filterByMetacode = m end end + + search = '%' + term.downcase + '%' + builder = policy_scope(Topic) if filterByMetacode if term == "" - @topics = [] + builder = builder.none else - search = term.downcase + '%' - - if user - @topics = Set.new(Topic.where('LOWER("name") like ?', search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')) - @topics2 = Set.new(Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')) - @topics3 = Set.new(Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')) - @topics4 = Set.new(Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"')) - else - @topics = Set.new(Topic.where('LOWER("name") like ?', search).where('metacode_id = ?', filterByMetacode.id).order('"name"')) - @topics2 = Set.new(Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"')) - @topics3 = Set.new(Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"')) - @topics4 = Set.new(Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"')) - end - - #get unique elements only through the magic of Sets - @topics = (@topics + @topics2 + @topics3 + @topics4).to_a + builder = builder.where('LOWER("name") like ? OR + LOWER("desc") like ? OR + LOWER("link") like ?', search, search, search) + builder = builder.where(metacode_id: filterByMetacode.id) end elsif desc - search = '%' + term.downcase + '%' - if !user - @topics = Topic.where('LOWER("desc") like ?', search).order('"name"') - elsif user - @topics = Topic.where('LOWER("desc") like ?', search).where('user_id = ?', user).order('"name"') - end + builder = builder.where('LOWER("desc") like ?', search) elsif link - search = '%' + term.downcase + '%' - if !user - @topics = Topic.where('LOWER("link") like ?', search).order('"name"') - elsif user - @topics = Topic.where('LOWER("link") like ?', search).where('user_id = ?', user).order('"name"') - end + builder = builder.where('LOWER("link") like ?', search) else #regular case, just search the name - search = term.downcase + '%' - if !user - @topics = Topic.where('LOWER("name") like ?', search).order('"name"') - @topics2 = Topic.where('LOWER("name") like ?', '%' + search).order('"name"') - @topics3 = Topic.where('LOWER("desc") like ?', '%' + search).order('"name"') - @topics4 = Topic.where('LOWER("link") like ?', '%' + search).order('"name"') - @topics = @topics + (@topics2 - @topics) - @topics = @topics + (@topics3 - @topics) - @topics = @topics + (@topics4 - @topics) - elsif user - @topics = Topic.where('LOWER("name") like ?', search).where('user_id = ?', user).order('"name"') - @topics2 = Topic.where('LOWER("name") like ?', '%' + search).where('user_id = ?', user).order('"name"') - @topics3 = Topic.where('LOWER("desc") like ?', '%' + search).where('user_id = ?', user).order('"name"') - @topics4 = Topic.where('LOWER("link") like ?', '%' + search).where('user_id = ?', user).order('"name"') - @topics = @topics + (@topics2 - @topics) - @topics = @topics + (@topics3 - @topics) - @topics = @topics + (@topics4 - @topics) - end + builder = builder.where('LOWER("name") like ? OR + LOWER("desc") like ? OR + LOWER("link") like ?', search, search, search) end + + builder = builder.where(user: user) if user + @topics = builder.order(:name) else @topics = [] end - - #read this next line as 'delete a topic if its private and you're either 1. logged out or 2. logged in but not the topic creator - @topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) } - + render json: autocomplete_array_json(@topics) end @@ -142,21 +107,21 @@ class MainController < ApplicationController term = term[5..-1] desc = true end + search = '%' + term.downcase + '%' - query = desc ? 'LOWER("desc") like ?' : 'LOWER("name") like ?' - if !user - # !connor why is the limit 5 done here and not above? also, why not limit after sorting alphabetically? - @maps = Map.where(query, search).limit(5).order('"name"') - elsif user - @maps = Map.where(query, search).where('user_id = ?', user).order('"name"') + builder = policy_scope(Map) + + if desc + builder = builder.where('LOWER("desc") like ?', search) + else + builder = builder.where('LOWER("name") like ?', search) end + builder = builder.where(user: user) if user + @maps = builder.order(:name) else @maps = [] end - #read this next line as 'delete a map if its private and you're either 1. logged out or 2. logged in but not the map creator - @maps.to_a.delete_if {|m| m.permission == "private" && (!authenticated? || (authenticated? && current_user.id != m.user_id)) } - render json: autocomplete_map_array_json(@maps) end @@ -167,7 +132,10 @@ class MainController < ApplicationController #remove "mapper:" if appended at beginning term = term[7..-1] if term.downcase[0..6] == "mapper:" - @mappers = User.where('LOWER("name") like ?', term.downcase + '%').order('"name"') + search = term.downcase + '%' + builder = policy_scope(User) # TODO do I need to policy scope? I guess yes to verify_policy_scoped + builder = builder.where('LOWER("name") like ?', search) + @mappers = builder.order(:name) else @mappers = [] end @@ -182,7 +150,7 @@ class MainController < ApplicationController topic2id = params[:topic2id] if term && !term.empty? - @synapses = Synapse.where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"') + @synapses = policy_scope(Synapse).where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"') # remove any duplicate synapse types that just differ by # leading or trailing whitespaces @@ -196,22 +164,18 @@ class MainController < ApplicationController boolean = true end } - - #limit to 5 results - @synapses = @synapses.slice(0,5) elsif topic1id && !topic1id.empty? - @one = Synapse.where('node1_id = ? AND node2_id = ?', topic1id, topic2id) - @two = Synapse.where('node2_id = ? AND node1_id = ?', topic1id, topic2id) + @one = policy_scope(Synapse).where('node1_id = ? AND node2_id = ?', topic1id, topic2id) + @two = policy_scope(Synapse).where('node2_id = ? AND node1_id = ?', topic1id, topic2id) @synapses = @one + @two @synapses.sort! {|s1,s2| s1.desc <=> s2.desc }.to_a - - #permissions - @synapses.delete_if {|s| s.permission == "private" && !authenticated? } - @synapses.delete_if {|s| s.permission == "private" && authenticated? && current_user.id != s.user_id } else @synapses = [] end + #limit to 5 results + @synapses = @synapses.slice(0,5) + render json: autocomplete_synapse_array_json(@synapses) end end diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index cba1cb3f..02c28a54 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -18,6 +18,7 @@ class MappingsController < ApplicationController @mapping = Mapping.new(mapping_params) authorize @mapping @mapping.user = current_user + if @mapping.save render json: @mapping, status: :created else From bf4fbbeb06439ed488c4776e8b4ba429a906858e Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 12:26:23 +1100 Subject: [PATCH 50/67] fix tokens --- app/controllers/api/restful_controller.rb | 2 +- app/controllers/api/tokens_controller.rb | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/restful_controller.rb b/app/controllers/api/restful_controller.rb index d6c544e2..06396e3d 100644 --- a/app/controllers/api/restful_controller.rb +++ b/app/controllers/api/restful_controller.rb @@ -5,7 +5,7 @@ class API::RestfulController < ActionController::Base snorlax_used_rest! rescue_from(Pundit::NotAuthorizedError) { |e| respond_with_standard_error e, 403 } - load_and_authorize_resource except: [:index, :create] + load_and_authorize_resource only: [:show, :update, :destroy] def create authorize resource_class diff --git a/app/controllers/api/tokens_controller.rb b/app/controllers/api/tokens_controller.rb index 481b41ba..3fcca370 100644 --- a/app/controllers/api/tokens_controller.rb +++ b/app/controllers/api/tokens_controller.rb @@ -1,13 +1,17 @@ class Api::TokensController < API::RestfulController - skip_authorization - def my_tokens raise Pundit::NotAuthorizedError.new unless current_user instantiate_collection page_collection: false, timeframe_collection: false respond_with_collection end + private + + def resource_serializer + "#{resource_name}_serializer".camelize.constantize + end + def visible_records current_user.tokens end From 7e7ef173e501301d659105af1e47081d98ff0cbe Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 12 Mar 2016 09:27:31 +0800 Subject: [PATCH 51/67] map policy spec --- spec/policies/map_policy_spec.rb | 97 ++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 1 + 2 files changed, 98 insertions(+) create mode 100644 spec/policies/map_policy_spec.rb diff --git a/spec/policies/map_policy_spec.rb b/spec/policies/map_policy_spec.rb new file mode 100644 index 00000000..b160fead --- /dev/null +++ b/spec/policies/map_policy_spec.rb @@ -0,0 +1,97 @@ +require 'rails_helper' + +RSpec.describe MapPolicy, type: :policy do + subject { described_class } + + context 'unauthenticated' do + context 'commons' do + let(:map) { create(:map, permission: :commons) } + permissions :show? do + it 'can view' do + expect(subject).to permit(nil, map) + end + end + permissions :create?, :update?, :destroy? do + it 'can not modify' do + expect(subject).to_not permit(nil, map) + end + end + end + + context 'private' do + let(:map) { create(:map, permission: :private) } + permissions :show?, :create?, :update?, :destroy? do + it 'can not view or modify' do + expect(subject).to_not permit(nil, map) + end + end + end + end + + # + # Now begin the logged-in tests + # + + context 'logged in' do + let(:user) { create(:user) } + + context 'commons' do + let(:owner) { create(:user) } + let(:map) { create(:map, permission: :commons, user: owner) } + permissions :show?, :create?, :update? do + it 'can view and modify' do + expect(subject).to permit(user, map) + end + end + permissions :destroy? do + it 'can not destroy' do + expect(subject).to_not permit(user, map) + end + it 'owner can destroy' do + expect(subject).to permit(owner, map) + end + end + end + + context 'public' do + let(:owner) { create(:user) } + let(:map) { create(:map, permission: :public, user: owner) } + permissions :show? do + it 'can view' do + expect(subject).to permit(user, map) + end + end + permissions :create? do + it 'can create' do + expect(subject).to permit(user, map) + end + end + permissions :update?, :destroy? do + it 'can not update/destroy' do + expect(subject).to_not permit(user, map) + end + it 'owner can update/destroy' do + expect(subject).to permit(owner, map) + end + end + end + + context 'private' do + let(:owner) { create(:user) } + let(:map) { create(:map, permission: :private, user: owner) } + permissions :create? do + it 'can create' do + expect(subject).to permit(user, map) + end + end + permissions :show?, :update?, :destroy? do + it 'can not view or modify' do + expect(subject).to_not permit(user, map) + end + it 'owner can view and modify' do + expect(subject).to permit(owner, map) + end + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 08ffd17f..d4028602 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ require 'simplecov' require 'support/controller_helpers' +require 'pundit/rspec' RSpec.configure do |config| config.expect_with :rspec do |expectations| From a295c61322efdb0384ec3b9203b655321eb7bdca Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 12:58:13 +1100 Subject: [PATCH 52/67] json response was broken --- app/controllers/main_controller.rb | 2 +- app/controllers/maps_controller.rb | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 363c9c94..7bc22c7e 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -13,7 +13,7 @@ class MainController < ApplicationController @maps = policy_scope(Map).order("updated_at DESC").page(1).per(20) respond_to do |format| format.html { - if authenticated? + if not authenticated? render 'main/home' else render 'maps/activemaps' diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 83f7cb89..d45c1432 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -13,11 +13,12 @@ class MapsController < ApplicationController @maps = policy_scope(Map).order("updated_at DESC") .page(page).per(20) - # root url => main/home. main/home renders maps/activemaps view. - redirect_to root_url and return if authenticated? - respond_to do |format| - format.html { respond_with(@maps, @user) } + format.html { + # root url => main/home. main/home renders maps/activemaps view. + redirect_to root_url and return if authenticated? + respond_with(@maps, @user) + } format.json { render json: @maps } end end @@ -81,7 +82,7 @@ class MapsController < ApplicationController respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map) } - format.json { render json: @map.as_json } + format.json { render json: @map } end end From 446619c451b529b29f1fc62e14e215d27861f73e Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 13:20:15 +1100 Subject: [PATCH 53/67] omg not having this was breaking things --- app/controllers/application_controller.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d030c6e6..4388337e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,6 +7,10 @@ class ApplicationController < ActionController::Base before_action :get_invite_link after_action :allow_embedding + def default_serializer_options + { root: false } + end + # this is for global login include ContentHelper From ada29c6832fee8629dbed804c0af7ee911859ab4 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Mar 2016 21:35:56 +1100 Subject: [PATCH 54/67] cleanup --- app/serializers/new_map_serializer.rb | 4 ---- app/serializers/new_synapse_serializer.rb | 4 ---- app/serializers/new_topic_serializer.rb | 4 ---- app/serializers/token_serializer.rb | 4 ---- postatoken.txt | 7 ------- postdata.txt | 1 - postmapping.txt | 1 - postsynapse.txt | 1 - posttopic.txt | 1 - 9 files changed, 27 deletions(-) delete mode 100644 postatoken.txt delete mode 100644 postdata.txt delete mode 100644 postmapping.txt delete mode 100644 postsynapse.txt delete mode 100644 posttopic.txt diff --git a/app/serializers/new_map_serializer.rb b/app/serializers/new_map_serializer.rb index 1e27420b..9b2ff400 100644 --- a/app/serializers/new_map_serializer.rb +++ b/app/serializers/new_map_serializer.rb @@ -13,8 +13,4 @@ class NewMapSerializer < ActiveModel::Serializer has_many :mappings, serializer: NewMappingSerializer has_many :contributors, root: :users, serializer: NewUserSerializer - #def filter(keys) - # keys.delete(:outcome_author) unless object.outcome_author.present? - # keys - #end end diff --git a/app/serializers/new_synapse_serializer.rb b/app/serializers/new_synapse_serializer.rb index e7cd9fd7..b145d605 100644 --- a/app/serializers/new_synapse_serializer.rb +++ b/app/serializers/new_synapse_serializer.rb @@ -12,8 +12,4 @@ class NewSynapseSerializer < ActiveModel::Serializer has_one :topic2, root: :topics, serializer: NewTopicSerializer has_one :user, serializer: NewUserSerializer - #def filter(keys) - # keys.delete(:outcome_author) unless object.outcome_author.present? - # keys - #end end diff --git a/app/serializers/new_topic_serializer.rb b/app/serializers/new_topic_serializer.rb index d36f1db0..cdbbedf9 100644 --- a/app/serializers/new_topic_serializer.rb +++ b/app/serializers/new_topic_serializer.rb @@ -11,8 +11,4 @@ class NewTopicSerializer < ActiveModel::Serializer has_one :user, serializer: NewUserSerializer has_one :metacode, serializer: NewMetacodeSerializer - #def filter(keys) - # keys.delete(:outcome_author) unless object.outcome_author.present? - # keys - #end end diff --git a/app/serializers/token_serializer.rb b/app/serializers/token_serializer.rb index 777a14c1..8eed535a 100644 --- a/app/serializers/token_serializer.rb +++ b/app/serializers/token_serializer.rb @@ -7,8 +7,4 @@ class TokenSerializer < ActiveModel::Serializer :created_at, :updated_at - #def filter(keys) - # keys.delete(:outcome_author) unless object.outcome_author.present? - # keys - #end end diff --git a/postatoken.txt b/postatoken.txt deleted file mode 100644 index c9d98ff3..00000000 --- a/postatoken.txt +++ /dev/null @@ -1,7 +0,0 @@ -$.post('http://localhost:3000/api/v1/tokens', {token: { - description: 'for stuff', - token: '1234', - user_id: 2 -}}) - -curl -X POST -d @postdata.txt http://localhost:3000/api/v1/maps --header "Authorization: Token token=fb5b3db125c94e9fb50f1e42054be856" --header "Content-Type:application/json" diff --git a/postdata.txt b/postdata.txt deleted file mode 100644 index 9daaf598..00000000 --- a/postdata.txt +++ /dev/null @@ -1 +0,0 @@ -{ "map": { "name":"tree", "desc": "green", "permission": "commons", "arranged": true }} diff --git a/postmapping.txt b/postmapping.txt deleted file mode 100644 index c9463f92..00000000 --- a/postmapping.txt +++ /dev/null @@ -1 +0,0 @@ -{ "mapping": { "xloc": 123, "yloc": 123, "map_id": 1, "mappable_type": "Topic", "mappable_id": 2 }} diff --git a/postsynapse.txt b/postsynapse.txt deleted file mode 100644 index da2617d8..00000000 --- a/postsynapse.txt +++ /dev/null @@ -1 +0,0 @@ -{ "synapse": { "desc": "link between", "permission": "commons", "node1_id": 1, "node2_id": 2, "category": "from-to" }} diff --git a/posttopic.txt b/posttopic.txt deleted file mode 100644 index e00d797f..00000000 --- a/posttopic.txt +++ /dev/null @@ -1 +0,0 @@ -{ "topic": { "name":"tree topic", "desc": "so green", "permission": "commons", "metacode_id": 1 }} From f072e39c4c19c6d466f38853a2e6dad0d953d731 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 02:27:05 +1100 Subject: [PATCH 55/67] pundit: sometimes no user --- app/policies/map_policy.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 50123877..1594e6d9 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -1,7 +1,11 @@ class MapPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) + if user + scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) + else + scope.where('maps.permission IN (?)', ["public", "commons"]) + end end end From 3aec00e07cfe97eb3616d157148b422195671de4 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 02:28:39 +1100 Subject: [PATCH 56/67] just don't include mappable for now --- app/serializers/new_mapping_serializer.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/serializers/new_mapping_serializer.rb b/app/serializers/new_mapping_serializer.rb index 9241305a..4e65e161 100644 --- a/app/serializers/new_mapping_serializer.rb +++ b/app/serializers/new_mapping_serializer.rb @@ -4,10 +4,12 @@ class NewMappingSerializer < ActiveModel::Serializer :xloc, :yloc, :created_at, - :updated_at + :updated_at, + :mappable_id, + :mappable_type + has_one :user, serializer: NewUserSerializer has_one :map, serializer: NewMapSerializer - has_one :mappable, polymorphic: true ##? def filter(keys) keys.delete(:xloc) unless object.mappable_type == "Topic" From b236f4c689acff80cbc98e2f615419bf277d1bd3 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 02:41:32 +1100 Subject: [PATCH 57/67] handle not logged in scenarios --- app/policies/map_policy.rb | 6 ++++-- app/policies/mapping_policy.rb | 9 +++++++-- app/policies/synapse_policy.rb | 8 +++++++- app/policies/topic_policy.rb | 8 +++++++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 1594e6d9..65f721bf 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -1,10 +1,12 @@ class MapPolicy < ApplicationPolicy class Scope < Scope def resolve + visible = ['public', 'commons'] + permission = 'maps.permission IN (?)' if user - scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) + scope.where(permission + ' OR maps.user_id = ?', visible, user.id) else - scope.where('maps.permission IN (?)', ["public", "commons"]) + scope.where(permission, visible) end end end diff --git a/app/policies/mapping_policy.rb b/app/policies/mapping_policy.rb index 787b5794..ed93bc66 100644 --- a/app/policies/mapping_policy.rb +++ b/app/policies/mapping_policy.rb @@ -5,8 +5,13 @@ class MappingPolicy < ApplicationPolicy # it would be nice if we could also base this on the mappable, but that # gets really complicated. Devin thinks it's OK to SHOW a mapping for # a private topic, since you can't see the private topic anyways - scope.joins(:maps).where('maps.permission IN (?) OR maps.user_id = ?', - ["public", "commons"], user.id) + visible = ['public', 'commons'] + permission = 'maps.permission IN (?)' + if user + scope.joins(:maps).where(permission + ' OR maps.user_id = ?', visible, user.id) + else + scope.where(permission, visible) + end end end diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index e8d49548..042c9a75 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -1,7 +1,13 @@ class SynapsePolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('synapses.permission IN (?) OR synapses.user_id = ?', ["public", "commons"], user.id) + visible = ['public', 'commons'] + permission = 'synapses.permission IN (?)' + if user + scope.where(permission + ' OR synapses.user_id = ?', visible, user.id) + else + scope.where(permission, visible) + end end end diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 43d4ec98..335a2ed2 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -1,7 +1,13 @@ class TopicPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('topics.permission IN (?) OR topics.user_id = ?', ["public", "commons"], user.id) + visible = ['public', 'commons'] + permission = 'topics.permission IN (?)' + if user + scope.where(permission + ' OR topics.user_id = ?', visible, user.id) + else + scope.where(permission, visible) + end end end From 5fbf7ac34d8624e3cef12650af32252eba19062d Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 03:16:31 +1100 Subject: [PATCH 58/67] hide metamaps_mobile in gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 43009ea4..52428f17 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ #assety stuff realtime/node_modules public/assets +public/metamaps_mobile vendor/ #secrets and config From 11e57c1b37114eee5bd9f57ca81750e31a0673ed Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 10:36:38 +1100 Subject: [PATCH 59/67] rebase onto develop which now has API and pundit --- Gemfile | 2 + Gemfile.lock | 9 +++ Procfile | 1 + Vagrantfile | 1 - app/controllers/mappings_controller.rb | 1 + app/models/concerns/routing.rb | 10 +++ app/models/event.rb | 34 +++++++++ app/models/events/new_mapping.rb | 18 +++++ app/models/map.rb | 3 + app/models/webhook.rb | 13 ++++ app/models/webhooks/slack/base.rb | 72 +++++++++++++++++++ .../webhooks/slack/synapse_added_to_map.rb | 26 +++++++ .../webhooks/slack/topic_added_to_map.rb | 30 ++++++++ app/serializers/event_serializer.rb | 15 ++++ app/serializers/webhook_serializer.rb | 3 + app/services/webhook_service.rb | 18 +++++ config/application.rb | 2 + .../20150930233907_create_delayed_jobs.rb | 22 ++++++ db/schema.rb | 27 +++++++ 19 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 app/models/concerns/routing.rb create mode 100644 app/models/event.rb create mode 100644 app/models/events/new_mapping.rb create mode 100644 app/models/webhook.rb create mode 100644 app/models/webhooks/slack/base.rb create mode 100644 app/models/webhooks/slack/synapse_added_to_map.rb create mode 100644 app/models/webhooks/slack/topic_added_to_map.rb create mode 100644 app/serializers/event_serializer.rb create mode 100644 app/serializers/webhook_serializer.rb create mode 100644 app/services/webhook_service.rb create mode 100644 db/migrate/20150930233907_create_delayed_jobs.rb diff --git a/Gemfile b/Gemfile index b7ea08e9..7fb90aeb 100644 --- a/Gemfile +++ b/Gemfile @@ -18,6 +18,8 @@ gem 'kaminari' # pagination gem 'uservoice-ruby' gem 'dotenv' gem 'snorlax', '~> 0.1.3' +gem 'httparty' +gem 'sequenced', '~> 2.0.0' gem 'active_model_serializers', '~> 0.8.1' gem 'paperclip' diff --git a/Gemfile.lock b/Gemfile.lock index a2a3b031..634f2031 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,6 +97,9 @@ GEM rails (> 3.0.0) globalid (0.3.6) activesupport (>= 4.1.0) + httparty (0.13.7) + json (~> 1.8) + multi_xml (>= 0.5.2) i18n (0.7.0) jbuilder (2.4.1) activesupport (>= 3.0.0, < 5.1) @@ -123,6 +126,7 @@ GEM mini_portile2 (2.0.0) minitest (5.8.4) multi_json (1.11.2) + multi_xml (0.5.5) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) oauth (0.5.1) @@ -210,6 +214,9 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + sequenced (2.0.0) + activerecord (>= 3.0) + activesupport (>= 3.0) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) simplecov (0.11.2) @@ -260,6 +267,7 @@ DEPENDENCIES factory_girl_rails formtastic formula + httparty jbuilder jquery-rails jquery-ui-rails @@ -279,6 +287,7 @@ DEPENDENCIES redis rspec-rails sass-rails + sequenced (~> 2.0.0) shoulda-matchers simplecov snorlax (~> 0.1.3) diff --git a/Procfile b/Procfile index 443f2e35..802726be 100644 --- a/Procfile +++ b/Procfile @@ -1 +1,2 @@ web: bundle exec rails server -p $PORT + diff --git a/Vagrantfile b/Vagrantfile index dad6c7c7..c9ea9363 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -16,7 +16,6 @@ sudo apt-get install nodejs -y sudo apt-get install npm -y sudo apt-get install postgresql -y sudo apt-get install libpq-dev -y -sudo apt-get install redis-server -y # get imagemagick sudo apt-get install imagemagick --fix-missing diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index 649ef8f3..936ffcc2 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -22,6 +22,7 @@ class MappingsController < ApplicationController if @mapping.save render json: @mapping, status: :created + Events::NewMapping.publish!(@mapping, current_user) else render json: @mapping.errors, status: :unprocessable_entity end diff --git a/app/models/concerns/routing.rb b/app/models/concerns/routing.rb new file mode 100644 index 00000000..2f8467bf --- /dev/null +++ b/app/models/concerns/routing.rb @@ -0,0 +1,10 @@ +module Routing + extend ActiveSupport::Concern + include Rails.application.routes.url_helpers + + included do + def default_url_options + ActionMailer::Base.default_url_options + end + end +end diff --git a/app/models/event.rb b/app/models/event.rb new file mode 100644 index 00000000..b49b4856 --- /dev/null +++ b/app/models/event.rb @@ -0,0 +1,34 @@ +class Event < ActiveRecord::Base + KINDS = %w[topic_added_to_map synapse_added_to_map] + + #has_many :notifications, dependent: :destroy + belongs_to :eventable, polymorphic: true + belongs_to :map + belongs_to :user + + scope :sequenced, -> { where('sequence_id is not null').order('sequence_id asc') } + scope :chronologically, -> { order('created_at asc') } + + after_create :notify_webhooks!, if: :map + + validates_inclusion_of :kind, :in => KINDS + validates_presence_of :eventable + + acts_as_sequenced scope: :map_id, column: :sequence_id, skip: lambda {|e| e.map.nil? || e.map_id.nil? } + + #def notify!(user) + # notifications.create!(user: user) + #end + + def belongs_to?(this_user) + self.user_id == this_user.id + end + + def notify_webhooks! + #group = self.discussion.group + self.map.webhooks.each { |webhook| WebhookService.publish! webhook: webhook, event: self } + #group.webhooks.each { |webhook| WebhookService.publish! webhook: webhook, event: self } + end + handle_asynchronously :notify_webhooks! + +end diff --git a/app/models/events/new_mapping.rb b/app/models/events/new_mapping.rb new file mode 100644 index 00000000..7d6e0696 --- /dev/null +++ b/app/models/events/new_mapping.rb @@ -0,0 +1,18 @@ +class Events::NewMapping < Event + #after_create :notify_users! + + def self.publish!(mapping, user) + create!(kind: mapping.mappable_type == "Topic" ? "topic_added_to_map" : "synapse_added_to_map", + eventable: mapping, + map: mapping.map, + user: user) + end + + private + + #def notify_users! + # unless comment_vote.user == comment_vote.comment_user + # notify!(comment_vote.comment_user) + # end + #end +end diff --git a/app/models/map.rb b/app/models/map.rb index 87c8d641..acfb627d 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -7,6 +7,9 @@ class Map < ActiveRecord::Base has_many :topics, through: :topicmappings, source: :mappable, source_type: "Topic" has_many :synapses, through: :synapsemappings, source: :mappable, source_type: "Synapse" + has_many :webhooks, as: :hookable + has_many :events, -> { includes :user }, as: :eventable, dependent: :destroy + # This method associates the attribute ":image" with a file attachment has_attached_file :screenshot, :styles => { :thumb => ['188x126#', :png] diff --git a/app/models/webhook.rb b/app/models/webhook.rb new file mode 100644 index 00000000..4e20272c --- /dev/null +++ b/app/models/webhook.rb @@ -0,0 +1,13 @@ +class Webhook < ActiveRecord::Base + belongs_to :hookable, polymorphic: true + + validates :uri, presence: true + validates :hookable, presence: true + validates_inclusion_of :kind, in: %w[slack] + validates :event_types, length: { minimum: 1 } + + def headers + {} + end + +end diff --git a/app/models/webhooks/slack/base.rb b/app/models/webhooks/slack/base.rb new file mode 100644 index 00000000..98503916 --- /dev/null +++ b/app/models/webhooks/slack/base.rb @@ -0,0 +1,72 @@ +Webhooks::Slack::Base = Struct.new(:event) do + include Routing + + def username + "Metamaps Bot" + end + + def icon_url + "https://pbs.twimg.com/profile_images/539300245029392385/dJ1bwnw7.jpeg" + end + + def text + "something" + end + + def attachments + [{ + title: attachment_title, + text: attachment_text, + fields: attachment_fields, + fallback: attachment_fallback + }] + end + + alias :read_attribute_for_serialization :send + + private + + #def motion_vote_field + # { + # title: "Vote on this proposal", + # value: "#{proposal_link(eventable, "yes")} · " + + # "#{proposal_link(eventable, "abstain")} · " + + # "#{proposal_link(eventable, "no")} · " + + # "#{proposal_link(eventable, "block")}" + # } + #end + + def view_map_on_metamaps(text = nil) + "<#{map_url(eventable.map)}|#{text || eventable.map.name}>" + end + + #def view_discussion_on_loomio(params = {}) + # { value: discussion_link(I18n.t(:"webhooks.slack.view_it_on_loomio"), params) } + #end + + #def proposal_link(proposal, position = nil) + # discussion_link position || proposal.name, { proposal: proposal.key, position: position } + #end + + #def discussion_link(text = nil, params = {}) + # "<#{discussion_url(eventable.map, params)}|#{text || eventable.discussion.title}>" + #end + + def eventable + @eventable ||= event.eventable + end + + def author + @author ||= eventable.author + end + +end + +#webhooks: +# slack: +# motion_closed: "*%{name}* has closed" +# motion_closing_soon: "*%{name}* has a proposal closing in 24 hours" +# motion_outcome_created: "*%{author}* published an outcome in *%{name}*" +# motion_outcome_updated: "*%{author}* updated the outcome for *%{name}*" +# new_motion: "*%{author}* started a new proposal in *%{name}*" +# view_it_on_loomio: "View it on Loomio" diff --git a/app/models/webhooks/slack/synapse_added_to_map.rb b/app/models/webhooks/slack/synapse_added_to_map.rb new file mode 100644 index 00000000..25093127 --- /dev/null +++ b/app/models/webhooks/slack/synapse_added_to_map.rb @@ -0,0 +1,26 @@ +class Webhooks::Slack::SynapseAddedToMap < Webhooks::Slack::Base + + def text + "\"*#{eventable.synapse.topic1.name}* #{eventable.synapse.desc || '->'} *#{eventable.synapse.topic2.name}*\" was added as a connection to the map *#{view_map_on_metamaps()}*" + end + + def attachment_fallback + "" #{}"*#{eventable.name}*\n#{eventable.description}\n" + end + + def attachment_title + "" #proposal_link(eventable) + end + + def attachment_text + "" # "#{eventable.description}\n" + end + + def attachment_fields + [{ + title: "nothing", + value: "nothing" + }] #[motion_vote_field] + end + +end diff --git a/app/models/webhooks/slack/topic_added_to_map.rb b/app/models/webhooks/slack/topic_added_to_map.rb new file mode 100644 index 00000000..6b4a16c8 --- /dev/null +++ b/app/models/webhooks/slack/topic_added_to_map.rb @@ -0,0 +1,30 @@ +class Webhooks::Slack::TopicAddedToMap < Webhooks::Slack::Base + + def text + "New #{eventable.topic.metacode.name} topic *#{eventable.topic.name}* was added to the map *#{view_map_on_metamaps()}*" + end + + def icon_url + eventable.topic.metacode.icon + end + + def attachment_fallback + "" #{}"*#{eventable.name}*\n#{eventable.description}\n" + end + + def attachment_title + "" #proposal_link(eventable) + end + + def attachment_text + "" # "#{eventable.description}\n" + end + + def attachment_fields + [{ + title: "nothing", + value: "nothing" + }] #[motion_vote_field] + end + +end diff --git a/app/serializers/event_serializer.rb b/app/serializers/event_serializer.rb new file mode 100644 index 00000000..0e87cd44 --- /dev/null +++ b/app/serializers/event_serializer.rb @@ -0,0 +1,15 @@ +class EventSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, :sequence_id, :kind, :map_id, :created_at + + has_one :actor, serializer: NewUserSerializer, root: 'users' + has_one :map, serializer: NewMapSerializer + + def actor + object.user || object.eventable.try(:user) + end + + def map + object.eventable.try(:map) || object.eventable.map + end +end diff --git a/app/serializers/webhook_serializer.rb b/app/serializers/webhook_serializer.rb new file mode 100644 index 00000000..9adfd101 --- /dev/null +++ b/app/serializers/webhook_serializer.rb @@ -0,0 +1,3 @@ +class WebhookSerializer < ActiveModel::Serializer + attributes :text, :username #, :attachments #, :icon_url +end diff --git a/app/services/webhook_service.rb b/app/services/webhook_service.rb new file mode 100644 index 00000000..7a4361b4 --- /dev/null +++ b/app/services/webhook_service.rb @@ -0,0 +1,18 @@ +class WebhookService + + def self.publish!(webhook:, event:) + return false unless webhook.event_types.include? event.kind + HTTParty.post webhook.uri, body: payload_for(webhook, event), headers: webhook.headers + end + + private + + def self.payload_for(webhook, event) + WebhookSerializer.new(webhook_object_for(webhook, event), root: false).to_json + end + + def self.webhook_object_for(webhook, event) + "Webhooks::#{webhook.kind.classify}::#{event.kind.classify}".constantize.new(event) + end + +end diff --git a/config/application.rb b/config/application.rb index 658a4203..04526695 100644 --- a/config/application.rb +++ b/config/application.rb @@ -10,6 +10,8 @@ Dotenv.load ".env.#{ENV["RAILS_ENV"]}", '.env' module Metamaps class Application < Rails::Application + config.active_job.queue_adapter = :delayed_job + # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/db/migrate/20150930233907_create_delayed_jobs.rb b/db/migrate/20150930233907_create_delayed_jobs.rb new file mode 100644 index 00000000..27fdcf6c --- /dev/null +++ b/db/migrate/20150930233907_create_delayed_jobs.rb @@ -0,0 +1,22 @@ +class CreateDelayedJobs < ActiveRecord::Migration + def self.up + create_table :delayed_jobs, force: true do |table| + table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue + table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually. + table.text :handler, null: false # YAML-encoded string of the object that will do work + table.text :last_error # reason for last failure (See Note below) + table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future. + table.datetime :locked_at # Set when a client is working on this object + table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead) + table.string :locked_by # Who is working on this object (if locked) + table.string :queue # The name of the queue this job is in + table.timestamps null: true + end + + add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority" + end + + def self.down + drop_table :delayed_jobs + end +end diff --git a/db/schema.rb b/db/schema.rb index 334fd4ad..38570d2f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -16,6 +16,23 @@ ActiveRecord::Schema.define(version: 20160310200131) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "events", force: :cascade do |t| + t.string "kind", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" + t.integer "eventable_id" + t.string "eventable_type", limit: 255 + t.integer "user_id" + t.integer "map_id" + t.integer "sequence_id" + end + + add_index "events", ["created_at"], name: "index_events_on_created_at", using: :btree + add_index "events", ["map_id", "sequence_id"], name: "index_events_on_map_id_and_sequence_id", unique: true, using: :btree + add_index "events", ["map_id"], name: "index_events_on_map_id", using: :btree + add_index "events", ["eventable_type", "eventable_id"], name: "index_events_on_eventable_type_and_eventable_id", using: :btree + add_index "events", ["sequence_id"], name: "index_events_on_sequence_id", using: :btree + create_table "in_metacode_sets", force: :cascade do |t| t.integer "metacode_id" t.integer "metacode_set_id" @@ -181,5 +198,15 @@ ActiveRecord::Schema.define(version: 20160310200131) do add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + create_table "webhooks", force: :cascade do |t| + t.integer "hookable_id" + t.string "hookable_type" + t.string "kind", null: false + t.string "uri", null: false + t.text "event_types", default: [], array: true + end + + add_index "webhooks", ["hookable_type", "hookable_id"], name: "index_webhooks_on_hookable_type_and_hookable_id", using: :btree + add_foreign_key "tokens", "users" end From d863d1c15bd811b4599eec0f55ca8f75a982bc78 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 10:42:55 +1100 Subject: [PATCH 60/67] remove traces of delayed_job --- config/application.rb | 1 - .../20150930233907_create_delayed_jobs.rb | 22 ------------------- 2 files changed, 23 deletions(-) delete mode 100644 db/migrate/20150930233907_create_delayed_jobs.rb diff --git a/config/application.rb b/config/application.rb index 04526695..e2030483 100644 --- a/config/application.rb +++ b/config/application.rb @@ -10,7 +10,6 @@ Dotenv.load ".env.#{ENV["RAILS_ENV"]}", '.env' module Metamaps class Application < Rails::Application - config.active_job.queue_adapter = :delayed_job # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers diff --git a/db/migrate/20150930233907_create_delayed_jobs.rb b/db/migrate/20150930233907_create_delayed_jobs.rb deleted file mode 100644 index 27fdcf6c..00000000 --- a/db/migrate/20150930233907_create_delayed_jobs.rb +++ /dev/null @@ -1,22 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration - def self.up - create_table :delayed_jobs, force: true do |table| - table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue - table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually. - table.text :handler, null: false # YAML-encoded string of the object that will do work - table.text :last_error # reason for last failure (See Note below) - table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future. - table.datetime :locked_at # Set when a client is working on this object - table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead) - table.string :locked_by # Who is working on this object (if locked) - table.string :queue # The name of the queue this job is in - table.timestamps null: true - end - - add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority" - end - - def self.down - drop_table :delayed_jobs - end -end From fe578ca3b26f123e05c46bf519e85af7e28126d7 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 11:24:00 +1100 Subject: [PATCH 61/67] add migrations --- db/migrate/20160312234946_create_events.rb | 13 +++++++++++++ db/migrate/20160312235006_create_webhooks.rb | 10 ++++++++++ db/schema.rb | 12 ++++++------ 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20160312234946_create_events.rb create mode 100644 db/migrate/20160312235006_create_webhooks.rb diff --git a/db/migrate/20160312234946_create_events.rb b/db/migrate/20160312234946_create_events.rb new file mode 100644 index 00000000..7ab71099 --- /dev/null +++ b/db/migrate/20160312234946_create_events.rb @@ -0,0 +1,13 @@ +class CreateEvents < ActiveRecord::Migration + def change + create_table :events do |t| + t.string :kind, limit: 255 + t.references :eventable, polymorphic: true, index: true + t.references :user, index: true + t.references :map, index: true + t.integer :sequence_id, index: true, default: nil, null: true + t.timestamps + end + add_index :events, [:map_id, :sequence_id], unique: true + end +end diff --git a/db/migrate/20160312235006_create_webhooks.rb b/db/migrate/20160312235006_create_webhooks.rb new file mode 100644 index 00000000..0d1cf899 --- /dev/null +++ b/db/migrate/20160312235006_create_webhooks.rb @@ -0,0 +1,10 @@ +class CreateWebhooks < ActiveRecord::Migration + def change + create_table :webhooks do |t| + t.references :hookable, polymorphic: true, index: true + t.string :kind, null: false + t.string :uri, null: false + t.text :event_types, array: true, default: [] + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 38570d2f..9bb034ab 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,27 +11,27 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160310200131) do +ActiveRecord::Schema.define(version: 20160312235006) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" create_table "events", force: :cascade do |t| t.string "kind", limit: 255 - t.datetime "created_at" - t.datetime "updated_at" t.integer "eventable_id" - t.string "eventable_type", limit: 255 + t.string "eventable_type" t.integer "user_id" t.integer "map_id" t.integer "sequence_id" + t.datetime "created_at" + t.datetime "updated_at" end - add_index "events", ["created_at"], name: "index_events_on_created_at", using: :btree + add_index "events", ["eventable_type", "eventable_id"], name: "index_events_on_eventable_type_and_eventable_id", using: :btree add_index "events", ["map_id", "sequence_id"], name: "index_events_on_map_id_and_sequence_id", unique: true, using: :btree add_index "events", ["map_id"], name: "index_events_on_map_id", using: :btree - add_index "events", ["eventable_type", "eventable_id"], name: "index_events_on_eventable_type_and_eventable_id", using: :btree add_index "events", ["sequence_id"], name: "index_events_on_sequence_id", using: :btree + add_index "events", ["user_id"], name: "index_events_on_user_id", using: :btree create_table "in_metacode_sets", force: :cascade do |t| t.integer "metacode_id" From 77d69dd2a363c73a3655509e7df00a25c585b475 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 11:56:18 +1100 Subject: [PATCH 62/67] turns out we do need delayed_job --- Gemfile | 2 ++ Gemfile.lock | 7 ++++++ Procfile | 1 + .../webhooks/slack/synapse_added_to_map.rb | 2 +- .../webhooks/slack/topic_added_to_map.rb | 4 ++-- app/serializers/webhook_serializer.rb | 2 +- bin/delayed_job | 5 +++++ config/application.rb | 2 +- .../20160313003721_create_delayed_jobs.rb | 22 +++++++++++++++++++ db/schema.rb | 18 ++++++++++++++- 10 files changed, 59 insertions(+), 6 deletions(-) create mode 100755 bin/delayed_job create mode 100644 db/migrate/20160313003721_create_delayed_jobs.rb diff --git a/Gemfile b/Gemfile index 7fb90aeb..bf5997af 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,8 @@ gem 'snorlax', '~> 0.1.3' gem 'httparty' gem 'sequenced', '~> 2.0.0' gem 'active_model_serializers', '~> 0.8.1' +gem 'delayed_job', '~> 4.0.2' +gem 'delayed_job_active_record', '~> 4.0.1' gem 'paperclip' gem 'aws-sdk', '< 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 634f2031..ff5c1317 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -73,6 +73,11 @@ GEM coffee-script-source (1.10.0) concurrent-ruby (1.0.1) debug_inspector (0.0.2) + delayed_job (4.0.6) + activesupport (>= 3.0, < 5.0) + delayed_job_active_record (4.0.3) + activerecord (>= 3.0, < 5.0) + delayed_job (>= 3.0, < 4.1) devise (3.5.6) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -262,6 +267,8 @@ DEPENDENCIES binding_of_caller cancan coffee-rails + delayed_job (~> 4.0.2) + delayed_job_active_record (~> 4.0.1) devise dotenv factory_girl_rails diff --git a/Procfile b/Procfile index 802726be..e00c3019 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,3 @@ web: bundle exec rails server -p $PORT +worker: bundle exec rake jobs:work diff --git a/app/models/webhooks/slack/synapse_added_to_map.rb b/app/models/webhooks/slack/synapse_added_to_map.rb index 25093127..3d70450b 100644 --- a/app/models/webhooks/slack/synapse_added_to_map.rb +++ b/app/models/webhooks/slack/synapse_added_to_map.rb @@ -1,7 +1,7 @@ class Webhooks::Slack::SynapseAddedToMap < Webhooks::Slack::Base def text - "\"*#{eventable.synapse.topic1.name}* #{eventable.synapse.desc || '->'} *#{eventable.synapse.topic2.name}*\" was added as a connection to the map *#{view_map_on_metamaps()}*" + "\"*#{eventable.mappable.topic1.name}* #{eventable.mappable.desc || '->'} *#{eventable.mappable.topic2.name}*\" was added as a connection to the map *#{view_map_on_metamaps()}*" end def attachment_fallback diff --git a/app/models/webhooks/slack/topic_added_to_map.rb b/app/models/webhooks/slack/topic_added_to_map.rb index 6b4a16c8..89e1194b 100644 --- a/app/models/webhooks/slack/topic_added_to_map.rb +++ b/app/models/webhooks/slack/topic_added_to_map.rb @@ -1,11 +1,11 @@ class Webhooks::Slack::TopicAddedToMap < Webhooks::Slack::Base def text - "New #{eventable.topic.metacode.name} topic *#{eventable.topic.name}* was added to the map *#{view_map_on_metamaps()}*" + "New #{eventable.mappable.metacode.name} topic *#{eventable.mappable.name}* was added to the map *#{view_map_on_metamaps()}*" end def icon_url - eventable.topic.metacode.icon + eventable.mappable.metacode.icon end def attachment_fallback diff --git a/app/serializers/webhook_serializer.rb b/app/serializers/webhook_serializer.rb index 9adfd101..ed013cae 100644 --- a/app/serializers/webhook_serializer.rb +++ b/app/serializers/webhook_serializer.rb @@ -1,3 +1,3 @@ class WebhookSerializer < ActiveModel::Serializer - attributes :text, :username #, :attachments #, :icon_url + attributes :text, :username, :icon_url #, :attachments end diff --git a/bin/delayed_job b/bin/delayed_job new file mode 100755 index 00000000..edf19598 --- /dev/null +++ b/bin/delayed_job @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) +require 'delayed/command' +Delayed::Command.new(ARGV).daemonize diff --git a/config/application.rb b/config/application.rb index e2030483..e7a47614 100644 --- a/config/application.rb +++ b/config/application.rb @@ -10,7 +10,7 @@ Dotenv.load ".env.#{ENV["RAILS_ENV"]}", '.env' module Metamaps class Application < Rails::Application - + config.active_job.queue_adapter = :delayed_job # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/db/migrate/20160313003721_create_delayed_jobs.rb b/db/migrate/20160313003721_create_delayed_jobs.rb new file mode 100644 index 00000000..27fdcf6c --- /dev/null +++ b/db/migrate/20160313003721_create_delayed_jobs.rb @@ -0,0 +1,22 @@ +class CreateDelayedJobs < ActiveRecord::Migration + def self.up + create_table :delayed_jobs, force: true do |table| + table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue + table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually. + table.text :handler, null: false # YAML-encoded string of the object that will do work + table.text :last_error # reason for last failure (See Note below) + table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future. + table.datetime :locked_at # Set when a client is working on this object + table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead) + table.string :locked_by # Who is working on this object (if locked) + table.string :queue # The name of the queue this job is in + table.timestamps null: true + end + + add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority" + end + + def self.down + drop_table :delayed_jobs + end +end diff --git a/db/schema.rb b/db/schema.rb index 9bb034ab..d0381055 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,11 +11,27 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160312235006) do +ActiveRecord::Schema.define(version: 20160313003721) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "delayed_jobs", force: :cascade do |t| + t.integer "priority", default: 0, null: false + t.integer "attempts", default: 0, null: false + t.text "handler", null: false + t.text "last_error" + t.datetime "run_at" + t.datetime "locked_at" + t.datetime "failed_at" + t.string "locked_by" + t.string "queue" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree + create_table "events", force: :cascade do |t| t.string "kind", limit: 255 t.integer "eventable_id" From 72b2e8f8f220ebfb104c22a8f4ffa61760904107 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 13 Mar 2016 11:58:09 +1100 Subject: [PATCH 63/67] doesn't look good for now, take it out, add it later --- app/models/webhooks/slack/topic_added_to_map.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/models/webhooks/slack/topic_added_to_map.rb b/app/models/webhooks/slack/topic_added_to_map.rb index 89e1194b..3574a464 100644 --- a/app/models/webhooks/slack/topic_added_to_map.rb +++ b/app/models/webhooks/slack/topic_added_to_map.rb @@ -3,10 +3,7 @@ class Webhooks::Slack::TopicAddedToMap < Webhooks::Slack::Base def text "New #{eventable.mappable.metacode.name} topic *#{eventable.mappable.name}* was added to the map *#{view_map_on_metamaps()}*" end - - def icon_url - eventable.mappable.metacode.icon - end + # todo: it would be sweet if it sends it with the metacode as the icon_url def attachment_fallback "" #{}"*#{eventable.name}*\n#{eventable.description}\n" From 74cf9ba7177db6d11100f6f8fd1f2306fc90d789 Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sat, 12 Mar 2016 19:40:56 -0800 Subject: [PATCH 64/67] Run tests on Travis CI; show build status badge --- .travis.yml | 9 +++++++++ README.md | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..58bf9d25 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +sudo: false +language: ruby +rvm: + - 2.1.3 +before_script: + - export RAILS_ENV=test + - cp .example-env .env + - bundle exec rake db:create + - bundle exec rake db:schema:load diff --git a/README.md b/README.md index 293265ac..cf871b82 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ Metamaps ======= [![Join the chat at https://gitter.im/metamaps/metamaps_gen002](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/metamaps/metamaps_gen002?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://jenkins.devinhoward.ca/job/metamaps_gen002.develop/badge/icon)](https://jenkins.devinhoward.ca/job/metamaps_gen002.develop/) +[![Build Status](https://travis-ci.org/metamaps/metamaps_gen002.svg)](https://travis-ci.org/metamaps/metamaps_gen002) -Welcome to the Metamaps GitHub repo. +Welcome to the Metamaps GitHub repo. ## About @@ -12,7 +12,7 @@ Metamaps is a free and AGPL open source technology for changemakers, innovators, You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in a private beta. -Metamaps is created and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch with us at team@metamaps.cc or @metamapps on twitter. +Metamaps is created and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch with us at team@metamaps.cc or @metamapps on twitter. To get connected with the community interested in Metamaps, join our [Google+ community][community]. @@ -52,7 +52,7 @@ We haven't figured out Vagrant for Windows yet, but we have a set of manual inst ## Contributing -Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved. +Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved. ## Community From 3fbb3d1dc9b9d80ba2b7d843d7e89e0f432b1a71 Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sun, 13 Mar 2016 00:20:18 -0800 Subject: [PATCH 65/67] more token entropy --- app/models/token.rb | 15 +++++++++++++-- spec/models/token_spec.rb | 7 ++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/models/token.rb b/app/models/token.rb index 15bdca79..714730fc 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -1,11 +1,22 @@ class Token < ActiveRecord::Base belongs_to :user - before_create :generate_token + before_create :assign_token + + CHARS = 32 private + def assign_token + self.token = generate_token + end + def generate_token - self.token = SecureRandom.uuid.gsub(/\-/,'') + loop do + candidate = SecureRandom.base64(CHARS).gsub(/\W/, '') + if candidate.size >= CHARS + return candidate[0...CHARS] + end + end end end diff --git a/spec/models/token_spec.rb b/spec/models/token_spec.rb index 18bba17d..9fedeb2a 100644 --- a/spec/models/token_spec.rb +++ b/spec/models/token_spec.rb @@ -1,5 +1,10 @@ require 'rails_helper' RSpec.describe Token, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + context "#generate_token" do + subject (:token) { Token.new } + it "should generate an alphanumeric token of 32 characters" do + expect(token.send(:generate_token)).to match /[a-zA-Z0-9]{32}/ + end + end end From f3eb55897156bd4e2e41460d66a1edabe60c29aa Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sun, 13 Mar 2016 13:28:07 -0700 Subject: [PATCH 66/67] fix test regex --- spec/models/token_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/token_spec.rb b/spec/models/token_spec.rb index 9fedeb2a..ddb8d696 100644 --- a/spec/models/token_spec.rb +++ b/spec/models/token_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Token, type: :model do context "#generate_token" do subject (:token) { Token.new } it "should generate an alphanumeric token of 32 characters" do - expect(token.send(:generate_token)).to match /[a-zA-Z0-9]{32}/ + expect(token.send(:generate_token)).to match /^[a-zA-Z0-9]{32}$/ end end end From 6f5258cbb7bd5ed145dba95d2d1c594f41fbbe85 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Mon, 14 Mar 2016 08:19:26 +1100 Subject: [PATCH 67/67] needed a policy for tokens --- app/policies/token_policy.rb | 24 ++++++++++++++++++++++++ app/serializers/token_serializer.rb | 2 -- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 app/policies/token_policy.rb diff --git a/app/policies/token_policy.rb b/app/policies/token_policy.rb new file mode 100644 index 00000000..393d2441 --- /dev/null +++ b/app/policies/token_policy.rb @@ -0,0 +1,24 @@ +class TokenPolicy < ApplicationPolicy + class Scope < Scope + def resolve + if user + scope.where('tokens.user_id = ?', user.id) + else + where(:id => nil).where("id IS NOT ?", nil) # to just return none + end + end + end + + def create? + user.present? + end + + def my_tokens? + user.present? + end + + def destroy? + user.present? && record.user == user + end + +end diff --git a/app/serializers/token_serializer.rb b/app/serializers/token_serializer.rb index 8eed535a..7abcc3df 100644 --- a/app/serializers/token_serializer.rb +++ b/app/serializers/token_serializer.rb @@ -1,9 +1,7 @@ class TokenSerializer < ActiveModel::Serializer - embed :ids, include: true attributes :id, :token, :description, - :user_id, :created_at, :updated_at