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 'redis'
gem 'pg'
gem 'cancancan'
gem 'pundit'
gem 'formula'
gem 'formtastic'
gem 'json'

View file

@ -56,8 +56,8 @@ GEM
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
byebug (8.2.2)
cancancan (1.10.1)
byebug (5.0.0)
columnize (= 0.9.0)
climate_control (0.0.3)
activesupport (>= 3.0)
cocaine (0.5.8)
@ -142,6 +142,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)
@ -249,7 +251,6 @@ DEPENDENCIES
best_in_place
better_errors
binding_of_caller
cancancan
coffee-rails
devise
dotenv
@ -266,6 +267,7 @@ DEPENDENCIES
pg
pry-byebug
pry-rails
pundit
quiet_assets
rails (= 4.2.4)
rails3-jquery-autocomplete

View file

@ -1,4 +1,6 @@
class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :handle_unauthorized
protect_from_forgery
before_action :get_invite_link
@ -22,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

View file

@ -3,20 +3,21 @@ 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
# 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 +214,4 @@ class MainController < ApplicationController
render json: autocomplete_synapse_array_json(@synapses)
end
end

View file

@ -1,12 +1,15 @@
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 +17,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 +29,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 +41,7 @@ class MappingsController < ApplicationController
# DELETE /mappings/1.json
def destroy
@mapping = Mapping.find(params[:id])
@map = @mapping.map
authorize! @mapping
@mapping.destroy

View file

@ -1,54 +1,74 @@
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
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"
@current = current_user
@maps = []
def activemaps
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
@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
# root url => main/home. main/home renders maps/activemaps view.
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, @user) }
format.json { render json: @maps }
end
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 }
end
end
# GET maps/:id
def show
@current = current_user
@map = Map.find(params[:id]).authorize_to_show(@current)
@map = Map.find(params[:id])
authorize! @map
if not @map
redirect_to root_url, notice: "Access denied. That map is private." and return
@ -57,11 +77,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)
@ -72,20 +92,19 @@ 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! @map
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()
@ -121,6 +140,7 @@ class MapsController < ApplicationController
mapping.xloc = topic[1]
mapping.yloc = topic[2]
@map.topicmappings << mapping
authorize! mapping, :create
mapping.save
end
@ -133,6 +153,7 @@ class MapsController < ApplicationController
mapping.map = @map
mapping.mappable = Synapse.find(synapse_id)
@map.synapsemappings << mapping
authorize! mapping, :create
mapping.save
end
end
@ -140,6 +161,8 @@ class MapsController < ApplicationController
@map.arranged = true
end
authorize! @map
if @map.save
respond_to do |format|
format.json { render :json => @map }
@ -153,8 +176,8 @@ 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! @map
respond_to do |format|
if !@map
@ -169,45 +192,36 @@ 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! @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
@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|
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

View file

@ -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)
#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 }

View file

@ -2,20 +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
@current = current_user
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.id != t.user_id)) }
@topics = policy_scope(Topic.where('LOWER("name") like ?', term.downcase + '%')).order('"name"')
else
@topics = []
end
@ -24,29 +19,16 @@ class TopicsController < ApplicationController
# GET topics/:id
def show
@current = current_user
@topic = Topic.find(params[:id]).authorize_to_show(@current)
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.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] + 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)
}
@ -56,28 +38,15 @@ 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! @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.id != t.user_id)) }
@allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.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
@ -91,121 +60,99 @@ 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 @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.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
@current = current_user
@topic = Topic.find(params[:id]).authorize_to_show(@current)
@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.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
@current = current_user
@topic = Topic.find(params[:id]).authorize_to_delete(@current)
@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

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,52 +2,42 @@
# @file
# Located at /
# Shows 3 most recently created topics, synapses, and maps.
#%>
<% if !authenticated? %>
<% content_for :title, "Home | Metamaps" %>
<div id="yield">
<div class="homeWrapper homeText">
<div class="homeTitle">Make Sense with Metamaps</div>
<div class="homeIntro">
<span class="green din-medium">METAMAPS.CC</span> 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 <span class="din-medium">invite-only beta.</span>
</div>
</div>
<div class="fullWidthWrapper withVideo">
<div class="homeWrapper">
<iframe class="homeVideo" src="//player.vimeo.com/video/113154814" width="560" height="315" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<div class="callToAction">
<h3>Who finds it useful?</h3>
<p>Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!</p>
<button type="button" class="button learnMoreCTA" onclick="Metamaps.GlobalUI.openLightbox('about');">LEARN MORE</button>
<a href="/explore/featured" class="exploreFeaturedCTA">EXPLORE FEATURED MAPS</a>
<a href="/request" class="requestInviteCTA" data-bypass="true">REQUEST INVITE</a>
</div>
<div class="clearfloat"></div>
</div>
</div>
<div class="fullWidthWrapper withPartners">
<div class="homeWrapper homePartners">
<% # our partners %>
</div>
</div>
</div><!-- end yield -->
<div class="github-fork-ribbon-wrapper right-bottom">
<div class="github-fork-ribbon">
<a href="https://github.com/metamaps/metamaps_gen002" target="_blank">Fork me on GitHub</a>
</div>
</div>
<script>
Metamaps.currentSection = "";
Metamaps.currentPage = "";
</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 %>
#
%>
<% content_for :title, "Home | Metamaps" %>
<div id="yield">
<div class="homeWrapper homeText">
<div class="homeTitle">Make Sense with Metamaps</div>
<div class="homeIntro">
<span class="green din-medium">METAMAPS.CC</span> 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 <span class="din-medium">invite-only beta.</span>
</div>
</div>
<div class="fullWidthWrapper withVideo">
<div class="homeWrapper">
<iframe class="homeVideo" src="https://player.vimeo.com/video/113154814" width="560" height="315" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<div class="callToAction">
<h3>Who finds it useful?</h3>
<p>Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!</p>
<button type="button" class="button learnMoreCTA" onclick="Metamaps.GlobalUI.openLightbox('about');">LEARN MORE</button>
<a href="/explore/featured" class="exploreFeaturedCTA">EXPLORE FEATURED MAPS</a>
<a href="/request" class="requestInviteCTA" data-bypass="true">REQUEST INVITE</a>
</div>
<div class="clearfloat"></div>
</div>
</div>
<div class="fullWidthWrapper withPartners">
<div class="homeWrapper homePartners">
<% # our partners %>
</div>
</div>
</div><!-- end yield -->
<div class="github-fork-ribbon-wrapper right-bottom">
<div class="github-fork-ribbon">
<a href="https://github.com/metamaps/metamaps_gen002" target="_blank">Fork me on GitHub</a>
</div>
</div>
<script>
Metamaps.currentSection = "";
Metamaps.currentPage = "";
</script>

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
end
config.active_record.raise_in_transactional_callbacks = true
# pundit errors return 403 FORBIDDEN
config.action_dispatch.rescue_responses["Pundit::NotAuthorizedError"] = :forbidden
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/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

View file

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