mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 12:57:29 +08:00
update message bus to support per client filtering
start work on user_tracking_state fix can_ban? in guardian expose protected scopes on topic_query we need move guardian spec to use build as opposed to creating topics / posts / users start work on user tracking spec
This commit is contained in:
parent
4ccd89f7df
commit
b5eff93a9d
|
@ -8,7 +8,7 @@ GIT
|
|||
|
||||
GIT
|
||||
remote: https://github.com/SamSaffron/message_bus
|
||||
revision: e5654728b1c1b97fa5c7bb79fd689b31cec3f01d
|
||||
revision: 031a107bbe6e468caa67ff540485d70230d1c362
|
||||
specs:
|
||||
message_bus (0.0.2)
|
||||
eventmachine
|
||||
|
|
41
app/models/user_tracking_state.rb
Normal file
41
app/models/user_tracking_state.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
# this class is used to mirror unread and new status back to end users
|
||||
# in JavaScript there is a mirror class that is kept in-sync using the mssage bus
|
||||
# the allows end users to always know which topics have unread posts in them
|
||||
# and which topics are new
|
||||
|
||||
class UserTrackingState
|
||||
|
||||
CHANNEL = "/user-tracking"
|
||||
|
||||
MessageBus.client_filter(CHANNEL) do |user_id, message|
|
||||
if user_id
|
||||
UserTrackingState.new(User.find(user_id)).filter(message)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def self.trigger_change(topic_id, post_number, user_id=nil)
|
||||
MessageBus.publish(CHANNEL, "CHANGE", user_ids: [user_id].compact)
|
||||
end
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
@query = TopicQuery.new(@user)
|
||||
end
|
||||
|
||||
def new_list
|
||||
@query
|
||||
.new_results(limit: false)
|
||||
.select(topics: [:id, :created_at])
|
||||
.map{|t| [t.id, t.created_at]}
|
||||
end
|
||||
|
||||
def unread_list
|
||||
[]
|
||||
end
|
||||
|
||||
def filter(message)
|
||||
end
|
||||
|
||||
end
|
|
@ -109,11 +109,9 @@ class Guardian
|
|||
alias :can_activate? :can_approve?
|
||||
|
||||
def can_ban?(user)
|
||||
return false if user.blank?
|
||||
return false unless @user.try(:admin?)
|
||||
return false if user.admin?
|
||||
true
|
||||
is_staff? && user && !user.staff?
|
||||
end
|
||||
|
||||
alias :can_deactivate? :can_ban?
|
||||
|
||||
def can_clear_flags?(post)
|
||||
|
|
|
@ -190,6 +190,19 @@ class TopicQuery
|
|||
create_list(:new_in_category) {|l| l.where(category_id: category.id).by_newest.first(25)}
|
||||
end
|
||||
|
||||
def new_results(list_opts={})
|
||||
default_list(list_opts)
|
||||
.where("topics.created_at >= :created_at", created_at: @user.treat_as_new_topic_start_date)
|
||||
.where("tu.last_read_post_number IS NULL")
|
||||
.where("COALESCE(tu.notification_level, :tracking) >= :tracking", tracking: TopicUser.notification_levels[:tracking])
|
||||
end
|
||||
|
||||
def unread_results(list_opts={})
|
||||
default_list(list_opts)
|
||||
.where("tu.last_read_post_number < topics.highest_post_number")
|
||||
.where("COALESCE(tu.notification_level, :regular) >= :tracking", regular: TopicUser.notification_levels[:regular], tracking: TopicUser.notification_levels[:tracking])
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def create_list(filter, list_opts={})
|
||||
|
@ -240,18 +253,6 @@ class TopicQuery
|
|||
result
|
||||
end
|
||||
|
||||
def new_results(list_opts={})
|
||||
default_list(list_opts)
|
||||
.where("topics.created_at >= :created_at", created_at: @user.treat_as_new_topic_start_date)
|
||||
.where("tu.last_read_post_number IS NULL")
|
||||
.where("COALESCE(tu.notification_level, :tracking) >= :tracking", tracking: TopicUser.notification_levels[:tracking])
|
||||
end
|
||||
|
||||
def unread_results(list_opts={})
|
||||
default_list(list_opts)
|
||||
.where("tu.last_read_post_number < topics.highest_post_number")
|
||||
.where("COALESCE(tu.notification_level, :regular) >= :tracking", regular: TopicUser.notification_levels[:regular], tracking: TopicUser.notification_levels[:tracking])
|
||||
end
|
||||
|
||||
def random_suggested_results_for(topic, count, exclude_topic_ids)
|
||||
results = default_list(unordered: true, per_page: count)
|
||||
|
|
|
@ -4,14 +4,14 @@ require_dependency 'post_destroyer'
|
|||
|
||||
describe Guardian do
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:moderator) { Fabricate(:moderator) }
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
let(:another_admin) { Fabricate(:another_admin) }
|
||||
let(:coding_horror) { Fabricate(:coding_horror) }
|
||||
let(:user) { build(:user) }
|
||||
let(:moderator) { build(:moderator) }
|
||||
let(:admin) { build(:admin) }
|
||||
let(:another_admin) { build(:another_admin) }
|
||||
let(:coding_horror) { build(:coding_horror) }
|
||||
|
||||
let(:topic) { Fabricate(:topic, user: user) }
|
||||
let(:post) { Fabricate(:post, topic: topic, user: topic.user) }
|
||||
let(:topic) { build(:topic, user: user) }
|
||||
let(:post) { build(:post, topic: topic, user: topic.user) }
|
||||
|
||||
it 'can be created without a user (not logged in)' do
|
||||
lambda { Guardian.new }.should_not raise_error
|
||||
|
@ -22,8 +22,8 @@ describe Guardian do
|
|||
end
|
||||
|
||||
describe 'post_can_act?' do
|
||||
let(:post) { Fabricate(:post) }
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:post) { build(:post) }
|
||||
let(:user) { build(:user) }
|
||||
|
||||
it "returns false when the user is nil" do
|
||||
Guardian.new(nil).post_can_act?(post, :like).should be_false
|
||||
|
@ -220,6 +220,9 @@ describe Guardian do
|
|||
|
||||
describe 'a Post' do
|
||||
it 'correctly handles post visibility' do
|
||||
post = Fabricate(:post)
|
||||
topic = post.topic
|
||||
|
||||
Guardian.new(user).can_see?(post).should be_true
|
||||
|
||||
post.trash!
|
||||
|
@ -613,6 +616,7 @@ describe Guardian do
|
|||
end
|
||||
|
||||
it "returns false when trying to delete your own post that has already been deleted" do
|
||||
post = Fabricate(:post)
|
||||
PostDestroyer.new(user, post).destroy
|
||||
post.reload
|
||||
Guardian.new(user).can_delete?(post).should be_false
|
||||
|
@ -642,7 +646,7 @@ describe Guardian do
|
|||
|
||||
context 'a Category' do
|
||||
|
||||
let(:category) { Fabricate(:category, user: moderator) }
|
||||
let(:category) { build(:category, user: moderator) }
|
||||
|
||||
it 'returns false when not logged in' do
|
||||
Guardian.new.can_delete?(category).should be_false
|
||||
|
@ -667,8 +671,33 @@ describe Guardian do
|
|||
|
||||
end
|
||||
|
||||
context 'can_ban?' do
|
||||
it 'returns false when a user tries to ban another user' do
|
||||
Guardian.new(user).can_ban?(coding_horror).should be_false
|
||||
end
|
||||
|
||||
it 'returns true when an admin tries to ban another user' do
|
||||
Guardian.new(admin).can_ban?(coding_horror).should be_true
|
||||
end
|
||||
|
||||
it 'returns true when a moderator tries to ban another user' do
|
||||
Guardian.new(moderator).can_ban?(coding_horror).should be_true
|
||||
end
|
||||
|
||||
it 'returns false when staff tries to ban staff' do
|
||||
Guardian.new(admin).can_ban?(moderator).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
context 'a PostAction' do
|
||||
let(:post_action) { PostAction.create(user_id: user.id, post_id: post.id, post_action_type_id: 1)}
|
||||
let(:post_action) {
|
||||
user.id = 1
|
||||
post.id = 1
|
||||
|
||||
a = PostAction.new(user_id: user.id, post_id: post.id, post_action_type_id: 1)
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
}
|
||||
|
||||
it 'returns false when not logged in' do
|
||||
Guardian.new.can_delete?(post_action).should be_false
|
||||
|
@ -732,6 +761,8 @@ describe Guardian do
|
|||
end
|
||||
|
||||
it "allows an admin to grant a regular user access" do
|
||||
admin.id = 1
|
||||
user.id = 2
|
||||
Guardian.new(admin).can_grant_admin?(user).should be_true
|
||||
end
|
||||
end
|
||||
|
@ -750,6 +781,9 @@ describe Guardian do
|
|||
end
|
||||
|
||||
it "allows an admin to revoke another admin's access" do
|
||||
admin.id = 1
|
||||
another_admin.id = 2
|
||||
|
||||
Guardian.new(admin).can_revoke_admin?(another_admin).should be_true
|
||||
end
|
||||
end
|
||||
|
|
34
spec/models/user_tracking_state_spec.rb
Normal file
34
spec/models/user_tracking_state_spec.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe UserTrackingState do
|
||||
|
||||
let(:user) do
|
||||
Fabricate(:user)
|
||||
end
|
||||
|
||||
let(:post) do
|
||||
Fabricate(:post)
|
||||
end
|
||||
|
||||
let(:state) do
|
||||
UserTrackingState.new(user)
|
||||
end
|
||||
|
||||
it "correctly gets the list of new topics" do
|
||||
state.new_list.should == []
|
||||
state.unread_list.should == []
|
||||
|
||||
new_post = post
|
||||
|
||||
new_list = state.new_list
|
||||
|
||||
new_list.length.should == 1
|
||||
new_list[0][0].should == post.topic.id
|
||||
new_list[0][1].should be_within(1.second).of(post.topic.created_at)
|
||||
|
||||
state.unread_list.should == []
|
||||
|
||||
# read it
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user