diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/account_deleter.rb | 2 | ||||
-rw-r--r-- | lib/bookmarklet_renderer.rb | 2 | ||||
-rw-r--r-- | lib/connection_tester.rb | 56 | ||||
-rw-r--r-- | lib/diaspora/federated/retraction.rb | 3 | ||||
-rw-r--r-- | lib/diaspora/federation/dispatcher.rb | 4 | ||||
-rw-r--r-- | lib/diaspora/federation/receive.rb | 4 | ||||
-rw-r--r-- | lib/diaspora/mentionable.rb | 24 | ||||
-rw-r--r-- | lib/diaspora/message_renderer.rb | 32 | ||||
-rw-r--r-- | lib/diaspora/taggable.rb | 4 | ||||
-rw-r--r-- | lib/error_page_renderer.rb | 32 | ||||
-rw-r--r-- | lib/node_info.rb | 33 | ||||
-rw-r--r-- | lib/tasks/assets.rake | 31 |
12 files changed, 120 insertions, 107 deletions
diff --git a/lib/account_deleter.rb b/lib/account_deleter.rb index 302669bc4..d7f976c1a 100644 --- a/lib/account_deleter.rb +++ b/lib/account_deleter.rb @@ -97,6 +97,6 @@ class AccountDeleter end def mark_account_deletion_complete - AccountDeletion.find_by(person: person)&.update_attributes(completed_at: Time.now.utc) + AccountDeletion.find_by(person: person)&.update(completed_at: Time.now.utc) end end diff --git a/lib/bookmarklet_renderer.rb b/lib/bookmarklet_renderer.rb index a8e998a73..d15fb7261 100644 --- a/lib/bookmarklet_renderer.rb +++ b/lib/bookmarklet_renderer.rb @@ -16,7 +16,7 @@ class BookmarkletRenderer end def source - @source ||= Rails.application.assets["bookmarklet.js"].pathname.to_s + @source ||= Rails.application.assets["bookmarklet.js"].filename end def body diff --git a/lib/connection_tester.rb b/lib/connection_tester.rb index 5bc58d75b..d66f418f8 100644 --- a/lib/connection_tester.rb +++ b/lib/connection_tester.rb @@ -1,10 +1,8 @@ - # frozen_string_literal: true class ConnectionTester include Diaspora::Logging - NODEINFO_SCHEMA = "http://nodeinfo.diaspora.software/ns/schema/1.0" NODEINFO_FRAGMENT = "/.well-known/nodeinfo" class << self @@ -97,16 +95,13 @@ class ConnectionTester # * is the SSL certificate valid (only on HTTPS) # * does the server return a successful HTTP status code # * is there a reasonable amount of redirects (3 by default) - # * is there a /.well-known/host-meta (this is needed to work, this can be replaced with a mandatory NodeInfo later) # (can't do a HEAD request, since that's not a defined route in the app) # # @raise [NetFailure, SSLFailure, HTTPFailure] if any of the checks fail # @return [Integer] HTTP status code def request with_http_connection do |http| - capture_response_time { http.get("/") } - response = http.get("/.well-known/host-meta") - handle_http_response(response) + capture_response_time { handle_http_response(http.get("/")) } end rescue HTTPFailure => e raise e @@ -114,8 +109,8 @@ class ConnectionTester raise NetFailure, e.message rescue Faraday::SSLError => e raise SSLFailure, e.message - rescue ArgumentError, FaradayMiddleware::RedirectLimitReached, Faraday::ClientError => e - raise HTTPFailure, e.message + rescue ArgumentError, Faraday::ClientError, Faraday::ServerError => e + raise HTTPFailure, "#{e.class}: #{e.message}" rescue StandardError => e unexpected_error(e) end @@ -123,20 +118,25 @@ class ConnectionTester # Try to find out the version of the other servers software. # Assuming the server speaks nodeinfo # - # @raise [NodeInfoFailure] if the document can't be fetched - # or the attempt to parse it failed + # @raise [HTTPFailure] if the document can't be fetched + # @raise [NodeInfoFailure] if the document can't be parsed or is invalid def nodeinfo with_http_connection do |http| ni_resp = http.get(NODEINFO_FRAGMENT) - nd_resp = http.get(find_nodeinfo_url(ni_resp.body)) - find_software_version(nd_resp.body) + ni_urls = find_nodeinfo_urls(ni_resp.body) + raise NodeInfoFailure, "No supported NodeInfo version found" if ni_urls.empty? + + version, url = ni_urls.max + find_software_version(version, http.get(url).body) end rescue NodeInfoFailure => e raise e - rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError => e + rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError, Faraday::TimeoutError => e raise NodeInfoFailure, "#{e.class}: #{e.message}" - rescue Faraday::ResourceNotFound, JSON::JSONError => e + rescue JSON::JSONError => e raise NodeInfoFailure, e.message[0..255].encode(Encoding.default_external, undef: :replace) + rescue Faraday::ClientError => e + raise HTTPFailure, "#{e.class}: #{e.message}" rescue StandardError => e unexpected_error(e) end @@ -175,30 +175,30 @@ class ConnectionTester def handle_http_response(response) @result.status_code = Integer(response.status) - if response.success? - raise HTTPFailure, "redirected to other hostname: #{response.env.url}" unless @uri.host == response.env.url.host + raise HTTPFailure, "unsuccessful response code: #{response.status}" unless response.success? + raise HTTPFailure, "redirected to other hostname: #{response.env.url}" unless @uri.host == response.env.url.host - @result.reachable = true - @result.ssl = (response.env.url.scheme == "https") - else - raise HTTPFailure, "unsuccessful response code: #{response.status}" - end + @result.reachable = true + @result.ssl = (response.env.url.scheme == "https") end - # walk the JSON document, get the actual document location - def find_nodeinfo_url(body) + # walk the JSON document, get the actual document locations + def find_nodeinfo_urls(body) jrd = JSON.parse(body) links = jrd.fetch("links") raise NodeInfoFailure, "invalid JRD: '#/links' is not an array!" unless links.is_a?(Array) - links.find { |entry| - entry.fetch("rel") == NODEINFO_SCHEMA - }.fetch("href") + + supported_rel_map = NodeInfo::VERSIONS.index_by {|v| "http://nodeinfo.diaspora.software/ns/schema/#{v}" } + links.map {|entry| + version = supported_rel_map[entry.fetch("rel")] + [version, entry.fetch("href")] if version + }.compact.to_h end # walk the JSON document, find the version string - def find_software_version(body) + def find_software_version(version, body) info = JSON.parse(body) - JSON::Validator.validate!(NodeInfo.schema("1.0"), info) + JSON::Validator.validate!(NodeInfo.schema(version), info) sw = info.fetch("software") @result.software_version = "#{sw.fetch('name')} #{sw.fetch('version')}" end diff --git a/lib/diaspora/federated/retraction.rb b/lib/diaspora/federated/retraction.rb index b0ea20dbc..538ba7e9b 100644 --- a/lib/diaspora/federated/retraction.rb +++ b/lib/diaspora/federated/retraction.rb @@ -36,7 +36,8 @@ class Retraction def defer_dispatch(user, include_target_author=true) subscribers = dispatch_subscribers(include_target_author) - Workers::DeferredRetraction.perform_async(user.id, self.class.to_s, data, subscribers.map(&:id), service_opts(user)) + Workers::DeferredRetraction.perform_async(user.id, self.class.to_s, data.deep_stringify_keys, + subscribers.map(&:id), service_opts(user).deep_stringify_keys) end def perform diff --git a/lib/diaspora/federation/dispatcher.rb b/lib/diaspora/federation/dispatcher.rb index 4e03e725f..2ad441715 100644 --- a/lib/diaspora/federation/dispatcher.rb +++ b/lib/diaspora/federation/dispatcher.rb @@ -21,7 +21,7 @@ module Diaspora end def self.defer_dispatch(sender, object, opts={}) - Workers::DeferredDispatch.perform_async(sender.id, object.class.to_s, object.id, opts) + Workers::DeferredDispatch.perform_async(sender.id, object.class.to_s, object.id, opts.deep_stringify_keys) end def dispatch @@ -69,7 +69,7 @@ module Diaspora when StatusMessage each_service {|service| Workers::PostToService.perform_async(service.id, object.id, opts[:url]) } when Retraction - each_service {|service| Workers::DeletePostFromService.perform_async(service.id, opts) } + each_service {|service| Workers::DeletePostFromService.perform_async(service.id, opts.deep_stringify_keys) } end end diff --git a/lib/diaspora/federation/receive.rb b/lib/diaspora/federation/receive.rb index dd136ac42..adc3a9c82 100644 --- a/lib/diaspora/federation/receive.rb +++ b/lib/diaspora/federation/receive.rb @@ -116,7 +116,7 @@ module Diaspora if persisted_photo persisted_photo.tap do |photo| - photo.update_attributes( + photo.update( text: entity.text, public: entity.public, created_at: entity.created_at, @@ -145,7 +145,7 @@ module Diaspora def self.profile(entity) author_of(entity).profile.tap do |profile| - profile.update_attributes( + profile.update( first_name: entity.first_name, last_name: entity.last_name, image_url: entity.image_url, diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index 59f2da8f0..d009ce6a5 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -1,4 +1,3 @@ - # frozen_string_literal: true module Diaspora::Mentionable @@ -55,8 +54,9 @@ module Diaspora::Mentionable # # @param [String] message text # @param [Array] allowed_people ids of people that are allowed to stay + # @param [Boolean] absolute_links (false) render mentions with absolute links # @return [String] message text with filtered mentions - def self.filter_people(msg_text, allowed_people) + def self.filter_people(msg_text, allowed_people, absolute_links: false) mentioned_ppl = people_from_string(msg_text) msg_text.to_s.gsub(REGEX) {|match_str| @@ -66,7 +66,7 @@ module Diaspora::Mentionable if person && allowed_people.include?(person.id) match_str else - "@#{MentionsInternal.profile_link(person, name, diaspora_id)}" + "@#{MentionsInternal.profile_link(person, name, diaspora_id, absolute: absolute_links)}" end } end @@ -93,7 +93,7 @@ module Diaspora::Mentionable # inline module for namespacing module MentionsInternal - extend ::PeopleHelper + extend ERB::Util # output a formatted mention link as defined by the given arguments. # if the display name is blank, falls back to the person's name. @@ -105,10 +105,15 @@ module Diaspora::Mentionable def self.mention_link(person, display_name, diaspora_id, opts) return display_name || diaspora_id unless person.present? + display_name ||= person.name if opts[:plain_text] - display_name || person.name + display_name else - person_link(person, class: PERSON_HREF_CLASS, display_name: display_name) + # rubocop:disable Rails/OutputSafety + remote_or_hovercard_link = Rails.application.routes.url_helpers.person_path(person).html_safe + "<a data-hovercard=\"#{remote_or_hovercard_link}\" href=\"#{remote_or_hovercard_link}\" " \ + "class=\"#{PERSON_HREF_CLASS}\">#{html_escape_once(display_name)}</a>".html_safe + # rubocop:enable Rails/OutputSafety end end @@ -117,11 +122,14 @@ module Diaspora::Mentionable # # @param [Person] AR Person # @param [String] display name + # @param [String] diaspora_id + # @param [Boolean] absolute (false) render absolute link # @return [String] markdown person link - def self.profile_link(person, display_name, diaspora_id) + def self.profile_link(person, display_name, diaspora_id, absolute: false) return display_name || diaspora_id unless person.present? - "[#{display_name || person.name}](#{local_or_remote_person_path(person)})" + url_helper = Rails.application.routes.url_helpers + "[#{display_name || person.name}](#{absolute ? url_helper.person_url(person) : url_helper.person_path(person)})" end end end diff --git a/lib/diaspora/message_renderer.rb b/lib/diaspora/message_renderer.rb index d3f0e0232..2f9ef423f 100644 --- a/lib/diaspora/message_renderer.rb +++ b/lib/diaspora/message_renderer.rb @@ -56,8 +56,8 @@ module Diaspora @message = renderer.render(message).strip end - def markdownify - renderer = Diaspora::Markdownify::HTML.new options[:markdown_render_options] + def markdownify(renderer_class=Diaspora::Markdownify::HTML) + renderer = renderer_class.new options[:markdown_render_options] markdown = Redcarpet::Markdown.new renderer, options[:markdown_options] @message = markdown.render message @@ -76,8 +76,8 @@ module Diaspora @message = Diaspora::Mentionable.format message, options[:mentioned_people] end - if options[:disable_hovercards] || options[:link_all_mentions] - @message = Diaspora::Mentionable.filter_people message, [] + if options[:disable_hovercards] + @message = Diaspora::Mentionable.filter_people(message, [], absolute_links: true) else make_mentions_plain_text end @@ -108,7 +108,6 @@ module Diaspora end DEFAULTS = {mentioned_people: [], - link_all_mentions: false, disable_hovercards: false, truncate: false, append: nil, @@ -137,12 +136,8 @@ module Diaspora # @param [Hash] opts Global options affecting output # @option opts [Array<Person>] :mentioned_people ([]) List of people # allowed to mention - # @option opts [Boolean] :link_all_mentions (false) Whether to link - # all mentions. This makes plain links to profiles for people not in - # :mentioned_people # @option opts [Boolean] :disable_hovercards (true) Render all mentions - # as profile links. This implies :link_all_mentions and ignores - # :mentioned_people + # as absolute profile links. This ignores :mentioned_people # @option opts [#to_i, Boolean] :truncate (false) Truncate message to # the specified length # @option opts [String] :append (nil) Append text to the end of @@ -205,7 +200,7 @@ module Diaspora render_tags squish append_and_truncate - }.html_safe + }.html_safe # rubocop:disable Rails/OutputSafety end # @param [Hash] opts Override global output options, see {#initialize} @@ -220,7 +215,20 @@ module Diaspora render_tags squish append_and_truncate - }.html_safe + }.html_safe # rubocop:disable Rails/OutputSafety + end + + def markdownified_for_mail + process(disable_hovercards: true) { + process_newlines + normalize + diaspora_links + camo_urls if AppConfig.privacy.camo.proxy_markdown_images? + render_mentions + markdownify(Diaspora::Markdownify::Email) + squish + append_and_truncate + }.html_safe # rubocop:disable Rails/OutputSafety end # Get a short summary of the message diff --git a/lib/diaspora/taggable.rb b/lib/diaspora/taggable.rb index ec9f9e6d8..6a75a1f38 100644 --- a/lib/diaspora/taggable.rb +++ b/lib/diaspora/taggable.rb @@ -15,8 +15,8 @@ module Diaspora # tag's name is limited to 255 charchters according to ActsAsTaggableOn gem, so we check the length of the name for each tag def tag_name_max_length - self.tag_list.each do |tag| - errors[:tags] << I18n.t('tags.name_too_long', :count => 255, :current_length => tag.length) if tag.length > 255 + tag_list.each do |tag| + errors.add(:tags, I18n.t("tags.name_too_long", count: 255, current_length: tag.length)) if tag.length > 255 end end protected :tag_name_max_length diff --git a/lib/error_page_renderer.rb b/lib/error_page_renderer.rb index 65bd09dbc..4e968f9e0 100644 --- a/lib/error_page_renderer.rb +++ b/lib/error_page_renderer.rb @@ -6,44 +6,14 @@ class ErrorPageRenderer def initialize options={} @codes = options.fetch :codes, [404, 500] @output = options.fetch :output, "public/%s.html" - @vars = options.fetch :vars, {} @template = options.fetch :template, "errors/error_%s" @layout = options.fetch :layout, "layouts/error_page" end def render @codes.each do |code| - view = build_action_view - view.assign @vars.merge(code: code) path = Rails.root.join(@output % code) - File.write path, view.render(template: @template % code, layout: @layout) + File.write path, ApplicationController.render(@template % code, layout: @layout, locals: {code: code}) end end - - def helpers(&block) - @helpers = block - end - - private - - def build_action_view - paths = ::ActionController::Base.view_paths - ::ActionView::Base.new(paths).tap do |view| - view.class_eval do - include Rails.application.helpers - include Rails.application.routes.url_helpers - end - view.assets_manifest = build_manifest(Rails.application) - view.class_eval(&@helpers) if @helpers - end - end - - # Internal API from the sprocket-rails railtie, if somebody finds a way to - # call it, please replace it. Might need to be updated on sprocket-rails - # updates. - def build_manifest(app) - config = app.config - path = File.join(config.paths['public'].first, config.assets.prefix) - Sprockets::Manifest.new(app.assets, path, config.assets.manifest) - end end diff --git a/lib/node_info.rb b/lib/node_info.rb index f2118af26..05c96dcb1 100644 --- a/lib/node_info.rb +++ b/lib/node_info.rb @@ -4,13 +4,13 @@ require "pathname" require "json-schema" module NodeInfo - VERSIONS = %w(1.0 2.0).freeze - SCHEMAS = {} - private_constant :VERSIONS, :SCHEMAS + VERSIONS = %w[1.0 2.0 2.1].freeze + SCHEMAS = {} # rubocop:disable Style/MutableConstant + private_constant :SCHEMAS - # rubocop:disable Metrics/BlockLength Document = Struct.new(:version, :software, :protocols, :services, :open_registrations, :usage, :metadata) do - Software = Struct.new(:name, :version) do + # rubocop:disable Lint/ConstantDefinitionInBlock + Software = Struct.new(:name, :version, :repository, :homepage) do def initialize(name=nil, version=nil) super(name, version) end @@ -21,6 +21,13 @@ module NodeInfo "version" => version } end + + def version_21_hash + version_10_hash.merge( + "repository" => repository, + "homepage" => homepage + ) + end end Protocols = Struct.new(:protocols) do @@ -80,6 +87,7 @@ module NodeInfo } end end + # rubocop:enable Lint/ConstantDefinitionInBlock def self.build new.tap do |doc| @@ -98,6 +106,8 @@ module NodeInfo version_10_hash when "2.0" version_20_hash + when "2.1" + version_21_hash end end @@ -144,6 +154,18 @@ module NodeInfo ) end + def version_21_hash + deep_compact( + "version" => "2.1", + "software" => software.version_21_hash, + "protocols" => protocols.version_20_array, + "services" => services.version_10_hash, + "openRegistrations" => open_registrations, + "usage" => usage.version_10_hash, + "metadata" => metadata + ) + end + def deep_compact(hash) hash.tap do |hash| hash.reject! {|_, value| @@ -153,7 +175,6 @@ module NodeInfo end end end - # rubocop:enable Metrics/BlockLength def self.schema(version) SCHEMAS[version] ||= JSON.parse( diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake index 38101d7b3..4c65b8500 100644 --- a/lib/tasks/assets.rake +++ b/lib/tasks/assets.rake @@ -1,35 +1,40 @@ # frozen_string_literal: true namespace :assets do + # create new assets manifest for tasks which run after assets:precompile + def assets_manifest + return @assets_manifest if @assets_manifest + + config = Diaspora::Application.config + path = File.join(config.paths["public"].first, config.assets.prefix) + @assets_manifest = Sprockets::Manifest.new(Diaspora::Application.assets, path, config.assets.manifest) + end + desc "Generate error pages" - task :generate_error_pages => :environment do + task generate_error_pages: :environment do + ApplicationController.view_context_class.assets_manifest = assets_manifest renderer = ErrorPageRenderer.new codes: [404, 422, 500] renderer.render end desc "Create non digest assets" task non_digest_assets: :environment do - logger = ::Logging::Logger["assets:non_digest_assets"] + Diaspora::Application.config.assets.non_digest_assets.each do |asset| + digested_path = assets_manifest.assets[asset] + raise Sprockets::Rails::Helper::AssetNotFound, "Precompiled asset for '#{asset}' not found" unless digested_path - non_digest_assets = Diaspora::Application.config.assets.non_digest_assets - - Rails.application.assets_manifest.assets.each do |logical_path, digested_path| - logical_pathname = Pathname.new(logical_path) - next unless non_digest_assets.any? {|testpath| logical_pathname.fnmatch?(testpath, File::FNM_PATHNAME) } - - full_digested_path = Rails.root.join("public", "assets", digested_path) - full_non_digested_path = Rails.root.join("public", "assets", logical_path) + full_digested_path = File.join(assets_manifest.directory, digested_path) + full_non_digested_path = File.join(assets_manifest.directory, asset) next unless FileUtils.uptodate?(full_digested_path, [full_non_digested_path]) - logger.info "Copying #{full_digested_path} to #{full_non_digested_path}" - + puts "Copying #{full_digested_path} to #{full_non_digested_path}" FileUtils.copy_file(full_digested_path, full_non_digested_path, true) end end # Augment precompile with error page generation - task :precompile do + Rake::Task[:precompile].enhance do Rake::Task["assets:generate_error_pages"].invoke Rake::Task["assets:non_digest_assets"].invoke end |