From 602ef2c8192255c65b2de9ac17f9a5d9489fa5e5 Mon Sep 17 00:00:00 2001 From: Gerhard Schlager Date: Mon, 27 May 2024 22:33:30 +0200 Subject: [PATCH] FIX: Store special characters in permalink URL as encoded characters see https://meta.discourse.org/t/permalink-not-working-with-cyrilics-symbols/301130 --- app/models/permalink.rb | 24 +++++++++++++++--------- spec/models/permalink_spec.rb | 30 ++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/app/models/permalink.rb b/app/models/permalink.rb index 3758860372e..ca07c75be2c 100644 --- a/app/models/permalink.rb +++ b/app/models/permalink.rb @@ -7,7 +7,7 @@ class Permalink < ActiveRecord::Base belongs_to :tag belongs_to :user - before_validation :normalize_url + before_validation :normalize_url, :encode_url validates :url, uniqueness: true @@ -66,10 +66,6 @@ class Permalink < ActiveRecord::Base find_by(url: normalize_url(url)) end - def normalize_url - self.url = Permalink.normalize_url(url) if url - end - def target_url return relative_external_url if external_url return post.relative_url if post @@ -80,10 +76,6 @@ class Permalink < ActiveRecord::Base nil end - def relative_external_url - external_url.match?(%r{\A/[^/]}) ? "#{Discourse.base_path}#{external_url}" : external_url - end - def self.filter_by(url = nil) permalinks = Permalink.includes(:topic, :post, :category, :tag, :user).order("permalinks.created_at desc") @@ -92,6 +84,20 @@ class Permalink < ActiveRecord::Base permalinks.limit!(100) permalinks.to_a end + + private + + def normalize_url + self.url = Permalink.normalize_url(url) if url + end + + def encode_url + self.url = UrlHelper.encode(url) if url + end + + def relative_external_url + external_url.match?(%r{\A/[^/]}) ? "#{Discourse.base_path}#{external_url}" : external_url + end end # == Schema Information diff --git a/spec/models/permalink_spec.rb b/spec/models/permalink_spec.rb index 4aaa4d6cb8b..99f353a3896 100644 --- a/spec/models/permalink_spec.rb +++ b/spec/models/permalink_spec.rb @@ -13,14 +13,40 @@ RSpec.describe Permalink do describe "new record" do it "strips blanks" do - permalink = described_class.create(url: " my/old/url ") + permalink = described_class.create!(url: " my/old/url ") expect(permalink.url).to eq("my/old/url") end it "removes leading slash" do - permalink = described_class.create(url: "/my/old/url") + permalink = described_class.create!(url: "/my/old/url") expect(permalink.url).to eq("my/old/url") end + + it "checks for unique URL" do + permalink = described_class.create(url: "/my/old/url") + expect(permalink.errors[:url]).to be_empty + + permalink = described_class.create(url: "/my/old/url") + expect(permalink.errors[:url]).to be_present + + permalink = described_class.create(url: "my/old/url") + expect(permalink.errors[:url]).to be_present + end + + context "with special characters in URL" do + it "percent encodes any special character" do + permalink = described_class.create!(url: "/2022/10/03/привет-sam") + expect(permalink.url).to eq("2022/10/03/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82-sam") + end + + it "checks for unique URL" do + permalink = described_class.create(url: "/2022/10/03/привет-sam") + expect(permalink.errors[:url]).to be_empty + + permalink = described_class.create(url: "/2022/10/03/привет-sam") + expect(permalink.errors[:url]).to be_present + end + end end describe "target_url" do