Prior to this commit the following situation existed: > The path /dashboard/analytics/org/:id requires user > authentication (e.g. signed in). However, it does not enforce > authorization. Anyone can see this page. The page, however, uses > javascript to populate the data. So no information, aside from the org > name associated with the :id leaks out. The javascript API end point > enforces organization membership. > > I would expect that the authorization in the HTML rendering would be > the same as the javascript API end point. This commit ensures that the dashboards#analytics end point uses the same policy logic as the API analytics end points. Further, it keeps folks who aren't org members out of the base HTML page for other orgs. Closes forem/forem/#16985
78 lines
2.4 KiB
Ruby
78 lines
2.4 KiB
Ruby
module Api
|
|
module V0
|
|
class AnalyticsController < ApiController
|
|
respond_to :json
|
|
|
|
rescue_from ArgumentError, with: :error_unprocessable_entity
|
|
rescue_from ApplicationPolicy::NotAuthorizedError, with: :error_unauthorized
|
|
|
|
before_action :authenticate_with_api_key_or_current_user!
|
|
before_action :authorize_user_organization
|
|
before_action :load_owner
|
|
before_action :validate_date_params, only: [:historical]
|
|
|
|
def totals
|
|
analytics = AnalyticsService.new(@owner, article_id: analytics_params[:article_id])
|
|
data = analytics.totals
|
|
render json: data.to_json
|
|
end
|
|
|
|
def historical
|
|
analytics = AnalyticsService.new(
|
|
@owner,
|
|
start_date: params[:start], end_date: params[:end], article_id: params[:article_id],
|
|
)
|
|
data = analytics.grouped_by_day
|
|
render json: data.to_json
|
|
end
|
|
|
|
def past_day
|
|
analytics = AnalyticsService.new(
|
|
@owner, start_date: 1.day.ago, article_id: params[:article_id]
|
|
)
|
|
data = analytics.grouped_by_day
|
|
render json: data.to_json
|
|
end
|
|
|
|
def referrers
|
|
analytics = AnalyticsService.new(
|
|
@owner,
|
|
start_date: params[:start], end_date: params[:end], article_id: params[:article_id],
|
|
)
|
|
data = analytics.referrers
|
|
render json: data.to_json
|
|
end
|
|
|
|
private
|
|
|
|
def authorize_user_organization
|
|
return unless analytics_params[:organization_id]
|
|
|
|
@org = Organization.find(analytics_params[:organization_id])
|
|
authorize(@org, :analytics?)
|
|
end
|
|
|
|
def load_owner
|
|
@owner = @org || @user
|
|
end
|
|
|
|
def validate_date_params
|
|
raise ArgumentError, I18n.t("api.v0.analytics_controller.start_missing") if analytics_params[:start].blank?
|
|
raise ArgumentError, I18n.t("api.v0.analytics_controller.invalid_date_format") unless valid_date_params?
|
|
end
|
|
|
|
def analytics_params
|
|
params.permit(:organization_id, :article_id, :start, :end)
|
|
end
|
|
|
|
def valid_date_params?
|
|
date_regex = /\A\d{4}-\d{1,2}-\d{1,2}\Z/ # for example, 2019-03-22 or 2019-2-1
|
|
if analytics_params[:end]
|
|
(analytics_params[:start] =~ date_regex)&.zero? && (analytics_params[:end] =~ date_regex)&.zero?
|
|
else
|
|
(analytics_params[:start] =~ date_regex)&.zero?
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|