Add Mastodon aliases and links to Webfinger when enabled #189
@ -11,6 +11,8 @@ DISCOURSE_CONNECT_SECRET='discourse_connect_ftw'
|
|||||||
|
|
||||||
EJABBERD_API_URL='http://xmpp.example.com/api'
|
EJABBERD_API_URL='http://xmpp.example.com/api'
|
||||||
|
|
||||||
|
MASTODON_PUBLIC_URL='http://example.social'
|
||||||
|
|
||||||
LNDHUB_API_URL='http://localhost:3026'
|
LNDHUB_API_URL='http://localhost:3026'
|
||||||
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
||||||
LNDHUB_PUBLIC_KEY='024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946'
|
LNDHUB_PUBLIC_KEY='024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946'
|
||||||
|
@ -3,7 +3,7 @@ class Services::ChatController < Services::BaseController
|
|||||||
before_action :require_service_available
|
before_action :require_service_available
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@service_enabled = current_user.services_enabled.include?(:xmpp)
|
@service_enabled = current_user.service_enabled?(:xmpp)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -3,7 +3,7 @@ class Services::MastodonController < Services::BaseController
|
|||||||
before_action :require_service_available
|
before_action :require_service_available
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@service_enabled = current_user.services_enabled.include?(:mastodon)
|
@service_enabled = current_user.service_enabled?(:mastodon)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -5,7 +5,7 @@ class Services::RemotestorageController < Services::BaseController
|
|||||||
|
|
||||||
# Dashboard
|
# Dashboard
|
||||||
def show
|
def show
|
||||||
# unless current_user.services_enabled.include?(:remotestorage)
|
# unless current_user.service_enabled?(:remotestorage)
|
||||||
# redirect_to service_remotestorage_info_path
|
# redirect_to service_remotestorage_info_path
|
||||||
# end
|
# end
|
||||||
@rs_auths = current_user.remote_storage_authorizations
|
@rs_auths = current_user.remote_storage_authorizations
|
||||||
|
@ -7,14 +7,15 @@ class WebfingerController < ApplicationController
|
|||||||
resource = params[:resource]
|
resource = params[:resource]
|
||||||
|
|
||||||
if resource && @useraddress = resource.match(/acct:(.+)/)&.[](1)
|
if resource && @useraddress = resource.match(/acct:(.+)/)&.[](1)
|
||||||
@username, @org = @useraddress.split("@")
|
@username, @domain = @useraddress.split("@")
|
||||||
|
|
||||||
unless Rails.env.development?
|
unless Rails.env.development?
|
||||||
# Allow different domains (e.g. localhost:3000) in development only
|
# Allow different domains (e.g. localhost:3000) in development only
|
||||||
head 404 and return unless @org == Setting.primary_domain
|
head 404 and return unless @domain == Setting.primary_domain
|
||||||
end
|
end
|
||||||
|
|
||||||
unless User.where(cn: @username.downcase, ou: Setting.primary_domain).any?
|
unless @user = User.where(ou: Setting.primary_domain)
|
||||||
|
.find_by(cn: @username.downcase)
|
||||||
head 404 and return
|
head 404 and return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -28,12 +29,50 @@ class WebfingerController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def webfinger
|
def webfinger
|
||||||
links = [];
|
jrd = {
|
||||||
|
subject: "acct:#{@user.address}",
|
||||||
|
aliases: [],
|
||||||
|
links: []
|
||||||
|
}
|
||||||
|
|
||||||
# TODO check if storage service is enabled for user, not just globally
|
if Setting.mastodon_enabled && @user.service_enabled?(:mastodon)
|
||||||
links << remotestorage_link if Setting.remotestorage_enabled
|
# https://docs.joinmastodon.org/spec/webfinger/
|
||||||
|
jrd[:aliases] += mastodon_aliases
|
||||||
|
jrd[:links] += mastodon_links
|
||||||
|
end
|
||||||
|
|
||||||
{ "links" => links }
|
if Setting.remotestorage_enabled && @user.service_enabled?(:remotestorage)
|
||||||
|
# https://datatracker.ietf.org/doc/draft-dejong-remotestorage/
|
||||||
|
jrd[:links] << remotestorage_link
|
||||||
|
end
|
||||||
|
|
||||||
|
jrd
|
||||||
|
end
|
||||||
|
|
||||||
|
def mastodon_aliases
|
||||||
|
[
|
||||||
|
"#{Setting.mastodon_public_url}/@#{@user.cn}",
|
||||||
|
"#{Setting.mastodon_public_url}/users/#{@user.cn}"
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def mastodon_links
|
||||||
|
[
|
||||||
|
{
|
||||||
|
rel: "http://webfinger.net/rel/profile-page",
|
||||||
|
type: "text/html",
|
||||||
|
href: "#{Setting.mastodon_public_url}/@#{@user.cn}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rel: "self",
|
||||||
|
type: "application/activity+json",
|
||||||
|
href: "#{Setting.mastodon_public_url}/users/#{@user.cn}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rel: "http://ostatus.org/schema/1.0/subscribe",
|
||||||
|
template: "#{Setting.mastodon_public_url}/authorize_interaction?uri={uri}"
|
||||||
|
}
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def remotestorage_link
|
def remotestorage_link
|
||||||
@ -41,9 +80,9 @@ class WebfingerController < ApplicationController
|
|||||||
storage_url = "#{Setting.rs_storage_url}/#{@username}"
|
storage_url = "#{Setting.rs_storage_url}/#{@username}"
|
||||||
|
|
||||||
{
|
{
|
||||||
"rel" => "http://tools.ietf.org/id/draft-dejong-remotestorage",
|
rel: "http://tools.ietf.org/id/draft-dejong-remotestorage",
|
||||||
"href" => storage_url,
|
href: storage_url,
|
||||||
"properties" => {
|
properties: {
|
||||||
"http://remotestorage.io/spec/version" => "draft-dejong-remotestorage-13",
|
"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/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/rfc6750#section-2.3" => nil, # access token via a HTTP query parameter
|
||||||
|
@ -2,8 +2,8 @@ class XmppExchangeContactsJob < ApplicationJob
|
|||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(inviter, invitee)
|
def perform(inviter, invitee)
|
||||||
return unless inviter.services_enabled.include?("xmpp") &&
|
return unless inviter.service_enabled?(:xmpp) &&
|
||||||
invitee.services_enabled.include?("xmpp") &&
|
invitee.service_enabled?(:xmpp) &&
|
||||||
inviter.preferences[:xmpp_exchange_contacts_with_invitees]
|
inviter.preferences[:xmpp_exchange_contacts_with_invitees]
|
||||||
|
|
||||||
ejabberd = EjabberdApiClient.new
|
ejabberd = EjabberdApiClient.new
|
||||||
|
@ -180,6 +180,10 @@ class User < ApplicationRecord
|
|||||||
ldap_entry[:services_enabled] || []
|
ldap_entry[:services_enabled] || []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def service_enabled?(name)
|
||||||
|
services_enabled.map(&:to_sym).include?(name.to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
def enable_service(service)
|
def enable_service(service)
|
||||||
current_services = services_enabled
|
current_services = services_enabled
|
||||||
new_services = Array(service).map(&:to_s)
|
new_services = Array(service).map(&:to_s)
|
||||||
|
@ -16,6 +16,10 @@ RSpec.describe User, type: :model do
|
|||||||
let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
|
let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
|
||||||
|
|
||||||
context "Mastodon service not configured" do
|
context "Mastodon service not configured" do
|
||||||
|
before do
|
||||||
|
Setting.mastodon_enabled = false
|
||||||
|
end
|
||||||
|
|
||||||
it "returns nil" do
|
it "returns nil" do
|
||||||
expect(user.mastodon_address).to be_nil
|
expect(user.mastodon_address).to be_nil
|
||||||
end
|
end
|
||||||
@ -80,6 +84,25 @@ RSpec.describe User, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#service_enabled?" do
|
||||||
|
before do
|
||||||
|
allow(user).to receive(:ldap_entry).and_return({
|
||||||
|
uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
|
||||||
|
services_enabled: ["gitea", "xmpp"]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true or false" do
|
||||||
|
expect(user.service_enabled?("gitea")).to be(true)
|
||||||
|
expect(user.service_enabled?("email")).to be(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false when service is not enabled" do
|
||||||
|
expect(user.service_enabled?(:gitea)).to be(true)
|
||||||
|
expect(user.service_enabled?(:email)).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#enable_service" do
|
describe "#enable_service" do
|
||||||
before do
|
before do
|
||||||
allow(user).to receive(:ldap_entry).and_return({
|
allow(user).to receive(:ldap_entry).and_return({
|
||||||
|
@ -1,13 +1,87 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe "WebFinger", type: :request do
|
RSpec.describe "WebFinger", type: :request do
|
||||||
describe "remoteStorage link relation" do
|
describe "User does not exist" do
|
||||||
context "user exists" do
|
it "returns a 404 status" do
|
||||||
before do
|
get "/.well-known/webfinger?resource=acct%3Ajane.doe%40kosmos.org"
|
||||||
create :user, cn: 'tony', ou: 'kosmos.org'
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "User exists" do
|
||||||
|
let(:user) { create :user, cn: 'tony', ou: 'kosmos.org' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow_any_instance_of(User).to receive(:ldap_entry).and_return({
|
||||||
|
uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
|
||||||
|
services_enabled: ["mastodon", "remotestorage"]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Mastodon entries" do
|
||||||
|
context "Mastodon available" do
|
||||||
|
it "includes the Mastodon aliases and links 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)
|
||||||
|
|
||||||
|
expect(res["aliases"]).to include("http://example.social/@tony")
|
||||||
|
expect(res["aliases"]).to include("http://example.social/users/tony")
|
||||||
|
|
||||||
|
profile_link = res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/profile-page"}
|
||||||
|
self_link = res["links"].find{|l| l["rel"] == "self"}
|
||||||
|
ostatus_link = res["links"].find{|l| l["rel"] == "http://ostatus.org/schema/1.0/subscribe"}
|
||||||
|
expect(profile_link["type"]).to eql("text/html")
|
||||||
|
expect(profile_link["href"]).to eql("http://example.social/@tony")
|
||||||
|
expect(self_link["type"]).to eql("application/activity+json")
|
||||||
|
expect(self_link["href"]).to eql("http://example.social/users/tony")
|
||||||
|
expect(ostatus_link["template"]).to eql("http://example.social/authorize_interaction?uri={uri}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "remoteStorage enabled globally" do
|
context "Mastodon not enabled for user" do
|
||||||
|
before do
|
||||||
|
allow_any_instance_of(User).to receive(:ldap_entry).and_return({
|
||||||
|
uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
|
||||||
|
services_enabled: ["xmpp"]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not include Mastodon aliases or links" do
|
||||||
|
get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["aliases"]).not_to include("http://example.social/@tony")
|
||||||
|
expect(res["aliases"]).not_to include("http://example.social/users/tony")
|
||||||
|
expect(res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/profile-page"}).to be(nil)
|
||||||
|
expect(res["links"].find{|l| l["rel"] == "self"}).to be(nil)
|
||||||
|
expect(res["links"].find{|l| l["rel"] == "http://ostatus.org/schema/1.0/subscribe"}).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Mastodon not available" do
|
||||||
|
before do
|
||||||
|
Setting.mastodon_enabled = false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not include Mastodon aliases or links" do
|
||||||
|
get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["aliases"]).not_to include("http://example.social/@tony")
|
||||||
|
expect(res["aliases"]).not_to include("http://example.social/users/tony")
|
||||||
|
expect(res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/profile-page"}).to be(nil)
|
||||||
|
expect(res["links"].find{|l| l["rel"] == "self"}).to be(nil)
|
||||||
|
expect(res["links"].find{|l| l["rel"] == "http://ostatus.org/schema/1.0/subscribe"}).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "remoteStorage entries" do
|
||||||
|
context "remoteStorage available" do
|
||||||
it "includes the remoteStorage link for the user" do
|
it "includes the remoteStorage link for the user" do
|
||||||
get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
|
get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
@ -22,6 +96,25 @@ RSpec.describe "WebFinger", type: :request do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "remoteStorage not enabled for user" do
|
||||||
|
before do
|
||||||
|
allow_any_instance_of(User).to receive(:ldap_entry).and_return({
|
||||||
|
uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
|
||||||
|
services_enabled: ["xmpp"]
|
||||||
|
})
|
||||||
|
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
|
||||||
|
|
||||||
context "remoteStorage not available" do
|
context "remoteStorage not available" do
|
||||||
before do
|
before do
|
||||||
Setting.remotestorage_enabled = false
|
Setting.remotestorage_enabled = false
|
||||||
@ -38,12 +131,5 @@ RSpec.describe "WebFinger", type: :request do
|
|||||||
end
|
end
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user