From b3238bfc3467524f0a946d94655a7b7fbecff5f6 Mon Sep 17 00:00:00 2001 From: Vinoth Kannan Date: Fri, 23 Feb 2024 11:42:28 +0530 Subject: [PATCH] FEATURE: call hub API to update Discourse discover enrollment. (#25634) Now forums can enroll their sites to be showcased in the Discourse [Discover](https://discourse.org/discover) directory. Once they enable the site setting `include_in_discourse_discover` to enroll their forum the `CallDiscourseHub` job will ping the `api.discourse.org/api/discover/enroll` endpoint. Then the Discourse Hub will fetch the basic details from the forum and add it to the review queue. If the site is approved then the forum details will be displayed in the `/discover` page. --- app/controllers/site_controller.rb | 2 ++ ...version_check.rb => call_discourse_hub.rb} | 4 +++- app/models/stat.rb | 3 +++ app/serializers/about_serializer.rb | 11 +++++++++- lib/discourse_hub.rb | 8 +++++++ lib/discourse_updates.rb | 2 +- lib/statistics.rb | 4 ++++ lib/tasks/scheduler.rake | 2 +- spec/jobs/call_discourse_hub_spec.rb | 16 ++++++++++++++ spec/lib/discourse_hub_spec.rb | 16 ++++++++++++++ spec/lib/discourse_updates_spec.rb | 6 +++--- spec/lib/plugin/instance_spec.rb | 1 + spec/requests/about_controller_spec.rb | 11 ++++++++++ .../admin/dashboard_controller_spec.rb | 2 +- .../admin/versions_controller_spec.rb | 2 +- spec/requests/site_controller_spec.rb | 21 +++++++++++++++++++ 16 files changed, 102 insertions(+), 9 deletions(-) rename app/jobs/scheduled/{version_check.rb => call_discourse_hub.rb} (90%) create mode 100644 spec/jobs/call_discourse_hub_spec.rb diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb index a8cc7ea2130..11ea1d58c0b 100644 --- a/app/controllers/site_controller.rb +++ b/app/controllers/site_controller.rb @@ -42,6 +42,8 @@ class SiteController < ApplicationController results[:mobile_logo_url] = UrlHelper.absolute(mobile_logo_url) end + results[:discourse_discover_enrolled] = true if SiteSetting.include_in_discourse_discover? + DiscourseHub.stats_fetched_at = Time.zone.now if request.user_agent == "Discourse Hub" # this info is always available cause it can be scraped from a 404 page diff --git a/app/jobs/scheduled/version_check.rb b/app/jobs/scheduled/call_discourse_hub.rb similarity index 90% rename from app/jobs/scheduled/version_check.rb rename to app/jobs/scheduled/call_discourse_hub.rb index 6df0e103f82..4c1808ade45 100644 --- a/app/jobs/scheduled/version_check.rb +++ b/app/jobs/scheduled/call_discourse_hub.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Jobs - class VersionCheck < ::Jobs::Scheduled + class CallDiscourseHub < ::Jobs::Scheduled every 1.day def execute(args) @@ -27,6 +27,8 @@ module Jobs raise e unless Rails.env.development? # Fail version check silently in development mode end end + + DiscourseHub.discover_enrollment if SiteSetting.include_in_discourse_discover? true end end diff --git a/app/models/stat.rb b/app/models/stat.rb index b993d7326a8..70e9b773e4b 100644 --- a/app/models/stat.rb +++ b/app/models/stat.rb @@ -46,6 +46,9 @@ class Stat Stat.new("users", show_in_ui: true, expose_via_api: true) { Statistics.users }, Stat.new("active_users", show_in_ui: true, expose_via_api: true) { Statistics.active_users }, Stat.new("likes", show_in_ui: true, expose_via_api: true) { Statistics.likes }, + Stat.new("discourse_discover", show_in_ui: false, expose_via_api: true) do + Statistics.discourse_discover + end, ] end diff --git a/app/serializers/about_serializer.rb b/app/serializers/about_serializer.rb index ea76852ab63..89a2efdb557 100644 --- a/app/serializers/about_serializer.rb +++ b/app/serializers/about_serializer.rb @@ -23,7 +23,8 @@ class AboutSerializer < ApplicationSerializer :https, :can_see_about_stats, :contact_url, - :contact_email + :contact_email, + :discourse_discover_enrolled def include_stats? can_see_about_stats @@ -49,6 +50,14 @@ class AboutSerializer < ApplicationSerializer SiteSetting.contact_email end + def discourse_discover_enrolled + SiteSetting.include_in_discourse_discover? + end + + def include_discourse_discover_enrolled? + SiteSetting.include_in_discourse_discover? + end + private def can_see_about_stats diff --git a/lib/discourse_hub.rb b/lib/discourse_hub.rb index 74f18dbcf42..34994430fbb 100644 --- a/lib/discourse_hub.rb +++ b/lib/discourse_hub.rb @@ -14,6 +14,14 @@ module DiscourseHub get("/version_check", version_check_payload) end + def self.discover_enrollment_payload + { include_in_discourse_discover: SiteSetting.include_in_discourse_discover? } + end + + def self.discover_enrollment + post("/discover/enroll", discover_enrollment_payload) + end + def self.stats_fetched_at=(time_with_zone) Discourse.redis.set STATS_FETCHED_AT_KEY, time_with_zone.to_i end diff --git a/lib/discourse_updates.rb b/lib/discourse_updates.rb index 6af0ee5ceb8..098c8f50b92 100644 --- a/lib/discourse_updates.rb +++ b/lib/discourse_updates.rb @@ -41,7 +41,7 @@ module DiscourseUpdates # Handle cases when version check data is old so we report something that makes sense if version_info.updated_at.nil? || last_installed_version != Discourse::VERSION::STRING || # never performed a version check # upgraded since the last version check is_stale_data - Jobs.enqueue(:version_check, all_sites: true) + Jobs.enqueue(:call_discourse_hub, all_sites: true) version_info.version_check_pending = true unless version_info.updated_at.nil? diff --git a/lib/statistics.rb b/lib/statistics.rb index 3ae1fc36f89..bf4779d11db 100644 --- a/lib/statistics.rb +++ b/lib/statistics.rb @@ -47,4 +47,8 @@ class Statistics count: User.real.count, } end + + def self.discourse_discover + { enrolled: SiteSetting.include_in_discourse_discover? } + end end diff --git a/lib/tasks/scheduler.rake b/lib/tasks/scheduler.rake index 5cff1bfb715..d180f53e812 100644 --- a/lib/tasks/scheduler.rake +++ b/lib/tasks/scheduler.rake @@ -17,7 +17,7 @@ task periodical_updates: :environment do end task version_check: :environment do - Jobs::VersionCheck.new.execute(nil) + Jobs::CallDiscourseHub.new.execute(nil) end desc "run every task the scheduler knows about in that order, use only for debugging" diff --git a/spec/jobs/call_discourse_hub_spec.rb b/spec/jobs/call_discourse_hub_spec.rb new file mode 100644 index 00000000000..890c8e66557 --- /dev/null +++ b/spec/jobs/call_discourse_hub_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +RSpec.describe Jobs::CallDiscourseHub do + describe "#execute" do + context "when `include_in_discourse_discover setting` enabled" do + it "calls `discover_enrollment` method in DiscourseHub" do + SiteSetting.version_checks = false + SiteSetting.include_in_discourse_discover = true + + DiscourseHub.stubs(:discover_enrollment).returns(true) + + described_class.new.execute({}) + end + end + end +end diff --git a/spec/lib/discourse_hub_spec.rb b/spec/lib/discourse_hub_spec.rb index d19e9f03ea5..3b7b4ea3d68 100644 --- a/spec/lib/discourse_hub_spec.rb +++ b/spec/lib/discourse_hub_spec.rb @@ -17,6 +17,22 @@ RSpec.describe DiscourseHub do end end + describe ".discover_enrollment" do + it "should trigger a POST request to hub" do + stub_request( + :post, + (ENV["HUB_BASE_URL"] || "http://local.hub:3000/api") + "/discover/enroll", + ).with(body: JSON[DiscourseHub.discover_enrollment_payload]).to_return( + status: 200, + body: "", + headers: { + }, + ) + + DiscourseHub.discover_enrollment + end + end + describe ".version_check_payload" do describe "when Discourse Hub has not fetched stats since past 7 days" do it "should include stats" do diff --git a/spec/lib/discourse_updates_spec.rb b/spec/lib/discourse_updates_spec.rb index e23b4dc6fac..dbe1e0d2c62 100644 --- a/spec/lib/discourse_updates_spec.rb +++ b/spec/lib/discourse_updates_spec.rb @@ -67,7 +67,7 @@ RSpec.describe DiscourseUpdates do end it "queues a version check" do - expect_enqueued_with(job: :version_check) { version } + expect_enqueued_with(job: :call_discourse_hub) { version } end end @@ -76,7 +76,7 @@ RSpec.describe DiscourseUpdates do context "with old version check data" do shared_examples "queue version check and report that version is ok" do it "queues a version check" do - expect_enqueued_with(job: :version_check) { version } + expect_enqueued_with(job: :call_discourse_hub) { version } end it "reports 0 missing versions" do @@ -105,7 +105,7 @@ RSpec.describe DiscourseUpdates do shared_examples "when last_installed_version is old" do it "queues a version check" do - expect_enqueued_with(job: :version_check) { version } + expect_enqueued_with(job: :call_discourse_hub) { version } end it "reports 0 missing versions" do diff --git a/spec/lib/plugin/instance_spec.rb b/spec/lib/plugin/instance_spec.rb index e2c0236b2b9..dd9f4464e09 100644 --- a/spec/lib/plugin/instance_spec.rb +++ b/spec/lib/plugin/instance_spec.rb @@ -103,6 +103,7 @@ TEXT :likes_7_days, :likes_30_days, :likes_count, + :discourse_discover_enrolled, ) end diff --git a/spec/requests/about_controller_spec.rb b/spec/requests/about_controller_spec.rb index eb719ae9f7d..54d1945e176 100644 --- a/spec/requests/about_controller_spec.rb +++ b/spec/requests/about_controller_spec.rb @@ -48,6 +48,17 @@ RSpec.describe AboutController do expect(response.parsed_body["about"].keys).to include("stats") end + it "adds Discourse Discover status if enabled" do + get "/about.json" + + expect(response.parsed_body["about"].keys).not_to include("discourse_discover_enrolled") + + SiteSetting.include_in_discourse_discover = true + get "/about.json" + + expect(response.parsed_body["about"]["discourse_discover_enrolled"]).to eq(true) + end + it "does not serialize stats when 'Guardian#can_see_about_stats?' is false" do Guardian.any_instance.stubs(:can_see_about_stats?).returns(false) get "/about.json" diff --git a/spec/requests/admin/dashboard_controller_spec.rb b/spec/requests/admin/dashboard_controller_spec.rb index ef1772e0c9d..f333d234c43 100644 --- a/spec/requests/admin/dashboard_controller_spec.rb +++ b/spec/requests/admin/dashboard_controller_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Admin::DashboardController do before do AdminDashboardData.stubs(:fetch_cached_stats).returns(reports: []) - Jobs::VersionCheck.any_instance.stubs(:execute).returns(true) + Jobs::CallDiscourseHub.any_instance.stubs(:execute).returns(true) end def populate_new_features(date1 = nil, date2 = nil) diff --git a/spec/requests/admin/versions_controller_spec.rb b/spec/requests/admin/versions_controller_spec.rb index 7751c6cf048..34c509839f5 100644 --- a/spec/requests/admin/versions_controller_spec.rb +++ b/spec/requests/admin/versions_controller_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Admin::VersionsController do fab!(:user) before do - Jobs::VersionCheck.any_instance.stubs(:execute).returns(true) + Jobs::CallDiscourseHub.any_instance.stubs(:execute).returns(true) DiscourseUpdates.stubs(:updated_at).returns(2.hours.ago) DiscourseUpdates.stubs(:latest_version).returns("1.2.33") DiscourseUpdates.stubs(:critical_updates_available?).returns(false) diff --git a/spec/requests/site_controller_spec.rb b/spec/requests/site_controller_spec.rb index 3cb4c16d9a7..a53353774b2 100644 --- a/spec/requests/site_controller_spec.rb +++ b/spec/requests/site_controller_spec.rb @@ -12,6 +12,7 @@ RSpec.describe SiteController do SiteSetting.logo_small = upload SiteSetting.apple_touch_icon = upload SiteSetting.mobile_logo = upload + SiteSetting.include_in_discourse_discover = true Theme.clear_default! get "/site/basic-info.json" @@ -28,6 +29,16 @@ RSpec.describe SiteController do expect(json["header_primary_color"]).to eq("333333") expect(json["header_background_color"]).to eq("ffffff") expect(json["login_required"]).to eq(true) + expect(json["discourse_discover_enrolled"]).to eq(true) + end + + it "skips `discourse_discover_enrolled` if `include_in_discourse_discover` setting disabled" do + SiteSetting.include_in_discourse_discover = false + + get "/site/basic-info.json" + json = response.parsed_body + + expect(json.keys).not_to include("discourse_discover_enrolled") end end @@ -56,6 +67,16 @@ RSpec.describe SiteController do expect(json["likes_30_days"]).to be_present end + it "returns Discourse Discover stats" do + SiteSetting.include_in_discourse_discover = true + About.refresh_stats + + get "/site/statistics.json" + json = response.parsed_body + + expect(json["discourse_discover_enrolled"]).to be_truthy + end + it "is not visible if site setting share_anonymized_statistics is disabled" do SiteSetting.share_anonymized_statistics = false