0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-12 04:31:29 +08:00
discourse/spec/requests/admin/reports_controller_spec.rb
Alan Guo Xiang Tan 548e2ae46a
FEATURE: Drill-down and pagination for top referrers/countries (#40364)
Admins can now drill from the redesigned Site Traffic dashboard into the
full Top Referrers and Top Countries reports. The dashboard panels show
only the top 5, and the reports themselves were capped at 50 rows, so
the long tail of where traffic comes from was hidden.

Key changes:

- **Drill-down on panel headers.** The Top Referrers and Top Countries
headers are now links to their full report, scoped to the dashboard's
current period.
- **Row cap raised to 200.** `top_referrers_by_browser_pageviews` and
`top_countries_by_browser_pageviews` return up to 200 rows instead of
50, matching the existing `web_crawlers` report, and the existing
client-side table pagination pages through them.
- **Reports reachable when pageview tracking is on.** The two
browser-pageview reports are no longer unconditionally hidden from the
reports API.
2026-06-02 09:57:39 +08:00

579 lines
18 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe Admin::ReportsController do
fab!(:admin)
fab!(:moderator)
fab!(:user)
describe "#index" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "includes admin-only reports" do
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r["type"] }).to include(
*Report::ADMIN_ONLY_REPORTS,
)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "excludes admin-only reports" do
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r["type"] }).not_to include(
*Report::ADMIN_ONLY_REPORTS,
)
end
it "includes suspicious logins when IP viewing is disabled" do
SiteSetting.moderators_view_ips = false
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r["type"] }).to include(
"suspicious_logins",
)
end
end
before { sign_in(admin) }
it "excludes page view mobile reports" do
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r["type"] }).not_to include(
"page_view_anon_browser_mobile_reqs",
"page_view_logged_in_browser_mobile_reqs",
"page_view_anon_mobile_reqs",
"page_view_logged_in_mobile_reqs",
)
end
it "excludes about and storage stats reports" do
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r["type"] }).not_to include(
"report_about",
"report_storage_stats",
)
end
context "when use_legacy_pageviews is true" do
before { SiteSetting.use_legacy_pageviews = true }
it "excludes the site_traffic report and includes legacy pageview reports" do
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r[:type] }).not_to include("site_traffic")
expect(response.parsed_body["reports"].map { |r| r[:type] }).to include(
*Report::HIDDEN_LEGACY_PAGEVIEW_REPORTS,
)
end
end
context "when use_legacy_pageviews is false" do
before { SiteSetting.use_legacy_pageviews = false }
it "includes the site_traffic report and excludes legacy pageview reports" do
get "/admin/reports.json"
expect(response.parsed_body["reports"].map { |r| r[:type] }).to include("site_traffic")
expect(response.parsed_body["reports"].map { |r| r[:type] }).not_to include(
*Report::HIDDEN_LEGACY_PAGEVIEW_REPORTS,
)
end
end
end
describe "#bulk" do
context "when logged in as an admin" do
before { sign_in(admin) }
context "with valid params" do
fab!(:topic)
it "renders the reports as JSON" do
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
},
likes: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(2)
end
it "uses the user's locale for report names and descriptions" do
SiteSetting.allow_user_locale = true
admin.update!(locale: "es")
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
},
likes: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].first["title"]).to eq(
I18n.t("reports.topics.title", locale: "es"),
)
expect(response.parsed_body["reports"].first["description"]).to eq(
I18n.t("reports.topics.description", locale: "es"),
)
end
end
context "with invalid params" do
context "with invalid report_type format" do
it "returns 404 when report_type contains special characters" do
get "/admin/reports/bulk.json", params: { reports: { "!!&asdfasdf" => { limit: 10 } } }
expect(response.status).to eq(404)
end
it "returns 404 when report_type contains path traversal characters" do
get "/admin/reports/bulk.json", params: { reports: { "../../etc" => { limit: 10 } } }
expect(response.status).to eq(404)
end
end
context "when limit param is invalid" do
include_examples "invalid limit params",
"/admin/reports/topics.json",
described_class::REPORTS_LIMIT
end
context "with nonexistent report" do
it "returns not found reports" do
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
},
not_found: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(2)
expect(response.parsed_body["reports"][0]["type"]).to eq("topics")
expect(response.parsed_body["reports"][1]["type"]).to eq("not_found")
end
end
context "with invalid start or end dates" do
it "doesn't return 500 error" do
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
start_date: "2015-0-1",
},
},
}
expect(response.status).to eq(400)
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
end_date: "2015-0-1",
},
},
}
expect(response.status).to eq(400)
end
end
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "returns report" do
Fabricate(:topic)
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
},
likes: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(2)
end
it "marks admin-only reports as not_found" do
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
},
admin_logins: {
limit: 10,
},
top_uploads: {
limit: 10,
},
topic_view_stats: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(4)
expect(response.parsed_body["reports"][0]["type"]).to eq("topics")
expect(response.parsed_body["reports"][1]).to include("error" => "not_found", "data" => nil)
expect(response.parsed_body["reports"][2]).to include("error" => "not_found", "data" => nil)
expect(response.parsed_body["reports"][3]).to include("error" => "not_found", "data" => nil)
end
it "redacts suspicious login IP addresses when IP viewing is disabled" do
SiteSetting.moderators_view_ips = false
DiscourseIpInfo.stubs(:get).returns(location: "Earth")
user.user_auth_token_logs.create!(
action: "suspicious",
client_ip: "1.1.1.1",
user_agent: "Mozilla/5.0",
created_at: 1.hour.ago,
)
get "/admin/reports/bulk.json", params: { reports: { suspicious_logins: { limit: 10 } } }
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(1)
report = response.parsed_body["reports"].first
row = report["data"].first
expect(report["type"]).to eq("suspicious_logins")
expect(row["username"]).to eq(user.username)
expect(row["client_ip"]).to be_nil
expect(row["location"]).to eq("Earth")
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/reports/bulk.json",
params: {
reports: {
topics: {
limit: 10,
},
not_found: {
limit: 10,
},
},
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when use_legacy_pageviews is true" do
before do
SiteSetting.use_legacy_pageviews = true
sign_in(admin)
end
it "marks the site_traffic report as not_found and does not run it" do
get "/admin/reports/bulk.json",
params: {
reports: {
site_traffic: {
limit: 10,
},
consolidated_page_views: {
limit: 10,
},
consolidated_page_views_browser_detection: {
limit: 10,
},
page_view_anon_reqs: {
limit: 10,
},
page_view_logged_in_reqs: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(5)
expect(response.parsed_body["reports"][0]).to include("error" => "not_found", "data" => nil)
expect(response.parsed_body["reports"][1]["type"]).to eq("consolidated_page_views")
expect(response.parsed_body["reports"][2]["type"]).to eq(
"consolidated_page_views_browser_detection",
)
expect(response.parsed_body["reports"][3]["type"]).to eq("page_view_anon_reqs")
expect(response.parsed_body["reports"][4]["type"]).to eq("page_view_logged_in_reqs")
end
end
context "when use_legacy_pageviews is false" do
before do
SiteSetting.use_legacy_pageviews = false
sign_in(admin)
end
it "marks the legacy pageview reports as not_found and does not run them" do
get "/admin/reports/bulk.json",
params: {
reports: {
site_traffic: {
limit: 10,
},
consolidated_page_views: {
limit: 10,
},
consolidated_page_views_browser_detection: {
limit: 10,
},
page_view_anon_reqs: {
limit: 10,
},
page_view_logged_in_reqs: {
limit: 10,
},
},
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(5)
expect(response.parsed_body["reports"][0]["type"]).to eq("site_traffic")
expect(response.parsed_body["reports"][1]["type"]).to eq("consolidated_page_views")
expect(response.parsed_body["reports"][2]).to include("error" => "not_found", "data" => nil)
expect(response.parsed_body["reports"][3]).to include("error" => "not_found", "data" => nil)
expect(response.parsed_body["reports"][4]).to include("error" => "not_found", "data" => nil)
end
end
end
describe "#show" do
context "when logged in as an admin" do
before { sign_in(admin) }
context "with invalid id form" do
let(:invalid_id) { "!!&asdfasdf" }
it "returns 404" do
get "/admin/reports/#{invalid_id}.json"
expect(response.status).to eq(404)
end
end
context "with valid type form" do
context "with missing report" do
it "returns a 404 error" do
get "/admin/reports/nonexistent.json"
expect(response.status).to eq(404)
end
end
context "when a report is found" do
it "renders the report as JSON" do
Fabricate(:topic)
get "/admin/reports/topics.json"
expect(response.status).to eq(200)
expect(response.parsed_body["report"]["total"]).to eq(1)
end
end
context "when limit param is invalid" do
include_examples "invalid limit params",
"/admin/reports/topics.json",
described_class::REPORTS_LIMIT
end
end
describe "when report is scoped to a category" do
fab!(:category)
fab!(:topic) { Fabricate(:topic, category: category) }
fab!(:other_topic, :topic)
it "should render the report as JSON" do
get "/admin/reports/topics.json", params: { category_id: category.id }
expect(response.status).to eq(200)
report = response.parsed_body["report"]
expect(report["type"]).to eq("topics")
expect(report["data"].count).to eq(1)
end
end
describe "when report is scoped to a group" do
fab!(:user)
fab!(:other_user, :user)
fab!(:group)
it "should render the report as JSON" do
group.add(user)
get "/admin/reports/signups.json", params: { group_id: group.id }
expect(response.status).to eq(200)
report = response.parsed_body["report"]
expect(report["type"]).to eq("signups")
expect(report["data"].count).to eq(1)
end
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "returns report" do
Fabricate(:topic)
get "/admin/reports/topics.json"
expect(response.status).to eq(200)
expect(response.parsed_body["report"]["total"]).to eq(1)
end
context "when moderators cannot view IPs" do
before do
SiteSetting.moderators_view_ips = false
DiscourseIpInfo.stubs(:get).returns(location: "Earth")
user.user_auth_token_logs.create!(
action: "suspicious",
client_ip: "1.1.1.1",
user_agent: "Mozilla/5.0",
created_at: 1.hour.ago,
)
end
it "redacts suspicious login IP address while retaining location" do
get "/admin/reports/suspicious_logins.json"
expect(response.status).to eq(200)
row = response.parsed_body.dig("report", "data", 0)
expect(row["username"]).to eq(user.username)
expect(row["client_ip"]).to be_nil
expect(row["location"]).to eq("Earth")
end
end
it "does not allow accessing admin-only reports" do
Report::ADMIN_ONLY_REPORTS.each do |report_type|
get "/admin/reports/#{report_type}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/reports/topics.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when use_legacy_pageviews is true" do
before do
SiteSetting.use_legacy_pageviews = true
sign_in(admin)
end
it "does not allow running site_traffic report" do
Report::HIDDEN_PAGEVIEW_REPORTS.each do |report_type|
get "/admin/reports/#{report_type}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it "does not allow running the page_view_legacy_total_reqs report" do
get "/admin/reports/page_view_legacy_total_reqs.json"
expect(response.status).to eq(404)
end
end
context "when use_legacy_pageviews is false" do
before do
SiteSetting.use_legacy_pageviews = false
sign_in(admin)
end
it "does not allow running legacy pageview reports" do
Report::HIDDEN_LEGACY_PAGEVIEW_REPORTS.each do |report_type|
get "/admin/reports/#{report_type}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it "does allow running the page_view_legacy_total_reqs report" do
get "/admin/reports/page_view_legacy_total_reqs.json"
expect(response.status).to eq(200)
end
end
context "with browser pageview reports" do
it "lets an admin run them only when persist_browser_pageview_events is enabled" do
sign_in(admin)
SiteSetting.persist_browser_pageview_events = false
Report::BROWSER_PAGEVIEW_REPORTS.each do |report_type|
get "/admin/reports/#{report_type}.json"
expect(response.status).to eq(404)
end
SiteSetting.persist_browser_pageview_events = true
Report::BROWSER_PAGEVIEW_REPORTS.each do |report_type|
get "/admin/reports/#{report_type}.json"
expect(response.status).to eq(200)
end
end
it "denies a moderator even when persist_browser_pageview_events is enabled" do
SiteSetting.persist_browser_pageview_events = true
sign_in(moderator)
Report::BROWSER_PAGEVIEW_REPORTS.each do |report_type|
get "/admin/reports/#{report_type}.json"
expect(response.status).to eq(404)
end
end
end
end
end