require 'securerandom' class SettingsController < ApplicationController before_action :authenticate_user! before_action :set_main_nav_section before_action :set_settings_section, only: [:show, :update, :update_email] before_action :set_user, only: [:show, :update, :update_email] def index redirect_to setting_path(:profile) end def show if @settings_section == "experiments" session[:shared_secret] ||= SecureRandom.base64(12) end end def update @user.preferences.merge!(user_params[:preferences] || {}) @user.display_name = user_params[:display_name] current_avatar_checksum = @user.avatar.attached? ? @user.avatar.blob.checksum : nil @user.avatar = user_params[:avatar] if user_params[:avatar].present? if @user.save if @user.display_name && (@user.display_name != @user.ldap_entry[:display_name]) LdapManager::UpdateDisplayName.call(@user.dn, @user.display_name) end if @user.avatar.attached? && (@user.avatar.blob.checksum != current_avatar_checksum) LdapManager::UpdateAvatar.call(@user.dn, @user.avatar_base64) end redirect_to setting_path(@settings_section), flash: { success: 'Settings saved.' } else @validation_errors = @user.errors render :show, status: :unprocessable_entity end end def update_email if @user.valid_ldap_authentication?(email_params[:current_password]) if @user.update email: email_params[:email] redirect_to setting_path(:account), flash: { notice: 'Please confirm your new address using the confirmation link we just sent you.' } else @validation_errors = @user.errors render :show, status: :unprocessable_entity end else redirect_to setting_path(:account), flash: { error: 'Password did not match your current password. Try again.' } end end def reset_password current_user.send_reset_password_instructions sign_out current_user msg = "We have sent you an email with a link to reset your password." redirect_to check_your_email_path, notice: msg end def set_nostr_pubkey signed_event = nostr_event_params[:signed_event].to_h.symbolize_keys is_valid_id = NostrManager::ValidateId.call(signed_event) is_valid_sig = NostrManager::VerifySignature.call(signed_event) is_correct_content = signed_event[:content] == "Connect my public key to #{current_user.address} (confirmation #{session[:shared_secret]})" unless is_valid_id && is_valid_sig && is_correct_content flash[:alert] = "Public key could not be verified" http_status :unprocessable_entity and return end pubkey_taken = User.all_except(current_user).where( ou: current_user.ou, nostr_pubkey: signed_event[:pubkey] ).any? if pubkey_taken flash[:alert] = "Public key already in use for a different account" http_status :unprocessable_entity and return end current_user.update! nostr_pubkey: signed_event[:pubkey] session[:shared_secret] = nil flash[:success] = "Public key verification successful" http_status :ok rescue flash[:alert] = "Public key could not be verified" http_status :unprocessable_entity and return end # DELETE /settings/nostr_pubkey def remove_nostr_pubkey current_user.update! nostr_pubkey: nil redirect_to setting_path(:experiments), flash: { success: 'Public key removed from account' } end private def set_main_nav_section @current_section = :settings end def set_settings_section @settings_section = params[:section] allowed_sections = [:profile, :account, :lightning, :xmpp, :experiments] unless allowed_sections.include?(@settings_section.to_sym) redirect_to setting_path(:profile) end end def set_user @user = current_user end def user_params params.require(:user).permit(:display_name, :avatar, preferences: [ :lightning_notify_sats_received, :xmpp_exchange_contacts_with_invitees ]) end def email_params params.require(:user).permit(:email, :current_password) end def nostr_event_params params.permit(signed_event: [ :id, :pubkey, :created_at, :kind, :tags, :content, :sig ]) end end