api: refactor api attribute declarations.
Replace the `method_attributes` and `hidden_attributes` methods with
`api_attributes`. `api_attributes` can be used as a class macro:
# include only the given attributes.
api_attributes :id, :created_at, :creator_name, ...
# include all default attributes plus the `creator_name` method.
api_attributes including: [:creator_name]
or as an instance method:
def api_attributes
[:id, :created_at, :creator_name, ...]
end
By default, all attributes are included except for IP addresses and
tsvector columns.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
class ReportsController < ApplicationController
|
||||
before_action :member_only, :except => [:upload_tags]
|
||||
before_action :moderator_only, :only => [:post_versions, :post_versions_create, :down_voting_post_report, :down_voting_post_report_create]
|
||||
respond_to :html, :xml, :json, only: [:upload_tags]
|
||||
|
||||
def uploads
|
||||
@report = Reports::Uploads.new(params[:min_date], params[:max_date], params[:queries])
|
||||
@@ -16,6 +17,7 @@ class ReportsController < ApplicationController
|
||||
def upload_tags
|
||||
@user = User.find(params[:user_id])
|
||||
@upload_reports = Reports::UploadTags.includes(versions: { post: :versions }).for_user(params[:user_id]).order("id desc").paginate(params[:page], :limit => params[:limit])
|
||||
respond_with(@upload_reports)
|
||||
end
|
||||
|
||||
def down_voting_post
|
||||
|
||||
@@ -17,7 +17,7 @@ class ApplicationResponder < ActionController::Responder
|
||||
options[:root] ||= resource.table_name.dasherize if resource.respond_to?(:table_name)
|
||||
end
|
||||
|
||||
options[:only] ||= params["only"].scan(/\w+/) if params["only"]
|
||||
options[:only] ||= params["only"].scan(/\w+/).map(&:to_sym) if params["only"]
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
@@ -1,32 +1,13 @@
|
||||
module Reports
|
||||
class UploadTags < ::Post
|
||||
|
||||
def readonly?
|
||||
true
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
|
||||
def as_json(options = {})
|
||||
options ||= {}
|
||||
options[:only] ||= [:id]
|
||||
super(options)
|
||||
end
|
||||
|
||||
def to_xml(options = {}, &block)
|
||||
options ||= {}
|
||||
options[:only] ||= [:id, :uploader_id]
|
||||
super(options, &block)
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
[:uploader_tags, :added_tags, :removed_tags]
|
||||
end
|
||||
|
||||
def api_attributes
|
||||
[:id, :uploader_id, :uploader_tags, :added_tags, :removed_tags]
|
||||
end
|
||||
|
||||
include ApiMethods
|
||||
|
||||
def uploader_tags_array
|
||||
@uploader_tags ||= begin
|
||||
uploader_versions = versions.where(updater_id: uploader_id)
|
||||
|
||||
@@ -215,35 +215,47 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
module ApiMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def serializable_hash(options = {})
|
||||
options ||= {}
|
||||
class_methods do
|
||||
def api_attributes(*attributes, including: [])
|
||||
return @api_attributes if @api_attributes
|
||||
|
||||
options[:include] ||= []
|
||||
if attributes.present?
|
||||
@api_attributes = attributes
|
||||
else
|
||||
@api_attributes = attribute_types.reject { |name, attr| attr.type.in?([:inet, :tsvector]) }.keys.map(&:to_sym)
|
||||
end
|
||||
|
||||
options[:except] ||= []
|
||||
options[:except] += hidden_attributes
|
||||
|
||||
options[:methods] ||= []
|
||||
options[:methods] += method_attributes
|
||||
|
||||
if options[:only]
|
||||
options[:methods] = options[:methods] & options[:only].map(&:to_sym)
|
||||
options[:include] = options[:include] & options[:only].map(&:to_sym)
|
||||
@api_attributes += including
|
||||
@api_attributes
|
||||
end
|
||||
end
|
||||
|
||||
def api_attributes
|
||||
self.class.api_attributes
|
||||
end
|
||||
|
||||
def serializable_hash(options = {})
|
||||
options[:only] ||= []
|
||||
options[:include] ||= []
|
||||
options[:methods] ||= []
|
||||
|
||||
attributes, methods = api_attributes.partition { |attr| has_attribute?(attr) }
|
||||
methods += options[:methods]
|
||||
includes = options[:include]
|
||||
|
||||
if options[:only].present?
|
||||
attributes &= options[:only]
|
||||
methods &= options[:only]
|
||||
includes &= options[:only]
|
||||
end
|
||||
|
||||
options[:only] = attributes
|
||||
options[:methods] = methods
|
||||
options[:include] = includes
|
||||
|
||||
hash = super(options)
|
||||
hash.transform_keys { |key| key.delete("?") }
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def hidden_attributes
|
||||
[:uploader_ip_addr, :updater_ip_addr, :creator_ip_addr]
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
concerning :ActiveRecordExtensions do
|
||||
|
||||
@@ -22,6 +22,8 @@ class Comment < ApplicationRecord
|
||||
:body => ->(user_name) {"@#{creator.name} mentioned you in a \"comment\":/posts/#{post_id}#comment-#{id} on post ##{post_id}:\n\n[quote]\n#{DText.excerpt(body, "@"+user_name)}\n[/quote]\n"},
|
||||
)
|
||||
|
||||
api_attributes including: [:creator_name, :updater_name]
|
||||
|
||||
module SearchMethods
|
||||
def deleted
|
||||
where("comments.is_deleted = true")
|
||||
@@ -145,14 +147,6 @@ class Comment < ApplicationRecord
|
||||
select { |comment| comment.visibility(user) == :visible }
|
||||
end
|
||||
|
||||
def hidden_attributes
|
||||
super + [:body_index]
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:creator_name, :updater_name]
|
||||
end
|
||||
|
||||
def creator_name
|
||||
creator.name
|
||||
end
|
||||
|
||||
@@ -18,6 +18,8 @@ class Dmail < ApplicationRecord
|
||||
after_create :update_recipient
|
||||
after_commit :send_email, on: :create
|
||||
|
||||
api_attributes including: [:key]
|
||||
|
||||
concerning :SpamMethods do
|
||||
class_methods do
|
||||
def is_spammer?(user)
|
||||
@@ -103,16 +105,6 @@ class Dmail < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
super + [:message_index]
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:key]
|
||||
end
|
||||
end
|
||||
|
||||
module SearchMethods
|
||||
def sent_by(user)
|
||||
where("dmails.from_id = ? AND dmails.owner_id != ?", user.id, user.id)
|
||||
@@ -156,7 +148,6 @@ class Dmail < ApplicationRecord
|
||||
|
||||
include AddressMethods
|
||||
include FactoryMethods
|
||||
include ApiMethods
|
||||
extend SearchMethods
|
||||
|
||||
def validate_sender_is_not_banned
|
||||
|
||||
@@ -62,30 +62,7 @@ class ForumPost < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def as_json(options = {})
|
||||
if CurrentUser.user.level < topic.min_level
|
||||
options[:only] = [:id]
|
||||
end
|
||||
|
||||
super(options)
|
||||
end
|
||||
|
||||
def to_xml(options = {})
|
||||
if CurrentUser.user.level < topic.min_level
|
||||
options[:only] = [:id]
|
||||
end
|
||||
|
||||
super(options)
|
||||
end
|
||||
|
||||
def hidden_attributes
|
||||
super + [:text_index]
|
||||
end
|
||||
end
|
||||
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
def self.new_reply(params)
|
||||
if params[:topic_id]
|
||||
|
||||
@@ -155,26 +155,6 @@ class ForumTopic < ApplicationRecord
|
||||
(response_count / Danbooru.config.posts_per_page.to_f).ceil
|
||||
end
|
||||
|
||||
def as_json(options = {})
|
||||
if CurrentUser.user.level < min_level
|
||||
options[:only] = [:id]
|
||||
end
|
||||
|
||||
super(options)
|
||||
end
|
||||
|
||||
def to_xml(options = {})
|
||||
if CurrentUser.user.level < min_level
|
||||
options[:only] = [:id]
|
||||
end
|
||||
|
||||
super(options)
|
||||
end
|
||||
|
||||
def hidden_attributes
|
||||
super + [:text_index, :min_level]
|
||||
end
|
||||
|
||||
def merge(topic)
|
||||
ForumPost.where(:id => self.posts.map(&:id)).update_all(:topic_id => topic.id)
|
||||
topic.update(response_count: topic.response_count + self.posts.length, updater_id: CurrentUser.id)
|
||||
|
||||
@@ -2,6 +2,8 @@ class ModAction < ApplicationRecord
|
||||
belongs_to :creator, :class_name => "User"
|
||||
before_validation :initialize_creator, :on => :create
|
||||
|
||||
api_attributes including: [:category_id]
|
||||
|
||||
#####DIVISIONS#####
|
||||
#Groups: 0-999
|
||||
#Individual: 1000-1999
|
||||
@@ -73,10 +75,6 @@ class ModAction < ApplicationRecord
|
||||
self.class.categories[category]
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:category_id]
|
||||
end
|
||||
|
||||
def serializable_hash(*args)
|
||||
super(*args).merge("description" => filtered_description)
|
||||
end
|
||||
|
||||
@@ -11,6 +11,8 @@ class Note < ApplicationRecord
|
||||
after_save :create_version
|
||||
validate :post_must_not_be_note_locked
|
||||
|
||||
api_attributes including: [:creator_name]
|
||||
|
||||
module SearchMethods
|
||||
def active
|
||||
where("is_active = TRUE")
|
||||
@@ -26,22 +28,11 @@ class Note < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
super + [:body_index]
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:creator_name]
|
||||
end
|
||||
end
|
||||
|
||||
def creator_name
|
||||
creator.name
|
||||
end
|
||||
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
def post_must_not_be_note_locked
|
||||
if is_locked?
|
||||
|
||||
@@ -17,6 +17,8 @@ class Pool < ApplicationRecord
|
||||
after_save :create_version
|
||||
after_create :synchronize!
|
||||
|
||||
api_attributes including: [:creator_name, :post_count]
|
||||
|
||||
module SearchMethods
|
||||
def deleted
|
||||
where("pools.is_deleted = true")
|
||||
@@ -288,10 +290,6 @@ class Pool < ApplicationRecord
|
||||
(post_count / CurrentUser.user.per_page.to_f).ceil
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:creator_name, :post_count]
|
||||
end
|
||||
|
||||
def creator_name
|
||||
creator.name
|
||||
end
|
||||
|
||||
@@ -1457,23 +1457,13 @@ class Post < ApplicationRecord
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
list = super + [:tag_index]
|
||||
unless CurrentUser.is_moderator?
|
||||
list += [:fav_string]
|
||||
end
|
||||
if !visible?
|
||||
list += [:md5, :file_ext]
|
||||
end
|
||||
super + list
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
list = super + [:uploader_name, :has_large, :has_visible_children, :children_ids, :is_favorited?] + TagCategory.categories.map {|x| "tag_string_#{x}".to_sym}
|
||||
if visible?
|
||||
list += [:file_url, :large_file_url, :preview_file_url]
|
||||
end
|
||||
list
|
||||
def api_attributes
|
||||
attributes = super
|
||||
attributes += [:uploader_name, :has_large, :has_visible_children, :children_ids, :is_favorited?] + TagCategory.categories.map {|x| "tag_string_#{x}".to_sym}
|
||||
attributes += [:file_url, :large_file_url, :preview_file_url] if visible?
|
||||
attributes -= [:md5, :file_ext] if !visible?
|
||||
attributes -= [:fav_string] if !CurrentUser.is_moderator?
|
||||
attributes
|
||||
end
|
||||
|
||||
def associated_attributes
|
||||
|
||||
@@ -9,6 +9,8 @@ class PostAppeal < ApplicationRecord
|
||||
before_validation :initialize_creator, :on => :create
|
||||
validates_uniqueness_of :creator_id, :scope => :post_id, :message => "have already appealed this post"
|
||||
|
||||
api_attributes including: [:is_resolved]
|
||||
|
||||
module SearchMethods
|
||||
def resolved
|
||||
joins(:post).where("posts.is_deleted = false and posts.is_flagged = false")
|
||||
@@ -64,8 +66,4 @@ class PostAppeal < ApplicationRecord
|
||||
def appeal_count_for_creator
|
||||
creator.post_appeals.recent.count
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:is_resolved]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -260,7 +260,7 @@ class PostArchive < ApplicationRecord
|
||||
updater.name
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
def api_attributes
|
||||
super + [:obsolete_added_tags, :obsolete_removed_tags, :unchanged_tags, :updater_name]
|
||||
end
|
||||
|
||||
|
||||
@@ -94,22 +94,13 @@ class PostFlag < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
list = super
|
||||
unless CurrentUser.can_view_flagger_on_post?(self)
|
||||
list += [:creator_id]
|
||||
end
|
||||
super + list
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:category]
|
||||
end
|
||||
def api_attributes
|
||||
attributes = super + [:category]
|
||||
attributes -= [:creator_id] unless CurrentUser.can_view_flagger_on_post?(self)
|
||||
attributes
|
||||
end
|
||||
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
def category
|
||||
case reason
|
||||
|
||||
@@ -72,6 +72,8 @@ class Upload < ApplicationRecord
|
||||
|
||||
scope :preprocessed, -> { where(status: "preprocessed") }
|
||||
|
||||
api_attributes including: [:uploader_name]
|
||||
|
||||
def initialize_attributes
|
||||
self.uploader_id = CurrentUser.id
|
||||
self.uploader_ip_addr = CurrentUser.ip_addr
|
||||
@@ -227,18 +229,11 @@ class Upload < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def method_attributes
|
||||
super + [:uploader_name]
|
||||
end
|
||||
end
|
||||
|
||||
include FileMethods
|
||||
include StatusMethods
|
||||
include UploaderMethods
|
||||
include VideoMethods
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
include SourceMethods
|
||||
|
||||
def uploader_is_not_limited
|
||||
|
||||
@@ -567,33 +567,28 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
# blacklist all attributes by default. whitelist only safe attributes.
|
||||
def hidden_attributes
|
||||
super + attributes.keys.map(&:to_sym)
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
list = super + [
|
||||
def api_attributes
|
||||
attributes = [
|
||||
:id, :created_at, :name, :inviter_id, :level, :base_upload_limit,
|
||||
:post_upload_count, :post_update_count, :note_update_count,
|
||||
:is_banned, :can_approve_posts, :can_upload_free, :is_super_voter,
|
||||
:level_string,
|
||||
:post_upload_count, :post_update_count, :note_update_count, :is_banned,
|
||||
:can_approve_posts, :can_upload_free, :is_super_voter, :level_string,
|
||||
]
|
||||
|
||||
if id == CurrentUser.user.id
|
||||
list += BOOLEAN_ATTRIBUTES + [
|
||||
attributes += BOOLEAN_ATTRIBUTES
|
||||
attributes += [
|
||||
:updated_at, :email, :last_logged_in_at, :last_forum_read_at,
|
||||
:recent_tags, :comment_threshold, :default_image_size,
|
||||
:favorite_tags, :blacklisted_tags, :time_zone, :per_page,
|
||||
:custom_style, :favorite_count,
|
||||
:api_regen_multiplier, :api_burst_limit, :remaining_api_limit,
|
||||
:statement_timeout, :favorite_group_limit, :favorite_limit,
|
||||
:tag_query_limit, :can_comment_vote?, :can_remove_from_pools?,
|
||||
:is_comment_limited?, :can_comment?, :can_upload?, :max_saved_searches,
|
||||
:custom_style, :favorite_count, :api_regen_multiplier,
|
||||
:api_burst_limit, :remaining_api_limit, :statement_timeout,
|
||||
:favorite_group_limit, :favorite_limit, :tag_query_limit,
|
||||
:can_comment_vote?, :can_remove_from_pools?, :is_comment_limited?,
|
||||
:can_comment?, :can_upload?, :max_saved_searches,
|
||||
]
|
||||
end
|
||||
|
||||
list
|
||||
attributes
|
||||
end
|
||||
|
||||
# extra attributes returned for /users/:id.json but not for /users.json.
|
||||
|
||||
@@ -67,11 +67,9 @@ class UserNameChangeRequest < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def hidden_attributes
|
||||
if CurrentUser.is_admin? || user == CurrentUser.user
|
||||
[]
|
||||
else
|
||||
super + [:change_reason, :rejection_reason]
|
||||
end
|
||||
def api_attributes
|
||||
attributes = super
|
||||
attributes -= [:change_reason, :rejection_reason] unless CurrentUser.is_admin? || user == CurrentUser.user
|
||||
attributes
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,6 +18,8 @@ class WikiPage < ApplicationRecord
|
||||
has_one :artist, -> {where(:is_active => true)}, :foreign_key => "name", :primary_key => "title"
|
||||
has_many :versions, -> {order("wiki_page_versions.id ASC")}, :class_name => "WikiPageVersion", :dependent => :destroy
|
||||
|
||||
api_attributes including: [:creator_name, :category_name]
|
||||
|
||||
module SearchMethods
|
||||
def titled(title)
|
||||
where("title = ?", title.mb_chars.downcase.tr(" ", "_"))
|
||||
@@ -88,22 +90,11 @@ class WikiPage < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
super + [:body_index]
|
||||
end
|
||||
|
||||
def method_attributes
|
||||
super + [:creator_name, :category_name]
|
||||
end
|
||||
end
|
||||
|
||||
def creator_name
|
||||
creator.name
|
||||
end
|
||||
|
||||
extend SearchMethods
|
||||
include ApiMethods
|
||||
|
||||
def validate_not_locked
|
||||
if is_locked? && !CurrentUser.is_builder?
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
class Delayed::Job
|
||||
def hidden_attributes
|
||||
[:handler]
|
||||
end
|
||||
end
|
||||
@@ -217,6 +217,19 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
context "in api responses" do
|
||||
should "not include restricted attributes" do
|
||||
as(@user) { @post.update(tag_string: "loli") }
|
||||
get_auth post_path(@post), @user, as: :json
|
||||
|
||||
assert_response :success
|
||||
assert_nil(response.parsed_body["md5"])
|
||||
assert_nil(response.parsed_body["file_url"])
|
||||
assert_nil(response.parsed_body["fav_string"])
|
||||
assert_equal(@post.uploader_name, response.parsed_body["uploader_name"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "update action" do
|
||||
|
||||
@@ -84,11 +84,10 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
should "render the current users's profile in json" do
|
||||
get_auth profile_path(format: :json), @user
|
||||
get_auth profile_path, @user, as: :json
|
||||
assert_response :success
|
||||
|
||||
json = as(@user) { @user.as_json(methods: @user.full_attributes + @user.method_attributes) }
|
||||
assert_equal(json, response.parsed_body)
|
||||
assert_equal(@user.upload_limit, response.parsed_body["upload_limit"])
|
||||
end
|
||||
|
||||
should "redirect anonymous users to the sign in page" do
|
||||
|
||||
Reference in New Issue
Block a user