From b932763080926b6bfa92fd0c410fb536b0e02aa4 Mon Sep 17 00:00:00 2001
From: Roman Bambycha <2233965@gmail.com>
Date: Mon, 17 Nov 2014 19:46:46 +0200
Subject: [PATCH] add function to disable editing, resolves #879
---
bin/gollum | 5 ++
lib/gollum/app.rb | 10 +++-
lib/gollum/editing_auth.rb | 34 ++++++++++++
lib/gollum/helpers.rb | 12 ++++
lib/gollum/templates/compare.mustache | 26 +++++----
lib/gollum/templates/history.mustache | 6 +-
lib/gollum/templates/page.mustache | 42 +++++++++-----
lib/gollum/templates/pages.mustache | 7 ++-
lib/gollum/views/compare.rb | 2 +-
lib/gollum/views/history.rb | 2 +-
lib/gollum/views/page.rb | 4 ++
lib/gollum/views/pages.rb | 2 +-
test/test_allow_editing.rb | 80 +++++++++++++++++++++++++++
test/test_app.rb | 2 +-
14 files changed, 199 insertions(+), 35 deletions(-)
create mode 100644 lib/gollum/editing_auth.rb
create mode 100644 test/test_allow_editing.rb
diff --git a/bin/gollum b/bin/gollum
index d85a8cf8..330405b7 100755
--- a/bin/gollum
+++ b/bin/gollum
@@ -22,6 +22,7 @@ options = { 'port' => 4567, 'bind' => '0.0.0.0' }
wiki_options = {
:live_preview => false,
:allow_uploads => false,
+ :allow_editing => true,
}
opts = OptionParser.new do |opts|
@@ -76,6 +77,10 @@ opts = OptionParser.new do |opts|
wiki_options[:ref] = ref
end
+ opts.on("--no-edit", "Restricts editing capability through frontend.") do
+ wiki_options[:allow_editing] = false
+ end
+
opts.on("--no-live-preview", "Disables livepreview.") do
wiki_options[:live_preview] = false
end
diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb
index a7de7750..b853a350 100644
--- a/lib/gollum/app.rb
+++ b/lib/gollum/app.rb
@@ -13,6 +13,8 @@ require 'gollum/views/has_page'
require File.expand_path '../helpers', __FILE__
+require 'gollum/editing_auth'
+
#required to upload bigger binary files
Gollum::set_git_timeout(120)
Gollum::set_git_max_filesize(190 * 10**6)
@@ -42,6 +44,7 @@ module Precious
class App < Sinatra::Base
register Mustache::Sinatra
include Precious::Helpers
+ use Precious::EditingAuth
dir = File.dirname(File.expand_path(__FILE__))
@@ -91,6 +94,8 @@ module Precious
settings.wiki_options.merge!({ :base_path => @base_url })
@css = settings.wiki_options[:css]
@js = settings.wiki_options[:js]
+ @mathjax_config = settings.wiki_options[:mathjax_config]
+ @allow_editing = settings.wiki_options[:allow_editing]
end
get '/' do
@@ -105,7 +110,6 @@ module Precious
# name, path, version
def wiki_page(name, path = nil, version = nil, exact = true)
wiki = wiki_new
-
path = name if path.nil?
name = extract_name(name) || wiki.index_page
path = extract_path(path)
@@ -126,6 +130,7 @@ module Precious
end
get '/edit/*' do
+ forbid unless @allow_editing
wikip = wiki_page(params[:splat].first)
@name = wikip.name
@path = wikip.path
@@ -253,6 +258,7 @@ module Precious
end
get '/delete/*' do
+ forbid unless @allow_editing
wikip = wiki_page(params[:splat].first)
name = wikip.name
wiki = wikip.wiki
@@ -267,6 +273,7 @@ module Precious
end
get '/create/*' do
+ forbid unless @allow_editing
wikip = wiki_page(params[:splat].first.gsub('+', '-'))
@name = wikip.name.to_url
@path = wikip.path
@@ -476,6 +483,7 @@ module Precious
elsif file = wiki.file(fullpath, wiki.ref, true)
show_file(file)
else
+ not_found unless @allow_editing
page_path = [path, name].compact.join('/')
redirect to("/create/#{clean_url(encodeURIComponent(page_path))}")
end
diff --git a/lib/gollum/editing_auth.rb b/lib/gollum/editing_auth.rb
new file mode 100644
index 00000000..9d502658
--- /dev/null
+++ b/lib/gollum/editing_auth.rb
@@ -0,0 +1,34 @@
+module Precious
+ class EditingAuth < Sinatra::Base
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ @env = env
+ # Blocks all potentially editable pages. Use EditingAuth::whitelist_pages to unblock pages.
+ unless (env["REQUEST_METHOD"] == "GET") || App::settings.wiki_options[:allow_editing]
+ return block unless excluded_page?
+ end
+ @app.call(env)
+ end
+
+ def block
+ [403, {'Content-Type' => 'text/html', 'Content-Length' => '9'}, ['Forbidden']]
+ end
+
+ def excluded_page?
+ return false if env["REQUEST_PATH"].nil?
+ whitelist_pages.any? do |whitelisted_page|
+ env["REQUEST_PATH"].include? whitelisted_page
+ end
+ end
+
+ private
+ # List pages paths as str that you want to whitelist.
+ # Pages will be compared with env["REQUEST_PATH"] using String::include? method.
+ def whitelist_pages
+ return ["/compare/"]
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/gollum/helpers.rb b/lib/gollum/helpers.rb
index 4fba20bf..ccda58e5 100644
--- a/lib/gollum/helpers.rb
+++ b/lib/gollum/helpers.rb
@@ -39,5 +39,17 @@ module Precious
url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/')
end
+ def forbid(msg = "Forbidden.")
+ @message = msg
+ status 403
+ halt mustache :error
+ end
+
+ def not_found(msg = nil)
+ @message = msg || "The requested page does not exist."
+ status 404
+ return mustache :error
+ end
+
end
end
diff --git a/lib/gollum/templates/compare.mustache b/lib/gollum/templates/compare.mustache
index b180a6a8..da723978 100644
--- a/lib/gollum/templates/compare.mustache
+++ b/lib/gollum/templates/compare.mustache
@@ -8,8 +8,10 @@
View Page
- Edit Page
+ {{#allow_editing}}
+ Edit Page
+ {{/allow_editing}}
Page History
@@ -25,11 +27,13 @@
{{/show_revert}}
@@ -52,9 +56,11 @@
Back to Page History
{{#show_revert}}
-
- Revert Changes
-
+ {{#allow_editing}}
+
+ Revert Changes
+
+ {{/allow_editing}}
{{/show_revert}}
Back to Top
diff --git a/lib/gollum/templates/history.mustache b/lib/gollum/templates/history.mustache
index 17c2357e..342b878b 100644
--- a/lib/gollum/templates/history.mustache
+++ b/lib/gollum/templates/history.mustache
@@ -7,8 +7,10 @@
View Page
- Edit Page
+ {{#allow_editing}}
+ Edit Page
+ {{/allow_editing}}
diff --git a/lib/gollum/templates/page.mustache b/lib/gollum/templates/page.mustache
index d7b7a53a..5c4b8884 100644
--- a/lib/gollum/templates/page.mustache
+++ b/lib/gollum/templates/page.mustache
@@ -18,18 +18,28 @@ Mousetrap.bind(['e'], function( e ) {
class="action-all-pages">All
Files
-
- New
- {{#allow_uploads}}
-
- Upload
- {{/allow_uploads}}
- {{#editable}}
-
- Rename
-
Edit
- {{/editable}}
+ {{#allow_editing}}
+
+ New
+ {{/allow_editing}}
+ {{#allow_editing}}
+ {{#allow_uploads}}
+
+ Upload
+ {{/allow_uploads}}
+ {{/allow_editing}}
+ {{#allow_editing}}
+ {{#editable}}
+
+ Rename
+ {{/editable}}
+ {{/allow_editing}}
+ {{#allow_editing}}
+ {{#editable}}
+
Edit
+ {{/editable}}
+ {{/allow_editing}}
{{#page_exists}}
diff --git a/lib/gollum/templates/pages.mustache b/lib/gollum/templates/pages.mustache
index 93e5e66d..7efc3dbe 100644
--- a/lib/gollum/templates/pages.mustache
+++ b/lib/gollum/templates/pages.mustache
@@ -7,9 +7,10 @@
Home
-
- New
-
+ {{#allow_editing}}
+
+ New
+ {{/allow_editing}}
diff --git a/lib/gollum/views/compare.rb b/lib/gollum/views/compare.rb
index df2e3a3a..a8abca8e 100644
--- a/lib/gollum/views/compare.rb
+++ b/lib/gollum/views/compare.rb
@@ -3,7 +3,7 @@ module Precious
class Compare < Layout
include HasPage
- attr_reader :page, :diff, :versions, :message
+ attr_reader :page, :diff, :versions, :message, :allow_editing
def title
"Comparison of #{@page.title}"
diff --git a/lib/gollum/views/history.rb b/lib/gollum/views/history.rb
index ca51254c..a3d19e3b 100644
--- a/lib/gollum/views/history.rb
+++ b/lib/gollum/views/history.rb
@@ -3,7 +3,7 @@ module Precious
class History < Layout
include HasPage
- attr_reader :page, :page_num
+ attr_reader :page, :page_num, :allow_editing
def title
@page.title
diff --git a/lib/gollum/views/page.rb b/lib/gollum/views/page.rb
index c30210e3..beff30ad 100644
--- a/lib/gollum/views/page.rb
+++ b/lib/gollum/views/page.rb
@@ -47,6 +47,10 @@ module Precious
@page_exists
end
+ def allow_editing
+ @allow_editing
+ end
+
def allow_uploads
@allow_uploads
end
diff --git a/lib/gollum/views/pages.rb b/lib/gollum/views/pages.rb
index 0a8d77d4..bd020d2a 100644
--- a/lib/gollum/views/pages.rb
+++ b/lib/gollum/views/pages.rb
@@ -3,7 +3,7 @@ require "pathname"
module Precious
module Views
class Pages < Layout
- attr_reader :results, :ref
+ attr_reader :results, :ref, :allow_editing
def title
"All pages in #{@ref}"
diff --git a/test/test_allow_editing.rb b/test/test_allow_editing.rb
new file mode 100644
index 00000000..d59b93ba
--- /dev/null
+++ b/test/test_allow_editing.rb
@@ -0,0 +1,80 @@
+# ~*~ encoding: utf-8 ~*~
+require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+
+context "Precious::Views::Editing" do
+ include Rack::Test::Methods
+ setup do
+ examples = testpath "examples"
+ @path = File.join(examples, "test.git")
+ Precious::App.set(:gollum_path, @path)
+ FileUtils.cp_r File.join(examples, "revert.git"), @path, :remove_destination => true
+ @wiki = Gollum::Wiki.new(@path)
+ end
+
+ teardown do
+ FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git]))
+ end
+
+ test "creating page is blocked" do
+ Precious::App.set(:wiki_options, { allow_editing: false})
+ post "/create", :content => 'abc', :page => "D",
+ :format => 'markdown', :message => 'def'
+ assert !last_response.ok?
+
+ page = @wiki.page('D')
+ assert page.nil?
+ end
+
+
+ test "frontend links for editing are not blocked" do
+ Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
+ get '/A'
+
+ assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template"
+ assert_match /New/, last_response.body, "'New' button is blocked in page template"
+ assert_match /Upload/, last_response.body, "'Upload' link is blocked in page template"
+ assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template"
+ assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template"
+
+ get '/pages'
+
+ assert_match /New/, last_response.body, "'New' link is blocked in pages template"
+
+ get '/history/A'
+
+ assert_match /Edit/, last_response.body, "'Edit' link is blocked in history template"
+
+ get '/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f'
+
+ assert_match /Edit Page/, last_response.body, "'Edit Page' link is blocked in compare template"
+ assert_match /Revert Changes/, last_response.body, "'Revert Changes' link is blocked in compare template"
+ end
+
+ test "frontend links for editing blocked" do
+ Precious::App.set(:wiki_options, { allow_editing: false })
+ get '/A'
+
+ assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template"
+ assert_no_match /New/, last_response.body, "'New' button not blocked in page template"
+ assert_no_match /Upload/, last_response.body, "'Upload' link not blocked in page template"
+ assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template"
+ assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template"
+
+ get '/pages'
+
+ assert_no_match /New/, last_response.body, "'New' link not blocked in pages template"
+
+ get '/history/A'
+
+ assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in history template"
+
+ get '/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f'
+
+ assert_no_match /Edit Page/, last_response.body, "'Edit Page' link not blocked in compare template"
+ assert_no_match /Revert Changes/, last_response.body, "'Revert Changes' link not blocked in compare template"
+ end
+
+ def app
+ Precious::App
+ end
+end
\ No newline at end of file
diff --git a/test/test_app.rb b/test/test_app.rb
index ffd0e7b3..ff0a5625 100644
--- a/test/test_app.rb
+++ b/test/test_app.rb
@@ -8,7 +8,7 @@ context "Frontend" do
@path = cloned_testpath("examples/revert.git")
@wiki = Gollum::Wiki.new(@path)
Precious::App.set(:gollum_path, @path)
- Precious::App.set(:wiki_options, {})
+ Precious::App.set(:wiki_options, {allow_editing: true})
end
teardown do