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