diff --git a/Gemfile b/Gemfile index a7d5f9485..1b3b30478 100644 --- a/Gemfile +++ b/Gemfile @@ -34,6 +34,7 @@ gem "haml", "~> 6.1" gem "hcaptcha", "~> 7.0" gem "mini_magick" gem "oj" +gem "panko_serializer" gem "rpush" gem "rqrcode" diff --git a/Gemfile.lock b/Gemfile.lock index 60e1d5a2c..e29e5f6f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -272,6 +272,9 @@ GEM oj (3.15.0) openssl (3.1.0) orm_adapter (0.5.0) + panko_serializer (0.8.0) + activesupport + oj (> 3.11.0, < 4.0.0) parallel (1.23.0) parser (3.2.2.3) ast (~> 2.4.1) @@ -523,6 +526,7 @@ DEPENDENCIES net-smtp oj openssl (~> 3.1) + panko_serializer pg pghero prometheus-client (~> 4.1) diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 7b9084b99..072a84324 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -8,12 +8,15 @@ class UserController < ApplicationController after_action :mark_notification_as_read, only: %i[show] def show - @pinned_answers = @user.answers.pinned.order(pinned_at: :desc).limit(10) - paginate_answers { |args| @user.cursored_answers(**args) } + unless request.format == Mime[:json] + @pinned_answers = @user.answers.pinned.order(pinned_at: :desc).limit(10) + paginate_answers { |args| @user.cursored_answers(**args) } + end respond_to do |format| format.html format.turbo_stream { render layout: false } + format.json { render json: UserSerializer.new(context: { controller: self }).serialize_to_json(@user) } end end diff --git a/app/serializers/image_serializer.rb b/app/serializers/image_serializer.rb new file mode 100644 index 000000000..f6fbaa80f --- /dev/null +++ b/app/serializers/image_serializer.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class ImageSerializer < Panko::Serializer + attributes :type, :url, :mime + aliases mime: "mediaType" + + def type = "Image" + def mime = object.content_type + def url = object.url +end diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb new file mode 100644 index 000000000..5fcd97d35 --- /dev/null +++ b/app/serializers/user_serializer.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class UserSerializer < Panko::Serializer + attributes :id, :type, :name, :url, :summary + aliases document_context: :@context + aliases created_at: :published + aliases screen_name: "preferredUsername" + + has_one :profile_picture, serializer: ImageSerializer, name: :icon + has_one :profile_header, serializer: ImageSerializer, name: :image + + def document_context = %w[https://www.w3.org/ns/activitystreams] + + def id = context[:controller].activitypub_user_url(object) + def url = context[:controller].user_url(object) + def type = "Person" + def name = object.profile.display_name + def summary = object.profile.description +end diff --git a/config/routes.rb b/config/routes.rb index 3af4b3a87..ffce31fc9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -171,6 +171,8 @@ get "/feedback/bugs(/*any)", to: "feedback#bugs", as: "feedback_bugs" get "/feedback/feature_requests(/*any)", to: "feedback#features", as: "feedback_features" + get "/users/:username", to: "user#show", as: "activitypub_user", defaults: { format: :json } + namespace :well_known, path: "/.well-known" do get "/change-password", to: redirect("/settings/account") get "/nodeinfo", to: "node_info#discovery"