Move remaining credentials from Rails credentials store to ENV #221
							
								
								
									
										14
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								.env.example
									
									
									
									
									
								
							@ -1,6 +1,14 @@
 | 
			
		||||
# PRIMARY_DOMAIN=kosmos.org
 | 
			
		||||
# AKKOUNTS_DOMAIN=accounts.example.com
 | 
			
		||||
 | 
			
		||||
# Generate this using `rails secret`
 | 
			
		||||
# SECRET_KEY_BASE=
 | 
			
		||||
 | 
			
		||||
# Generate these using `rails db:encryption:init`
 | 
			
		||||
# (Optional, needed for LndHub integration)
 | 
			
		||||
# ENCRYPTION_PRIMARY_KEY=
 | 
			
		||||
# ENCRYPTION_KEY_DERIVATION_SALT=
 | 
			
		||||
 | 
			
		||||
# The default backend is SQLite
 | 
			
		||||
# DB_ADAPTER=postgresql
 | 
			
		||||
# PG_HOST=localhost
 | 
			
		||||
@ -29,8 +37,12 @@
 | 
			
		||||
 | 
			
		||||
# LDAP_HOST=localhost
 | 
			
		||||
# LDAP_PORT=389
 | 
			
		||||
# LDAP_USE_TLS=false
 | 
			
		||||
# LDAP_UID_ATTR=cn
 | 
			
		||||
# LDAP_BASE="ou=kosmos.org,cn=users,dc=kosmos,dc=org"
 | 
			
		||||
# LDAP_ADMIN_USER="cn=Directory Manager"
 | 
			
		||||
# LDAP_ADMIN_PASSWORD=passthebutter
 | 
			
		||||
# LDAP_SUFFIX='dc=kosmos,dc=org'
 | 
			
		||||
# LDAP_SUFFIX="dc=kosmos,dc=org"
 | 
			
		||||
 | 
			
		||||
# REDIS_URL='redis://localhost:6379/1'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,9 @@
 | 
			
		||||
PRIMARY_DOMAIN=kosmos.org
 | 
			
		||||
AKKOUNTS_DOMAIN=accounts.kosmos.org
 | 
			
		||||
 | 
			
		||||
ENCRYPTION_PRIMARY_KEY=YhNLBgCFMAzw5dV3gISxnGrhNDMQwRdn
 | 
			
		||||
ENCRYPTION_KEY_DERIVATION_SALT=h28g16MRZ1sghF2jTCos1DiLZXUswinR
 | 
			
		||||
 | 
			
		||||
REDIS_URL='redis://localhost:6379/0'
 | 
			
		||||
 | 
			
		||||
BTCPAY_PUBLIC_URL='https://btcpay.example.com'
 | 
			
		||||
@ -21,7 +24,8 @@ LNDHUB_PUBLIC_KEY='024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de55648
 | 
			
		||||
NOSTR_PRIVATE_KEY='7c3ef7e448505f0615137af38569d01807d3b05b5005d5ecf8aaafcd40323cea'
 | 
			
		||||
NOSTR_PUBLIC_KEY='bdd76ce2934b2f591f9fad2ebe9da18f20d2921de527494ba00eeaa0a0efadcf'
 | 
			
		||||
 | 
			
		||||
RS_STORAGE_URL='https://storage.kosmos.org'
 | 
			
		||||
RS_REDIS_URL='redis://localhost:6379/1'
 | 
			
		||||
RS_STORAGE_URL='https://storage.kosmos.org'
 | 
			
		||||
RS_AKKOUNTS_DOMAIN=localhost
 | 
			
		||||
 | 
			
		||||
WEBHOOKS_ALLOWED_IPS='10.1.1.23'
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Gemfile
									
									
									
									
									
								
							@ -25,9 +25,6 @@ gem 'bcrypt', '~> 3.1'
 | 
			
		||||
# Configuration
 | 
			
		||||
gem 'dotenv-rails'
 | 
			
		||||
 | 
			
		||||
# Security
 | 
			
		||||
gem 'lockbox'
 | 
			
		||||
 | 
			
		||||
# Authentication
 | 
			
		||||
gem 'warden'
 | 
			
		||||
gem 'devise', '~> 4.9.0'
 | 
			
		||||
 | 
			
		||||
@ -244,7 +244,6 @@ GEM
 | 
			
		||||
      rb-inotify (~> 0.9, >= 0.9.10)
 | 
			
		||||
    lnurl (1.1.1)
 | 
			
		||||
      bech32 (~> 1.1)
 | 
			
		||||
    lockbox (2.0.1)
 | 
			
		||||
    logger (1.7.0)
 | 
			
		||||
    loofah (2.24.0)
 | 
			
		||||
      crass (~> 1.0.2)
 | 
			
		||||
@ -551,7 +550,6 @@ DEPENDENCIES
 | 
			
		||||
  letter_opener_web
 | 
			
		||||
  listen (~> 3.2)
 | 
			
		||||
  lnurl
 | 
			
		||||
  lockbox
 | 
			
		||||
  manifique (~> 1.1.0)
 | 
			
		||||
  mission_control-jobs
 | 
			
		||||
  net-ldap
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ class Admin::LightningController < Admin::BaseController
 | 
			
		||||
  def index
 | 
			
		||||
    @current_section = :lightning
 | 
			
		||||
 | 
			
		||||
    @users = User.pluck(:cn, :ou, :ln_account)
 | 
			
		||||
    @users = User.pluck(:cn, :ou, :lndhub_username)
 | 
			
		||||
    @accounts = LndhubAccount.with_balances.order(balance: :desc).to_a
 | 
			
		||||
 | 
			
		||||
    @ln = {}
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ class LnurlpayController < ApplicationController
 | 
			
		||||
      pubkey: Setting.lndhub_public_key,
 | 
			
		||||
      customData: [{
 | 
			
		||||
        customKey: "696969",
 | 
			
		||||
        customValue: @user.ln_account
 | 
			
		||||
        customValue: @user.lndhub_username
 | 
			
		||||
      }]
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ class Services::LightningController < ApplicationController
 | 
			
		||||
  before_action :lndhub_fetch_balance
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    @wallet_setup_url = "lndhub://#{current_user.ln_account}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}"
 | 
			
		||||
    @wallet_setup_url = "lndhub://#{current_user.lndhub_username}:#{current_user.lndhub_password}@#{ENV['LNDHUB_PUBLIC_URL']}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def transactions
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ class WebhooksController < ApplicationController
 | 
			
		||||
  before_action :process_payload
 | 
			
		||||
 | 
			
		||||
  def lndhub
 | 
			
		||||
    @user = User.find_by!(ln_account: @payload[:user_login])
 | 
			
		||||
    @user = User.find_by!(lndhub_username: @payload[:user_login])
 | 
			
		||||
 | 
			
		||||
    if @zap = @user.zaps.find_by(payment_request: @payload[:payment_request])
 | 
			
		||||
      settled_at = Time.parse(@payload[:settled_at])
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,12 @@ class CreateLndhubAccountJob < ApplicationJob
 | 
			
		||||
  queue_as :default
 | 
			
		||||
 | 
			
		||||
  def perform(user)
 | 
			
		||||
    return if user.ln_account.present? && user.ln_password.present?
 | 
			
		||||
    return if user.lndhub_username.present? && user.lndhub_password.present?
 | 
			
		||||
 | 
			
		||||
    lndhub = LndhubV2.new
 | 
			
		||||
    credentials = lndhub.create_account
 | 
			
		||||
 | 
			
		||||
    user.update! ln_account: credentials["login"],
 | 
			
		||||
                 ln_password: credentials["password"]
 | 
			
		||||
    user.update! lndhub_username: credentials["login"],
 | 
			
		||||
                 lndhub_password: credentials["password"]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ class LndhubUser < LndhubBase
 | 
			
		||||
                      foreign_key: "user_id"
 | 
			
		||||
 | 
			
		||||
  belongs_to :user, class_name: "User",
 | 
			
		||||
                    primary_key: "ln_account",
 | 
			
		||||
                    primary_key: "lndhub_username",
 | 
			
		||||
                    foreign_key: "login"
 | 
			
		||||
 | 
			
		||||
  def balance
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ class User < ApplicationRecord
 | 
			
		||||
  has_many :zaps
 | 
			
		||||
 | 
			
		||||
  has_one  :lndhub_user, class_name: "LndhubUser", inverse_of: "user",
 | 
			
		||||
                         primary_key: "ln_account", foreign_key: "login"
 | 
			
		||||
                         primary_key: "lndhub_username", foreign_key: "login"
 | 
			
		||||
 | 
			
		||||
  has_many :accounts, through: :lndhub_user
 | 
			
		||||
 | 
			
		||||
@ -66,7 +66,7 @@ class User < ApplicationRecord
 | 
			
		||||
  # Encrypted database columns
 | 
			
		||||
  #
 | 
			
		||||
 | 
			
		||||
  has_encrypted :ln_login, :ln_password
 | 
			
		||||
  encrypts :lndhub_password
 | 
			
		||||
 | 
			
		||||
  # Include default devise modules. Others available are:
 | 
			
		||||
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,10 @@ class Lndhub < ApplicationService
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authenticate(user)
 | 
			
		||||
    credentials = post "auth?type=auth", { login: user.ln_account, password: user.ln_password }
 | 
			
		||||
    credentials = post "auth?type=auth", {
 | 
			
		||||
      login: user.lndhub_username,
 | 
			
		||||
      password: user.lndhub_password
 | 
			
		||||
    }
 | 
			
		||||
    self.auth_token = credentials["access_token"]
 | 
			
		||||
    self.auth_token
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@ -276,7 +276,7 @@
 | 
			
		||||
      </thead>
 | 
			
		||||
      <tbody>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <td><%= @user.ln_account %></td>
 | 
			
		||||
          <td><%= @user.lndhub_username %></td>
 | 
			
		||||
          <td><%= number_with_delimiter @lndhub_user.balance %> sats</td>
 | 
			
		||||
          <td><%= number_with_delimiter @lndhub_user.sum_incoming %> sats</td>
 | 
			
		||||
          <td><%= number_with_delimiter @lndhub_user.sum_outgoing %> sats</td>
 | 
			
		||||
@ -285,7 +285,7 @@
 | 
			
		||||
      </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
    <% else %>
 | 
			
		||||
      <p>No LndHub user found for account <strong class="font-mono"><%= @user.ln_account %></strong>.
 | 
			
		||||
      <p>No LndHub user found for account <strong class="font-mono"><%= @user.lndhub_username %></strong>.
 | 
			
		||||
    <% end %>
 | 
			
		||||
  </section>
 | 
			
		||||
  <% end %>
 | 
			
		||||
 | 
			
		||||
@ -54,5 +54,8 @@ module Akkounts
 | 
			
		||||
 | 
			
		||||
    # The default includes webp, which requires webp support everywhere
 | 
			
		||||
    config.active_storage.web_image_content_types = %w[image/png image/jpeg image/gif]
 | 
			
		||||
 | 
			
		||||
    config.active_record.encryption.primary_key = ENV["ENCRYPTION_PRIMARY_KEY"]
 | 
			
		||||
    config.active_record.encryption.key_derivation_salt = ENV["ENCRYPTION_KEY_DERIVATION_SALT"]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
zaTF2ZJaU/M9CYmXEJoDmS1oniSV/1YT0UnM1jysEhMknn3bYOzRBZM3eGJ5Mr6bJYz6cv5hSDL5pT0/6hqgpV04dc/fVDplWO4eEpD1kBFM3LjIPCe9REbRlRUwODpoV/y6wWOFme8nFMS9uOSFkL6RtMuQli0os5Rp+2Jal2lJwAujFjFwuuj+1iRzqc3pzeIIy0clPmR9ANxXS+rPL3jmxty6QzVMr9Q658roVD38yRg0CNgs09eZ/FvqeqXlQkwDfg2/zX9tg5ocGwvHzmicZJ/yU6kl6liqNAJvEDrolm0gSzemY8NfhCySd5wjEvpP+uvKxbd5M3rhagC8S9MmpmxewuOKbDFEyTSRO6Kp2yakdcLSn12ZPB+X0nlMRno+UEzh0EvcX2mxRXppIKrsRUGVeYmj4GMI0vyLW1eCuyPLueN7sOnSjhtM84URNWkSnb0LTxlYxOJGbnwzn85QVpFdXtDktbaXvMWcVdH9XdMDbaBs1G7BIA6Z8i+mxLVVEbQWQM6VBrUhpkpWfphLmN5b16LYbGTzdKnR0iPcsNr8Tsl8vYfeWH8S0ujD105lS39v37YimN6E5l4X2CrqG+DNBtKfbqC0E3lhZMqDRWetxzaxE47oe4g=--0EKrvwe2YTfsbssz--SbmUH0sMiy5uUhpxFImgMA==
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
6b101c9addbfa5f959b5859f756bc9d7
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
vqH5By5qFLImVjdlWj+7FwGg8APKnr/AEd7WqekG7L0vNA32WGBpwS1uGzs02LIcATRwGj8DyJxiBOB/w9z8cwoO+t6Woi5hAnOSCQwFWKLT0dZq7jgtT8pxK0Yu/Nf91PEFN1rc/8ZFy2KKVpbtMbMPyivT38e/ctBZD/lHrWkndvLXYvFVhqWjUnDOGbhwl/U0RZgqBBjvlm3B0JkQfiN8VXPlCJL2Cd8kd0+MpRCRTgtcxA==--OdVXnDP7OhzJxCsP--+8SI6IFIeXyDxXb+WpqhIQ==
 | 
			
		||||
@ -45,7 +45,7 @@ Devise.setup do |config|
 | 
			
		||||
  # Configure the e-mail address which will be shown in Devise::Mailer,
 | 
			
		||||
  # note that it will be overwritten if you use your own mailer class
 | 
			
		||||
  # with default "from" parameter.
 | 
			
		||||
  config.mailer_sender = 'accounts@kosmos.org'
 | 
			
		||||
  config.mailer_sender = ENV["SMTP_FROM_ADDRESS"] || 'accounts@localhost'
 | 
			
		||||
 | 
			
		||||
  # Configure the class responsible to send e-mails.
 | 
			
		||||
  # config.mailer = 'Devise::Mailer'
 | 
			
		||||
 | 
			
		||||
@ -28,11 +28,11 @@ authorizations: &AUTHORIZATIONS
 | 
			
		||||
development:
 | 
			
		||||
  host: <%= ENV["LDAP_HOST"] || "localhost" %>
 | 
			
		||||
  port: <%= ENV["LDAP_PORT"] || "389" %>
 | 
			
		||||
  attribute: cn
 | 
			
		||||
  base: <%= ENV["LDAP_BASE"] || "ou=kosmos.org,cn=users,dc=kosmos,dc=org" %>
 | 
			
		||||
  admin_user: "cn=Directory Manager"
 | 
			
		||||
  admin_password: <%= ENV["LDAP_ADMIN_PASSWORD"] %>
 | 
			
		||||
  ssl: <%= ENV["LDAP_USE_TLS"] || "false" %>
 | 
			
		||||
  attribute: <%= ENV["LDAP_UID_ATTR"] || "cn" %>
 | 
			
		||||
  base: <%= ENV["LDAP_BASE"] || "ou=kosmos.org,cn=users,dc=kosmos,dc=org" %>
 | 
			
		||||
  admin_user: <%= ENV["LDAP_ADMIN_USER"] || "cn=Directory Manager" %>
 | 
			
		||||
  admin_password: <%= ENV["LDAP_ADMIN_PASSWORD"] %>
 | 
			
		||||
  # <<: *AUTHORIZATIONS
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
@ -46,11 +46,11 @@ test:
 | 
			
		||||
  # <<: *AUTHORIZATIONS
 | 
			
		||||
 | 
			
		||||
production:
 | 
			
		||||
  host: ldap.kosmos.local
 | 
			
		||||
  port: 389
 | 
			
		||||
  attribute: cn
 | 
			
		||||
  base: ou=kosmos.org,cn=users,dc=kosmos,dc=org
 | 
			
		||||
  admin_user: <%= Rails.application.credentials.ldap[:username] rescue nil %>
 | 
			
		||||
  admin_password: <%= Rails.application.credentials.ldap[:password] rescue nil %>
 | 
			
		||||
  # ssl: false
 | 
			
		||||
  host: <%= ENV["LDAP_HOST"] || "localhost" %>
 | 
			
		||||
  port: <%= ENV["LDAP_PORT"] || "389" %>
 | 
			
		||||
  ssl: <%= ENV["LDAP_USE_TLS"] || "false" %>
 | 
			
		||||
  attribute: <%= ENV["LDAP_UID_ATTR"] || "cn" %>
 | 
			
		||||
  base: <%= ENV["LDAP_BASE"] || "ou=kosmos.org,cn=users,dc=kosmos,dc=org" %>
 | 
			
		||||
  admin_user: <%= ENV["LDAP_ADMIN_USER"] || "cn=Directory Manager" %>
 | 
			
		||||
  admin_password: <%= ENV["LDAP_ADMIN_PASSWORD"] %>
 | 
			
		||||
  # <<: *AUTHORIZATIONS
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,6 @@
 | 
			
		||||
class AddLndhubPasswordToUsers < ActiveRecord::Migration[8.0]
 | 
			
		||||
  def change
 | 
			
		||||
    add_column :users, :lndhub_username, :string
 | 
			
		||||
    add_column :users, :lndhub_password, :text
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										11
									
								
								db/migrate/20250506125947_migrate_lockbox_data.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								db/migrate/20250506125947_migrate_lockbox_data.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
class MigrateLockboxData < ActiveRecord::Migration[8.0]
 | 
			
		||||
  def up
 | 
			
		||||
    User.find_each do |user|
 | 
			
		||||
      ln_account = user.ln_account
 | 
			
		||||
      ln_password = user.ln_password
 | 
			
		||||
      user.lndhub_username = ln_account
 | 
			
		||||
      user.lndhub_password = ln_password
 | 
			
		||||
      user.save!
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										6
									
								
								db/migrate/20250506154628_remove_ln_fields_from_users.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								db/migrate/20250506154628_remove_ln_fields_from_users.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
class RemoveLnFieldsFromUsers < ActiveRecord::Migration[8.0]
 | 
			
		||||
  def change
 | 
			
		||||
    remove_column :users, :ln_account
 | 
			
		||||
    remove_column :users, :ln_password_ciphertext
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,4 +1,16 @@
 | 
			
		||||
ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
# This file is auto-generated from the current state of the database. Instead
 | 
			
		||||
# of editing this file, please use the migrations feature of Active Record to
 | 
			
		||||
# incrementally modify your database, and then regenerate this schema definition.
 | 
			
		||||
#
 | 
			
		||||
# This file is the source Rails uses to define your schema when running `bin/rails
 | 
			
		||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
 | 
			
		||||
# be faster and is potentially less error prone than running all of your
 | 
			
		||||
# migrations from scratch. Old migrations may fail to apply correctly if those
 | 
			
		||||
# migrations use external dependencies or application code.
 | 
			
		||||
#
 | 
			
		||||
# It's strongly recommended that you check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema[8.0].define(version: 1) do
 | 
			
		||||
  create_table "solid_queue_blocked_executions", force: :cascade do |t|
 | 
			
		||||
    t.bigint "job_id", null: false
 | 
			
		||||
    t.string "queue_name", null: false
 | 
			
		||||
@ -6,24 +18,24 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.string "concurrency_key", null: false
 | 
			
		||||
    t.datetime "expires_at", null: false
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "concurrency_key", "priority", "job_id" ], name: "index_solid_queue_blocked_executions_for_release"
 | 
			
		||||
    t.index [ "expires_at", "concurrency_key" ], name: "index_solid_queue_blocked_executions_for_maintenance"
 | 
			
		||||
    t.index [ "job_id" ], name: "index_solid_queue_blocked_executions_on_job_id", unique: true
 | 
			
		||||
    t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release"
 | 
			
		||||
    t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance"
 | 
			
		||||
    t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_claimed_executions", force: :cascade do |t|
 | 
			
		||||
    t.bigint "job_id", null: false
 | 
			
		||||
    t.bigint "process_id"
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "job_id" ], name: "index_solid_queue_claimed_executions_on_job_id", unique: true
 | 
			
		||||
    t.index [ "process_id", "job_id" ], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id"
 | 
			
		||||
    t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true
 | 
			
		||||
    t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_failed_executions", force: :cascade do |t|
 | 
			
		||||
    t.bigint "job_id", null: false
 | 
			
		||||
    t.text "error"
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "job_id" ], name: "index_solid_queue_failed_executions_on_job_id", unique: true
 | 
			
		||||
    t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_jobs", force: :cascade do |t|
 | 
			
		||||
@ -37,17 +49,17 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.string "concurrency_key"
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.datetime "updated_at", null: false
 | 
			
		||||
    t.index [ "active_job_id" ], name: "index_solid_queue_jobs_on_active_job_id"
 | 
			
		||||
    t.index [ "class_name" ], name: "index_solid_queue_jobs_on_class_name"
 | 
			
		||||
    t.index [ "finished_at" ], name: "index_solid_queue_jobs_on_finished_at"
 | 
			
		||||
    t.index [ "queue_name", "finished_at" ], name: "index_solid_queue_jobs_for_filtering"
 | 
			
		||||
    t.index [ "scheduled_at", "finished_at" ], name: "index_solid_queue_jobs_for_alerting"
 | 
			
		||||
    t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id"
 | 
			
		||||
    t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name"
 | 
			
		||||
    t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at"
 | 
			
		||||
    t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering"
 | 
			
		||||
    t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_pauses", force: :cascade do |t|
 | 
			
		||||
    t.string "queue_name", null: false
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "queue_name" ], name: "index_solid_queue_pauses_on_queue_name", unique: true
 | 
			
		||||
    t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_processes", force: :cascade do |t|
 | 
			
		||||
@ -59,9 +71,9 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.text "metadata"
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.string "name", null: false
 | 
			
		||||
    t.index [ "last_heartbeat_at" ], name: "index_solid_queue_processes_on_last_heartbeat_at"
 | 
			
		||||
    t.index [ "name", "supervisor_id" ], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true
 | 
			
		||||
    t.index [ "supervisor_id" ], name: "index_solid_queue_processes_on_supervisor_id"
 | 
			
		||||
    t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at"
 | 
			
		||||
    t.index ["name", "supervisor_id"], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true
 | 
			
		||||
    t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_ready_executions", force: :cascade do |t|
 | 
			
		||||
@ -69,9 +81,9 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.string "queue_name", null: false
 | 
			
		||||
    t.integer "priority", default: 0, null: false
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "job_id" ], name: "index_solid_queue_ready_executions_on_job_id", unique: true
 | 
			
		||||
    t.index [ "priority", "job_id" ], name: "index_solid_queue_poll_all"
 | 
			
		||||
    t.index [ "queue_name", "priority", "job_id" ], name: "index_solid_queue_poll_by_queue"
 | 
			
		||||
    t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true
 | 
			
		||||
    t.index ["priority", "job_id"], name: "index_solid_queue_poll_all"
 | 
			
		||||
    t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_recurring_executions", force: :cascade do |t|
 | 
			
		||||
@ -79,8 +91,8 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.string "task_key", null: false
 | 
			
		||||
    t.datetime "run_at", null: false
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "job_id" ], name: "index_solid_queue_recurring_executions_on_job_id", unique: true
 | 
			
		||||
    t.index [ "task_key", "run_at" ], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true
 | 
			
		||||
    t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true
 | 
			
		||||
    t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_recurring_tasks", force: :cascade do |t|
 | 
			
		||||
@ -95,8 +107,8 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.text "description"
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.datetime "updated_at", null: false
 | 
			
		||||
    t.index [ "key" ], name: "index_solid_queue_recurring_tasks_on_key", unique: true
 | 
			
		||||
    t.index [ "static" ], name: "index_solid_queue_recurring_tasks_on_static"
 | 
			
		||||
    t.index ["key"], name: "index_solid_queue_recurring_tasks_on_key", unique: true
 | 
			
		||||
    t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_scheduled_executions", force: :cascade do |t|
 | 
			
		||||
@ -105,8 +117,8 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.integer "priority", default: 0, null: false
 | 
			
		||||
    t.datetime "scheduled_at", null: false
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.index [ "job_id" ], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true
 | 
			
		||||
    t.index [ "scheduled_at", "priority", "job_id" ], name: "index_solid_queue_dispatch_all"
 | 
			
		||||
    t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true
 | 
			
		||||
    t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  create_table "solid_queue_semaphores", force: :cascade do |t|
 | 
			
		||||
@ -115,9 +127,9 @@ ActiveRecord::Schema[7.1].define(version: 1) do
 | 
			
		||||
    t.datetime "expires_at", null: false
 | 
			
		||||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.datetime "updated_at", null: false
 | 
			
		||||
    t.index [ "expires_at" ], name: "index_solid_queue_semaphores_on_expires_at"
 | 
			
		||||
    t.index [ "key", "value" ], name: "index_solid_queue_semaphores_on_key_and_value"
 | 
			
		||||
    t.index [ "key" ], name: "index_solid_queue_semaphores_on_key", unique: true
 | 
			
		||||
    t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at"
 | 
			
		||||
    t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value"
 | 
			
		||||
    t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@
 | 
			
		||||
#
 | 
			
		||||
# It's strongly recommended that you check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema[8.0].define(version: 2025_04_28_123317) do
 | 
			
		||||
ActiveRecord::Schema[8.0].define(version: 2025_05_06_154628) do
 | 
			
		||||
  create_table "active_storage_attachments", force: :cascade do |t|
 | 
			
		||||
    t.string "name", null: false
 | 
			
		||||
    t.string "record_type", null: false
 | 
			
		||||
@ -127,12 +127,12 @@ ActiveRecord::Schema[8.0].define(version: 2025_04_28_123317) do
 | 
			
		||||
    t.datetime "confirmed_at", precision: nil
 | 
			
		||||
    t.datetime "confirmation_sent_at", precision: nil
 | 
			
		||||
    t.string "unconfirmed_email"
 | 
			
		||||
    t.text "ln_password_ciphertext"
 | 
			
		||||
    t.string "ln_account"
 | 
			
		||||
    t.datetime "remember_created_at"
 | 
			
		||||
    t.string "remember_token"
 | 
			
		||||
    t.text "preferences"
 | 
			
		||||
    t.string "pgp_fpr"
 | 
			
		||||
    t.string "lndhub_username"
 | 
			
		||||
    t.text "lndhub_password"
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -40,19 +40,22 @@ services:
 | 
			
		||||
      SOLID_QUEUE_IN_PUMA: true
 | 
			
		||||
      LAUNCHY_DRY_RUN: true
 | 
			
		||||
      BROWSER: /dev/null
 | 
			
		||||
      ENCRYPTION_PRIMARY_KEY: YhNLBgCFMAzw5dV3gISxnGrhNDMQwRdn
 | 
			
		||||
      ENCRYPTION_KEY_DERIVATION_SALT: h28g16MRZ1sghF2jTCos1DiLZXUswinR
 | 
			
		||||
      PRIMARY_DOMAIN: kosmos.org
 | 
			
		||||
      AKKOUNTS_DOMAIN: accounts.kosmos.org
 | 
			
		||||
      LDAP_HOST: ldap
 | 
			
		||||
      LDAP_PORT: 3389
 | 
			
		||||
      LDAP_ADMIN_PASSWORD: passthebutter
 | 
			
		||||
      LDAP_USE_TLS: "false"
 | 
			
		||||
      REDIS_URL: redis://redis:6379/0
 | 
			
		||||
      ACTIVE_STORAGE_PATH: "/akkounts/tmp/attachments"
 | 
			
		||||
      ACTIVE_STORAGE_PATH: /akkounts/tmp/attachments
 | 
			
		||||
      RS_REDIS_URL: redis://redis:6379/1
 | 
			
		||||
      RS_STORAGE_URL: "http://localhost:4567"
 | 
			
		||||
      RS_STORAGE_URL: http://localhost:4567
 | 
			
		||||
      RS_AKKOUNTS_DOMAIN: localhost
 | 
			
		||||
      S3_ENABLED: false
 | 
			
		||||
      NOSTR_PUBLIC_KEY: bdd76ce2934b2f591f9fad2ebe9da18f20d2921de527494ba00eeaa0a0efadcf
 | 
			
		||||
      NOSTR_PRIVATE_KEY: 7c3ef7e448505f0615137af38569d01807d3b05b5005d5ecf8aaafcd40323cea
 | 
			
		||||
      NOSTR_RELAY_URL: "ws://strfry:7777"
 | 
			
		||||
      NOSTR_RELAY_URL: ws://strfry:7777
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - ldap
 | 
			
		||||
      - redis
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,6 @@ FactoryBot.define do
 | 
			
		||||
    email { "jimmy@example.com" }
 | 
			
		||||
    password { "dis-muh-password" }
 | 
			
		||||
    confirmed_at { DateTime.now }
 | 
			
		||||
    ln_account { "123456" }
 | 
			
		||||
    lndhub_username { "123456" }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -19,14 +19,14 @@ RSpec.describe CreateLndhubAccountJob, type: :job do
 | 
			
		||||
      .with { |req| req.body == '{}' }
 | 
			
		||||
 | 
			
		||||
    user.reload
 | 
			
		||||
    expect(user.ln_account).to eq("abc123")
 | 
			
		||||
    expect(user.ln_password).to eq("def456")
 | 
			
		||||
    expect(user.lndhub_username).to eq("abc123")
 | 
			
		||||
    expect(user.lndhub_password).to eq("def456")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context "with existing credentials stored" do
 | 
			
		||||
    before do
 | 
			
		||||
      user.ln_account = "foo"
 | 
			
		||||
      user.ln_password = "bar"
 | 
			
		||||
      user.lndhub_username = "foo"
 | 
			
		||||
      user.lndhub_password = "bar"
 | 
			
		||||
      user.save!
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
@ -36,8 +36,8 @@ RSpec.describe CreateLndhubAccountJob, type: :job do
 | 
			
		||||
      expect(WebMock).to_not have_requested(:post, "http://localhost:3023/create")
 | 
			
		||||
 | 
			
		||||
      user.reload
 | 
			
		||||
      expect(user.ln_account).to eq("foo")
 | 
			
		||||
      expect(user.ln_password).to eq("bar")
 | 
			
		||||
      expect(user.lndhub_username).to eq("foo")
 | 
			
		||||
      expect(user.lndhub_password).to eq("bar")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe Zap, type: :model do
 | 
			
		||||
  describe "#request_event" do
 | 
			
		||||
    let(:user) { create :user, cn: 'satoshi', ou: 'kosmos.org', ln_account: 'abcdefg123456' }
 | 
			
		||||
    let(:user) { create :user, cn: 'satoshi', ou: 'kosmos.org', lndhub_username: 'abcdefg123456' }
 | 
			
		||||
    let(:zap) { create :zap, user: user }
 | 
			
		||||
 | 
			
		||||
    it "returns the stored request as a Nostr::Event" do
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ RSpec.describe "/lnurlpay", type: :request do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context "Valid user" do
 | 
			
		||||
    let(:user) { create :user, cn: 'satoshi', ou: 'kosmos.org', ln_account: 'abcdefg123456' }
 | 
			
		||||
    let(:user) { create :user, cn: 'satoshi', ou: 'kosmos.org', lndhub_username: 'abcdefg123456' }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      login_as user, :scope => :user
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@ RSpec.describe "WebFinger", type: :request do
 | 
			
		||||
          expect(rs_link["href"]).to eql("#{Setting.rs_storage_url}/tony")
 | 
			
		||||
 | 
			
		||||
          oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"]
 | 
			
		||||
          expect(oauth_url).to eql("http://accounts.kosmos.org/rs/oauth/tony")
 | 
			
		||||
          expect(oauth_url).to eql("http://localhost/rs/oauth/tony")
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it "returns CORS headers" do
 | 
			
		||||
 | 
			
		||||
@ -50,7 +50,7 @@ RSpec.describe "Webhooks", type: :request do
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    describe "Valid payload for incoming payment" do
 | 
			
		||||
      let(:user) { create :user, ln_account: "123456abcdef" }
 | 
			
		||||
      let(:user) { create :user, lndhub_username: "123456abcdef" }
 | 
			
		||||
      let(:payload) { JSON.parse(File.read(File.expand_path("../fixtures/lndhub/incoming.json", File.dirname(__FILE__)))) }
 | 
			
		||||
 | 
			
		||||
      before { user.save! } #FIXME this should not be necessary
 | 
			
		||||
@ -132,7 +132,7 @@ RSpec.describe "Webhooks", type: :request do
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    describe "Valid payload for zap transaction" do
 | 
			
		||||
      let(:user) { create :user, ln_account: "123456abcdef" }
 | 
			
		||||
      let(:user) { create :user, lndhub_username: "123456abcdef" }
 | 
			
		||||
      let(:zap) { create :zap, user: user }
 | 
			
		||||
      let(:payload) { JSON.parse(File.read(File.expand_path("../fixtures/lndhub/incoming-zap.json", File.dirname(__FILE__)))) }
 | 
			
		||||
      let(:zap_receipt) {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe NostrManager::CreateZapReceipt, type: :model do
 | 
			
		||||
  let(:user) { create :user, ln_account: "123456abcdef" }
 | 
			
		||||
  let(:user) { create :user, lndhub_username: "123456abcdef" }
 | 
			
		||||
  let(:zap) { create :zap, user: user }
 | 
			
		||||
 | 
			
		||||
  # before do
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe NostrManager::PublishZapReceipt, type: :model do
 | 
			
		||||
  let(:user) { create :user, ln_account: "123456abcdef" }
 | 
			
		||||
  let(:user) { create :user, lndhub_username: "123456abcdef" }
 | 
			
		||||
  let(:zap) { create :zap, user: user }
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user