diff --git a/.env.example b/.env.example
index 48b0fec..5550c06 100644
--- a/.env.example
+++ b/.env.example
@@ -1,10 +1,16 @@
LDAP_HOST=localhost
LDAP_PORT=389
LDAP_ADMIN_PASSWORD=passthebutter
-LDAP_SUFFIX="dc=kosmos,dc=org"
+LDAP_SUFFIX='dc=kosmos,dc=org'
WEBHOOKS_ALLOWED_IPS='10.1.1.163'
+DISCOURSE_PUBLIC_URL='https://community.kosmos.org'
+GITEA_PUBLIC_URL='https://gitea.kosmos.org'
+MASTODON_PUBLIC_URL='https://kosmos.social'
+MEDIAWIKI_PUBLIC_URL='https://wiki.kosmos.org'
+
+EJABBERD_ADMIN_URL='https://xmpp.kosmos.org/admin'
EJABBERD_API_URL='https://xmpp.kosmos.org/api'
BTCPAY_API_URL='http://localhost:23001/api/v1'
@@ -18,3 +24,4 @@ LNDHUB_PG_PORT=5432
LNDHUB_PG_DATABASE=lndhub
LNDHUB_PG_USERNAME=lndhub
LNDHUB_PG_PASSWORD=''
+
diff --git a/app/components/form_elements/fieldset_component.html.erb b/app/components/form_elements/fieldset_component.html.erb
new file mode 100644
index 0000000..4d82a56
--- /dev/null
+++ b/app/components/form_elements/fieldset_component.html.erb
@@ -0,0 +1,13 @@
+<%= tag.public_send(@tag, class: "mb-6 last:mb-0") do %>
+
+<% end %>
diff --git a/app/components/form_elements/fieldset_component.rb b/app/components/form_elements/fieldset_component.rb
new file mode 100644
index 0000000..8896137
--- /dev/null
+++ b/app/components/form_elements/fieldset_component.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module FormElements
+ class FieldsetComponent < ViewComponent::Base
+ def initialize(tag: "li", title:, description: nil)
+ @tag = tag
+ @title = title
+ @descripton = description
+ end
+ end
+end
diff --git a/app/components/form_elements/fieldset_toggle_component.html.erb b/app/components/form_elements/fieldset_toggle_component.html.erb
new file mode 100644
index 0000000..504a5b5
--- /dev/null
+++ b/app/components/form_elements/fieldset_toggle_component.html.erb
@@ -0,0 +1,26 @@
+<%= tag.public_send @tag, class: "flex items-center justify-between mb-6 last:mb-0",
+ data: @form.present? ? {
+ controller: "settings--toggle",
+ :'settings--toggle-switch-enabled-value' => @enabled.to_s
+ } : nil do %>
+
+
+
<%= @descripton %>
+
+
+ <%= render FormElements::ToggleComponent.new(
+ enabled: @enabled,
+ input_enabled: @input_enabled,
+ class_names: @form.present? ? "hidden" : nil,
+ data: {
+ :'settings--toggle-target' => "button",
+ action: "settings--toggle#toggleSwitch"
+ }) %>
+ <% if @form.present? %>
+ <%= @form.check_box @attribute, {
+ checked: @enabled,
+ data: { :'settings--toggle-target' => "checkbox" }
+ }, "true", "false" %>
+ <% end %>
+
+<% end %>
diff --git a/app/components/form_elements/fieldset_toggle_component.rb b/app/components/form_elements/fieldset_toggle_component.rb
new file mode 100644
index 0000000..b38bee7
--- /dev/null
+++ b/app/components/form_elements/fieldset_toggle_component.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module FormElements
+ class FieldsetToggleComponent < ViewComponent::Base
+ def initialize(form: nil, attribute: nil, tag: "li", enabled: false,
+ input_enabled: true, title:, description:)
+ @form = form
+ @attribute = attribute
+ @tag = tag
+ @enabled = enabled
+ @input_enabled = input_enabled
+ @title = title
+ @descripton = description
+ @button_text = @enabled ? "Switch off" : "Switch on"
+ end
+ end
+end
diff --git a/app/components/form_elements/toggle_component.html.erb b/app/components/form_elements/toggle_component.html.erb
new file mode 100644
index 0000000..41a6708
--- /dev/null
+++ b/app/components/form_elements/toggle_component.html.erb
@@ -0,0 +1,15 @@
+<%= button_tag type: "button", name: "toggle", data: @data,
+ role: "switch", aria: { checked: @enabled.to_s },
+ disabled: !@input_enabled,
+ class: "#{ @enabled ? 'bg-blue-600' : 'bg-gray-200' }
+ #{ @class_names.present? ? @class_names : '' }
+ relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer
+ rounded-full border-2 border-transparent transition-colors
+ duration-200 ease-in-out focus:outline-none focus:ring-2
+ focus:ring-blue-600 focus:ring-offset-2" do %>
+ <%= @button_text %>
+
+<% end %>
diff --git a/app/components/form_elements/toggle_component.rb b/app/components/form_elements/toggle_component.rb
new file mode 100644
index 0000000..d2f5eae
--- /dev/null
+++ b/app/components/form_elements/toggle_component.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module FormElements
+ class ToggleComponent < ViewComponent::Base
+ def initialize(enabled:, input_enabled: true, data: nil, class_names: nil)
+ @enabled = !!enabled
+ @input_enabled = input_enabled
+ @data = data
+ @class_names = class_names
+ end
+ end
+end
diff --git a/app/components/sidenav_link_component.rb b/app/components/sidenav_link_component.rb
index 999871b..60e58ed 100644
--- a/app/components/sidenav_link_component.rb
+++ b/app/components/sidenav_link_component.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
class SidenavLinkComponent < ViewComponent::Base
- def initialize(name:, path:, icon:, active: false, disabled: false)
+ def initialize(name:, level: 1, path:, icon:, active: false, disabled: false)
@name = name
+ @level = level
@path = path
@icon = icon
@active = active
@@ -12,12 +13,15 @@ class SidenavLinkComponent < ViewComponent::Base
end
def class_names_link(path)
+ px = @level == 1 ? "px-4" : "pl-8 pr-4"
+ base = "#{px} py-2 group border-l-4 flex items-center text-base font-medium"
+
if @active
- "bg-teal-50 border-teal-500 text-teal-700 hover:bg-teal-50 hover:text-teal-700 group border-l-4 px-4 py-2 flex items-center text-base font-medium"
+ "#{base} bg-teal-50 border-teal-500 text-teal-700 hover:bg-teal-50 hover:text-teal-700"
elsif @disabled
- "border-transparent text-gray-400 hover:bg-gray-50 group border-l-4 px-4 py-2 flex items-center text-base font-medium"
+ "#{base} border-transparent text-gray-400 hover:bg-gray-50"
else
- "border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900 group border-l-4 px-4 py-2 flex items-center text-base font-medium"
+ "#{base} border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900"
end
end
diff --git a/app/controllers/admin/settings/registrations_controller.rb b/app/controllers/admin/settings/registrations_controller.rb
index 3f2019e..1d888a5 100644
--- a/app/controllers/admin/settings/registrations_controller.rb
+++ b/app/controllers/admin/settings/registrations_controller.rb
@@ -1,38 +1,12 @@
class Admin::Settings::RegistrationsController < Admin::SettingsController
-
def index
end
def create
- @errors = ActiveModel::Errors.new(Setting.new)
-
- setting_params.keys.each do |key|
- next if setting_params[key].nil?
-
- setting = Setting.new(var: key)
- setting.value = setting_params[key].strip
- unless setting.valid?
- @errors.merge!(setting.errors)
- end
- end
-
- if @errors.any?
- render :index
- end
-
- setting_params.keys.each do |key|
- Setting.send("#{key}=", setting_params[key].strip) unless setting_params[key].nil?
- end
+ update_settings
redirect_to admin_settings_registrations_path, flash: {
success: "Settings saved"
}
end
-
- private
-
- def setting_params
- params.require(:setting).permit(:reserved_usernames)
- end
-
end
diff --git a/app/controllers/admin/settings/services_controller.rb b/app/controllers/admin/settings/services_controller.rb
index ebdad4e..54384c6 100644
--- a/app/controllers/admin/settings/services_controller.rb
+++ b/app/controllers/admin/settings/services_controller.rb
@@ -1,9 +1,19 @@
class Admin::Settings::ServicesController < Admin::SettingsController
-
def index
+ @service = params[:s]
+
+ if @service.blank?
+ redirect_to admin_settings_services_path(params: { s: "discourse" })
+ end
end
- def update
- end
+ def create
+ service = params.require(:service)
+ update_settings
+
+ redirect_to admin_settings_services_path(params: { s: service }), flash: {
+ success: "Settings saved"
+ }
+ end
end
diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb
index 8353f9b..8a168b1 100644
--- a/app/controllers/admin/settings_controller.rb
+++ b/app/controllers/admin/settings_controller.rb
@@ -4,9 +4,37 @@ class Admin::SettingsController < Admin::BaseController
def index
end
+ def update_settings
+ @errors = ActiveModel::Errors.new(Setting.new)
+ changed_keys = []
+
+ setting_params.keys.each do |key|
+ next if setting_params[key].nil? ||
+ (Setting.send(key).to_s == setting_params[key].strip)
+ changed_keys.push(key)
+ setting = Setting.new(var: key)
+ setting.value = setting_params[key].strip
+ unless setting.valid?
+ @errors.merge!(setting.errors)
+ end
+ end
+
+ if @errors.any?
+ render :index and return
+ end
+
+ changed_keys.each do |key|
+ Setting.send("#{key}=", setting_params[key].strip)
+ end
+ end
+
private
- def set_current_section
- @current_section = :settings
- end
+ def set_current_section
+ @current_section = :settings
+ end
+
+ def setting_params
+ params.require(:setting).permit(Setting.editable_keys.map(&:to_sym))
+ end
end
diff --git a/app/javascript/controllers/settings/toggle_controller.js b/app/javascript/controllers/settings/toggle_controller.js
new file mode 100644
index 0000000..587a4e0
--- /dev/null
+++ b/app/javascript/controllers/settings/toggle_controller.js
@@ -0,0 +1,30 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = [ "button", "switch", "checkbox" ]
+ static values = { switchEnabled: Boolean }
+
+ connect () {
+ this.buttonTarget.classList.remove("hidden")
+ this.checkboxTarget.classList.add("hidden")
+ }
+
+ toggleSwitch () {
+ this.switchEnabledValue = !this.switchEnabledValue
+ this.checkboxTarget.checked = this.switchEnabledValue
+
+ if (this.switchEnabledValue) {
+ this.buttonTarget.setAttribute("aria-checked", "true");
+ this.buttonTarget.classList.remove("bg-gray-200")
+ this.buttonTarget.classList.add("bg-blue-600")
+ this.switchTarget.classList.remove("translate-x-0")
+ this.switchTarget.classList.add("translate-x-5")
+ } else {
+ this.buttonTarget.setAttribute("aria-checked", "false");
+ this.buttonTarget.classList.remove("bg-blue-600")
+ this.buttonTarget.classList.add("bg-gray-200")
+ this.switchTarget.classList.remove("translate-x-5")
+ this.switchTarget.classList.add("translate-x-0")
+ }
+ }
+}
diff --git a/app/jobs/xmpp_exchange_contacts_job.rb b/app/jobs/xmpp_exchange_contacts_job.rb
index 01f64f1..50f6fa2 100644
--- a/app/jobs/xmpp_exchange_contacts_job.rb
+++ b/app/jobs/xmpp_exchange_contacts_job.rb
@@ -7,12 +7,12 @@ class XmppExchangeContactsJob < ApplicationJob
ejabberd.add_rosteritem({
"localuser": username, "localhost": domain,
"user": inviter.cn, "host": inviter.ou,
- "nick": inviter.cn, "group": "Friends", "subs": "both"
+ "nick": inviter.cn, "group": Setting.ejabberd_buddy_roster, "subs": "both"
})
ejabberd.add_rosteritem({
"localuser": inviter.cn, "localhost": inviter.ou,
"user": username, "host": domain,
- "nick": username, "group": "Friends", "subs": "both"
+ "nick": username, "group": Setting.ejabberd_buddy_roster, "subs": "both"
})
end
end
diff --git a/app/models/setting.rb b/app/models/setting.rb
index 0bca086..56aa785 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -10,19 +10,84 @@ class Setting < RailsSettings::Base
account accounts donations mail webmaster support
]
+ #
+ # Discourse
+ #
+
+ field :discourse_public_url, type: :string, readonly: true,
+ default: ENV["DISCOURSE_PUBLIC_URL"].presence
+
+ field :discourse_enabled, type: :boolean,
+ default: (ENV["DISCOURSE_PUBLIC_URL"].present?.to_s || false)
+
+ #
+ # ejabberd
+ #
+
+ field :ejabberd_enabled, type: :boolean,
+ default: (ENV["EJABBERD_API_URL"].present?.to_s || false)
+
+ field :ejabberd_api_url, type: :string, readonly: true,
+ default: ENV["EJABBERD_API_URL"].presence
+
+ field :ejabberd_admin_url, type: :string, readonly: true,
+ default: ENV["EJABBERD_ADMIN_URL"].presence
+
+ field :ejabberd_buddy_roster, type: :string,
+ default: "Buddies"
+
+ #
+ # Gitea
+ #
+
+ field :gitea_public_url, type: :string, readonly: true,
+ default: ENV["GITEA_PUBLIC_URL"].presence
+
+ field :gitea_enabled, type: :boolean,
+ default: (ENV["GITEA_PUBLIC_URL"].present?.to_s || false)
+
#
# Lightning Network
#
+ field :lndhub_api_url, type: :string, readonly: true,
+ default: ENV["LNDHUB_API_URL"].presence
+
field :lndhub_enabled, type: :boolean,
default: (ENV["LNDHUB_API_URL"].present?.to_s || false)
field :lndhub_admin_enabled, type: :boolean,
default: (ENV["LNDHUB_ADMIN_UI"] || false)
- field :lndhub_public_key, type: :string,
+ field :lndhub_public_key, type: :string, readonly: true,
default: (ENV["LNDHUB_PUBLIC_KEY"] || "")
field :lndhub_keysend_enabled, type: :boolean,
default: -> { self.lndhub_public_key.present?.to_s || false }
+
+ #
+ # Mastodon
+ #
+
+ field :mastodon_public_url, type: :string, readonly: true,
+ default: ENV["MASTODON_PUBLIC_URL"].presence
+
+ field :mastodon_enabled, type: :boolean,
+ default: (ENV["MASTODON_PUBLIC_URL"].present?.to_s || false)
+
+ #
+ # MediaWiki
+ #
+
+ field :mediawiki_public_url, type: :string, readonly: true,
+ default: ENV["MEDIAWIKI_PUBLIC_URL"].presence
+
+ field :mediawiki_enabled, type: :boolean,
+ default: (ENV["MEDIAWIKI_PUBLIC_URL"].present?.to_s || false)
+
+ #
+ # Nostr
+ #
+
+ field :nostr_enabled, type: :boolean, default: true
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 31599c4..5734369 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -53,7 +53,7 @@ class User < ApplicationRecord
end
def devise_after_confirmation
- enable_service %w[discourse gitea wiki xmpp]
+ enable_service %w[discourse gitea mediawiki ejabberd]
end
def reset_password(new_password, new_password_confirmation)
diff --git a/app/services/create_account.rb b/app/services/create_account.rb
index c5cb69a..bc05e50 100644
--- a/app/services/create_account.rb
+++ b/app/services/create_account.rb
@@ -15,7 +15,7 @@ class CreateAccount < ApplicationService
if @invitation.present?
update_invitation(user.id)
- exchange_xmpp_contacts
+ exchange_xmpp_contacts if Setting.ejabberd_enabled
end
end
diff --git a/app/views/admin/settings/_errors.html.erb b/app/views/admin/settings/_errors.html.erb
new file mode 100644
index 0000000..84bd2a6
--- /dev/null
+++ b/app/views/admin/settings/_errors.html.erb
@@ -0,0 +1,7 @@
+
+
+ <% errors.full_messages.each do |msg| %>
+ - <%= msg %>
+ <% end %>
+
+
diff --git a/app/views/admin/settings/registrations/index.html.erb b/app/views/admin/settings/registrations/index.html.erb
index 68e1827..90b67af 100644
--- a/app/views/admin/settings/registrations/index.html.erb
+++ b/app/views/admin/settings/registrations/index.html.erb
@@ -4,14 +4,9 @@
<%= form_for(Setting.new, url: admin_settings_registrations_path) do |f| %>
Registrations
+
<% if @errors && @errors.any? %>
-
-
- <% @errors.full_messages.each do |msg| %>
- - <%= msg %>
- <% end %>
-
-
+ <%= render partial: "admin/settings/errors", locals: { errors: @errors } %>
<% end %>
-
+
<%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>
diff --git a/app/views/admin/settings/services/_discourse.html.erb b/app/views/admin/settings/services/_discourse.html.erb
new file mode 100644
index 0000000..498dd5f
--- /dev/null
+++ b/app/views/admin/settings/services/_discourse.html.erb
@@ -0,0 +1,17 @@
+Discourse
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :discourse_enabled,
+ enabled: Setting.discourse_enabled?,
+ title: "Enable Discourse integration",
+ description: "Discourse configuration present and features enabled"
+ ) %>
+ <% if Setting.discourse_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
+ <%= f.text_field :discourse_public_url,
+ value: Setting.discourse_public_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <% end %>
+
diff --git a/app/views/admin/settings/services/_ejabberd.html.erb b/app/views/admin/settings/services/_ejabberd.html.erb
new file mode 100644
index 0000000..46e3ca6
--- /dev/null
+++ b/app/views/admin/settings/services/_ejabberd.html.erb
@@ -0,0 +1,30 @@
+ejabberd (XMPP)
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :ejabberd_enabled,
+ enabled: Setting.ejabberd_enabled?,
+ title: "Enable ejabberd integration",
+ description: "ejabberd configuration present and features enabled"
+ ) %>
+ <% if Setting.ejabberd_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "API URL") do %>
+ <%= f.text_field :ejabberd_api_url,
+ value: Setting.ejabberd_api_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <%= render FormElements::FieldsetComponent.new(title: "Admin URL") do %>
+ <%= f.text_field :ejabberd_admin_url,
+ value: Setting.ejabberd_admin_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <%= render FormElements::FieldsetComponent.new(
+ title: "Contact roster name",
+ description: "Used when exchanging contacts after signup from invitation"
+ ) do %>
+ <%= f.text_field :ejabberd_buddy_roster,
+ value: Setting.ejabberd_buddy_roster,
+ class: "w-full" %>
+ <% end %>
+ <% end %>
+
diff --git a/app/views/admin/settings/services/_gitea.html.erb b/app/views/admin/settings/services/_gitea.html.erb
new file mode 100644
index 0000000..7c0238d
--- /dev/null
+++ b/app/views/admin/settings/services/_gitea.html.erb
@@ -0,0 +1,17 @@
+Gitea
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :gitea_enabled,
+ enabled: Setting.gitea_enabled?,
+ title: "Enable Gitea integration",
+ description: "Gitea configuration present and features enabled"
+ ) %>
+ <% if Setting.gitea_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
+ <%= f.text_field :gitea_public_url,
+ value: Setting.gitea_public_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <% end %>
+
diff --git a/app/views/admin/settings/services/_lndhub.html.erb b/app/views/admin/settings/services/_lndhub.html.erb
new file mode 100644
index 0000000..e9d3c2e
--- /dev/null
+++ b/app/views/admin/settings/services/_lndhub.html.erb
@@ -0,0 +1,38 @@
+Lightning Network
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :lndhub_enabled,
+ enabled: Setting.lndhub_enabled?,
+ title: "Enable LNDHub integration",
+ description: "LNDHub configuration present and wallet features enabled"
+ ) %>
+ <% if Setting.lndhub_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "API URL") do %>
+ <%= f.text_field :lndhub_api_url,
+ value: Setting.lndhub_api_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <% end %>
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :lndhub_admin_enabled,
+ enabled: Setting.lndhub_admin_enabled?,
+ title: "Enable LNDHub admin panel",
+ description: "LNDHub database configuration present and admin panel enabled"
+ ) %>
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :lndhub_keysend_enabled,
+ enabled: Setting.lndhub_keysend_enabled?,
+ title: "Enable keysend payments",
+ description: "Allow users to receive invoice-less payments to their Lightning Address"
+ ) %>
+ <% if Setting.lndhub_keysend_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "Public key", description: "The public key of the Lightning node used by LNDHub") do %>
+ <%= f.text_field :lndhub_public_key,
+ value: Setting.lndhub_public_key,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <% end %>
+
diff --git a/app/views/admin/settings/services/_mastodon.html.erb b/app/views/admin/settings/services/_mastodon.html.erb
new file mode 100644
index 0000000..1270860
--- /dev/null
+++ b/app/views/admin/settings/services/_mastodon.html.erb
@@ -0,0 +1,17 @@
+Mastodon
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :mastodon_enabled,
+ enabled: Setting.mastodon_enabled?,
+ title: "Enable Mastodon integration",
+ description: "Mastodon configuration present and features enabled"
+ ) %>
+ <% if Setting.mastodon_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
+ <%= f.text_field :mastodon_public_url,
+ value: Setting.mastodon_public_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <% end %>
+
diff --git a/app/views/admin/settings/services/_mediawiki.html.erb b/app/views/admin/settings/services/_mediawiki.html.erb
new file mode 100644
index 0000000..2456f20
--- /dev/null
+++ b/app/views/admin/settings/services/_mediawiki.html.erb
@@ -0,0 +1,17 @@
+MediaWiki
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :mediawiki_enabled,
+ enabled: Setting.mediawiki_enabled?,
+ title: "Enable MediaWiki integration",
+ description: "MediaWiki configuration present and features enabled"
+ ) %>
+ <% if Setting.mediawiki_enabled? %>
+ <%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
+ <%= f.text_field :mediawiki_public_url,
+ value: Setting.mediawiki_public_url,
+ class: "w-full", disabled: true %>
+ <% end %>
+ <% end %>
+
diff --git a/app/views/admin/settings/services/_nostr.html.erb b/app/views/admin/settings/services/_nostr.html.erb
new file mode 100644
index 0000000..664d089
--- /dev/null
+++ b/app/views/admin/settings/services/_nostr.html.erb
@@ -0,0 +1,10 @@
+Nostr
+
+ <%= render FormElements::FieldsetToggleComponent.new(
+ form: f,
+ attribute: :nostr_enabled,
+ enabled: Setting.nostr_enabled?,
+ title: "Enable Nostr integration (experimental)",
+ description: "Allow adding nostr pubkeys and resolve user addresses via NIP-05"
+ ) %>
+
diff --git a/app/views/admin/settings/services/index.html.erb b/app/views/admin/settings/services/index.html.erb
index a4a4fec..58360dd 100644
--- a/app/views/admin/settings/services/index.html.erb
+++ b/app/views/admin/settings/services/index.html.erb
@@ -1,39 +1,23 @@
<%= render HeaderComponent.new(title: "Settings") %>
<%= render MainWithSidenavComponent.new(sidenav_partial: 'shared/admin_sidenav_settings') do %>
-
- Lightning Network
- <%= form_for(Setting.new, url: admin_settings_services_path) do |f| %>
- <% if @errors && @errors.any? %>
-
-
- <% @errors.full_messages.each do |msg| %>
- - <%= msg %>
- <% end %>
-
-
- <% end %>
+ <%= form_for(Setting.new, url: admin_settings_services_path) do |f| %>
+ <%= hidden_field_tag :service, @service %>
-
- -
-
-
-
LNDHub configuration present and wallet features enabled
-
- <%= f.check_box :lndhub_enabled, checked: Setting.lndhub_enabled?,
- disabled: true,
- class: "relative ml-4 inline-flex flex-shrink-0" %>
-
- -
-
-
-
LNDHub database configuration present and admin panel enabled
-
- <%= f.check_box :lndhub_admin_enabled, checked: Setting.lndhub_admin_enabled?,
- disabled: true,
- class: "relative ml-4 inline-flex flex-shrink-0" %>
-
-
+ <% if @errors && @errors.any? %>
+
+ <%= render partial: "admin/settings/errors", locals: { errors: @errors } %>
+
<% end %>
-
+
+
+ <%= render partial: @service, locals: { f: f } %>
+
+
+
+
+ <%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>
+
+
+ <% end %>
<% end %>
diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb
index 4679e6f..5d89827 100644
--- a/app/views/admin/users/show.html.erb
+++ b/app/views/admin/users/show.html.erb
@@ -65,28 +65,87 @@
Services
-
+
+
+
+ Name |
+ Enabled |
+ |
+
+
+ <% if Setting.discourse_enabled %>
Discourse |
- <%= check_box_tag 'service_discourse', 'enabled', @services_enabled.include?("discourse"), disabled: true %> |
+
+ <%= render FormElements::ToggleComponent.new(
+ enabled: @services_enabled.include?("discourse"),
+ input_enabled: false
+ ) %>
+ |
+
+ <%= link_to "Open profile", "#{Setting.discourse_public_url}/u/#{@user.cn}/summary", class: "btn-sm btn-gray" %>
+ |
+ <% end %>
+ <% if Setting.gitea_enabled %>
Gitea |
- <%= check_box_tag 'service_gitea', 'enabled', @services_enabled.include?("gitea"), disabled: true %> |
+
+ <%= render FormElements::ToggleComponent.new(
+ enabled: @services_enabled.include?("gitea"),
+ input_enabled: false
+ ) %>
+ |
+
+ <%= link_to "Open profile", "#{Setting.gitea_public_url}/#{@user.cn}", class: "btn-sm btn-gray" %>
+ |
+ <% end %>
+ <% if Setting.mastodon_enabled %>
Mastodon |
- <%= check_box_tag 'service_mastodon', 'enabled', @services_enabled.include?("mastodon"), disabled: true %> |
+
+ <%= render FormElements::ToggleComponent.new(
+ enabled: @services_enabled.include?("mastodon"),
+ input_enabled: false
+ ) %>
+ |
+
+ <%= link_to "Open profile", "#{Setting.mastodon_public_url}/@#{@user.cn}", class: "btn-sm btn-gray" %>
+ |
+ <% end %>
+ <% if Setting.mediawiki_enabled %>
- Wiki |
- <%= check_box_tag 'service_wiki', 'enabled', @services_enabled.include?("wiki"), disabled: true %> |
+ MediaWiki |
+
+ <%= render FormElements::ToggleComponent.new(
+ enabled: @services_enabled.include?("mediawiki"),
+ input_enabled: false
+ ) %>
+ |
+
+ <%= link_to "Open profile", "#{Setting.mediawiki_public_url}/Special:Contributions/#{@user.cn}", class: "btn-sm btn-gray" %>
+ |
+ <% end %>
+ <% if Setting.ejabberd_enabled %>
- XMPP |
- <%= check_box_tag 'service_xmpp', 'enabled', @services_enabled.include?("xmpp"), disabled: true %> |
+ XMPP (ejabberd) |
+
+ <%= render FormElements::ToggleComponent.new(
+ enabled: @services_enabled.include?("ejabberd"),
+ input_enabled: false
+ ) %>
+ |
+
+ <% if Setting.ejabberd_admin_url.present? %>
+ <%= link_to "Open profile", "#{Setting.ejabberd_admin_url}/server/#{@user.ou}/user/#{@user.cn}/", class: "btn-sm btn-gray" %>
+ <% end %>
+ |
+ <% end %>
diff --git a/app/views/icons/_x.html.erb b/app/views/icons/_x.html.erb
index 7d5875c..d85f208 100644
--- a/app/views/icons/_x.html.erb
+++ b/app/views/icons/_x.html.erb
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/app/views/shared/_admin_sidenav_settings.html.erb b/app/views/shared/_admin_sidenav_settings.html.erb
index d675242..387cd9b 100644
--- a/app/views/shared/_admin_sidenav_settings.html.erb
+++ b/app/views/shared/_admin_sidenav_settings.html.erb
@@ -6,6 +6,9 @@
name: "Services", path: admin_settings_services_path, icon: "grid",
active: current_page?(admin_settings_services_path)
) %>
+<% if current_page?(admin_settings_services_path) %>
+ <%= render partial: "shared/admin_sidenav_settings_services" %>
+<% end %>
<%= render SidenavLinkComponent.new(
name: "Security", path: "#", icon: "shield", disabled: true
) %>
diff --git a/app/views/shared/_admin_sidenav_settings_services.html.erb b/app/views/shared/_admin_sidenav_settings_services.html.erb
new file mode 100644
index 0000000..c897b6d
--- /dev/null
+++ b/app/views/shared/_admin_sidenav_settings_services.html.erb
@@ -0,0 +1,49 @@
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "Discourse",
+ path: admin_settings_services_path(params: { s: "discourse" }),
+ icon: Setting.discourse_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "discourse" })),
+) %>
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "ejabberd",
+ path: admin_settings_services_path(params: { s: "ejabberd" }),
+ icon: Setting.ejabberd_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "ejabberd" })),
+) %>
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "Gitea",
+ path: admin_settings_services_path(params: { s: "gitea" }),
+ icon: Setting.gitea_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "gitea" })),
+) %>
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "LNDHub",
+ path: admin_settings_services_path(params: { s: "lndhub" }),
+ icon: Setting.lndhub_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "lndhub" })),
+) %>
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "Mastodon",
+ path: admin_settings_services_path(params: { s: "mastodon" }),
+ icon: Setting.mastodon_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "mastodon" })),
+) %>
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "MediaWiki",
+ path: admin_settings_services_path(params: { s: "mediawiki" }),
+ icon: Setting.mediawiki_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "mediawiki" })),
+) %>
+<%= render SidenavLinkComponent.new(
+ level: 2,
+ name: "Nostr",
+ path: admin_settings_services_path(params: { s: "nostr" }),
+ icon: Setting.nostr_enabled? ? "check" : "x",
+ active: current_page?(admin_settings_services_path(params: { s: "nostr" })),
+) %>
diff --git a/spec/features/admin/settings_spec.rb b/spec/features/admin/settings_spec.rb
index bd586c7..7a394ba 100644
--- a/spec/features/admin/settings_spec.rb
+++ b/spec/features/admin/settings_spec.rb
@@ -18,4 +18,33 @@ RSpec.describe 'Admin/global settings', type: :feature do
click_button "Save"
expect(Setting.reserved_usernames).to eq(['Kosmos', 'Kredits'])
end
+
+ describe "Service settings" do
+ scenario "Opening service settings shows page for first service" do
+ visit admin_settings_services_path
+
+ expect(current_url).to eq(admin_settings_services_url(params: { s: "discourse" }))
+ end
+
+ scenario "View ejabberd settings" do
+ visit admin_settings_services_path(params: { s: "ejabberd" })
+
+ expect(page).to have_content("Enable ejabberd integration")
+ expect(page).to have_field("API URL",
+ with: "http://xmpp.example.com/api",
+ disabled: true)
+ end
+
+ scenario "Disable ejabberd integration" do
+ visit admin_settings_services_path(params: { s: "ejabberd" })
+ expect(page).to have_checked_field("setting[ejabberd_enabled]")
+
+ uncheck "setting[ejabberd_enabled]"
+ click_button "Save"
+
+ expect(current_url).to eq(admin_settings_services_url(params: { s: "ejabberd" }))
+ expect(page).to_not have_checked_field("setting[ejabberd_enabled]")
+ expect(page).to_not have_field("API URL", disabled: true)
+ end
+ end
end
diff --git a/spec/jobs/xmpp_exchange_contacts_job_spec.rb b/spec/jobs/xmpp_exchange_contacts_job_spec.rb
index 0064b69..f7732dc 100644
--- a/spec/jobs/xmpp_exchange_contacts_job_spec.rb
+++ b/spec/jobs/xmpp_exchange_contacts_job_spec.rb
@@ -17,9 +17,9 @@ RSpec.describe XmppExchangeContactsJob, type: :job do
perform_enqueued_jobs { job }
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem")
- .with { |req| req.body == '{"localuser":"isaacnewton","localhost":"kosmos.org","user":"willherschel","host":"kosmos.org","nick":"willherschel","group":"Friends","subs":"both"}' }
+ .with { |req| req.body == '{"localuser":"isaacnewton","localhost":"kosmos.org","user":"willherschel","host":"kosmos.org","nick":"willherschel","group":"Buddies","subs":"both"}' }
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem")
- .with { |req| req.body == '{"localuser":"willherschel","localhost":"kosmos.org","user":"isaacnewton","host":"kosmos.org","nick":"isaacnewton","group":"Friends","subs":"both"}' }
+ .with { |req| req.body == '{"localuser":"willherschel","localhost":"kosmos.org","user":"isaacnewton","host":"kosmos.org","nick":"isaacnewton","group":"Buddies","subs":"both"}' }
end
after do