From 7c0e50c2c270e696b7dbd6540d00b4cc38e25375 Mon Sep 17 00:00:00 2001 From: Jason Robinson <mail@jasonrobinson.me> Date: Tue, 19 May 2015 23:01:37 +0300 Subject: [PATCH] Introduce 'authorized' configuration option for services Since the Facebook API has changed and additional permissions are required for all users on a pod to cross-post, an additional 'authorized' flag is needed to be set for the Facebook service. This flag allows either all users, one user or no users to use the cross-posting service. Clarifies the situation for #5923, #5260 and #5085. closes #5985 --- Changelog.md | 2 +- app/presenters/statistics_presenter.rb | 6 +- app/views/services/_add_remove_services.haml | 25 ++-- app/views/shared/_right_sections.html.haml | 5 +- config/defaults.yml | 5 + config/diaspora.yml.example | 7 + lib/configuration_methods.rb | 7 + spec/lib/configuration_methods_spec.rb | 71 +++++++--- spec/presenters/statistics_presenter_spec.rb | 138 +++++++++++++------ 9 files changed, 190 insertions(+), 76 deletions(-) diff --git a/Changelog.md b/Changelog.md index 2de7a30f1f..0f8d3c4f34 100644 --- a/Changelog.md +++ b/Changelog.md @@ -39,7 +39,6 @@ * Fix a freeze in new post parsing [#5965](https://github.com/diaspora/diaspora/pull/5965) * Add case insensitive unconfirmed email addresses as authentication key [#5967](https://github.com/diaspora/diaspora/pull/5967) * Fix liking on single post views when accessed via GUID [#5978](https://github.com/diaspora/diaspora/pull/5978) -* Gracefully handle mailer failures when a like is already deleted again [#5983](https://github.com/diaspora/diaspora/pull/5983) ## Features * Hide post title of limited post in comment notification email [#5843](https://github.com/diaspora/diaspora/pull/5843) @@ -54,6 +53,7 @@ * Add a "Manage followed tags" page to mass unfollow tags in the mobile interface [#5945](https://github.com/diaspora/diaspora/pull/5945) * Add popover/tooltip about email visibility to registration/settings page [#5956](https://github.com/diaspora/diaspora/pull/5956) * Fetch person posts on sharing request [#5960](https://github.com/diaspora/diaspora/pull/5960) +* Introduce 'authorized' configuration option for services [#5985](https://github.com/diaspora/diaspora/pull/5985) # 0.5.0.1 diff --git a/app/presenters/statistics_presenter.rb b/app/presenters/statistics_presenter.rb index 51d2b367c0..af88e68711 100644 --- a/app/presenters/statistics_presenter.rb +++ b/app/presenters/statistics_presenter.rb @@ -98,7 +98,7 @@ class StatisticsPresenter def all_services_helper result = {} Configuration::KNOWN_SERVICES.each {|service, options| - result[service.to_s] = AppConfig["services.#{service}.enable"] + result[service.to_s] = AppConfig.show_service?(service, nil) } result end @@ -109,13 +109,13 @@ class StatisticsPresenter def available_services Configuration::KNOWN_SERVICES.select {|service| - AppConfig["services.#{service}.enable"] + AppConfig.show_service?(service, nil) }.map(&:to_s) end def legacy_services Configuration::KNOWN_SERVICES.each_with_object({}) {|service, result| - result[service.to_s] = AppConfig["services.#{service}.enable"] + result[service.to_s] = AppConfig.show_service?(service, nil) } end diff --git a/app/views/services/_add_remove_services.haml b/app/views/services/_add_remove_services.haml index 35190c8fd9..bac69588f2 100644 --- a/app/views/services/_add_remove_services.haml +++ b/app/views/services/_add_remove_services.haml @@ -4,19 +4,20 @@ - if AppConfig.configured_services.count > 0 - AppConfig.configured_services.each do |provider| - %h3= t("services.provider.#{provider}") - - services_for_provider = @services.select{|x| x.provider == provider.to_s} - - if services_for_provider.count > 0 - - services_for_provider.each do |service| - != t("services.index.logged_in_as", nickname: content_tag(:strong, service.nickname )) - = link_to t("services.index.disconnect"), - service_path(service), - data: { confirm: t("services.index.really_disconnect", service: t("services.provider.#{provider}")) }, - method: :delete + - if AppConfig.show_service?(provider, current_user) + %h3= t("services.provider.#{provider}") + - services_for_provider = @services.select{|x| x.provider == provider.to_s} + - if services_for_provider.count > 0 + - services_for_provider.each do |service| + != t("services.index.logged_in_as", nickname: content_tag(:strong, service.nickname )) + = link_to t("services.index.disconnect"), + service_path(service), + data: { confirm: t("services.index.really_disconnect", service: t("services.provider.#{provider}")) }, + method: :delete - - else - = t("services.index.not_logged_in") - = link_to(t("services.index.connect"), "/auth/#{provider}") + - else + = t("services.index.not_logged_in") + = link_to(t("services.index.connect"), "/auth/#{provider}") - else .well diff --git a/app/views/shared/_right_sections.html.haml b/app/views/shared/_right_sections.html.haml index fb64a3e83f..feb135bebb 100644 --- a/app/views/shared/_right_sections.html.haml +++ b/app/views/shared/_right_sections.html.haml @@ -57,8 +57,9 @@ #right_service_icons - AppConfig.configured_services.each do |service| - - unless current_user.services.any?{|x| x.provider == service} - = link_to(content_tag(:div, nil, :class => "social_media_logos-#{service.to_s.downcase}-24x24", :title => service.to_s.titleize), "/auth/#{service}") + - if AppConfig.show_service?(service, current_user) + - unless current_user.services.any?{|x| x.provider == service} + = link_to(content_tag(:div, nil, :class => "social_media_logos-#{service.to_s.downcase}-24x24", :title => service.to_s.titleize), "/auth/#{service}") .section .title diff --git a/config/defaults.yml b/config/defaults.yml index add0ee97ef..f37804600c 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -146,18 +146,22 @@ defaults: app_id: secret: open_graph_namespace: 'joindiaspora' + authorized: false twitter: enable: false key: secret: + authorized: true tumblr: enable: false key: secret: + authorized: true wordpress: enable: false key: secret: + authorized: true mail: enable: false sender_address: 'no-reply@example.org' @@ -211,6 +215,7 @@ test: enable: true app_id: 'fake' secret: 'sdoigjosdfijg' + authorized: true mail: enable: true integration1: diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index 378e0d6d32..91fe4191b9 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -536,6 +536,13 @@ configuration: ## Section #app_id: 'abcdef' #secret: 'change_me' + ## This setting is required to define whether the Facebook app has permissions to post + ## false == No permissions (default) + ## true == Permissions for all users to post. App MUST have 'publish_actions' approved by Facebook! + ## "username" == Set to local username to allow a single user to cross-post. The person who has created + ## the Facebook app will always be able to cross-post, even without 'publish_actions'. + #authorized: false + ## OAuth credentials for Twitter twitter: ## Section diff --git a/lib/configuration_methods.rb b/lib/configuration_methods.rb index 8e87454ba2..107fde37c0 100644 --- a/lib/configuration_methods.rb +++ b/lib/configuration_methods.rb @@ -34,6 +34,13 @@ module Configuration end attr_writer :configured_services + def show_service?(service, user) + return false unless self["services.#{service}.enable"] + # Return true only if 'authorized' is true or equal to user username + (user && self["services.#{service}.authorized"] == user.username) || + self["services.#{service}.authorized"] == true + end + def secret_token if heroku? return ENV['SECRET_TOKEN'] if ENV['SECRET_TOKEN'] diff --git a/spec/lib/configuration_methods_spec.rb b/spec/lib/configuration_methods_spec.rb index 5ca9e3ca21..966b4c0396 100644 --- a/spec/lib/configuration_methods_spec.rb +++ b/spec/lib/configuration_methods_spec.rb @@ -8,40 +8,40 @@ describe Configuration::Methods do extend Configuration::Methods end end - + describe "#pod_uri" do before do @settings.environment.url = nil @settings.instance_variable_set(:@pod_uri, nil) end - + it "properly parses the pod url" do @settings.environment.url = "http://example.org/" expect(@settings.pod_uri.scheme).to eq("http") expect(@settings.pod_uri.host).to eq("example.org") end - + it "adds a trailing slash if there isn't one" do @settings.environment.url = "http://example.org" expect(@settings.pod_uri.to_s).to eq("http://example.org/") end - + it "does not add an extra trailing slash" do @settings.environment.url = "http://example.org/" expect(@settings.pod_uri.to_s).to eq("http://example.org/") end - + it "adds http:// on the front if it's missing" do @settings.environment.url = "example.org/" expect(@settings.pod_uri.to_s).to eq("http://example.org/") end - + it "does not add a prefix if there already is https:// on the front" do @settings.environment.url = "https://example.org/" expect(@settings.pod_uri.to_s).to eq("https://example.org/") end end - + describe "#bare_pod_uri" do it 'is #pod_uri.authority stripping www.' do pod_uri = double @@ -50,7 +50,7 @@ describe Configuration::Methods do expect(@settings.bare_pod_uri).to eq('example.org') end end - + describe "#configured_services" do it "includes the enabled services only" do services = double @@ -69,7 +69,40 @@ describe Configuration::Methods do expect(@settings.configured_services).not_to include :wordpress end end - + + describe "#show_service" do + before do + AppConfig.services.twitter.authorized = true + AppConfig.services.twitter.enable = true + AppConfig.services.facebook.authorized = true + AppConfig.services.facebook.enable = true + AppConfig.services.wordpress.authorized = false + AppConfig.services.wordpress.enable = true + AppConfig.services.tumblr.authorized = "alice" + AppConfig.services.tumblr.enable = true + end + + it "shows service with no authorized key" do + expect(AppConfig.show_service?("twitter", bob)).to be_truthy + end + + it "shows service with authorized key true" do + expect(AppConfig.show_service?("facebook", bob)).to be_truthy + end + + it "doesn't show service with authorized key false" do + expect(AppConfig.show_service?("wordpress", bob)).to be_falsey + end + + it "doesn't show service with authorized key not equal to username" do + expect(AppConfig.show_service?("tumblr", bob)).to be_falsey + end + + it "shows service with authorized key equal to username" do + expect(AppConfig.show_service?("tumblr", alice)).to be_truthy + end + end + describe "#version_string" do before do @version = double @@ -83,61 +116,61 @@ describe Configuration::Methods do it "includes the version" do expect(@settings.version_string).to include @version.number end - + context "with git available" do before do allow(@settings).to receive(:git_available?).and_return(true) allow(@settings).to receive(:git_revision).and_return("1234567890") end - + it "includes the 'patchlevel'" do expect(@settings.version_string).to include "-p#{@settings.git_revision[0..7]}" expect(@settings.version_string).not_to include @settings.git_revision[0..8] end end end - + describe "#get_redis_options" do context "with REDISTOGO_URL set" do before do ENV["REDISTOGO_URL"] = "redis://myserver" end - + it "uses that" do expect(@settings.get_redis_options[:url]).to match "myserver" end end - + context "with REDIS_URL set" do before do ENV["REDISTOGO_URL"] = nil ENV["REDIS_URL"] = "redis://yourserver" end - + it "uses that" do expect(@settings.get_redis_options[:url]).to match "yourserver" end end - + context "with redis set" do before do ENV["REDISTOGO_URL"] = nil ENV["REDIS_URL"] = nil @settings.environment.redis = "redis://ourserver" end - + it "uses that" do expect(@settings.get_redis_options[:url]).to match "ourserver" end end - + context "with a unix socket set" do before do ENV["REDISTOGO_URL"] = nil ENV["REDIS_URL"] = nil @settings.environment.redis = "unix:///tmp/redis.sock" end - + it "uses that" do expect(@settings.get_redis_options[:url]).to match "/tmp/redis.sock" end diff --git a/spec/presenters/statistics_presenter_spec.rb b/spec/presenters/statistics_presenter_spec.rb index 40661f123e..364525ec01 100644 --- a/spec/presenters/statistics_presenter_spec.rb +++ b/spec/presenters/statistics_presenter_spec.rb @@ -1,76 +1,136 @@ -require 'spec_helper' +require "spec_helper" describe StatisticsPresenter do before do @presenter = StatisticsPresenter.new end - describe '#as_json' do - it 'works' do + describe "#as_json" do + it "works" do expect(@presenter.as_json).to be_present expect(@presenter.as_json).to be_a Hash end end - describe '#statistics contents' do + describe "#statistics contents" do before do AppConfig.privacy.statistics.user_counts = false AppConfig.privacy.statistics.post_counts = false AppConfig.privacy.statistics.comment_counts = false end - it 'provides generic pod data in json' do - expect(@presenter.as_json).to eq({ - "name" => AppConfig.settings.pod_name, - "network" => "Diaspora", - "version" => AppConfig.version_string, + it "provides generic pod data in json" do + expect(@presenter.as_json).to eq( + "name" => AppConfig.settings.pod_name, + "network" => "Diaspora", + "version" => AppConfig.version_string, "registrations_open" => AppConfig.settings.enable_registrations?, - "services"=> ["facebook",], - "facebook" => true, - "tumblr" => false, - "twitter" => false, - "wordpress" => false, - }) + "services" => ["facebook"], + "facebook" => true, + "tumblr" => false, + "twitter" => false, + "wordpress" => false + ) end - context 'when services are enabled' do + context "when services are enabled" do before do - AppConfig.privacy.statistics.user_counts = true - AppConfig.privacy.statistics.post_counts = true - AppConfig.privacy.statistics.comment_counts = true AppConfig.services = { - "facebook" => {"enable" => true}, - "twitter" => {"enable" => true}, + "facebook" => { + "enable" => true, + "authorized" => true + }, + "twitter" => {"enable" => true}, "wordpress" => {"enable" => false}, - "tumblr" => {"enable" => false} + "tumblr" => { + "enable" => true, + "authorized" => false + } + } + end + + it "provides services in json" do + expect(@presenter.as_json).to eq( + "name" => AppConfig.settings.pod_name, + "network" => "Diaspora", + "version" => AppConfig.version_string, + "registrations_open" => AppConfig.settings.enable_registrations?, + "services" => %w(twitter facebook), + "facebook" => true, + "twitter" => true, + "tumblr" => false, + "wordpress" => false + ) + end + end + + context "when some services are set to username authorized" do + before do + AppConfig.services = { + "facebook" => { + "enable" => true, + "authorized" => "bob" + }, + "twitter" => {"enable" => true}, + "wordpress" => { + "enable" => true, + "authorized" => "alice" + }, + "tumblr" => { + "enable" => true, + "authorized" => false + } } end - it 'provides generic pod data and counts in json' do - expect(@presenter.as_json).to eq({ - "name" => AppConfig.settings.pod_name, - "network" => "Diaspora", - "version" => AppConfig.version_string, + it "provides services in json" do + expect(@presenter.as_json).to eq( + "name" => AppConfig.settings.pod_name, + "network" => "Diaspora", + "version" => AppConfig.version_string, "registrations_open" => AppConfig.settings.enable_registrations?, - "total_users" => User.active.count, + "services" => ["twitter"], + "facebook" => false, + "twitter" => true, + "tumblr" => false, + "wordpress" => false + ) + end + end + + context "when counts are enabled" do + before do + AppConfig.privacy.statistics.user_counts = true + AppConfig.privacy.statistics.post_counts = true + AppConfig.privacy.statistics.comment_counts = true + end + + it "provides generic pod data and counts in json" do + expect(@presenter.as_json).to eq( + "name" => AppConfig.settings.pod_name, + "network" => "Diaspora", + "version" => AppConfig.version_string, + "registrations_open" => AppConfig.settings.enable_registrations?, + "total_users" => User.active.count, "active_users_halfyear" => User.halfyear_actives.count, - "active_users_monthly" => User.monthly_actives.count, - "local_posts" => @presenter.local_posts, - "local_comments" => @presenter.local_comments, - "services" => ["twitter","facebook"], - "facebook" => true, - "twitter" => true, - "tumblr" => false, - "wordpress" => false - }) + "active_users_monthly" => User.monthly_actives.count, + "local_posts" => @presenter.local_posts, + "local_comments" => @presenter.local_comments, + "services" => ["facebook"], + "facebook" => true, + "twitter" => false, + "tumblr" => false, + "wordpress" => false + ) end end - context 'when registrations are closed' do + + context "when registrations are closed" do before do AppConfig.settings.enable_registrations = false end - it 'should mark open_registrations to be false' do + it "should mark open_registrations to be false" do expect(@presenter.open_registrations?).to be false end end -- GitLab