mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 15:25:35 +08:00
readonly mode
This commit is contained in:
parent
faf03fdeb1
commit
e7472dc374
|
@ -8,6 +8,7 @@ Discourse.addInitializer(function() {
|
|||
|
||||
Discourse.MessageBus.alwaysLongPoll = Discourse.Environment === "development";
|
||||
Discourse.MessageBus.start();
|
||||
|
||||
Discourse.MessageBus.subscribe("/global/asset-version", function(version){
|
||||
Discourse.set("assetVersion", version);
|
||||
|
||||
|
@ -24,5 +25,15 @@ Discourse.addInitializer(function() {
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
Discourse.set("isReadOnly", Discourse.Site.currentProp("is_readonly"));
|
||||
|
||||
Discourse.MessageBus.subscribe("/global/read-only", function (enabled) {
|
||||
Discourse.set("isReadOnly", enabled);
|
||||
if (enabled) {
|
||||
bootbox.alert(I18n.t("read_only_mode_enabled"));
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus);
|
||||
}, true);
|
||||
|
|
|
@ -29,7 +29,7 @@ class ApplicationController < ActionController::Base
|
|||
before_filter :set_mobile_view
|
||||
before_filter :inject_preview_style
|
||||
before_filter :disable_customization
|
||||
before_filter :block_if_maintenance_mode
|
||||
before_filter :block_if_readonly_mode
|
||||
before_filter :authorize_mini_profiler
|
||||
before_filter :store_incoming_links
|
||||
before_filter :preload_json
|
||||
|
@ -50,7 +50,6 @@ class ApplicationController < ActionController::Base
|
|||
raise
|
||||
end
|
||||
|
||||
|
||||
# Some exceptions
|
||||
class RenderEmpty < Exception; end
|
||||
|
||||
|
@ -87,6 +86,11 @@ class ApplicationController < ActionController::Base
|
|||
rescue_discourse_actions("[error: 'invalid access']", 403) # TODO: this breaks json responses
|
||||
end
|
||||
|
||||
rescue_from Discourse::ReadOnly do
|
||||
# can this happen on a not .json format?
|
||||
render json: failed_json.merge(message: I18n.t("read_only_mode_enabled"))
|
||||
end
|
||||
|
||||
def rescue_discourse_actions(message, error)
|
||||
if request.format && request.format.json?
|
||||
# TODO: this doesn't make sense. Stuffing an html page into a json response will cause
|
||||
|
@ -249,16 +253,6 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def block_if_maintenance_mode
|
||||
if Discourse.maintenance_mode?
|
||||
if request.format.json?
|
||||
render status: 503, json: failed_json.merge(message: I18n.t('site_under_maintenance'))
|
||||
else
|
||||
render status: 503, file: File.join( Rails.root, 'public', '503.html' ), layout: false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mini_profiler_enabled?
|
||||
defined?(Rack::MiniProfiler) && current_user.try(:admin?)
|
||||
end
|
||||
|
@ -288,6 +282,11 @@ class ApplicationController < ActionController::Base
|
|||
redirect_to :login if SiteSetting.login_required?
|
||||
end
|
||||
|
||||
def block_if_readonly_mode
|
||||
return if request.put? && request.fullpath == "/admin/backups/readonly"
|
||||
raise Discourse::ReadOnly.new unless request.get? || !Discourse.readonly_mode?
|
||||
end
|
||||
|
||||
def build_not_found_page(status=404, layout=false)
|
||||
@top_viewed = Topic.top_viewed(10)
|
||||
@recent = Topic.recent(10)
|
||||
|
|
|
@ -8,7 +8,8 @@ class SiteSerializer < ApplicationSerializer
|
|||
:periods,
|
||||
:top_menu_items,
|
||||
:anonymous_top_menu_items,
|
||||
:uncategorized_category_id # this is hidden so putting it here
|
||||
:uncategorized_category_id, # this is hidden so putting it here
|
||||
:is_readonly
|
||||
|
||||
has_many :categories, serializer: BasicCategorySerializer, embed: :objects
|
||||
has_many :post_action_types, embed: :objects
|
||||
|
@ -45,4 +46,8 @@ class SiteSerializer < ApplicationSerializer
|
|||
SiteSetting.uncategorized_category_id
|
||||
end
|
||||
|
||||
def is_readonly
|
||||
Discourse.readonly_mode?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -409,7 +409,9 @@ uncategorized:
|
|||
summary_likes_required: 1
|
||||
summary_percent_filter: 20
|
||||
send_welcome_message: true
|
||||
allow_import: false
|
||||
allow_import:
|
||||
client: true
|
||||
default: false
|
||||
educate_until_posts:
|
||||
client: true
|
||||
default: 2
|
||||
|
|
|
@ -27,6 +27,9 @@ module Discourse
|
|||
|
||||
class InvalidPost < Exception; end
|
||||
|
||||
# When read-only mode is enabled
|
||||
class ReadOnly < Exception; end
|
||||
|
||||
# Cross site request forgery
|
||||
class CSRF < Exception; end
|
||||
|
||||
|
@ -138,18 +141,20 @@ module Discourse
|
|||
return base_url_no_prefix + base_uri
|
||||
end
|
||||
|
||||
def self.enable_maintenance_mode
|
||||
$redis.set maintenance_mode_key, 1
|
||||
def self.enable_readonly_mode
|
||||
$redis.set readonly_mode_key, 1
|
||||
MessageBus.publish(readonly_channel, true)
|
||||
true
|
||||
end
|
||||
|
||||
def self.disable_maintenance_mode
|
||||
$redis.del maintenance_mode_key
|
||||
def self.disable_readonly_mode
|
||||
$redis.del readonly_mode_key
|
||||
MessageBus.publish(readonly_channel, false)
|
||||
true
|
||||
end
|
||||
|
||||
def self.maintenance_mode?
|
||||
!!$redis.get( maintenance_mode_key )
|
||||
def self.readonly_mode?
|
||||
!!$redis.get(readonly_mode_key)
|
||||
end
|
||||
|
||||
def self.git_version
|
||||
|
@ -198,9 +203,12 @@ module Discourse
|
|||
Rails.configuration.action_controller.asset_host
|
||||
end
|
||||
|
||||
private
|
||||
def self.readonly_mode_key
|
||||
"readonly_mode"
|
||||
end
|
||||
|
||||
def self.maintenance_mode_key
|
||||
'maintenance_mode'
|
||||
def self.readonly_channel
|
||||
"/global/read-only"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -82,5 +82,39 @@ describe Discourse do
|
|||
|
||||
end
|
||||
|
||||
context "#enable_readonly_mode" do
|
||||
|
||||
it "adds a key in redis and publish a message through the message bus" do
|
||||
$redis.expects(:set).with(Discourse.readonly_mode_key, 1)
|
||||
MessageBus.expects(:publish).with(Discourse.readonly_channel, true)
|
||||
Discourse.enable_readonly_mode
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "#disable_readonly_mode" do
|
||||
|
||||
it "removes a key from redis and publish a message through the message bus" do
|
||||
$redis.expects(:del).with(Discourse.readonly_mode_key)
|
||||
MessageBus.expects(:publish).with(Discourse.readonly_channel, false)
|
||||
Discourse.disable_readonly_mode
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "#readonly_mode?" do
|
||||
|
||||
it "returns true when the key is present in redis" do
|
||||
$redis.expects(:get).with(Discourse.readonly_mode_key).returns("1")
|
||||
Discourse.readonly_mode?.should == true
|
||||
end
|
||||
|
||||
it "returns false when the key is not present in redis" do
|
||||
$redis.expects(:get).with(Discourse.readonly_mode_key).returns(nil)
|
||||
Discourse.readonly_mode?.should == false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user