Update nostr gem, switch to Ruby for bech32 encoding
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
Râu Cao 2024-01-15 12:37:41 +03:00
parent 1a5a2177b4
commit b4f0c60ea0
Signed by: raucao
GPG Key ID: 37036C356E56CC51
9 changed files with 32 additions and 22 deletions

View File

@ -62,7 +62,7 @@ gem "sentry-rails"
gem 'discourse_api'
gem "lnurl"
gem 'manifique', git: 'https://gitea.kosmos.org/5apps/manifique.git', branch: 'master'
gem 'nostr', git: 'https://gitea.kosmos.org/kosmos/nostr-gem.git', branch: 'feature/ruby_2.7_compat'
gem 'nostr', git: 'https://gitea.kosmos.org/kosmos/nostr-gem.git', ref: 'd59f31a'
group :development, :test do
# Use sqlite3 as the database for Active Record

View File

@ -10,12 +10,12 @@ GIT
GIT
remote: https://gitea.kosmos.org/kosmos/nostr-gem.git
revision: 596529d9eb50d13b3f385245636698fccf37b442
branch: feature/ruby_2.7_compat
revision: d59f31a3c63c7642fe2d3eb50b785da54fdabfab
ref: d59f31a
specs:
nostr (0.4.0)
bech32 (~> 1.3)
bip-schnorr (~> 0.4)
nostr (0.5.0)
bech32 (~> 1.4)
bip-schnorr (~> 0.6)
ecdsa (~> 1.2)
event_emitter (~> 0.2)
faye-websocket (~> 0.11)
@ -115,7 +115,7 @@ GEM
thor (>= 1.1.0)
benchmark (0.2.1)
bindex (0.8.1)
bip-schnorr (0.6.0)
bip-schnorr (0.7.0)
ecdsa_ext (~> 0.5.0)
brow (0.4.1)
builder (3.2.4)
@ -259,6 +259,7 @@ GEM
method_source (1.0.0)
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.20.0)
multipart-post (2.3.0)
net-imap (0.3.7)
@ -272,6 +273,9 @@ GEM
net-smtp (0.4.0)
net-protocol
nio4r (2.5.9)
nokogiri (1.15.4)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.15.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.15.4-x86_64-linux)
@ -422,6 +426,8 @@ GEM
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.6.7)
mini_portile2 (~> 2.8.0)
sqlite3 (1.6.7-arm64-darwin)
sqlite3 (1.6.7-x86_64-linux)
stimulus-rails (1.3.0)

View File

@ -1,5 +1,4 @@
import { Controller } from "@hotwired/stimulus"
import { bech32 } from "bech32"
function hexToBytes (hex) {
let bytes = []
@ -15,10 +14,6 @@ export default class extends Controller {
static values = { userAddress: String, pubkeyHex: String, sharedSecret: String }
connect () {
if (this.hasPubkeyHexValue && this.pubkeyHexValue.length > 0) {
this.pubkeyBech32InputTarget.value = this.pubkeyBech32
}
if (window.nostr) {
if (this.hasSetPubkeyTarget) {
this.setPubkeyTarget.disabled = false
@ -53,11 +48,6 @@ export default class extends Controller {
}
}
get pubkeyBech32 () {
const words = bech32.toWords(hexToBytes(this.pubkeyHexValue))
return bech32.encode('npub', words)
}
get csrfToken () {
const element = document.head.querySelector('meta[name="csrf-token"]')
return element.getAttribute("content")

View File

@ -1,3 +1,5 @@
require 'nostr'
class User < ApplicationRecord
include EmailValidatable
@ -185,6 +187,11 @@ class User < ApplicationRecord
ldap.delete_attribute(dn,:service)
end
def nostr_pubkey_bech32
return nil unless nostr_pubkey.present?
Nostr::PublicKey.new(nostr_pubkey).to_bech32
end
private
def ldap

View File

@ -7,7 +7,7 @@
data-settings--nostr-pubkey-pubkey-hex-value="<%= current_user.nostr_pubkey %>">
<p class="<%= current_user.nostr_pubkey.present? ? '' : 'hidden' %> mt-2 flex gap-1">
<input type="text" value="<%= current_user.nostr_pubkey %>" disabled
<input type="text" value="<%= current_user.nostr_pubkey_bech32 %>" disabled
data-settings--nostr-pubkey-target="pubkeyBech32Input"
name="nostr_public_key" class="relative grow" />
<%= link_to nostr_pubkey_settings_path,

View File

@ -5,5 +5,4 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "bech32" # @2.0.0
pin "tailwindcss-stimulus-components" # @4.0.3

View File

@ -28,7 +28,7 @@ RSpec.describe 'Experimental Settings', type: :feature do
scenario 'Remove nostr pubkey from account' do
visit setting_path(:experiments)
expect(page).to have_field("nostr_public_key",
with: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3",
with: "npub1qlsc3g0lsl8pw8230w8d9wm6xxcax3f6pkemz5measrmwfxjxteslf2hac",
disabled: true)
click_link "Remove"

View File

@ -205,4 +205,14 @@ RSpec.describe User, type: :model do
end
end
end
describe "#nostr_pubkey_bech32" do
before do
user.update! nostr_pubkey: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"
end
it "encodes the hexadecimal pubkey to bech32" do
expect(user.nostr_pubkey_bech32).to eq("npub1qlsc3g0lsl8pw8230w8d9wm6xxcax3f6pkemz5measrmwfxjxteslf2hac")
end
end
end

View File

@ -1,2 +0,0 @@
var e={};Object.defineProperty(e,"__esModule",{value:true});e.bech32m=e.bech32=void 0;const r="qpzry9x8gf2tvdw0s3jn54khce6mua7l";const t={};for(let e=0;e<r.length;e++){const o=r.charAt(e);t[o]=e}function polymodStep(e){const r=e>>25;return(33554431&e)<<5^996825010&-(r>>0&1)^642813549&-(r>>1&1)^513874426&-(r>>2&1)^1027748829&-(r>>3&1)^705979059&-(r>>4&1)}function prefixChk(e){let r=1;for(let t=0;t<e.length;++t){const o=e.charCodeAt(t);if(o<33||o>126)return"Invalid prefix ("+e+")";r=polymodStep(r)^o>>5}r=polymodStep(r);for(let t=0;t<e.length;++t){const o=e.charCodeAt(t);r=polymodStep(r)^31&o}return r}function convert(e,r,t,o){let n=0;let c=0;const s=(1<<t)-1;const f=[];for(let o=0;o<e.length;++o){n=n<<r|e[o];c+=r;while(c>=t){c-=t;f.push(n>>c&s)}}if(o)c>0&&f.push(n<<t-c&s);else{if(c>=r)return"Excess padding";if(n<<t-c&s)return"Non-zero padding"}return f}function toWords(e){return convert(e,8,5,true)}function fromWordsUnsafe(e){const r=convert(e,5,8,false);if(Array.isArray(r))return r}function fromWords(e){const r=convert(e,5,8,false);if(Array.isArray(r))return r;throw new Error(r)}function getLibraryFromEncoding(e){let o;o="bech32"===e?1:734539939;function encode(e,t,n){n=n||90;if(e.length+7+t.length>n)throw new TypeError("Exceeds length limit");e=e.toLowerCase();let c=prefixChk(e);if("string"===typeof c)throw new Error(c);let s=e+"1";for(let e=0;e<t.length;++e){const o=t[e];if(o>>5!==0)throw new Error("Non 5-bit word");c=polymodStep(c)^o;s+=r.charAt(o)}for(let e=0;e<6;++e)c=polymodStep(c);c^=o;for(let e=0;e<6;++e){const t=c>>5*(5-e)&31;s+=r.charAt(t)}return s}function __decode(e,r){r=r||90;if(e.length<8)return e+" too short";if(e.length>r)return"Exceeds length limit";const n=e.toLowerCase();const c=e.toUpperCase();if(e!==n&&e!==c)return"Mixed-case string "+e;e=n;const s=e.lastIndexOf("1");if(-1===s)return"No separator character for "+e;if(0===s)return"Missing prefix for "+e;const f=e.slice(0,s);const i=e.slice(s+1);if(i.length<6)return"Data too short";let d=prefixChk(f);if("string"===typeof d)return d;const l=[];for(let e=0;e<i.length;++e){const r=i.charAt(e);const o=t[r];if(void 0===o)return"Unknown character "+r;d=polymodStep(d)^o;e+6>=i.length||l.push(o)}return d!==o?"Invalid checksum for "+e:{prefix:f,words:l}}function decodeUnsafe(e,r){const t=__decode(e,r);if("object"===typeof t)return t}function decode(e,r){const t=__decode(e,r);if("object"===typeof t)return t;throw new Error(t)}return{decodeUnsafe:decodeUnsafe,decode:decode,encode:encode,toWords:toWords,fromWordsUnsafe:fromWordsUnsafe,fromWords:fromWords}}e.bech32=getLibraryFromEncoding("bech32");e.bech32m=getLibraryFromEncoding("bech32m");const o=e.__esModule,n=e.bech32m,c=e.bech32;export default e;export{o as __esModule,c as bech32,n as bech32m};