FEATURE: A new site setting `public_user_custom_fields` which allows you

to whitelist custom fields that will be exposed to the Ember client
application.
This commit is contained in:
Robin Ward 2014-05-14 14:38:04 -04:00
parent fc048f067f
commit 3211c60bbe
6 changed files with 65 additions and 12 deletions

View File

@ -5,6 +5,31 @@ module HasCustomFields
included do
has_many :_custom_fields, dependent: :destroy, :class_name => "#{name}CustomField"
after_save :save_custom_fields
# To avoid n+1 queries, we have this function to retrieve lots of custom fields in one
# go and create a "sideloaded" version for easy querying by id.
def self.custom_fields_for_ids(ids, whitelisted_fields)
klass = "#{name}CustomField".constantize
foreign_key = "#{name.underscore}_id".to_sym
result = {}
return result if whitelisted_fields.blank?
klass.where(foreign_key => ids, :name => whitelisted_fields).pluck(foreign_key, :name, :value).each do |cf|
result[cf[0]] ||= {}
unload_field(result[cf[0]], cf[1], cf[2])
end
result
end
def self.unload_field(target, key, value)
if target.has_key?(key)
target[key] = [target[key]] if !target[key].is_a? Array
target[key] << value
else
target[key] = value
end
end
end
def reload(options = nil)
@ -32,14 +57,7 @@ module HasCustomFields
def refresh_custom_fields_from_db
target = Hash.new
_custom_fields.pluck(:name,:value).each do |key, value|
if target.has_key? key
if !target[key].is_a? Array
target[key] = [target[key]]
end
target[key] << value
else
target[key] = value
end
self.class.unload_field(target, key, value)
end
@custom_fields_orig = target
@custom_fields = @custom_fields_orig.dup
@ -90,4 +108,4 @@ module HasCustomFields
refresh_custom_fields_from_db
end
end
end
end

View File

@ -48,8 +48,8 @@ class PostSerializer < BasicPostSerializer
:user_deleted,
:edit_reason,
:can_view_edit_history,
:wiki
:wiki,
:user_custom_fields
def moderator?
!!(object.user && object.user.moderator?)
@ -216,6 +216,16 @@ class PostSerializer < BasicPostSerializer
scope.can_view_post_revisions?(object)
end
def user_custom_fields
@topic_view.user_custom_fields[object.user_id]
end
def include_user_custom_fields?
return if @topic_view.blank?
custom_fields = @topic_view.user_custom_fields
custom_fields && custom_fields[object.user_id]
end
private
def post_actions

View File

@ -861,6 +861,7 @@ en:
detect_custom_avatars: "Whether or not to check that users have uploaded custom avatars"
max_daily_gravatar_crawls: "The maximum amount of times Discourse will check gravatar for custom avatars in a day"
public_user_custom_fields: "A whitelist of custom fields for a user that can be shown publically."
allow_profile_backgrounds: "Allows users to upload profile backgrounds"

View File

@ -530,3 +530,7 @@ uncategorized:
hidden: true
notify_about_flags_after: 48
public_user_custom_fields:
list: true
default: ''

View File

@ -7,7 +7,7 @@ require_dependency 'gaps'
class TopicView
attr_reader :topic, :posts, :guardian, :filtered_posts
attr_accessor :draft, :draft_key, :draft_sequence
attr_accessor :draft, :draft_key, :draft_sequence, :user_custom_fields
def initialize(topic_id, user=nil, options={})
@user = user
@ -30,6 +30,10 @@ class TopicView
filter_posts(options)
if SiteSetting.public_user_custom_fields.present? && @posts
@user_custom_fields = User.custom_fields_for_ids(@posts.map(&:user_id), SiteSetting.public_user_custom_fields.split('|'))
end
@draft_key = @topic.draft_key
@draft_sequence = DraftSequence.current(@user, @draft_key)
end

View File

@ -152,5 +152,21 @@ describe HasCustomFields do
test_item.custom_fields.should == {"jack" => "black", "bob" => "marley"}
test_item2.custom_fields.should == {"sixto" => "rodriguez", "de" => "la playa"}
end
it "supports bulk retrieval with a list of ids" do
item1 = CustomFieldsTestItem.new
item1.custom_fields = {"a" => ["b", "c", "d"], 'not_whitelisted' => 'secret'}
item1.save
item2 = CustomFieldsTestItem.new
item2.custom_fields = {"e" => 'hallo'}
item2.save
fields = CustomFieldsTestItem.custom_fields_for_ids([item1.id, item2.id], ['a', 'e'])
fields.should be_present
fields[item1.id]['a'].should =~ ['b', 'c', 'd']
fields[item1.id]['not_whitelisted'].should be_blank
fields[item2.id]['e'].should == 'hallo'
end
end
end