From 0774c889182d1e7512fd55f1246d9f5e82902aba Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Mon, 10 Apr 2023 21:23:21 +0200 Subject: [PATCH 1/2] WebFinger endpoint --- app/controllers/webfinger_controller.rb | 59 +++++++++++++++++++++++++ config/routes.rb | 2 + spec/requests/webfinger_spec.rb | 49 ++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 app/controllers/webfinger_controller.rb create mode 100644 spec/requests/webfinger_spec.rb diff --git a/app/controllers/webfinger_controller.rb b/app/controllers/webfinger_controller.rb new file mode 100644 index 0000000..8cae5e2 --- /dev/null +++ b/app/controllers/webfinger_controller.rb @@ -0,0 +1,59 @@ +class WebfingerController < ApplicationController + + before_action :allow_cross_origin, :only => [:show] + + layout false + + def show + resource = params[:resource] + + if resource && resource.match(/acct:\w+/) + useraddress = resource.split(":").last + username, org = useraddress.split("@") + username.downcase! + unless User.where(cn: username, ou: org).any? + head 404 and return + end + + render json: webfinger(useraddress).to_json, + content_type: "application/jrd+json" + else + head 422 and return + end + end + + private + + def webfinger(useraddress) + links = []; + + links << remotestorage_link(useraddress) if Setting.remotestorage_enabled + + { "links" => links } + end + + def remotestorage_link(useraddress) + # TODO use when OAuth routes are available + # auth_url = new_rs_oauth_url(useraddress) + auth_url = "https://example.com/rs/oauth" + storage_url = "#{Setting.rs_storage_url}/#{useraddress}" + + { + "rel" => "http://tools.ietf.org/id/draft-dejong-remotestorage", + "href" => storage_url, + "properties" => { + "http://remotestorage.io/spec/version" => "draft-dejong-remotestorage-13", + "http://tools.ietf.org/html/rfc6749#section-4.2" => auth_url, + "http://tools.ietf.org/html/rfc6750#section-2.3" => nil, # access token via a HTTP query parameter + "http://tools.ietf.org/html/rfc7233": "GET", # content range requests + "http://remotestorage.io/spec/web-authoring": nil + } + } + end + + def allow_cross_origin + headers['Access-Control-Allow-Origin'] = '*' + headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS' + end + +end diff --git a/config/routes.rb b/config/routes.rb index e729019..e75eda4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -54,6 +54,8 @@ Rails.application.routes.draw do end end + get ".well-known/webfinger" => "webfinger#show" + authenticate :user, ->(user) { user.is_admin? } do mount Sidekiq::Web => '/sidekiq' end diff --git a/spec/requests/webfinger_spec.rb b/spec/requests/webfinger_spec.rb new file mode 100644 index 0000000..ffa9ca2 --- /dev/null +++ b/spec/requests/webfinger_spec.rb @@ -0,0 +1,49 @@ +require 'rails_helper' + +RSpec.describe "WebFinger", type: :request do + describe "remoteStorage link relation" do + context "user exists" do + before do + create :user, cn: 'tony', ou: 'kosmos.org' + end + + context "remoteStorage service enabled" do + it "includes the remoteStorage link for the user" do + get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org" + expect(response).to have_http_status(:ok) + + res = JSON.parse(response.body) + rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"} + + expect(rs_link["href"]).to eql("https://storage.kosmos.org/tony@kosmos.org") + + oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"] + expect(oauth_url).to eql("https://example.com/rs/oauth") + end + end + + context "remoteStorage service disabled" do + before do + Setting.remotestorage_enabled = false + end + + it "does not include the remoteStorage link" do + get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org" + expect(response).to have_http_status(:ok) + + res = JSON.parse(response.body) + rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"} + + expect(rs_link).to be_nil + end + end + end + + context "user does not exist" do + it "does return a 404 status" do + get "/.well-known/webfinger?resource=acct%3Ajane.doe%40kosmos.org" + expect(response).to have_http_status(:not_found) + end + end + end +end From a2100b23a9c87f0ebadb6bc96a3ded7f4c50dd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Tue, 11 Apr 2023 11:41:30 +0200 Subject: [PATCH 2/2] Formatting, wording --- app/controllers/webfinger_controller.rb | 6 ++---- spec/requests/webfinger_spec.rb | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/controllers/webfinger_controller.rb b/app/controllers/webfinger_controller.rb index 8cae5e2..5cf4012 100644 --- a/app/controllers/webfinger_controller.rb +++ b/app/controllers/webfinger_controller.rb @@ -1,6 +1,5 @@ class WebfingerController < ApplicationController - - before_action :allow_cross_origin, :only => [:show] + before_action :allow_cross_origin_requests, only: [:show] layout false @@ -51,9 +50,8 @@ class WebfingerController < ApplicationController } end - def allow_cross_origin + def allow_cross_origin_requests headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS' end - end diff --git a/spec/requests/webfinger_spec.rb b/spec/requests/webfinger_spec.rb index ffa9ca2..f944a7a 100644 --- a/spec/requests/webfinger_spec.rb +++ b/spec/requests/webfinger_spec.rb @@ -7,7 +7,7 @@ RSpec.describe "WebFinger", type: :request do create :user, cn: 'tony', ou: 'kosmos.org' end - context "remoteStorage service enabled" do + context "remoteStorage enabled globally" do it "includes the remoteStorage link for the user" do get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org" expect(response).to have_http_status(:ok) @@ -22,7 +22,7 @@ RSpec.describe "WebFinger", type: :request do end end - context "remoteStorage service disabled" do + context "remoteStorage not available" do before do Setting.remotestorage_enabled = false end