diff --git a/app/assets/javascripts/discourse.js b/app/assets/javascripts/discourse.js index c619a7dcb1..8b4f2dd755 100644 --- a/app/assets/javascripts/discourse.js +++ b/app/assets/javascripts/discourse.js @@ -166,6 +166,16 @@ Discourse = Ember.Application.createWithMixins({ return loginController.authenticationComplete(options); }, + loginRequired: function() { + return ( + Discourse.SiteSettings.login_required && !Discourse.User.current() + ); + }.property(), + + redirectIfLoginRequired: function(route) { + if(this.get('loginRequired')) { route.transitionTo('login'); } + }, + /** Our own $.ajax method. Makes sure the .then method executes in an Ember runloop for performance reasons. Also automatically adjusts the URL to support installs diff --git a/app/assets/javascripts/discourse/controllers/static_controller.js b/app/assets/javascripts/discourse/controllers/static_controller.js index deb5b37dc1..a432d7a1d7 100644 --- a/app/assets/javascripts/discourse/controllers/static_controller.js +++ b/app/assets/javascripts/discourse/controllers/static_controller.js @@ -28,7 +28,7 @@ Discourse.StaticController = Discourse.Controller.extend({ }); Discourse.StaticController.reopenClass({ - pages: ['faq', 'tos', 'privacy'] + pages: ['faq', 'tos', 'privacy', 'login'] }); diff --git a/app/assets/javascripts/discourse/routes/filtered_list_route.js b/app/assets/javascripts/discourse/routes/filtered_list_route.js index 2344b62b43..a612724afd 100644 --- a/app/assets/javascripts/discourse/routes/filtered_list_route.js +++ b/app/assets/javascripts/discourse/routes/filtered_list_route.js @@ -8,6 +8,8 @@ **/ Discourse.FilteredListRoute = Discourse.Route.extend({ + redirect: function() { Discourse.redirectIfLoginRequired(this); }, + exit: function() { this._super(); diff --git a/app/assets/javascripts/discourse/routes/list_categories_route.js b/app/assets/javascripts/discourse/routes/list_categories_route.js index 0ef914f9a9..4647fa7904 100644 --- a/app/assets/javascripts/discourse/routes/list_categories_route.js +++ b/app/assets/javascripts/discourse/routes/list_categories_route.js @@ -8,6 +8,8 @@ **/ Discourse.ListCategoriesRoute = Discourse.Route.extend({ + redirect: function() { Discourse.redirectIfLoginRequired(this); }, + events: { createCategory: function() { diff --git a/app/assets/javascripts/discourse/routes/topic_route.js b/app/assets/javascripts/discourse/routes/topic_route.js index 61f9290078..4c3b495d14 100644 --- a/app/assets/javascripts/discourse/routes/topic_route.js +++ b/app/assets/javascripts/discourse/routes/topic_route.js @@ -8,6 +8,8 @@ **/ Discourse.TopicRoute = Discourse.Route.extend({ + redirect: function() { Discourse.redirectIfLoginRequired(this); }, + events: { // Modals that can pop up within a topic diff --git a/app/assets/javascripts/discourse/templates/header.js.handlebars b/app/assets/javascripts/discourse/templates/header.js.handlebars index cfea2889e1..df4d1d5f2f 100644 --- a/app/assets/javascripts/discourse/templates/header.js.handlebars +++ b/app/assets/javascripts/discourse/templates/header.js.handlebars @@ -29,10 +29,34 @@ {{/if}}
+ We are excited to have you participate in <%= SiteSetting.title %>. Please + create an account or login to continue. +
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 5819336521..20884d459c 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -501,6 +501,8 @@ en: # TODO: perhaps we need a way of protecting these settings for hosted solution, global settings ... + login_required: "Require authentication to read posts" + enable_local_logins: "Enable local authentication" enable_local_account_create: "Enable local account creation" enable_google_logins: "Enable Google authentication" diff --git a/config/routes.rb b/config/routes.rb index f974c5c9eb..245c8e0a15 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -103,6 +103,7 @@ Discourse::Application.routes.draw do resources :static post 'login' => 'static#enter' + get 'login' => 'static#show', id: 'login' get 'faq' => 'static#show', id: 'faq' get 'tos' => 'static#show', id: 'tos' get 'privacy' => 'static#show', id: 'privacy' diff --git a/spec/controllers/static_controller_spec.rb b/spec/controllers/static_controller_spec.rb index 2e2bccc510..10f652fb03 100644 --- a/spec/controllers/static_controller_spec.rb +++ b/spec/controllers/static_controller_spec.rb @@ -24,4 +24,26 @@ describe StaticController do end end + describe '#enter' do + context 'without a redirect path' do + it 'redirects to the root url' do + xhr :post, :enter + expect(response).to redirect_to root_path + end + end + + context 'with a redirect path' do + it 'redirects to the redirect path' do + xhr :post, :enter, redirect: '/foo' + expect(response).to redirect_to '/foo' + end + end + + context 'when the redirect path is the login page' do + it 'redirects to the root url' do + xhr :post, :enter, redirect: login_path + expect(response).to redirect_to root_path + end + end + end end diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb index fe600a116d..fe0ea2d0f8 100644 --- a/spec/controllers/topics_controller_spec.rb +++ b/spec/controllers/topics_controller_spec.rb @@ -435,6 +435,25 @@ describe TopicsController do end + context "when 'login required' site setting has been enabled" do + before { SiteSetting.stubs(:login_required?).returns(true) } + + context 'and the user is logged in' do + before { log_in(:coding_horror) } + + it 'shows the topic' do + get :show, topic_id: topic.id, slug: topic.slug + expect(response).to be_successful + end + end + + context 'and the user is not logged in' do + it 'redirects to the login page' do + get :show, topic_id: topic.id, slug: topic.slug + expect(response).to redirect_to login_path + end + end + end end describe '#feed' do