Compare commits
5 Commits
334b47353e
...
595bb03c5a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
595bb03c5a
|
||
|
|
62cd0eb7d1
|
||
|
|
f19baaf22a
|
||
|
|
23821f9e65
|
||
|
|
a33410eeb4
|
@@ -1,5 +1,5 @@
|
||||
<%= tag.public_send @tag, class: "flex items-center justify-between mb-6 last:mb-0",
|
||||
data: @form.present? ? {
|
||||
data: @form_enabled ? {
|
||||
controller: "settings--toggle",
|
||||
:'settings--toggle-switch-enabled-value' => @enabled.to_s
|
||||
} : nil do %>
|
||||
@@ -11,16 +11,23 @@
|
||||
<%= render FormElements::ToggleComponent.new(
|
||||
enabled: @enabled,
|
||||
input_enabled: @input_enabled,
|
||||
class_names: @form.present? ? "hidden" : nil,
|
||||
class_names: @form_enabled ? "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" %>
|
||||
<% if @form_enabled %>
|
||||
<% if @attribute.present? %>
|
||||
<%= @form.check_box @attribute, {
|
||||
checked: @enabled,
|
||||
data: { :'settings--toggle-target' => "checkbox" }
|
||||
}, "true", "false" %>
|
||||
<% else %>
|
||||
<input name="<%= @field_name %>" type="hidden" value="false" autocomplete="off">
|
||||
<%= check_box_tag @field_name, "true", @enabled, {
|
||||
data: { :'settings--toggle-target' => "checkbox" }
|
||||
} %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
module FormElements
|
||||
class FieldsetToggleComponent < ViewComponent::Base
|
||||
def initialize(form: nil, attribute: nil, tag: "li", enabled: false,
|
||||
input_enabled: true, title:, description:)
|
||||
def initialize(tag: "li", form: nil, attribute: nil, field_name: nil,
|
||||
enabled: false, input_enabled: true, title:, description:)
|
||||
@tag = tag
|
||||
@form = form
|
||||
@attribute = attribute
|
||||
@tag = tag
|
||||
@field_name = field_name
|
||||
@form_enabled = @form.present? || @field_name.present?
|
||||
@enabled = enabled
|
||||
@input_enabled = input_enabled
|
||||
@title = title
|
||||
|
||||
@@ -12,6 +12,13 @@ class SettingsController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
@user = current_user
|
||||
@user.preferences.merge! user_params[:preferences]
|
||||
@user.save!
|
||||
|
||||
redirect_to setting_path(@settings_section), flash: {
|
||||
success: 'Settings saved.'
|
||||
}
|
||||
end
|
||||
|
||||
def reset_password
|
||||
@@ -29,10 +36,17 @@ class SettingsController < ApplicationController
|
||||
|
||||
def set_settings_section
|
||||
@settings_section = params[:section]
|
||||
allowed_sections = [:profile, :account, :notifications]
|
||||
allowed_sections = [:profile, :account, :lightning, :xmpp]
|
||||
|
||||
unless allowed_sections.include?(@settings_section.to_sym)
|
||||
redirect_to setting_path(:profile)
|
||||
end
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(preferences: [
|
||||
lightning: [:notify_sats_received],
|
||||
xmpp: [:exchange_contacts_with_invitees]
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
class User < ApplicationRecord
|
||||
include EmailValidatable
|
||||
|
||||
serialize :preferences, Hash, default: {}
|
||||
|
||||
# Relations
|
||||
has_many :invitations, dependent: :destroy
|
||||
has_one :invitation, inverse_of: :invitee, foreign_key: 'invited_user_id'
|
||||
@@ -55,13 +57,16 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def devise_after_confirmation
|
||||
enable_service %w[ discourse ejabberd gitea mediawiki ]
|
||||
enable_service %w[ discourse gitea mediawiki xmpp ]
|
||||
|
||||
#TODO enable in development when we have easy setup of ejabberd etc.
|
||||
return if Rails.env.development?
|
||||
|
||||
if inviter.present?
|
||||
exchange_xmpp_contact_with_inviter if Setting.ejabberd_enabled?
|
||||
if Setting.ejabberd_enabled? &&
|
||||
inviter.pref_enabled?("xmpp:exchange_contacts_with_invitees")
|
||||
exchange_xmpp_contact_with_inviter
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -133,9 +138,14 @@ class User < ApplicationRecord
|
||||
ldap.delete_attribute(dn,:service)
|
||||
end
|
||||
|
||||
def pref_enabled?(key)
|
||||
value = preferences.dig(*key.split(":"))
|
||||
[true, "true", "enabled", 1].include?(value)
|
||||
end
|
||||
|
||||
def exchange_xmpp_contact_with_inviter
|
||||
return unless inviter.services_enabled.include?("ejabberd") &&
|
||||
services_enabled.include?("ejabberd")
|
||||
return unless inviter.services_enabled.include?("xmpp") &&
|
||||
services_enabled.include?("xmpp")
|
||||
XmppExchangeContactsJob.perform_later(inviter, self.cn, self.ou)
|
||||
end
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
<td>XMPP (ejabberd)</td>
|
||||
<td>
|
||||
<%= render FormElements::ToggleComponent.new(
|
||||
enabled: @services_enabled.include?("ejabberd"),
|
||||
enabled: @services_enabled.include?("xmpp"),
|
||||
input_enabled: false
|
||||
) %>
|
||||
</td>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-circle"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-circle <%= custom_class %>"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 449 B |
27
app/views/settings/_lightning.html.erb
Normal file
27
app/views/settings/_lightning.html.erb
Normal file
@@ -0,0 +1,27 @@
|
||||
<%= form_for @user, url: setting_path(:lightning), html: { :method => :put } do |f| %>
|
||||
<section>
|
||||
<h3>Notifications</h3>
|
||||
<ul role="list">
|
||||
<%= render FormElements::FieldsetComponent.new(
|
||||
positioning: :horizontal,
|
||||
title: "Sats received",
|
||||
description: "Notify me when sats are sent to my Lightning Address"
|
||||
) do %>
|
||||
<% f.fields_for :preferences do |p| %>
|
||||
<% p.fields_for :lightning do |l| %>
|
||||
<%= l.select :notify_sats_received, options_for_select([
|
||||
["off", "off"],
|
||||
["Chat (Jabber)", "xmpp"],
|
||||
["E-Mail", "email"]
|
||||
], selected: @user.preferences.dig('lightning', 'notify_sats_received')) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<p class="pt-6 border-t border-gray-200 text-right">
|
||||
<%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>
|
||||
</p>
|
||||
</section>
|
||||
<% end %>
|
||||
18
app/views/settings/_xmpp.html.erb
Normal file
18
app/views/settings/_xmpp.html.erb
Normal file
@@ -0,0 +1,18 @@
|
||||
<%= form_for @user, url: setting_path(:xmpp), html: { :method => :put } do |f| %>
|
||||
<section>
|
||||
<h3>Contacts</h3>
|
||||
<ul role="list">
|
||||
<%= render FormElements::FieldsetToggleComponent.new(
|
||||
field_name: "user[preferences][xmpp][exchange_contacts_with_invitees]",
|
||||
enabled: @user.pref_enabled?("xmpp:exchange_contacts_with_invitees"),
|
||||
title: "Exchange contacts when invited user signs up",
|
||||
description: "Add each others contacts, so you can chat with them immediately"
|
||||
) %>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<p class="pt-6 border-t border-gray-200 text-right">
|
||||
<%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>
|
||||
</p>
|
||||
</section>
|
||||
<% end %>
|
||||
@@ -6,7 +6,15 @@
|
||||
name: "Account", path: setting_path(:account), icon: "key",
|
||||
active: current_page?(setting_path(:account))
|
||||
) %>
|
||||
<% if Setting.ejabberd_enabled %>
|
||||
<%= render SidenavLinkComponent.new(
|
||||
name: "Notifications", path: setting_path(:notifications), icon: "bell",
|
||||
active: current_page?(setting_path(:notifications))
|
||||
name: "Chat", path: setting_path(:xmpp), icon: "message-circle",
|
||||
active: current_page?(setting_path(:xmpp))
|
||||
) %>
|
||||
<% end %>
|
||||
<% if Setting.lndhub_enabled %>
|
||||
<%= render SidenavLinkComponent.new(
|
||||
name: "Wallet", path: setting_path(:lightning), icon: "zap",
|
||||
active: current_page?(setting_path(:lightning))
|
||||
) %>
|
||||
<% end %>
|
||||
|
||||
5
db/migrate/20230403135149_add_preferences_to_users.rb
Normal file
5
db/migrate/20230403135149_add_preferences_to_users.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddPreferencesToUsers < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :users, :preferences, :text
|
||||
end
|
||||
end
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_03_19_101128) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_04_03_135149) do
|
||||
create_table "donations", force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "amount_sats"
|
||||
@@ -57,8 +57,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_19_101128) do
|
||||
t.text "ln_login_ciphertext"
|
||||
t.text "ln_password_ciphertext"
|
||||
t.string "ln_account"
|
||||
t.string "nostr_pubkey"
|
||||
t.datetime "remember_created_at"
|
||||
t.string "remember_token"
|
||||
t.text "preferences"
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||
end
|
||||
|
||||
@@ -109,7 +109,7 @@ RSpec.describe User, type: :model do
|
||||
|
||||
before do
|
||||
Invitation.create! user: user, invited_user_id: guest.id, used_at: DateTime.now
|
||||
allow_any_instance_of(User).to receive(:services_enabled).and_return(%w[ ejabberd ])
|
||||
allow_any_instance_of(User).to receive(:services_enabled).and_return(%w[ xmpp ])
|
||||
end
|
||||
|
||||
it "enqueues a job to exchange XMPP contacts between inviter and invitee" do
|
||||
@@ -131,14 +131,16 @@ RSpec.describe User, type: :model do
|
||||
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||
|
||||
it "enables default services" do
|
||||
expect(user).to receive(:enable_service).with(%w[ discourse ejabberd gitea mediawiki ])
|
||||
expect(user).to receive(:enable_service).with(%w[ discourse gitea mediawiki xmpp ])
|
||||
user.send(:devise_after_confirmation)
|
||||
end
|
||||
|
||||
context "for invited user with ejabberd enabled" do
|
||||
context "for invited user with xmpp enabled" do
|
||||
let(:guest) { create :user, id: 2, cn: "isaacnewton", ou: "kosmos.org", email: "newt@example.com" }
|
||||
|
||||
before do
|
||||
# TODO remove when defaults are implemented
|
||||
user.update! preferences: {"xmpp" => { "exchange_contacts_with_invitees" => true }}
|
||||
Invitation.create! user: user, invited_user_id: guest.id, used_at: DateTime.now
|
||||
allow_any_instance_of(User).to receive(:enable_service).and_return(true)
|
||||
end
|
||||
@@ -147,6 +149,63 @@ RSpec.describe User, type: :model do
|
||||
expect(guest).to receive(:exchange_xmpp_contact_with_inviter)
|
||||
guest.send(:devise_after_confirmation)
|
||||
end
|
||||
|
||||
context "automatic contact exchange disabled" do
|
||||
before do
|
||||
user.update! preferences: {"xmpp" => { "exchange_contacts_with_invitees" => false }}
|
||||
end
|
||||
|
||||
it "does not exchange XMPP contacts with the inviter" do
|
||||
expect(guest).to_not receive(:exchange_xmpp_contact_with_inviter)
|
||||
guest.send(:devise_after_confirmation)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#pref_enabled?" do
|
||||
describe "preference not set" do
|
||||
# TODO return default value
|
||||
it "returns false" do
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "preference is set" do
|
||||
it "returns true for boolean true" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => true}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(true)
|
||||
end
|
||||
|
||||
it "returns true for string 'true'" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => "true"}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(true)
|
||||
end
|
||||
|
||||
it "returns true for string 'enabled'" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => "enabled"}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(true)
|
||||
end
|
||||
|
||||
it "returns true for integer 1" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => 1}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(true)
|
||||
end
|
||||
|
||||
it "returns false for boolean false" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => false}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(false)
|
||||
end
|
||||
|
||||
it "returns false for string 'false'" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => "false"}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(false)
|
||||
end
|
||||
|
||||
it "returns false for integer 0" do
|
||||
user.preferences.merge!({"lightning" => {"notify_sats_received" => 0}})
|
||||
expect(user.pref_enabled?("lightning:notify_sats_received")).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user