diff options
-rw-r--r-- | Changelog.md | 5 | ||||
-rw-r--r-- | app/assets/javascripts/app/views/photos_view.js | 9 | ||||
-rw-r--r-- | app/assets/javascripts/app/views/pod_entry_view.js | 3 | ||||
-rw-r--r-- | app/assets/templates/pod_table_entry_tpl.jst.hbs | 2 | ||||
-rw-r--r-- | app/models/pod.rb | 28 | ||||
-rw-r--r-- | db/migrate/20221030193943_cleanup_duplicate_pods.rb | 48 | ||||
-rw-r--r-- | lib/diaspora/mentionable.rb | 10 | ||||
-rw-r--r-- | lib/diaspora/message_renderer.rb | 5 | ||||
-rw-r--r-- | spec/factories.rb | 1 | ||||
-rw-r--r-- | spec/javascripts/app/views/pod_entry_view_spec.js | 4 | ||||
-rw-r--r-- | spec/lib/diaspora/message_renderer_spec.rb | 10 | ||||
-rw-r--r-- | spec/models/pod_spec.rb | 17 |
12 files changed, 123 insertions, 19 deletions
diff --git a/Changelog.md b/Changelog.md index 350946272..f6585b78e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -53,6 +53,9 @@ We use yarn to install the frontend dependencies now, so you need to have that i * Make inline code inside links show the link color [#8387](https://github.com/diaspora/diaspora/pull/8387) * Fix fetching public posts on first account search was missing some data [#8390](https://github.com/diaspora/diaspora/pull/8390) * Add redirect from mobile UI photo URLs to post when not using mobile UI [#8400](https://github.com/diaspora/diaspora/pull/8400) +* Escape mentions before markdown parsing in mobile UI [#8398](https://github.com/diaspora/diaspora/pull/8398) +* Cleanup duplicate pods in database [#8403](https://github.com/diaspora/diaspora/pull/8403) +* Fix scrolling issue after closing photo viewer on photos page [#8404](https://github.com/diaspora/diaspora/pull/8404) ## Features * Add client-side cropping of profile image uploads [#7581](https://github.com/diaspora/diaspora/pull/7581) @@ -64,6 +67,8 @@ We use yarn to install the frontend dependencies now, so you need to have that i * Add support for webp images and convert new png/jpg to webp to save space and bandwidth [#8358](https://github.com/diaspora/diaspora/pull/8358) * Show total and active pods count in the pods list for podmins [#8383](https://github.com/diaspora/diaspora/pull/8383) * Allow to select multiple aspects when posting on mobile [#8217](https://github.com/diaspora/diaspora/pull/8217) +* Add info links to drawer in mobile UI [#8405](https://github.com/diaspora/diaspora/pull/8405) +* Tell users that there is no help in mobile version, allow to switch to desktop [#8407](https://github.com/diaspora/diaspora/pull/8407) # 0.7.18.1 diff --git a/app/assets/javascripts/app/views/photos_view.js b/app/assets/javascripts/app/views/photos_view.js index 7390a357c..14d484dd9 100644 --- a/app/assets/javascripts/app/views/photos_view.js +++ b/app/assets/javascripts/app/views/photos_view.js @@ -2,23 +2,16 @@ app.views.Photos = app.views.InfScroll.extend({ className: "clearfix row", - postClass : app.views.Photo, initialize : function() { this.stream = this.model; this.collection = this.stream.items; + new app.views.Gallery({el: this.$el}); // viable for extraction this.stream.fetch(); this.setupInfiniteScroll(); - }, - - postRenderTemplate: function(){ - var photoAttachments = $("#main-stream > div"); - if(photoAttachments.length > 0) { - new app.views.Gallery({ el: photoAttachments }); - } } }); // @license-end diff --git a/app/assets/javascripts/app/views/pod_entry_view.js b/app/assets/javascripts/app/views/pod_entry_view.js index 112b6708f..3d3d098ab 100644 --- a/app/assets/javascripts/app/views/pod_entry_view.js +++ b/app/assets/javascripts/app/views/pod_entry_view.js @@ -27,12 +27,13 @@ app.views.PodEntry = app.views.Base.extend({ presenter: function() { return _.extend({}, this.defaultPresenter(), { /* jshint camelcase: false */ + hasPort: (this.model.get("port") >= 0), is_unchecked: (this.model.get("status")==="unchecked"), has_no_errors: (this.model.get("status")==="no_errors"), has_errors: (this.model.get("status")!=="no_errors"), status_text: Diaspora.I18n.t("admin.pods.states."+this.model.get("status")), pod_url: (this.model.get("ssl") ? "https" : "http") + "://" + this.model.get("host") + - (this.model.get("port") ? ":" + this.model.get("port") : ""), + (this.model.get("port") >= 0 ? ":" + this.model.get("port") : ""), response_time_fmt: this._fmtResponseTime() /* jshint camelcase: true */ }); diff --git a/app/assets/templates/pod_table_entry_tpl.jst.hbs b/app/assets/templates/pod_table_entry_tpl.jst.hbs index 3c2bb0605..76940a4a5 100644 --- a/app/assets/templates/pod_table_entry_tpl.jst.hbs +++ b/app/assets/templates/pod_table_entry_tpl.jst.hbs @@ -7,7 +7,7 @@ {{/if}} </i> </td> -<td class="pod-title" title="{{host}}">{{host}}</td> +<td class="pod-title" title="{{host}}">{{host}}{{#if hasPort}}:{{port}}{{/if}}</td> <td class="added"> <small><time datetime="{{created_at}}" title="{{localTime created_at}}"></time></small> </td> diff --git a/app/models/pod.rb b/app/models/pod.rb index 1edc4e899..0f3177c2b 100644 --- a/app/models/pod.rb +++ b/app/models/pod.rb @@ -22,7 +22,7 @@ class Pod < ApplicationRecord ConnectionTester::SSLFailure => :ssl_failed, ConnectionTester::HTTPFailure => :http_failed, ConnectionTester::NodeInfoFailure => :version_failed - } + }.freeze # this are only the most common errors, the rest will be +unknown_error+ CURL_ERROR_MAP = { @@ -34,7 +34,13 @@ class Pod < ApplicationRecord redirected_to_other_hostname: :http_failed }.freeze - DEFAULT_PORTS = [URI::HTTP::DEFAULT_PORT, URI::HTTPS::DEFAULT_PORT] + # use -1 as port for default ports + # we can't use the real default port (80/443) because we need to handle them + # like both are the same and not both can exist at the same time. + # we also can't use nil, because databases don't handle NULL in unique indexes + # (except postgres >= 15 with "NULLS NOT DISTINCT"). + DEFAULT_PORT = -1 + DEFAULT_PORTS = [URI::HTTP::DEFAULT_PORT, URI::HTTPS::DEFAULT_PORT].freeze has_many :people @@ -51,8 +57,8 @@ class Pod < ApplicationRecord class << self def find_or_create_by(opts) # Rename this method to not override an AR method uri = URI.parse(opts.fetch(:url)) - port = DEFAULT_PORTS.include?(uri.port) ? nil : uri.port - find_or_initialize_by(host: uri.host, port: port).tap do |pod| + port = DEFAULT_PORTS.include?(uri.port) ? DEFAULT_PORT : uri.port + find_or_initialize_by(host: uri.host.downcase, port: port).tap do |pod| pod.ssl ||= (uri.scheme == "https") pod.save end @@ -147,13 +153,21 @@ class Pod < ApplicationRecord # @return [URI] def uri - @uri ||= (ssl ? URI::HTTPS : URI::HTTP).build(host: host, port: port) + @uri ||= (ssl ? URI::HTTPS : URI::HTTP).build(host: host, port: real_port) @uri.dup end + def real_port + if port == DEFAULT_PORT + ssl ? URI::HTTPS::DEFAULT_PORT : URI::HTTP::DEFAULT_PORT + else + port + end + end + def not_own_pod pod_uri = AppConfig.pod_uri - pod_port = DEFAULT_PORTS.include?(pod_uri.port) ? nil : pod_uri.port - errors.add(:base, "own pod not allowed") if pod_uri.host == host && pod_port == port + pod_port = DEFAULT_PORTS.include?(pod_uri.port) ? DEFAULT_PORT : pod_uri.port + errors.add(:base, "own pod not allowed") if pod_uri.host.downcase == host && pod_port == port end end diff --git a/db/migrate/20221030193943_cleanup_duplicate_pods.rb b/db/migrate/20221030193943_cleanup_duplicate_pods.rb new file mode 100644 index 000000000..18fd5740d --- /dev/null +++ b/db/migrate/20221030193943_cleanup_duplicate_pods.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +class CleanupDuplicatePods < ActiveRecord::Migration[6.1] + class Pod < ApplicationRecord + end + + def change + reversible do |change| + change.up do + remove_duplicates + cleanup_mixed_case_pods + + Pod.where(port: nil).update_all(port: -1) # rubocop:disable Rails/SkipsModelValidations + end + + change.down do + Pod.where(port: -1).update_all(port: nil) # rubocop:disable Rails/SkipsModelValidations + end + end + + change_column_null :pods, :port, false + end + + private + + def remove_duplicates + Pod.where(port: nil).group(:host).having("count(*) > 1").pluck(:host).each do |host| + cleanup_duplicates(Pod.where(host: host).order(:id).ids) + end + end + + def cleanup_mixed_case_pods + Pod.where("lower(host) != host").pluck(:host, :port).each do |host, port| + pod_ids = Pod.where("lower(host) = ?", host.downcase).where(port: port).order(:id).ids + cleanup_duplicates(pod_ids.dup) if pod_ids.size > 1 + Pod.find(pod_ids.first).update(host: host.downcase) + end + end + + def cleanup_duplicates(duplicate_ids) + target_pod_id = duplicate_ids.shift + + duplicate_ids.each do |pod_id| + Person.where(pod_id: pod_id).update_all(pod_id: target_pod_id) # rubocop:disable Rails/SkipsModelValidations + Pod.delete(pod_id) + end + end +end diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index 39dc7b085..41dcb79f7 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -71,6 +71,16 @@ module Diaspora::Mentionable } end + # Escapes special chars in mentions to not be parsed as markdown + # + # @param [String] text containing mentions + # @return [String] escaped message + def self.escape_for_markdown(msg_text) + msg_text.to_s.gsub(REGEX) {|match_str| + match_str.gsub("_", "\\_") + } + end + private_class_method def self.find_or_fetch_person_by_identifier(identifier) Person.find_or_fetch_by_identifier(identifier) if Validation::Rule::DiasporaId.new.valid_value?(identifier) rescue DiasporaFederation::Discovery::DiscoveryError diff --git a/lib/diaspora/message_renderer.rb b/lib/diaspora/message_renderer.rb index 7cb0df3fd..6981e7a20 100644 --- a/lib/diaspora/message_renderer.rb +++ b/lib/diaspora/message_renderer.rb @@ -71,6 +71,10 @@ module Diaspora end end + def escape_mentions_for_markdown + @message = Diaspora::Mentionable.escape_for_markdown(message) + end + def render_mentions unless options[:disable_hovercards] || options[:mentioned_people].empty? @message = Diaspora::Mentionable.format message, options[:mentioned_people] @@ -210,6 +214,7 @@ module Diaspora normalize diaspora_links camo_urls if AppConfig.privacy.camo.proxy_markdown_images? + escape_mentions_for_markdown markdownify render_mentions render_tags diff --git a/spec/factories.rb b/spec/factories.rb index 04da06dbc..6d0e8de47 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -249,6 +249,7 @@ FactoryBot.define do factory :pod do sequence(:host) {|n| "pod#{n}.example#{r_str}.com" } + port { -1 } ssl { true } end diff --git a/spec/javascripts/app/views/pod_entry_view_spec.js b/spec/javascripts/app/views/pod_entry_view_spec.js index 2c04effc8..8840cd022 100644 --- a/spec/javascripts/app/views/pod_entry_view_spec.js +++ b/spec/javascripts/app/views/pod_entry_view_spec.js @@ -30,11 +30,13 @@ describe("app.views.PodEntry", function() { this.pod.set({ status: "no_errors", ssl: true, - host: "pod.example.com" + host: "pod.example.com", + port: -1 }); var actual = this.view.presenter(); expect(actual).toEqual(jasmine.objectContaining({ /* jshint camelcase: false */ + hasPort: false, is_unchecked: false, has_no_errors: true, has_errors: false, diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb index a9a12e85b..ca000890e 100644 --- a/spec/lib/diaspora/message_renderer_spec.rb +++ b/spec/lib/diaspora/message_renderer_spec.rb @@ -183,6 +183,16 @@ describe Diaspora::MessageRenderer do ).to match(/hovercard/) end + it "does not parse mentions as markdown" do + new_person = FactoryBot.create(:person, diaspora_handle: "__underscore__@example.org") + expect( + message( + "Hey @{#{new_person.diaspora_handle}}!", + mentioned_people: [new_person] + ).markdownified + ).to match(%r{>#{new_person.name}</a>}) + end + it 'should process text with both a hashtag and a link' do expect( message("Test #tag?\nhttps://joindiaspora.com\n").markdownified diff --git a/spec/models/pod_spec.rb b/spec/models/pod_spec.rb index ac5520c73..2e3bc9b09 100644 --- a/spec/models/pod_spec.rb +++ b/spec/models/pod_spec.rb @@ -16,26 +16,36 @@ describe Pod, type: :model do it "ignores default ports" do pod = Pod.find_or_create_by(url: "https://example.org:443/") expect(pod.host).to eq("example.org") - expect(pod.port).to be_nil + expect(pod.port).to eq(Pod::DEFAULT_PORT) end it "sets ssl boolean" do pod = Pod.find_or_create_by(url: "https://example.org/") expect(pod.ssl).to be true + expect(pod.port).to eq(Pod::DEFAULT_PORT) end it "updates ssl boolean if upgraded to https" do pod = Pod.find_or_create_by(url: "http://example.org/") expect(pod.ssl).to be false + expect(pod.port).to eq(Pod::DEFAULT_PORT) pod = Pod.find_or_create_by(url: "https://example.org/") expect(pod.ssl).to be true + expect(pod.port).to eq(Pod::DEFAULT_PORT) end it "does not update ssl boolean if downgraded to http" do pod = Pod.find_or_create_by(url: "https://example.org/") expect(pod.ssl).to be true + expect(pod.port).to eq(Pod::DEFAULT_PORT) pod = Pod.find_or_create_by(url: "http://example.org/") expect(pod.ssl).to be true + expect(pod.port).to eq(Pod::DEFAULT_PORT) + end + + it "normalizes hostname to lowercase" do + pod = Pod.find_or_create_by(url: "https://eXaMpLe.oRg/") + expect(pod.host).to eq("example.org") end context "validation" do @@ -205,6 +215,11 @@ describe Pod, type: :model do pod = FactoryBot.create(:pod) expect(pod.url_to("/receive/public")).to eq("https://#{pod.host}/receive/public") end + + it "includes non-default port in pod url" do + pod = FactoryBot.create(:pod, port: 3000) + expect(pod.url_to("/receive/public")).to eq("https://#{pod.host}:#{pod.port}/receive/public") + end end describe "#update_offline_since" do |