* Add API endpoints for analytics * Remove comment and spacing * Use proper time formatting * Refactor and clean up some logic * Add pro and org member traits * Use shared examples for analytics API spec * Add analytics authorization specs * Remove accidental include Pundit * Raise not_authorized for invalid requests * Make attributes and time methods private * Add custom UnauthorizedError * Raise and use rescue_from to handle 4xx requests * Enforce date parameters to follow a specific format * Use current user to allow same origin requests * Use custom headers and not params for token auth * Default to current user for same origin requests * Use correct boolean for choosing user * Update tests to use request headers and add stricter tests
83 lines
2.8 KiB
Ruby
83 lines
2.8 KiB
Ruby
module Api
|
|
module V0
|
|
class AnalyticsController < ApiController
|
|
rescue_from ArgumentError, with: :unprocessable_entity
|
|
rescue_from UnauthorizedError, with: :not_authorized
|
|
|
|
def totals
|
|
user = get_authenticated_user!
|
|
|
|
data = if params[:organization_id]
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
raise UnauthorizedError unless org && belongs_to_org?(user, org)
|
|
|
|
AnalyticsService.new(organization: org).totals
|
|
else
|
|
AnalyticsService.new(user: user).totals
|
|
end
|
|
render json: data.to_json
|
|
end
|
|
|
|
def historical
|
|
raise ArgumentError, "Required 'start' parameter is missing" if params[:start].blank?
|
|
raise ArgumentError, "Date parameters 'start' or 'end' must be in the format of 'yyyy-mm-dd'" unless valid_date_params?
|
|
|
|
user = get_authenticated_user!
|
|
|
|
data = if params[:organization_id]
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
raise UnauthorizedError unless org && belongs_to_org?(user, org)
|
|
|
|
AnalyticsService.new(organization: org, start: params[:start], end: params[:end]).stats_grouped_by_day
|
|
else
|
|
AnalyticsService.new(user: user, start: params[:start], end: params[:end]).stats_grouped_by_day
|
|
end
|
|
render json: data.to_json
|
|
end
|
|
|
|
def past_day
|
|
user = get_authenticated_user!
|
|
|
|
data = if params[:organization_id]
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
raise UnauthorizedError unless org && belongs_to_org?(user, org)
|
|
|
|
AnalyticsService.new(organization: org, start: DateTime.current - 1.day).stats_grouped_by_day
|
|
else
|
|
AnalyticsService.new(user: user, start: DateTime.current - 1.day).stats_grouped_by_day
|
|
end
|
|
render json: data.to_json
|
|
end
|
|
|
|
private
|
|
|
|
def get_authenticated_user!
|
|
user = if request.headers["HTTP_API_KEY"].blank?
|
|
current_user
|
|
else
|
|
api_secret = ApiSecret.find_by(secret: request.headers["HTTP_API_KEY"])
|
|
raise UnauthorizedError if api_secret.blank?
|
|
|
|
api_secret.user
|
|
end
|
|
|
|
raise UnauthorizedError unless user.present? && user.has_role?(:pro)
|
|
|
|
user
|
|
end
|
|
|
|
def belongs_to_org?(user, org)
|
|
user.organization_id == org.id
|
|
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 params[:end]
|
|
(params[:start] =~ date_regex)&.zero? && (params[:end] =~ date_regex)&.zero?
|
|
else
|
|
(params[:start] =~ date_regex)&.zero?
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|