Merge branch 'feature/own_relay' into live
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Râu Cao 2024-06-20 13:59:59 +02:00
commit bafddd436b
Signed by: raucao
GPG Key ID: 37036C356E56CC51
7 changed files with 100 additions and 10 deletions

View File

@ -29,6 +29,7 @@
# #
# Service Integrations # Service Integrations
# (sorted alphabetically by service name)
# #
# BTCPAY_PUBLIC_URL='https://btcpay.example.com' # BTCPAY_PUBLIC_URL='https://btcpay.example.com'
@ -62,5 +63,9 @@
# MEDIAWIKI_PUBLIC_URL='https://wiki.kosmos.org' # MEDIAWIKI_PUBLIC_URL='https://wiki.kosmos.org'
# NOSTR_PRIVATE_KEY='123456abcdef...'
# NOSTR_PUBLIC_KEY='123456abcdef...'
# NOSTR_RELAY_URL='wss://nostr.kosmos.org'
# RS_STORAGE_URL='https://storage.kosmos.org' # RS_STORAGE_URL='https://storage.kosmos.org'
# RS_REDIS_URL='redis://localhost:6379/2' # RS_REDIS_URL='redis://localhost:6379/2'

View File

@ -1,16 +1,35 @@
class WellKnownController < ApplicationController class WellKnownController < ApplicationController
before_action :require_nostr_enabled, only: [ :nostr ]
def nostr def nostr
http_status :unprocessable_entity and return if params[:name].blank? http_status :unprocessable_entity and return if params[:name].blank?
domain = request.headers["X-Forwarded-Host"].presence || Setting.primary_domain domain = request.headers["X-Forwarded-Host"].presence || Setting.primary_domain
relay_url = Setting.nostr_relay_url
if params[:name] == "_"
# pubkey for the primary domain without a username (e.g. kosmos.org)
res = { names: { "_": Setting.nostr_public_key } }
else
@user = User.where(cn: params[:name], ou: domain).first @user = User.where(cn: params[:name], ou: domain).first
http_status :not_found and return if @user.nil? || @user.nostr_pubkey.blank? http_status :not_found and return if @user.nil? || @user.nostr_pubkey.blank?
res = { names: { @user.cn => @user.nostr_pubkey } }
end
if relay_url
res[:relays] = { @user.nostr_pubkey => [ relay_url ] }
end
respond_to do |format| respond_to do |format|
format.json do format.json do
render json: { render json: res.to_json
names: { "#{@user.cn}": @user.nostr_pubkey }
}.to_json
end end
end end
end end
private
def require_nostr_enabled
http_status :not_found unless Setting.nostr_enabled?
end
end end

View File

@ -169,6 +169,9 @@ class Setting < RailsSettings::Base
field :nostr_public_key, type: :string, field :nostr_public_key, type: :string,
default: ENV["NOSTR_PUBLIC_KEY"].presence default: ENV["NOSTR_PUBLIC_KEY"].presence
field :nostr_relay_url, type: :string,
default: ENV["NOSTR_RELAY_URL"].presence
field :nostr_zaps_relay_limit, type: :integer, field :nostr_zaps_relay_limit, type: :integer,
default: 12 default: 12

View File

@ -6,8 +6,13 @@ module NostrManager
def call def call
tags = parse_tags(@zap.request_event.tags) tags = parse_tags(@zap.request_event.tags)
relays = tags[:relays].take(Setting.nostr_zaps_relay_limit)
tags[:relays].take(Setting.nostr_zaps_relay_limit).each do |relay_url| if Setting.nostr_relay_url.present?
relays << Setting.nostr_relay_url
end
relays.uniq.each do |relay_url|
if @delayed if @delayed
NostrPublishEventJob.perform_later(event: @zap.receipt, relay_url: relay_url) NostrPublishEventJob.perform_later(event: @zap.receipt, relay_url: relay_url)
else else

View File

@ -19,6 +19,11 @@
title: "Public key", title: "Public key",
description: "The corresponding public key of the accounts service" description: "The corresponding public key of the accounts service"
) %> ) %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :nostr_relay_url,
title: "Relay URL",
description: "Websockets URL of a relay associated with #{Setting.primary_domain}"
) %>
</ul> </ul>
</section> </section>
<section> <section>

View File

@ -2,21 +2,21 @@ require 'rails_helper'
RSpec.describe "Well-known URLs", type: :request do RSpec.describe "Well-known URLs", type: :request do
describe "GET /nostr" do describe "GET /nostr" do
context "without username param" do describe "without username param" do
it "returns a 422 status" do it "returns a 422 status" do
get "/.well-known/nostr.json" get "/.well-known/nostr.json"
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
end end
end end
context "non-existent user" do describe "non-existent user" do
it "returns a 404 status" do it "returns a 404 status" do
get "/.well-known/nostr.json?name=bob" get "/.well-known/nostr.json?name=bob"
expect(response).to have_http_status(:not_found) expect(response).to have_http_status(:not_found)
end end
end end
context "user does not have a nostr pubkey configured" do describe "user does not have a nostr pubkey configured" do
let(:user) { create :user, cn: 'spongebob', ou: 'kosmos.org' } let(:user) { create :user, cn: 'spongebob', ou: 'kosmos.org' }
before do before do
@ -30,7 +30,7 @@ RSpec.describe "Well-known URLs", type: :request do
end end
end end
context "user with nostr pubkey" do describe "user with nostr pubkey" do
let(:user) { create :user, cn: 'bobdylan', ou: 'kosmos.org' } let(:user) { create :user, cn: 'bobdylan', ou: 'kosmos.org' }
before do before do
user.save! user.save!
@ -45,6 +45,46 @@ RSpec.describe "Well-known URLs", type: :request do
expect(res["names"].keys.size).to eq(1) expect(res["names"].keys.size).to eq(1)
expect(res["names"]["bobdylan"]).to eq(user.nostr_pubkey) expect(res["names"]["bobdylan"]).to eq(user.nostr_pubkey)
end end
context "without relay configured" do
it "does not include a recommended relay" do
get "/.well-known/nostr.json?name=bobdylan"
res = JSON.parse(response.body)
expect(res["relays"]).to be_nil
end
end
context "with relay configured" do
before do
Setting.nostr_relay_url = "wss://nostr.kosmos.org"
end
it "includes a recommended relay" do
get "/.well-known/nostr.json?name=bobdylan"
res = JSON.parse(response.body)
expect(res["relays"][user.nostr_pubkey].length).to eq(1)
expect(res["relays"][user.nostr_pubkey].first).to eq("wss://nostr.kosmos.org")
end
end
end
describe "placeholder username for domain's own pubkey" do
it "returns the configured nostr pubkey" do
get "/.well-known/nostr.json?name=_"
res = JSON.parse(response.body)
expect(res["names"]["_"]).to eq(Setting.nostr_public_key)
end
context "nostr service integration not enabled" do
before do
Setting.nostr_enabled = false
end
it "returns a 404 status" do
get "/.well-known/nostr.json?name=_"
expect(response).to have_http_status(:not_found)
end
end
end end
end end
end end

View File

@ -35,6 +35,19 @@ RSpec.describe NostrManager::PublishZapReceipt, type: :model do
described_class.call(zap: zap) described_class.call(zap: zap)
end end
context "with own relay configured" do
before do
Setting.nostr_relay_url = "wss://foobar.kosmos.org"
end
it "also publishes the receipt to our own relay" do
expect(NostrPublishEventJob).to receive(:perform_later)
.exactly(13).times.and_return(true)
described_class.call(zap: zap)
end
end
end end
end end
end end