Compare commits

...

6 Commits

Author SHA1 Message Date
fc2bec6246
Make default user services configurable by admin
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-09-05 11:11:32 +02:00
5addd25186
Add service details config, use for known services 2024-09-05 11:10:54 +02:00
215d178e69
Remove empty spec files 2024-09-05 11:10:10 +02:00
5474bf66e7
Turn default services into a configurable setting
With the default value being all enabled services
2024-09-04 13:06:32 +02:00
ef2a37e2bf
Sort user services in LDAP entry
Makes it predictable for programmatic comparisons (e.g. tests)
2024-09-04 13:05:36 +02:00
0e3180602c
Rename "xmpp" user service back to "ejabberd"
If we ever add support for others, we can combine them as "xmpp" in
helper methods
2024-09-04 13:03:45 +02:00
25 changed files with 170 additions and 56 deletions

View File

@ -9,4 +9,12 @@ class Admin::Settings::RegistrationsController < Admin::SettingsController
success: "Settings saved"
}
end
private
def setting_params
params.require(:setting).permit([
:reserved_usernames, default_services: []
])
end
end

View File

@ -9,11 +9,12 @@ class Admin::SettingsController < Admin::BaseController
changed_keys = []
setting_params.keys.each do |key|
next if setting_params[key].nil? ||
(Setting.send(key).to_s == setting_params[key].strip)
next if clean_param(key).nil? ||
(Setting.send(key).to_s == clean_param(key))
changed_keys.push(key)
setting = Setting.new(var: key)
setting.value = setting_params[key].strip
setting.value = clean_param(key)
unless setting.valid?
@errors.merge!(setting.errors)
end
@ -24,7 +25,8 @@ class Admin::SettingsController < Admin::BaseController
end
changed_keys.each do |key|
Setting.send("#{key}=", setting_params[key].strip)
Setting.send("#{key}=", clean_param(key))
end
end
@ -37,4 +39,12 @@ class Admin::SettingsController < Admin::BaseController
def setting_params
params.require(:setting).permit(Setting.editable_keys.map(&:to_sym))
end
def clean_param(key)
if Setting.get_field(key)[:type] == :string
setting_params[key].strip!
else
setting_params[key]
end
end
end

View File

@ -3,7 +3,7 @@ class Services::ChatController < Services::BaseController
before_action :require_service_available
def show
@service_enabled = current_user.service_enabled?(:xmpp)
@service_enabled = current_user.service_enabled?(:ejabberd)
end
private

View File

@ -1,2 +0,0 @@
module DashboardHelper
end

View File

@ -1,2 +0,0 @@
module DonationsHelper
end

View File

@ -1,2 +0,0 @@
module InvitationsHelper
end

View File

@ -1,2 +0,0 @@
module LnurlpayHelper
end

View File

@ -0,0 +1,12 @@
module ServicesHelper
def service_human_name(key, category = :external)
SERVICES[category][key][:name] || key.to_s
end
def service_display_name(key, category = :external)
SERVICES[category][key][:display_name] ||
service_human_name(key, category)
end
end

View File

@ -1,2 +0,0 @@
module SettingsHelper
end

View File

@ -1,2 +0,0 @@
module SignupHelper
end

View File

@ -1,2 +0,0 @@
module UsersHelper
end

View File

@ -1,2 +0,0 @@
module WalletHelper
end

View File

@ -1,2 +0,0 @@
module WelcomeHelper
end

View File

@ -2,8 +2,8 @@ class XmppExchangeContactsJob < ApplicationJob
queue_as :default
def perform(inviter, invitee)
return unless inviter.service_enabled?(:xmpp) &&
invitee.service_enabled?(:xmpp) &&
return unless inviter.service_enabled?(:ejabberd) &&
invitee.service_enabled?(:ejabberd) &&
inviter.preferences[:xmpp_exchange_contacts_with_invitees]
ejabberd = EjabberdApiClient.new

View File

@ -21,8 +21,11 @@ class Setting < RailsSettings::Base
include Settings::RemoteStorageSettings
include Settings::XmppSettings
def self.default_services
# TODO Make configurable from respective service settings page
%w[ discourse gitea mastodon mediawiki remotestorage xmpp ]
def self.available_services
known_services = SERVICES[:external].keys
known_services.select {|s| Setting.send "#{s}_enabled?" }
end
field :default_services, type: :array,
default: self.available_services
end

View File

@ -180,14 +180,14 @@ class User < ApplicationRecord
def enable_service(service)
current_services = services_enabled
new_services = Array(service).map(&:to_s)
services = (current_services + new_services).uniq
services = (current_services + new_services).uniq.sort
ldap.replace_attribute(dn, :serviceEnabled, services)
end
def disable_service(service)
current_services = services_enabled
disabled_services = Array(service).map(&:to_s)
services = (current_services - disabled_services).uniq
services = (current_services - disabled_services).uniq.sort
ldap.replace_attribute(dn, :serviceEnabled, services)
end

View File

@ -9,18 +9,35 @@
<%= render partial: "admin/settings/errors", locals: { errors: @errors } %>
<% end %>
<label class="block">
<p class="font-bold mb-1">Reserved usernames</p>
<p class="text-gray-500">
These usernames cannot be registered as accounts:
</p>
<%= f.text_area :reserved_usernames,
value: Setting.reserved_usernames.join("\n"),
class: "h-44 mb-2" %>
<p class="text-sm text-gray-500">
One username per line
</p>
</label>
<ul role="list">
<%= render FormElements::FieldsetComponent.new(
title: "Reserved usernames",
description: "These usernames cannot be registered as accounts."
) do %>
<%= f.text_area :reserved_usernames,
value: Setting.reserved_usernames.join("\n"),
class: "h-44 w-60" %>
<p class="text-sm text-gray-500">
One username per line
</p>
<% end %>
<li>
<p class="font-bold mb-1">Default services</p>
<p class="text-gray-500">
These services are enabled for new users by default after signup.
</p>
<div class="flex flex-wrap gap-x-6 gap-y-2">
<% Setting.available_services.each do |option| %>
<div class="md:inline-block">
<%= f.check_box :default_services,
{ multiple: true, checked: Setting.default_services.include?(option) },
option, nil %>
<%= f.label "default_services_#{option.parameterize}", service_human_name(option) %>
</div>
<% end %>
</div>
</li>
</ul>
</section>
<section>

View File

@ -0,0 +1,2 @@
config_path = Rails.root.join('config', 'services.yml')
SERVICES = YAML.load_file(config_path).deep_symbolize_keys.with_indifferent_access

30
config/services.yml Normal file
View File

@ -0,0 +1,30 @@
internal:
btcpay:
name: BTCPay Server
postgres:
name: PostgreSQL
sentry:
name: Sentry
external:
discourse:
name: Discourse
droneci:
name: Drone CI
ejabberd:
display_name: Chat
email:
name: E-Mail
gitea:
name: Gitea
lndhub:
name: LNDHub
display_name: Lightning Network
mastodon:
name: Mastodon
mediawiki:
name: MediaWiki
nostr:
name: Nostr
remotestorage:
name: remoteStorage
display_name: Storage

View File

@ -0,0 +1,25 @@
require 'rails_helper'
describe ServicesHelper do
describe "#service_human_name" do
it "returns the human name when it's configured" do
expect(service_human_name("mastodon")).to eq("Mastodon")
end
it "returns the key when there is no human name" do
expect(service_human_name("ejabberd")).to eq("ejabberd")
end
end
describe "#service_display_name" do
it "returns the display name when it's configured" do
expect(service_display_name("lndhub")).to eq("Lightning Network")
end
it "returns the human name when there is no display name" do
expect(service_display_name("mastodon")).to eq("Mastodon")
end
end
end

View File

@ -44,7 +44,7 @@ RSpec.describe CreateLdapUserJob, type: :job do
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"])
Setting.default_services = ["ejabberd", "discourse"]
perform_enqueued_jobs { job_for_preconfirmed_account }
@ -56,7 +56,7 @@ RSpec.describe CreateLdapUserJob, type: :job do
sn: "halfinney",
uid: "halfinney",
mail: "halfinney@example.com",
serviceEnabled: ["xmpp", "discourse"],
serviceEnabled: ["ejabberd", "discourse"],
userPassword: "remember-remember-the-5th-of-november"
}
)

View File

@ -13,7 +13,7 @@ RSpec.describe XmppExchangeContactsJob, type: :job do
before do
stub_request(:post, "http://xmpp.example.com/api/add_rosteritem")
.to_return(status: 200, body: "", headers: {})
allow_any_instance_of(User).to receive(:services_enabled).and_return(["xmpp"])
allow_any_instance_of(User).to receive(:services_enabled).and_return(["ejabberd"])
end
it "posts add_rosteritem commands to the ejabberd API" do

View File

@ -0,0 +1,25 @@
require 'rails_helper'
RSpec.describe Setting, type: :model do
describe ".available_services" do
before do
Setting.discourse_enabled = true
Setting.ejabberd_enabled = true
Setting.email_enabled = false
Setting.gitea_enabled = false
Setting.lndhub_enabled = true
Setting.mastodon_enabled = true
Setting.mediawiki_enabled = false
Setting.nostr_enabled = false
Setting.remotestorage_enabled = true
end
it "contains all enabled services" do
expect(Setting.available_services).to eq(%w[
discourse ejabberd lndhub mastodon remotestorage
])
end
end
end

View File

@ -78,9 +78,9 @@ RSpec.describe User, type: :model do
it "returns the entries from the LDAP service attribute" do
expect(user).to receive(:ldap_entry).and_return({
uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
services_enabled: ["discourse", "email", "gitea", "wiki", "xmpp"]
services_enabled: ["discourse", "ejabberd", "email", "gitea", "wiki"]
})
expect(user.services_enabled).to eq(["discourse", "email", "gitea", "wiki", "xmpp"])
expect(user.services_enabled).to eq(["discourse", "ejabberd", "email", "gitea", "wiki"])
end
end
@ -88,7 +88,7 @@ RSpec.describe User, type: :model 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"]
services_enabled: ["ejabberd", "gitea"]
})
end
@ -121,9 +121,9 @@ RSpec.describe User, type: :model do
it "adds multiple service to the LDAP entry" do
expect_any_instance_of(LdapService).to receive(:replace_attribute)
.with(dn, :serviceEnabled, ["discourse", "gitea", "wiki", "xmpp"]).and_return(true)
.with(dn, :serviceEnabled, ["discourse", "ejabberd", "gitea", "wiki"]).and_return(true)
user.enable_service([:wiki, :xmpp])
user.enable_service([:ejabberd, :wiki])
end
end
@ -131,7 +131,7 @@ RSpec.describe User, type: :model do
before do
allow(user).to receive(:ldap_entry).and_return({
uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
services_enabled: ["discourse", "gitea", "xmpp"]
services_enabled: ["discourse", "ejabberd", "gitea"]
})
allow(user).to receive(:dn).and_return(dn)
end
@ -140,14 +140,14 @@ RSpec.describe User, type: :model do
expect_any_instance_of(LdapService).to receive(:replace_attribute)
.with(dn, :serviceEnabled, ["discourse", "gitea"]).and_return(true)
user.disable_service(:xmpp)
user.disable_service(:ejabberd)
end
it "removes multiple services from the LDAP entry" do
expect_any_instance_of(LdapService).to receive(:replace_attribute)
.with(dn, :serviceEnabled, ["discourse"]).and_return(true)
user.disable_service([:xmpp, "gitea"])
user.disable_service([:ejabberd, "gitea"])
end
end
@ -178,7 +178,7 @@ RSpec.describe User, type: :model do
after { clear_enqueued_jobs }
it "enables default services" do
expect(user).to receive(:enable_service).with(%w[ discourse gitea mastodon mediawiki remotestorage xmpp ])
expect(user).to receive(:enable_service).with(Setting.default_services)
user.send :devise_after_confirmation
end

View File

@ -44,7 +44,7 @@ RSpec.describe "WebFinger", type: :request 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"]
services_enabled: ["ejabberd"]
})
end
@ -100,7 +100,7 @@ RSpec.describe "WebFinger", type: :request 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"]
services_enabled: ["ejabberd"]
})
end