diff --git a/Gemfile b/Gemfile index 59739ec97e4..09fd7ccfedb 100644 --- a/Gemfile +++ b/Gemfile @@ -28,7 +28,7 @@ gem "yajl-ruby", "1.4.1" # Authentication gem "devise", "4.8.0" -gem "devise_lastseenable", "0.0.6" +gem "devise_last_seen", "0.2.1" gem "devise-two-factor", "4.0.0" gem "rqrcode", "2.0.0" diff --git a/Gemfile.lock b/Gemfile.lock index 1bf8afb66dc..a675ed3c089 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -205,9 +205,8 @@ GEM devise (~> 4.0) railties (< 6.2) rotp (~> 6.0) - devise_lastseenable (0.0.6) + devise_last_seen (0.2.1) devise - rails (>= 3.0.4) diaspora_federation (0.2.6) faraday (>= 0.9.0, < 0.16.0) faraday_middleware (>= 0.10.0, < 0.14.0) @@ -814,7 +813,7 @@ DEPENDENCIES database_cleaner-active_record (= 1.8.0) devise (= 4.8.0) devise-two-factor (= 4.0.0) - devise_lastseenable (= 0.0.6) + devise_last_seen (= 0.2.1) diaspora_federation-json_schema (= 0.2.6) diaspora_federation-rails (= 0.2.6) diaspora_federation-test (= 0.2.6) diff --git a/app/helpers/stream_helper.rb b/app/helpers/stream_helper.rb index 503580dd6ef..beeee4cdd42 100644 --- a/app/helpers/stream_helper.rb +++ b/app/helpers/stream_helper.rb @@ -5,15 +5,15 @@ # the COPYRIGHT file. module StreamHelper - def next_page_path(opts ={}) + def next_page_path(_opts={}) if controller.instance_of?(TagsController) - tag_path(:name => @stream.tag_name, :max_time => time_for_scroll(@stream)) + tag_path(name: @stream.tag_names, max_time: time_for_scroll(@stream)) elsif controller.instance_of?(PeopleController) - local_or_remote_person_path(@person, :max_time => time_for_scroll(@stream)) + local_or_remote_person_path(@person, max_time: time_for_scroll(@stream)) elsif controller.instance_of?(StreamsController) next_stream_path else - raise 'in order to use pagination for this new controller, update next_page_path in stream helper' + raise "in order to use pagination for this new controller, update next_page_path in stream helper" end end @@ -22,6 +22,7 @@ def reshare?(post) end private + # rubocop:disable Rails/HelperInstanceVariable def next_stream_path if current_page?(:stream) @@ -50,7 +51,7 @@ def next_stream_path def time_for_scroll(stream) if stream.stream_posts.empty? - (Time.now() + 1).to_i + (Time.zone.now + 1).to_i else stream.stream_posts.last.send(stream.order.to_sym).to_i end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index a55ba9118af..6a95b031d36 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -45,18 +45,40 @@ def self.guids_for_author(person) Post.connection.select_values(Post.where(:author_id => person.id).select('posts.guid').to_sql) end + def self.any_user_tag_stream(user, tag_ids) + owned_or_visible_by_user(user).any_tag_stream(tag_ids) + end + def self.user_tag_stream(user, tag_ids) - owned_or_visible_by_user(user).tag_stream(tag_ids) + owned_or_visible_by_user(user).all_tag_stream(tag_ids) + end + + def self.public_all_tag_stream(tag_ids) + all_public.select("DISTINCT #{table_name}.*").all_tag_stream(tag_ids) end - def self.public_tag_stream(tag_ids) - all_public.select("DISTINCT #{table_name}.*").tag_stream(tag_ids) + def self.public_any_tag_stream(tag_ids) + all_public.select("DISTINCT #{table_name}.*").any_tag_stream(tag_ids) end - def self.tag_stream(tag_ids) + def self.any_tag_stream(tag_ids) joins(:taggings).where("taggings.tag_id IN (?)", tag_ids) end + def self.all_tag_stream(tag_ids) + if tag_ids.empty? + # A empty list means an unknown tag in Taggings list + tag_ids = [-1] + end + + joins("INNER JOIN ( + SELECT taggable_id FROM taggings + WHERE taggings.tag_id IN (#{tag_ids.join(',')}) AND taggings.taggable_type = 'Post' + GROUP BY taggable_id + HAVING COUNT(*) >= #{tag_ids.length}) + taggable ON taggable.taggable_id = posts.id") + end + def nsfw !!(text.try(:match, /#nsfw/i) || super) # rubocop:disable Style/DoubleNegation end diff --git a/app/presenters/tag_stream_presenter.rb b/app/presenters/tag_stream_presenter.rb index 0f78f01e0cc..56f13dc424c 100644 --- a/app/presenters/tag_stream_presenter.rb +++ b/app/presenters/tag_stream_presenter.rb @@ -7,7 +7,7 @@ def title def metas_attributes { - keywords: {name: "keywords", content: tag_name}, + keywords: {name: "keywords", content: tag_names}, description: {name: "description", content: description}, og_url: {property: "og:url", content: url}, og_title: {property: "og:title", content: title}, @@ -18,10 +18,10 @@ def metas_attributes private def description - I18n.t("streams.tags.title", tags: tag_name) + I18n.t("streams.tags.title", tags: tag_names) end def url - tag_url tag_name + tag_url tag_names end end diff --git a/app/views/tags/show.mobile.haml b/app/views/tags/show.mobile.haml index 1194d0316e0..ab23c77d760 100644 --- a/app/views/tags/show.mobile.haml +++ b/app/views/tags/show.mobile.haml @@ -5,13 +5,14 @@ %h1 = @stream.display_tag_name - if user_signed_in? - - unless tag_followed? - .btn.btn-success.tag_following_action{data: {name: @stream.tag_name}} - = t(".follow", tag: @stream.tag_name) + -# rubocop:disable Style/IdenticalConditionalBranches + - if tag_followed? + .btn.btn-danger.tag_following_action{data: {name: @stream.tag_names}} + = t(".stop_following", tag: @stream.tag_names) - else - .btn.btn-danger.tag_following_action{data: {name: @stream.tag_name}} - = t(".stop_following", tag: @stream.tag_name) - + .btn.btn-success.tag_following_action{data: {name: @stream.tag_names}} + = t(".follow", tag: @stream.tag_names) + -# rubocop:enable Style/IdenticalConditionalBranches #main-stream.stream = render 'shared/stream', :posts => @stream.stream_posts = render 'shared/stream_more_button' diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb index ca3c9636c39..3a4fe41816f 100644 --- a/config/initializers/diaspora_federation.rb +++ b/config/initializers/diaspora_federation.rb @@ -104,6 +104,17 @@ on :receive_entity do |entity, sender, recipient_id| Person.by_account_identifier(sender).pod.try(:schedule_check_if_needed) + if User.exists?(recipient_id) + User.find(recipient_id).tap do |user| + next unless user&.person&.account_migration + + Diaspora::Federation::Dispatcher.build( + user, + user.person&.account_migration, + subscribers: [Person.by_account_identifier(sender)] + ).dispatch + end + end case entity when DiasporaFederation::Entities::AccountDeletion diff --git a/lib/evil_query.rb b/lib/evil_query.rb index 4ac15b34e52..4720045d472 100644 --- a/lib/evil_query.rb +++ b/lib/evil_query.rb @@ -73,7 +73,7 @@ def aspects_post_ids! def followed_tags_posts! logger.debug("[EVIL-QUERY] followed_tags_posts!") - StatusMessage.public_tag_stream(@user.followed_tag_ids).excluding_hidden_content(@user) + StatusMessage.public_any_tag_stream(@user.followed_tag_ids).excluding_hidden_content(@user) end def mentioned_posts diff --git a/lib/stream/followed_tag.rb b/lib/stream/followed_tag.rb index b4ad5767e02..8c8b8d6e8f2 100644 --- a/lib/stream/followed_tag.rb +++ b/lib/stream/followed_tag.rb @@ -16,7 +16,12 @@ def title # @return [ActiveRecord::Association] AR association of posts def posts - @posts ||= StatusMessage.user_tag_stream(user, tag_ids) + if tag_ids.empty? + @posts = StatusMessage.none + else + @posts ||= StatusMessage.any_user_tag_stream(user, tag_ids) + end + @posts end private diff --git a/lib/stream/tag.rb b/lib/stream/tag.rb index bec10d341f7..f1c7df0a869 100644 --- a/lib/stream/tag.rb +++ b/lib/stream/tag.rb @@ -5,46 +5,43 @@ # the COPYRIGHT file. class Stream::Tag < Stream::Base - attr_accessor :tag_name, :people_page , :people_per_page + attr_accessor :tag_names, :people_page, :people_per_page - def initialize(user, tag_name, opts={}) - self.tag_name = tag_name + def initialize(user, tag_names, opts={}) + self.tag_names = tag_names.downcase.gsub("#", "") self.people_page = opts[:page] || 1 self.people_per_page = 15 super(user, opts) end - def tag - @tag ||= ActsAsTaggableOn::Tag.named(tag_name).first + def tags + @tags ||= ActsAsTaggableOn::Tag.named_any(tag_names.split(" ")) end def display_tag_name - @display_tag_name ||= "##{tag_name}" + @display_tag_name ||= tag_names.split(" ").map {|t| "##{t}" }.join(" ") end def tagged_people - @people ||= ::Person.profile_tagged_with(tag_name).paginate(:page => people_page, :per_page => people_per_page) + @tagged_people ||= ::Person.profile_tagged_with(tag_names).paginate(page: people_page, per_page: people_per_page) end def tagged_people_count - @people_count ||= ::Person.profile_tagged_with(tag_name).count + @tagged_people_count ||= ::Person.profile_tagged_with(tag_names).count end def posts @posts ||= if user - StatusMessage.user_tag_stream(user, tag.id) + StatusMessage.user_tag_stream(user, tags.pluck(:id)) else - StatusMessage.public_tag_stream(tag.id) + StatusMessage.public_all_tag_stream(tags.pluck(:id)) end end def stream_posts - return [] unless tag - super - end + return [] unless tags - def tag_name=(tag_name) - @tag_name = tag_name.downcase.gsub('#', '') + super end private diff --git a/spec/integration/api/streams_controller_spec.rb b/spec/integration/api/streams_controller_spec.rb index fa650664d45..deaa2494765 100644 --- a/spec/integration/api/streams_controller_spec.rb +++ b/spec/integration/api/streams_controller_spec.rb @@ -249,8 +249,8 @@ params: {access_token: access_token_public_only_read_only} ) expect(response.status).to eq(200) - post = response_body_data(response) - expect(post.length).to eq(1) + posts = response_body_data(response) + expect(posts.any? {|post| post["public"] == true }).to be_truthy end it "fails with invalid credentials" do diff --git a/spec/lib/stream/tag_spec.rb b/spec/lib/stream/tag_spec.rb index 476bc8a1ba4..c13c2851d3d 100644 --- a/spec/lib/stream/tag_spec.rb +++ b/spec/lib/stream/tag_spec.rb @@ -108,12 +108,12 @@ describe '#tag_name=' do it 'downcases the tag' do stream = Stream::Tag.new(nil, "WHAT") - expect(stream.tag_name).to eq('what') + expect(stream.tag_names).to eq("what") end it 'removes #es' do stream = Stream::Tag.new(nil, "#WHAT") - expect(stream.tag_name).to eq('what') + expect(stream.tag_names).to eq("what") end end diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index cbbd36a3205..b0fa883753c 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -41,22 +41,22 @@ describe ".tag_steam" do it "returns status messages tagged with the tag" do - tag_stream = StatusMessage.send(:tag_stream, [@tag_id]) + tag_stream = StatusMessage.send(:all_tag_stream, [@tag_id]) expect(tag_stream).to include @status_message1 expect(tag_stream).to include @status_message2 end end - describe ".public_tag_stream" do + describe ".public_any_tag_stream" do it "returns public status messages tagged with the tag" do - expect(StatusMessage.public_tag_stream([@tag_id])).to eq([@status_message1]) + expect(StatusMessage.public_any_tag_stream([@tag_id])).to eq([@status_message1]) end it "returns a post with two tags only once" do status_message = FactoryBot.create(:status_message, text: "#hashtag #test", public: true) test_tag_id = ActsAsTaggableOn::Tag.where(name: "test").first.id - expect(StatusMessage.public_tag_stream([@tag_id, test_tag_id])) + expect(StatusMessage.public_any_tag_stream([@tag_id, test_tag_id])) .to match_array([@status_message1, status_message]) end end @@ -65,9 +65,9 @@ it "returns tag stream thats owned or visible by" do relation = double expect(StatusMessage).to receive(:owned_or_visible_by_user).with(bob).and_return(relation) - expect(relation).to receive(:tag_stream).with([@tag_id]) + expect(relation).to receive(:any_tag_stream).with([@tag_id]) - StatusMessage.user_tag_stream(bob, [@tag_id]) + StatusMessage.any_user_tag_stream(bob, [@tag_id]) end end end