diff --git a/app/controllers/rate_limits_controller.rb b/app/controllers/rate_limits_controller.rb new file mode 100644 index 000000000..daaa8d899 --- /dev/null +++ b/app/controllers/rate_limits_controller.rb @@ -0,0 +1,8 @@ +class RateLimitsController < ApplicationController + respond_to :html, :json, :xml + + def index + @rate_limits = authorize RateLimit.visible(CurrentUser.user).paginated_search(params, count_pages: true) + respond_with(@rate_limits) + end +end diff --git a/app/models/rate_limit.rb b/app/models/rate_limit.rb index b3d0b8ab0..dc9daee90 100644 --- a/app/models/rate_limit.rb +++ b/app/models/rate_limit.rb @@ -5,6 +5,22 @@ class RateLimit < ApplicationRecord expired.delete_all end + def self.visible(user) + if user.is_owner? + all + elsif user.is_anonymous? + none + else + where(key: [user.cache_key]) + end + end + + def self.search(params) + q = search_attributes(params, :id, :created_at, :updated_at, :limited, :points, :action, :key) + q = q.apply_default_order(params) + q + end + # `action` is the action being limited. Usually a controller endpoint. # `keys` is who is being limited. Usually a [user, ip] pair, meaning the action is limited both by the user's ID and their IP. # `cost` is the number of points the action costs. diff --git a/app/policies/rate_limit_policy.rb b/app/policies/rate_limit_policy.rb new file mode 100644 index 000000000..9970ac553 --- /dev/null +++ b/app/policies/rate_limit_policy.rb @@ -0,0 +1,5 @@ +class RateLimitPolicy < ApplicationPolicy + def index? + true + end +end diff --git a/app/views/rate_limits/index.html.erb b/app/views/rate_limits/index.html.erb new file mode 100644 index 000000000..4ac3ffcc0 --- /dev/null +++ b/app/views/rate_limits/index.html.erb @@ -0,0 +1,21 @@ +
+
+ <%= table_for @rate_limits, class: "striped autofit" do |t| %> + <% t.column :action %> + + <% t.column :key %> + + <% t.column :points do |rate_limit| %> + <%= rate_limit.points.round(2) %> + <% end %> + + <% t.column :limited? %> + + <% t.column :updated_at do |rate_limit| %> + <%= time_ago_in_words_tagged rate_limit.updated_at %> + <% end %> + <% end %> + + <%= numbered_paginator(@rate_limits) %> +
+
diff --git a/config/routes.rb b/config/routes.rb index 61010d9ed..82df33b1c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -220,6 +220,7 @@ Rails.application.routes.draw do end end resources :artist_commentary_versions, :only => [:index, :show] + resources :rate_limits, only: [:index] resource :related_tag, :only => [:show, :update] resources :recommended_posts, only: [:index] resources :robots, only: [:index] diff --git a/test/functional/rate_limits_controller_test.rb b/test/functional/rate_limits_controller_test.rb new file mode 100644 index 000000000..499a018cc --- /dev/null +++ b/test/functional/rate_limits_controller_test.rb @@ -0,0 +1,33 @@ +require 'test_helper' + +class RateLimitsControllerTest < ActionDispatch::IntegrationTest + context "The rate limits controller" do + context "index action" do + setup do + @user = create(:user) + create(:rate_limit, key: @user.cache_key) + end + + should "show all rate limits to the owner" do + get_auth rate_limits_path, create(:owner_user) + + assert_response :success + assert_select "tbody tr", count: 2 # 2 because the login action creates a second rate limit. + end + + should "show the user their own rate limits" do + get_auth rate_limits_path, @user + + assert_response :success + assert_select "tbody tr", count: 1 + end + + should "not show users rate limits belonging to other users" do + get_auth rate_limits_path, create(:user) + + assert_response :success + assert_select "tbody tr", count: 0 + end + end + end +end