Merge remote-tracking branch 'origin/feature/pundit' into feature/api.pundit

This commit is contained in:
Connor Turland 2016-03-12 07:19:19 +11:00
commit e6017c4129
23 changed files with 542 additions and 321 deletions

View file

@ -6,7 +6,7 @@ gem 'rails', '4.2.4'
gem 'devise' gem 'devise'
gem 'redis' gem 'redis'
gem 'pg' gem 'pg'
gem 'cancancan' gem 'pundit'
gem 'formula' gem 'formula'
gem 'formtastic' gem 'formtastic'
gem 'json' gem 'json'

View file

@ -56,8 +56,8 @@ GEM
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
builder (3.2.2) builder (3.2.2)
byebug (8.2.2) byebug (5.0.0)
cancancan (1.10.1) columnize (= 0.9.0)
climate_control (0.0.3) climate_control (0.0.3)
activesupport (>= 3.0) activesupport (>= 3.0)
cocaine (0.5.8) cocaine (0.5.8)
@ -142,6 +142,8 @@ GEM
pry (~> 0.10) pry (~> 0.10)
pry-rails (0.3.4) pry-rails (0.3.4)
pry (>= 0.9.10) pry (>= 0.9.10)
pundit (1.1.0)
activesupport (>= 3.0.0)
quiet_assets (1.1.0) quiet_assets (1.1.0)
railties (>= 3.1, < 5.0) railties (>= 3.1, < 5.0)
rack (1.6.4) rack (1.6.4)
@ -249,7 +251,6 @@ DEPENDENCIES
best_in_place best_in_place
better_errors better_errors
binding_of_caller binding_of_caller
cancancan
coffee-rails coffee-rails
devise devise
dotenv dotenv
@ -266,6 +267,7 @@ DEPENDENCIES
pg pg
pry-byebug pry-byebug
pry-rails pry-rails
pundit
quiet_assets quiet_assets
rails (= 4.2.4) rails (= 4.2.4)
rails3-jquery-autocomplete rails3-jquery-autocomplete

View file

@ -1,4 +1,6 @@
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :handle_unauthorized
protect_from_forgery protect_from_forgery
before_action :get_invite_link before_action :get_invite_link
@ -23,6 +25,10 @@ class ApplicationController < ActionController::Base
end end
end end
def handle_unauthorized
head :forbidden # TODO make this better
end
private private
def require_no_user def require_no_user

View file

@ -4,19 +4,20 @@ class MainController < ApplicationController
include UsersHelper include UsersHelper
include SynapsesHelper include SynapsesHelper
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index
respond_to :html, :json respond_to :html, :json
# home page # home page
def home def home
@current = current_user @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(1).per(20)
respond_to do |format| respond_to do |format|
format.html { format.html {
if authenticated? if authenticated?
@maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(1).per(20) render 'main/home'
respond_with(@maps, @current)
else else
respond_with(@current) render 'maps/activemaps'
end end
} }
end end
@ -213,5 +214,4 @@ class MainController < ApplicationController
render json: autocomplete_synapse_array_json(@synapses) render json: autocomplete_synapse_array_json(@synapses)
end end
end end

View file

@ -1,12 +1,15 @@
class MappingsController < ApplicationController class MappingsController < ApplicationController
before_action :require_user, only: [:create, :update, :destroy] before_action :require_user, only: [:create, :update, :destroy]
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index
respond_to :json respond_to :json
# GET /mappings/1.json # GET /mappings/1.json
def show def show
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
authorize! @mapping
render json: @mapping render json: @mapping
end end
@ -14,6 +17,7 @@ class MappingsController < ApplicationController
# POST /mappings.json # POST /mappings.json
def create def create
@mapping = Mapping.new(mapping_params) @mapping = Mapping.new(mapping_params)
authorize! @mapping
if @mapping.save if @mapping.save
render json: @mapping, status: :created render json: @mapping, status: :created
@ -25,6 +29,7 @@ class MappingsController < ApplicationController
# PUT /mappings/1.json # PUT /mappings/1.json
def update def update
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
authorize! @mapping
if @mapping.update_attributes(mapping_params) if @mapping.update_attributes(mapping_params)
head :no_content head :no_content
@ -36,7 +41,7 @@ class MappingsController < ApplicationController
# DELETE /mappings/1.json # DELETE /mappings/1.json
def destroy def destroy
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
@map = @mapping.map authorize! @mapping
@mapping.destroy @mapping.destroy

View file

@ -1,54 +1,74 @@
class MapsController < ApplicationController class MapsController < ApplicationController
before_action :require_user, only: [:create, :update, :screenshot, :destroy] 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 respond_to :html, :json
autocomplete :map, :name, :full => true, :extra_data => [:user_id] autocomplete :map, :name, :full => true, :extra_data => [:user_id]
# GET /explore/active # GET /explore/active
# GET /explore/featured def activemaps
# GET /explore/mapper/:id
def index
return redirect_to activemaps_url if request.path == "/explore"
@current = current_user
@maps = []
page = params[:page].present? ? params[:page] : 1 page = params[:page].present? ? params[:page] : 1
@maps = policy_scope(Map).order("updated_at DESC")
.page(page).per(20)
if request.path.index("/explore/active") != nil # root url => main/home. main/home renders maps/activemaps view.
@maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) redirect_to root_url and return if authenticated?
@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
respond_to do |format| respond_to do |format|
format.html { format.html { respond_with(@maps, @user) }
if @request == "active" && authenticated? format.json { render json: @maps }
redirect_to root_url and return
end end
respond_with(@maps, @request, @user) end
}
# GET /explore/featured
def featuredmaps
page = params[:page].present? ? params[:page] : 1
@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) }
format.json { render json: @maps }
end
end
# GET /explore/mine
def mymaps
return redirect_to activemaps_url if !authenticated?
page = params[:page].present? ? params[:page] : 1
@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) }
format.json { render json: @maps }
end
end
# GET /explore/mapper/:id
def usermaps
page = params[:page].present? ? params[:page] : 1
@user = User.find(params[:id])
@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) }
format.json { render json: @maps } format.json { render json: @maps }
end end
end end
# GET maps/:id # GET maps/:id
def show def show
@map = Map.find(params[:id])
@current = current_user authorize! @map
@map = Map.find(params[:id]).authorize_to_show(@current)
if not @map if not @map
redirect_to root_url, notice: "Access denied. That map is private." and return redirect_to root_url, notice: "Access denied. That map is private." and return
@ -57,11 +77,11 @@ class MapsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
@allmappers = @map.contributors @allmappers = @map.contributors
@alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.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.id != s.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| @allmappings = @map.mappings.to_a.delete_if {|m|
object = m.mappable 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) respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map)
@ -72,20 +92,19 @@ class MapsController < ApplicationController
# GET maps/:id/contains # GET maps/:id/contains
def contains def contains
@map = Map.find(params[:id])
@current = current_user authorize! @map
@map = Map.find(params[:id]).authorize_to_show(@current)
if not @map if not @map
redirect_to root_url, notice: "Access denied. That map is private." and return redirect_to root_url, notice: "Access denied. That map is private." and return
end end
@allmappers = @map.contributors @allmappers = @map.contributors
@alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.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.id != s.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| @allmappings = @map.mappings.to_a.delete_if {|m|
object = m.mappable 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() @json = Hash.new()
@ -121,6 +140,7 @@ class MapsController < ApplicationController
mapping.xloc = topic[1] mapping.xloc = topic[1]
mapping.yloc = topic[2] mapping.yloc = topic[2]
@map.topicmappings << mapping @map.topicmappings << mapping
authorize! mapping, :create
mapping.save mapping.save
end end
@ -133,6 +153,7 @@ class MapsController < ApplicationController
mapping.map = @map mapping.map = @map
mapping.mappable = Synapse.find(synapse_id) mapping.mappable = Synapse.find(synapse_id)
@map.synapsemappings << mapping @map.synapsemappings << mapping
authorize! mapping, :create
mapping.save mapping.save
end end
end end
@ -140,6 +161,8 @@ class MapsController < ApplicationController
@map.arranged = true @map.arranged = true
end end
authorize! @map
if @map.save if @map.save
respond_to do |format| respond_to do |format|
format.json { render :json => @map } format.json { render :json => @map }
@ -153,8 +176,8 @@ class MapsController < ApplicationController
# PUT maps/:id # PUT maps/:id
def update def update
@current = current_user @map = Map.find(params[:id])
@map = Map.find(params[:id]).authorize_to_edit(@current) authorize! @map
respond_to do |format| respond_to do |format|
if !@map if !@map
@ -169,10 +192,9 @@ class MapsController < ApplicationController
# POST maps/:id/upload_screenshot # POST maps/:id/upload_screenshot
def screenshot def screenshot
@current = current_user @map = Map.find(params[:id])
@map = Map.find(params[:id]).authorize_to_edit(@current) authorize! @map
if @map
png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1]) png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1])
StringIO.open(png) do |data| StringIO.open(png) do |data|
data.class.class_eval { attr_accessor :original_filename, :content_type } data.class.class_eval { attr_accessor :original_filename, :content_type }
@ -186,27 +208,19 @@ class MapsController < ApplicationController
else else
render :json => {:message => "Failed to upload image."} render :json => {:message => "Failed to upload image."}
end end
else
render :json => {:message => "Unauthorized to set map screenshot."}
end
end end
# DELETE maps/:id # DELETE maps/:id
def destroy def destroy
@current = current_user @map = Map.find(params[:id])
authorize! @map
@map = Map.find(params[:id]).authorize_to_delete(@current) @map.delete
@map.delete if @map
respond_to do |format| respond_to do |format|
format.json { format.json do
if @map head :no_content
render json: "success"
else
render json: "unauthorized"
end end
}
end end
end end

View file

@ -2,18 +2,15 @@ class SynapsesController < ApplicationController
include TopicsHelper include TopicsHelper
before_action :require_user, only: [:create, :update, :destroy] before_action :require_user, only: [:create, :update, :destroy]
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index
respond_to :json respond_to :json
# GET /synapses/1.json # GET /synapses/1.json
def show def show
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
authorize! @synapse
#.authorize_to_show(@current)
#if not @synapse
# redirect_to root_url and return
#end
render json: @synapse render json: @synapse
end end
@ -23,6 +20,7 @@ class SynapsesController < ApplicationController
def create def create
@synapse = Synapse.new(synapse_params) @synapse = Synapse.new(synapse_params)
@synapse.desc = "" if @synapse.desc.nil? @synapse.desc = "" if @synapse.desc.nil?
authorize! @synapse
respond_to do |format| respond_to do |format|
if @synapse.save if @synapse.save
@ -38,6 +36,7 @@ class SynapsesController < ApplicationController
def update def update
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
@synapse.desc = "" if @synapse.desc.nil? @synapse.desc = "" if @synapse.desc.nil?
authorize! @synapse
respond_to do |format| respond_to do |format|
if @synapse.update_attributes(synapse_params) if @synapse.update_attributes(synapse_params)
@ -50,8 +49,9 @@ class SynapsesController < ApplicationController
# DELETE synapses/:id # DELETE synapses/:id
def destroy def destroy
@synapse = Synapse.find(params[:id]).authorize_to_delete(current_user) @synapse = Synapse.find(params[:id])
@synapse.delete if @synapse authorize! @synapse
@synapse.delete
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }

View file

@ -2,20 +2,15 @@ class TopicsController < ApplicationController
include TopicsHelper include TopicsHelper
before_action :require_user, only: [:create, :update, :destroy] before_action :require_user, only: [:create, :update, :destroy]
after_action :verify_authorized
respond_to :html, :js, :json respond_to :html, :js, :json
# GET /topics/autocomplete_topic # GET /topics/autocomplete_topic
def autocomplete_topic def autocomplete_topic
@current = current_user
term = params[:term] term = params[:term]
if term && !term.empty? if term && !term.empty?
@topics = Topic.where('LOWER("name") like ?', term.downcase + '%').order('"name"') @topics = policy_scope(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.id != t.user_id)) }
else else
@topics = [] @topics = []
end end
@ -24,29 +19,16 @@ class TopicsController < ApplicationController
# GET topics/:id # GET topics/:id
def show def show
@current = current_user @topic = Topic.find(params[:id])
@topic = Topic.find(params[:id]).authorize_to_show(@current) authorize! @topic
if not @topic
redirect_to root_url, notice: "Access denied. That topic is private." and return
end
respond_to do |format| respond_to do |format|
format.html { 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 @alltopics = ([@topic] + policy_scope(@topic.relatives)
@allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } @allsynapses = policy_scope(@topic.synapses)
@allcreators = [] @allcreators = @alltopics.map(&:user).uniq
@alltopics.each do |t| @allcreators += @allsynapses.map(&:user).uniq
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
respond_with(@allsynapses, @alltopics, @allcreators, @topic) respond_with(@allsynapses, @alltopics, @allcreators, @topic)
} }
@ -56,27 +38,14 @@ class TopicsController < ApplicationController
# GET topics/:id/network # GET topics/:id/network
def network def network
@current = current_user @topic = Topic.find(params[:id])
@topic = Topic.find(params[:id]).authorize_to_show(@current) authorize! @topic
if not @topic @alltopics = [@topic] + policy_scope(@topic.relatives)
redirect_to root_url, notice: "Access denied. That topic is private." and return @allsynapses = policy_scope(@topic.synapses)
end
@alltopics = @topic.relatives.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @allcreators = @alltopics.map(&:user).uniq
@allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) } @allcreators += @allsynapses.map(&:user).uniq
@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 = Hash.new()
@json['topic'] = @topic @json['topic'] = @topic
@ -91,29 +60,19 @@ class TopicsController < ApplicationController
# GET topics/:id/relative_numbers # GET topics/:id/relative_numbers
def relative_numbers def relative_numbers
@current = current_user @topic = Topic.find(params[:id])
@topic = Topic.find(params[:id]).authorize_to_show(@current) authorize @topic
if not @topic topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
redirect_to root_url, notice: "Access denied. That topic is private." and return
@alltopics = policy_scope(@topic.relatives).to_a.uniq
@alltopics.delete_if! do |topic|
topicsAlreadyHas.index(topic.id) != nil
end end
@topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] @json = Hash.new(0)
@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)))
}
@alltopics.uniq!
@json = Hash.new()
@alltopics.each do |t| @alltopics.each do |t|
if @json[t.metacode.id]
@json[t.metacode.id] += 1 @json[t.metacode.id] += 1
else
@json[t.metacode.id] = 1
end
end end
respond_to do |format| respond_to do |format|
@ -123,45 +82,31 @@ class TopicsController < ApplicationController
# GET topics/:id/relatives # GET topics/:id/relatives
def relatives def relatives
@current = current_user @topic = Topic.find(params[:id])
@topic = Topic.find(params[:id]).authorize_to_show(@current) authorize! @topic
if not @topic topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
redirect_to root_url, notice: "Access denied. That topic is private." and return
alltopics = policy_scope(@topic.relatives).to_a.uniq.delete_if do |topic|
topicsAlreadyHas.index(topic.id.to_s) != nil
end end
@topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] #find synapses between topics in alltopics array
allsynapses = policy_scope(@topic.synapses)
@alltopics = @topic.relatives.to_a.delete_if {|t| synapse_ids = (allsynapses.map(&:topic1_id) + allsynapses.map(&:topic2_id)).uniq
@topicsAlreadyHas.index(t.id.to_s) != nil || allsynapses.delete_if! do |synapse|
(params[:metacode] && t.metacode_id.to_s != params[:metacode]) || synapse_ids.index(synapse.id) != nil
(t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)))
}
@alltopics.uniq!
@allsynapses = @topic.synapses.to_a.delete_if {|s|
(s.topic1 == @topic && @alltopics.index(s.topic2) == nil) ||
(s.topic2 == @topic && @alltopics.index(s.topic1) == nil)
}
@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
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 end
@json = Hash.new() @json = Hash.new()
@json['topics'] = @alltopics @json['topics'] = alltopics
@json['synapses'] = @allsynapses @json['synapses'] = allsynapses
@json['creators'] = @allcreators @json['creators'] = allcreators
respond_to do |format| respond_to do |format|
format.json { render json: @json } format.json { render json: @json }
@ -172,6 +117,7 @@ class TopicsController < ApplicationController
# POST /topics.json # POST /topics.json
def create def create
@topic = Topic.new(topic_params) @topic = Topic.new(topic_params)
authorize! @topic
respond_to do |format| respond_to do |format|
if @topic.save if @topic.save
@ -186,6 +132,7 @@ class TopicsController < ApplicationController
# PUT /topics/1.json # PUT /topics/1.json
def update def update
@topic = Topic.find(params[:id]) @topic = Topic.find(params[:id])
authorize! @topic
respond_to do |format| respond_to do |format|
if @topic.update_attributes(topic_params) if @topic.update_attributes(topic_params)
@ -198,10 +145,10 @@ class TopicsController < ApplicationController
# DELETE topics/:id # DELETE topics/:id
def destroy def destroy
@current = current_user @topic = Topic.find(params[:id])
@topic = Topic.find(params[:id]).authorize_to_delete(@current) authorize! @topic
@topic.delete if @topic
@topic.delete
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }
end end

View file

@ -0,0 +1,61 @@
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
# 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
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end

View file

@ -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

View file

@ -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 || admin_override
end
end

View file

@ -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

View file

@ -0,0 +1,23 @@
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
end
def update?
user.present? && (record.permission == 'commons' || record.user == user)
end
def destroy?
record.user == user || admin_override
end
end

View file

@ -0,0 +1,39 @@
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)
end
def destroy?
record.user == user || admin_override
end
def autocomplete_topic?
user.present?
end
def network?
show?
end
def relative_numbers?
show?
end
def relatives?
show?
end
end

View file

@ -2,9 +2,9 @@
# @file # @file
# Located at / # Located at /
# Shows 3 most recently created topics, synapses, and maps. # Shows 3 most recently created topics, synapses, and maps.
#%> #
%>
<% if !authenticated? %>
<% content_for :title, "Home | Metamaps" %> <% content_for :title, "Home | Metamaps" %>
<div id="yield"> <div id="yield">
<div class="homeWrapper homeText"> <div class="homeWrapper homeText">
@ -15,7 +15,7 @@
</div> </div>
<div class="fullWidthWrapper withVideo"> <div class="fullWidthWrapper withVideo">
<div class="homeWrapper"> <div class="homeWrapper">
<iframe class="homeVideo" src="//player.vimeo.com/video/113154814" width="560" height="315" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> <iframe class="homeVideo" src="https://player.vimeo.com/video/113154814" width="560" height="315" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<div class="callToAction"> <div class="callToAction">
<h3>Who finds it useful?</h3> <h3>Who finds it useful?</h3>
<p>Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!</p> <p>Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!</p>
@ -41,13 +41,3 @@
Metamaps.currentSection = ""; Metamaps.currentSection = "";
Metamaps.currentPage = ""; Metamaps.currentPage = "";
</script> </script>
<% elsif authenticated? %>
<% content_for :title, "Explore Active Maps | Metamaps" %>
<script>
Metamaps.Maps.Active = <%= @maps.to_json.html_safe %>;
Metamaps.currentSection = "";
Metamaps.currentPage = "";
Metamaps.GlobalUI.Search.open();
Metamaps.GlobalUI.Search.lock();
</script>
<% end %>

View file

@ -0,0 +1,15 @@
<% #
# @file
# Shows a list of recently active maps
# GET /explore/active(.:format)
# %>
<script>
Metamaps.Maps.Active = <%= @maps.to_json.html_safe %>;
Metamaps.currentPage = "active";
<% content_for :title, "Explore Active Maps | Metamaps" %>
Metamaps.currentSection = "explore";
Metamaps.GlobalUI.Search.isOpen = true;
Metamaps.GlobalUI.Search.lock();
</script>

View file

@ -0,0 +1,15 @@
<% #
# @file
# Shows a list of featured maps
# GET /explore/featured(.:format)
# %>
<script>
Metamaps.Maps.Featured = <%= @maps.to_json.html_safe %>;
Metamaps.currentPage = "featured";
<% content_for :title, "Explore Featured Maps | Metamaps" %>
Metamaps.currentSection = "explore";
Metamaps.GlobalUI.Search.isOpen = true;
Metamaps.GlobalUI.Search.lock();
</script>

View file

@ -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)
# %>
<script>
<% if @request == "you" %>
Metamaps.Maps.Mine = <%= @maps.to_json.html_safe %>;
Metamaps.currentPage = "mine";
<% content_for :title, "Explore My Maps | Metamaps" %>
<% elsif @request == "featured" %>
Metamaps.Maps.Featured = <%= @maps.to_json.html_safe %>;
Metamaps.currentPage = "featured";
<% content_for :title, "Explore Featured Maps | Metamaps" %>
<% elsif @request == "active" %>
Metamaps.Maps.Active = <%= @maps.to_json.html_safe %>;
Metamaps.currentPage = "active";
<% content_for :title, "Explore Active Maps | Metamaps" %>
<% elsif @request == "mapper" %>
Metamaps.Maps.Mapper = {
models: <%= @maps.to_json.html_safe %>,
id: <%= params[:id] %>
};
Metamaps.currentPage = "mapper";
<% content_for :title, @user.name + " | Metamaps" %>
<% end %>
Metamaps.currentSection = "explore";
Metamaps.GlobalUI.Search.isOpen = true;
Metamaps.GlobalUI.Search.lock();
</script>

View file

@ -0,0 +1,15 @@
<% #
# @file
# Shows a list of current user's maps
# GET /explore/mine(.:format)
# %>
<script>
Metamaps.Maps.Mine = <%= @maps.to_json.html_safe %>;
Metamaps.currentPage = "mine";
<% content_for :title, "Explore My Maps | Metamaps" %>
Metamaps.currentSection = "explore";
Metamaps.GlobalUI.Search.isOpen = true;
Metamaps.GlobalUI.Search.lock();
</script>

View file

@ -0,0 +1,18 @@
<% #
# @file
# Shows a list of a user's maps
# GET /explore/mapper/:id(.:format)
# %>
<script>
Metamaps.Maps.Mapper = {
models: <%= @maps.to_json.html_safe %>,
id: <%= params[:id] %>
};
Metamaps.currentPage = "mapper";
<% content_for :title, @user.name + " | Metamaps" %>
Metamaps.currentSection = "explore";
Metamaps.GlobalUI.Search.isOpen = true;
Metamaps.GlobalUI.Search.lock();
</script>

View file

@ -53,5 +53,8 @@ module Metamaps
g.test_framework :rspec g.test_framework :rspec
end end
config.active_record.raise_in_transactional_callbacks = true config.active_record.raise_in_transactional_callbacks = true
# pundit errors return 403 FORBIDDEN
config.action_dispatch.rescue_responses["Pundit::NotAuthorizedError"] = :forbidden
end end
end end

View file

@ -30,11 +30,12 @@ Metamaps::Application.routes.draw do
get 'topics/:id/relative_numbers', to: 'topics#relative_numbers', as: :relative_numbers get 'topics/:id/relative_numbers', to: 'topics#relative_numbers', as: :relative_numbers
get 'topics/:id/relatives', to: 'topics#relatives', as: :relatives get 'topics/:id/relatives', to: 'topics#relatives', as: :relatives
get 'explore/active', to: 'maps#index', as: :activemaps resources :maps, except: [:index, :new, :edit]
get 'explore/featured', to: 'maps#index', as: :featuredmaps get 'explore/active', to: 'maps#activemaps'
get 'explore/mine', to: 'maps#index', as: :mymaps get 'explore/featured', to: 'maps#featuredmaps'
get 'explore/mapper/:id', to: 'maps#index', as: :usermaps get 'explore/mine', to: 'maps#mymaps'
resources :maps, except: [:new, :edit] get 'explore/mapper/:id', to: 'maps#usermaps'
get 'maps/:id/contains', to: 'maps#contains', as: :contains get 'maps/:id/contains', to: 'maps#contains', as: :contains
post 'maps/:id/upload_screenshot', to: 'maps#screenshot', as: :screenshot post 'maps/:id/upload_screenshot', to: 'maps#screenshot', as: :screenshot

View file

@ -10,7 +10,7 @@ RSpec.describe MapsController, type: :controller do
describe 'GET #index' do describe 'GET #index' do
it 'viewable maps as @maps' do it 'viewable maps as @maps' do
get :index, {} get :activemaps
expect(assigns(:maps)).to eq([map]) expect(assigns(:maps)).to eq([map])
end end
end end