12 Commits

Author SHA1 Message Date
6ddeacb779 Merge pull request 'Add Mastodon aliases and links to Webfinger when enabled' (#189) from feature/mastodon_webfinger into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #189
Reviewed-by: galfert <garret.alfert@gmail.com>
2024-04-14 10:18:15 +00:00
78aff3d796 Fix spec
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
The test env has Mastodon enabled now
2024-04-04 17:22:57 +03:00
8f600f44bd Add Mastodon aliases and links to Webfinger when enabled
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
Also requires "remotestorage" service to be enabled via attribute
2024-04-04 17:17:57 +03:00
819ecf6ad8 Add #service_enabled? method to user model 2024-04-04 13:28:09 +03:00
670b2da1ef Ad-hoc content update
All checks were successful
continuous-integration/drone/push Build is passing
Before #186 is implemented
2024-03-29 10:33:28 +04:00
ed5c5b3081 Add remotestorage queue to Sidekiq config
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-29 09:47:30 +04:00
4ee6bfddfa Merge pull request 'Improvements/adjustments for Mastodon integration' (#185) from chore/mastodon into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #185
2024-03-29 05:24:10 +00:00
8b60890061 Add Phanpy to recommended Mastodon apps
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
It's too good not to.
2024-03-29 09:21:17 +04:00
0367450c4b Replace hyphen with underscore in Mastodon address
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Unfortunately, Mastodon only allows underscores for usernames, and
reversely, akkounts only allows hyphens and no underscores.
2024-03-29 09:08:15 +04:00
e6f5623c7f Enable Mastodon service by default (for now) 2024-03-29 09:06:41 +04:00
367f566ccb Merge pull request 'Add global setting for default services, enable for preconfirmed accounts' (#184) from feature/preconfirmed_accounts into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #184
2024-03-28 13:23:22 +00:00
80e69df75c Add global setting for default services, enable for preconfirmed accounts
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
Co-authored-by: Greg Karékinian <greg@karekinian.com>
2024-03-28 17:21:20 +04:00
18 changed files with 374 additions and 48 deletions

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,7 +1,7 @@
class CreateLdapUserJob < ApplicationJob class CreateLdapUserJob < ApplicationJob
queue_as :default queue_as :default
def perform(username, domain, email, hashed_pw) def perform(username:, domain:, email:, hashed_pw:, confirmed: false)
dn = "cn=#{username},ou=#{domain},cn=users,dc=kosmos,dc=org" dn = "cn=#{username},ou=#{domain},cn=users,dc=kosmos,dc=org"
attr = { attr = {
objectclass: ["top", "account", "person", "extensibleObject"], objectclass: ["top", "account", "person", "extensibleObject"],
@@ -12,6 +12,10 @@ class CreateLdapUserJob < ApplicationJob
userPassword: hashed_pw userPassword: hashed_pw
} }
if confirmed
attr[:serviceEnabled] = Setting.default_services
end
ldap_client.add(dn: dn, attributes: attr) ldap_client.add(dn: dn, attributes: attr)
end end

View File

@@ -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

View File

@@ -206,4 +206,9 @@ class Setting < RailsSettings::Base
# #
# field :email_imap_port, type: :string, # field :email_imap_port, type: :string,
# default: ENV["EMAIL_IMAP_PORT"].presence || 993 # default: ENV["EMAIL_IMAP_PORT"].presence || 993
def self.default_services
# TODO Make configurable from respective service settings page
%w[ discourse gitea mastodon mediawiki xmpp ]
end
end end

View File

@@ -93,9 +93,7 @@ class User < ApplicationRecord
LdapManager::UpdateEmail.call(dn: self.dn, address: self.email) LdapManager::UpdateEmail.call(dn: self.dn, address: self.email)
else else
# E-Mail from signup confirmed (i.e. account activation) # E-Mail from signup confirmed (i.e. account activation)
enable_default_services
# TODO Make configurable, only activate globally enabled services
enable_service %w[ discourse gitea mediawiki xmpp ]
# TODO enable in development when we have easy setup of ejabberd etc. # TODO enable in development when we have easy setup of ejabberd etc.
return if Rails.env.development? || !Setting.ejabberd_enabled? return if Rails.env.development? || !Setting.ejabberd_enabled?
@@ -133,7 +131,7 @@ class User < ApplicationRecord
def mastodon_address def mastodon_address
return nil unless Setting.mastodon_enabled? return nil unless Setting.mastodon_enabled?
"#{self.cn}@#{Setting.mastodon_address_domain}" "#{self.cn.gsub("-", "_")}@#{Setting.mastodon_address_domain}"
end end
def valid_attribute?(attribute_name) def valid_attribute?(attribute_name)
@@ -141,6 +139,10 @@ class User < ApplicationRecord
self.errors[attribute_name].blank? self.errors[attribute_name].blank?
end end
def enable_default_services
enable_service Setting.default_services
end
def ln_create_invoice(payload) def ln_create_invoice(payload)
lndhub = Lndhub.new lndhub = Lndhub.new
lndhub.authenticate self lndhub.authenticate self
@@ -178,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)

View File

@@ -35,11 +35,15 @@ class CreateAccount < ApplicationService
@invitation.update! invited_user_id: user_id, used_at: DateTime.now @invitation.update! invited_user_id: user_id, used_at: DateTime.now
end end
# TODO move to confirmation
# (and/or add email_confirmed to entry and use in login filter)
def add_ldap_document def add_ldap_document
hashed_pw = Devise.ldap_auth_password_builder.call(@password) hashed_pw = Devise.ldap_auth_password_builder.call(@password)
CreateLdapUserJob.perform_later(@username, @domain, @email, hashed_pw) CreateLdapUserJob.perform_later(
username: @username,
domain: @domain,
email: @email,
hashed_pw: hashed_pw,
confirmed: @confirmed
)
end end
def create_lndhub_account(user) def create_lndhub_account(user)

View File

@@ -16,8 +16,8 @@
<p> <p>
There's something to do for everyone, especially non-programmers! For There's something to do for everyone, especially non-programmers! For
example, we need more help with graphics, UI/UX design, and example, we need more help with graphics, UI/UX design, and
content/copywriting. We also need moderators for social media. And beta content/copywriting. Also, testing any of our software and reporting
testers for our software. The list doesn't end there. issues you encounter along the way is very valuable.
</p> </p>
<p> <p>
A good way to get started is to join one of our A good way to get started is to join one of our
@@ -43,7 +43,7 @@
</p> </p>
<p> <p>
We have run two 6-month trials so far, with the next trial period We have run two 6-month trials so far, with the next trial period
starting sometime in Q1 2024. Watch your email for notifications about it! starting sometime in Q2 2024. Watch your email for notifications about it!
</p> </p>
</section> </section>
<% end %> <% end %>

View File

@@ -98,7 +98,17 @@
description: "The official Web app", description: "The official Web app",
icon_path: "/img/logos/icon_mastodon-2.svg", icon_path: "/img/logos/icon_mastodon-2.svg",
links: [ links: [
["Launch", "https://kosmos.social"] ["Launch", "https://kosmos.social"],
["GitHub", "https://github.com/mastodon/mastodon"]
]
) %>
<%= render AppInfoComponent.new(
name: "Phanpy",
description: " A slick, feature-rich Web app for mobile and desktop",
icon_path: "/img/logos/icon_phanpy.svg",
links: [
["Launch", "https://phanpy.social"],
["GitHub", "https://github.com/cheeaun/phanpy"]
] ]
) %> ) %>
<%= render AppInfoComponent.new( <%= render AppInfoComponent.new(
@@ -150,6 +160,15 @@
["Google Play", "https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"] ["Google Play", "https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"]
] ]
) %> ) %>
<%= render AppInfoComponent.new(
name: "Phanpy",
description: " A slick, feature-rich Web app for mobile and desktop",
icon_path: "/img/logos/icon_phanpy.svg",
links: [
["Launch", "https://phanpy.social"],
["GitHub", "https://github.com/cheeaun/phanpy"]
]
) %>
</div> </div>
<div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel"> <div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel">
<%= render AppInfoComponent.new( <%= render AppInfoComponent.new(
@@ -180,6 +199,15 @@
["App Store", "https://apps.apple.com/app/mammoth-for-mastodon/id1667573899"] ["App Store", "https://apps.apple.com/app/mammoth-for-mastodon/id1667573899"]
] ]
) %> ) %>
<%= render AppInfoComponent.new(
name: "Phanpy",
description: " A slick, feature-rich Web app for mobile and desktop",
icon_path: "/img/logos/icon_phanpy.svg",
links: [
["Launch", "https://phanpy.social"],
["GitHub", "https://github.com/cheeaun/phanpy"]
]
) %>
</div> </div>
<div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel"> <div class="hidden grid grid-cols-1 gap-6" data-tabs-target="panel">
<%= render AppInfoComponent.new( <%= render AppInfoComponent.new(

View File

@@ -2,3 +2,4 @@
:queues: :queues:
- default - default
- mailers - mailers
- remotestorage

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="54"
height="54"
viewBox="0 0 54 54"
version="1.1"
xml:space="preserve"
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"
id="svg4"
sodipodi:docname="icon_phanpy.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:serif="http://www.serif.com/"><defs
id="defs4" /><sodipodi:namedview
id="namedview4"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="16.359375"
inkscape:cx="26.192932"
inkscape:cy="24.542502"
inkscape:window-width="2160"
inkscape:window-height="1281"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<rect
id="Logo-simple"
serif:id="Logo simple"
x="0"
y="0"
width="63.993999"
height="63.993999"
style="fill:none" />
<g
id="Logo-simple1"
serif:id="Logo simple"
transform="translate(-5.123639,-4.9968626)">
<g
id="g4">
<path
d="m 37.774,11.471 c 14.639,3.752 19.034,16.557 15.889,31.304 -0.696,3.261 -2.563,6.661 -6.356,8.693 -3.204,1.717 -8.07,2.537 -15.338,0.55 0,0 -9.634,-2.404 -9.634,-2.404 C 11.651,46.992 8.378,38.733 10.027,31.823 13.654,16.622 25.57,8.343 37.774,11.471 Z"
style="fill:#a4bff7"
id="path1" />
<path
d="m 36.76,15.429 c 12.289,3.15 15.547,14.114 12.907,26.493 -0.947,4.44 -4.937,9.365 -16.664,6.143 L 23.319,45.648 C 15.465,43.725 12.789,37.848 14.001,32.771 17.017,20.132 26.612,12.828 36.76,15.429 Z"
style="fill:#d8e7fe"
id="path2" />
<path
d="m 27.471,24.991 c -1.457,-0.698 -7.229,3.213 -7.663,8.926 -0.182,2.39 4.55,3.237 5.071,-0.169 0.725,-4.743 3.715,-8.218 2.592,-8.757 z"
style="fill:#6081e6"
id="path3" />
<path
d="m 38.217,26.996 c -2.083,0.327 -0.382,5.901 -0.595,10.727 -0.123,2.8 4.388,3.464 4.703,2.011 1.098,-5.073 -2.066,-13.058 -4.108,-12.738 z"
style="fill:#6081e6"
id="path4" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -3,12 +3,24 @@ require 'rails_helper'
RSpec.describe CreateLdapUserJob, type: :job do RSpec.describe CreateLdapUserJob, type: :job do
let(:ldap_client_mock) { instance_double(Net::LDAP) } let(:ldap_client_mock) { instance_double(Net::LDAP) }
subject(:job) { before do
allow_any_instance_of(described_class).to receive(:ldap_client).and_return(ldap_client_mock) allow_any_instance_of(described_class).to receive(:ldap_client).and_return(ldap_client_mock)
end
subject(:job) {
described_class.perform_later( described_class.perform_later(
'halfinney', 'kosmos.org', 'halfinney@example.com', username: 'halfinney', domain: 'kosmos.org',
'remember-remember-the-5th-of-november' email: 'halfinney@example.com',
hashed_pw: 'remember-remember-the-5th-of-november'
)
}
subject(:job_for_preconfirmed_account) {
described_class.perform_later(
username: 'halfinney', domain: 'kosmos.org',
email: 'halfinney@example.com',
hashed_pw: 'remember-remember-the-5th-of-november',
confirmed: true
) )
} }
@@ -30,6 +42,26 @@ RSpec.describe CreateLdapUserJob, type: :job do
) )
end end
it "adds default services for pre-confirmed accounts" do
allow(ldap_client_mock).to receive(:add) # spy on mock
allow(Setting).to receive(:default_services).and_return(["xmpp", "discourse"])
perform_enqueued_jobs { job_for_preconfirmed_account }
expect(ldap_client_mock).to have_received(:add).with(
dn: "cn=halfinney,ou=kosmos.org,cn=users,dc=kosmos,dc=org",
attributes: {
objectclass: ["top", "account", "person", "extensibleObject"],
cn: "halfinney",
sn: "halfinney",
uid: "halfinney",
mail: "halfinney@example.com",
serviceEnabled: ["xmpp", "discourse"],
userPassword: "remember-remember-the-5th-of-november"
}
)
end
after do after do
clear_enqueued_jobs clear_enqueued_jobs
clear_performed_jobs clear_performed_jobs

View File

@@ -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
@@ -41,6 +45,14 @@ RSpec.describe User, type: :model do
expect(user.mastodon_address).to eq("jimmy@kosmos.social") expect(user.mastodon_address).to eq("jimmy@kosmos.social")
end end
end end
describe "username contains hyphen/dash" do
let(:jammy) { build :user, cn: "jammy-jellyfish", ou: "kosmos.org" }
it "returns the user address" do
expect(jammy.mastodon_address).to eq("jammy_jellyfish@kosmos.org")
end
end
end end
end end
@@ -72,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({
@@ -147,7 +178,7 @@ RSpec.describe User, type: :model do
after { clear_enqueued_jobs } after { clear_enqueued_jobs }
it "enables default services" do it "enables default services" do
expect(user).to receive(:enable_service).with(%w[ discourse gitea mediawiki xmpp ]) expect(user).to receive(:enable_service).with(%w[ discourse gitea mastodon mediawiki xmpp ])
user.send :devise_after_confirmation user.send :devise_after_confirmation
end end

View File

@@ -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

View File

@@ -53,11 +53,32 @@ RSpec.describe CreateAccount, type: :model do
expect(enqueued_jobs.size).to eq(1) expect(enqueued_jobs.size).to eq(1)
args = enqueued_jobs.first['arguments'] args = enqueued_jobs.first['arguments'][0]
expect(args[0]).to eq('halfinney') expect(args["username"]).to eq('halfinney')
expect(args[1]).to eq('kosmos.org') expect(args["domain"]).to eq('kosmos.org')
expect(args[2]).to eq('halfinney@example.com') expect(args["email"]).to eq('halfinney@example.com')
expect(args[3]).to match(/^{SSHA512}.{171}=/) expect(args["hashed_pw"]).to match(/^{SSHA512}.{171}=/)
end
after do
clear_enqueued_jobs
end
end
describe "#add_ldap_document for pre-confirmed account" do
include ActiveJob::TestHelper
let(:service) { CreateAccount.new(account: {
username: 'halfinney',
email: 'halfinney@example.com',
password: 'remember-remember-the-5th-of-november',
confirmed: true
})}
it "enqueues a job to create the LDAP user document" do
service.send(:add_ldap_document)
args = enqueued_jobs.first['arguments'][0]
expect(args["confirmed"]).to be(true)
end end
after do after do