From a098ea43bb821b08e6ed0644bd80f494fa142a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Wed, 14 May 2025 15:39:50 +0400 Subject: [PATCH] Add avatar URL to Webfinger when available --- app/controllers/webfinger_controller.rb | 14 +++++++++ app/helpers/application_helper.rb | 11 +++++-- spec/requests/webfinger_spec.rb | 40 +++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/app/controllers/webfinger_controller.rb b/app/controllers/webfinger_controller.rb index 7b28719..a8e00f7 100644 --- a/app/controllers/webfinger_controller.rb +++ b/app/controllers/webfinger_controller.rb @@ -33,6 +33,10 @@ class WebfingerController < WellKnownController links: [] } + if @user.avatar.attached? + jrd[:links] += avatar_link + end + if Setting.mastodon_enabled && @user.service_enabled?(:mastodon) # https://docs.joinmastodon.org/spec/webfinger/ jrd[:aliases] += mastodon_aliases @@ -47,6 +51,16 @@ class WebfingerController < WellKnownController jrd end + def avatar_link + [ + { + rel: "http://webfinger.net/rel/avatar", + type: @user.avatar.content_type, + href: helpers.image_url_for(@user.avatar) + } + ] + end + def mastodon_aliases [ "#{Setting.mastodon_public_url}/@#{@user.cn}", diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a43b13e..c166e06 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -16,8 +16,15 @@ module ApplicationHelper end def image_url_for(attachment) - if Setting.s3_enabled? - s3_image_url(attachment) + return s3_image_url(attachment) if Setting.s3_enabled? + + if attachment.record.is_a?(User) && attachment.name == "avatar" + hash, format = attachment.blob.filename.to_s.split(".", 2) + user_avatar_url( + username: attachment.record.cn, + hash: hash, + format: format + ) else Rails.application.routes.url_helpers.rails_blob_path(attachment, only_path: true) end diff --git a/spec/requests/webfinger_spec.rb b/spec/requests/webfinger_spec.rb index 285c146..a37d3cb 100644 --- a/spec/requests/webfinger_spec.rb +++ b/spec/requests/webfinger_spec.rb @@ -18,6 +18,46 @@ RSpec.describe "WebFinger", type: :request do }) end + describe "Avatar" do + context "not available" do + it "does not include an avatar link" do + get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org" + expect(response).to have_http_status(:ok) + res = JSON.parse(response.body) + + link = res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/avatar"} + expect(link).to be_nil + end + end + + context "available" do + let(:fixture_path) { Rails.root.join("spec/fixtures/files/taipei.jpg") } + let(:img_data) { File.read(fixture_path) } + let(:img_hash) { Digest::SHA256.hexdigest(img_data) } + + before do + ActiveStorage::Blob.create_and_upload!( + io: File.open(fixture_path), + filename: "#{img_hash}.jpg", + content_type: "image/jpeg" + ).tap do |blob| + user.avatar.attach(blob) + end + end + + it "includes a public avatar link" do + get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org" + expect(response).to have_http_status(:ok) + res = JSON.parse(response.body) + + link = res["links"].find { |l| l["rel"] == "http://webfinger.net/rel/avatar" } + expect(link).to be_present + expect(link["type"]).to eq("image/jpeg") + expect(link["href"]).to match(%r{users/tony/avatars/#{img_hash}.jpg}) + end + end + end + describe "Mastodon entries" do context "Mastodon available" do it "includes the Mastodon aliases and links for the user" do