14 Commits

Author SHA1 Message Date
78ecef80dc WIP: Import deno modules for use with import maps
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-09 15:17:35 +02:00
64de4deddd Fix serviceEnabled indicator on admin page
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-24 21:38:01 +02:00
8f7994d82e 0.10.0
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2024-09-18 15:49:07 +02:00
a7d0e71ab6 Fix spec
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-18 14:46:46 +02:00
27d9f73c61 Set host for RS auth url
Some checks failed
continuous-integration/drone/push Build is failing
With X-Forwarded-Host set on the proxied request, Rails uses that host
for URLs. But we need it to be the accounts domain.
2024-09-14 17:17:09 +02:00
ed3de8b16f Allow CORS for all LNURL endpoints
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-14 16:46:14 +02:00
d7b4c67953 Fix config when set to empty string
All checks were successful
continuous-integration/drone/push Build is passing
2024-09-14 16:40:22 +02:00
7489d4a32f Merge pull request 'Add config for separate primary domain Nostr pubkey' (#204) from feature/nostr_pubkey_primary_domain into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #204
Reviewed-by: Greg <greg@noreply.kosmos.org>
2024-09-13 12:33:11 +00:00
ac77e5b7c1 Allow ENV var for new setting
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 5s
2024-09-11 16:31:04 +02:00
e544c28105 Config for separate primary domain Nostr pubkey
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Allow to configure a separate key for the NIP-05 address of the primary
domain vs the accounts domain.
2024-09-11 16:28:12 +02:00
4909dac5c2 Fix typo
All checks were successful
continuous-integration/drone/push Build is passing
The return value of `strip!` is `nil`
2024-09-11 16:26:48 +02:00
3cf4348695 Merge pull request 'Make default user services configurable by admins' (#203) from feature/default_service_settings into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #203
Reviewed-by: galfert <garret.alfert@gmail.com>
2024-09-11 11:21:38 +00:00
af3da0a26c Set CORS headers for all .well-known responses
All checks were successful
continuous-integration/drone/push Build is passing
So we don't have to consider it for reverse proxies etc.
2024-09-10 16:06:11 +02:00
2d32320c7d Style check boxes
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 5s
2024-09-05 11:24:38 +02:00
19 changed files with 538 additions and 25 deletions

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
@jsr:registry=https://npm.jsr.io

View File

@@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y nodejs
WORKDIR /akkounts WORKDIR /akkounts
COPY ["Gemfile", "Gemfile.lock", "package.json", "./"] COPY ["Gemfile", "Gemfile.lock", "package.json", "yarn.lock", "./"]
RUN bundle install RUN bundle install
RUN gem install foreman RUN gem install foreman

View File

@@ -542,4 +542,4 @@ DEPENDENCIES
webmock webmock
BUNDLED WITH BUNDLED WITH
2.5.5 2.5.11

View File

@@ -25,7 +25,6 @@ class Admin::SettingsController < Admin::BaseController
end end
changed_keys.each do |key| changed_keys.each do |key|
Setting.send("#{key}=", clean_param(key)) Setting.send("#{key}=", clean_param(key))
end end
end end
@@ -42,7 +41,7 @@ class Admin::SettingsController < Admin::BaseController
def clean_param(key) def clean_param(key)
if Setting.get_field(key)[:type] == :string if Setting.get_field(key)[:type] == :string
setting_params[key].strip! setting_params[key].strip
else else
setting_params[key] setting_params[key]
end end

View File

@@ -1,7 +1,7 @@
class LnurlpayController < ApplicationController class LnurlpayController < ApplicationController
before_action :check_service_available before_action :check_service_available
before_action :find_user before_action :find_user
before_action :set_cors_access_control_headers, only: [:invoice] before_action :set_cors_access_control_headers
MIN_SATS = 10 MIN_SATS = 10
MAX_SATS = 1_000_000 MAX_SATS = 1_000_000

View File

@@ -1,8 +1,6 @@
class WebfingerController < ApplicationController class WebfingerController < WellKnownController
before_action :allow_cross_origin_requests, only: [:show] before_action :allow_cross_origin_requests, only: [:show]
layout false
def show def show
resource = params[:resource] resource = params[:resource]
@@ -76,7 +74,7 @@ class WebfingerController < ApplicationController
end end
def remotestorage_link def remotestorage_link
auth_url = new_rs_oauth_url(@username) auth_url = new_rs_oauth_url(@username, host: Setting.accounts_domain)
storage_url = "#{Setting.rs_storage_url}/#{@username}" storage_url = "#{Setting.rs_storage_url}/#{@username}"
{ {
@@ -91,10 +89,4 @@ class WebfingerController < ApplicationController
} }
} }
end end
def allow_cross_origin_requests
return unless Rails.env.development?
headers['Access-Control-Allow-Origin'] = "*"
headers['Access-Control-Allow-Methods'] = "GET"
end
end end

View File

@@ -1,5 +1,8 @@
class WellKnownController < ApplicationController class WellKnownController < ApplicationController
before_action :require_nostr_enabled, only: [ :nostr ] before_action :require_nostr_enabled, only: [ :nostr ]
before_action :allow_cross_origin_requests, only: [ :nostr ]
layout false
def nostr def nostr
http_status :unprocessable_entity and return if params[:name].blank? http_status :unprocessable_entity and return if params[:name].blank?
@@ -7,8 +10,14 @@ class WellKnownController < ApplicationController
relay_url = Setting.nostr_relay_url.presence relay_url = Setting.nostr_relay_url.presence
if params[:name] == "_" if params[:name] == "_"
# pubkey for the primary domain without a username (e.g. kosmos.org) if domain == Setting.primary_domain
res = { names: { "_": Setting.nostr_public_key } } # pubkey for the primary domain without a username (e.g. kosmos.org)
res = { names: { "_": Setting.nostr_public_key_primary_domain.presence || Setting.nostr_public_key } }
else
# pubkey for the akkounts domain without a username (e.g. accounts.kosmos.org)
res = { names: { "_": Setting.nostr_public_key } }
end
res[:relays] = { "_" => [ relay_url ] } if relay_url res[:relays] = { "_" => [ relay_url ] } if relay_url
else else
@user = User.where(cn: params[:name], ou: domain).first @user = User.where(cn: params[:name], ou: domain).first
@@ -30,4 +39,9 @@ class WellKnownController < ApplicationController
def require_nostr_enabled def require_nostr_enabled
http_status :not_found unless Setting.nostr_enabled? http_status :not_found unless Setting.nostr_enabled?
end end
def allow_cross_origin_requests
headers['Access-Control-Allow-Origin'] = "*"
headers['Access-Control-Allow-Methods'] = "GET"
end
end end

View File

@@ -1,4 +1,5 @@
import { Controller } from "@hotwired/stimulus" import { Controller } from "@hotwired/stimulus"
// import { Nostrify } from '@nostrify/nostrify';
// Connects to data-controller="nostr-login" // Connects to data-controller="nostr-login"
export default class extends Controller { export default class extends Controller {
@@ -6,6 +7,9 @@ export default class extends Controller {
static values = { site: String, sharedSecret: String } static values = { site: String, sharedSecret: String }
connect() { connect() {
// window.Nostrify = Nostrify;
// console.log(Nostrify);
if (window.nostr) { if (window.nostr) {
this.loginButtonTarget.disabled = false this.loginButtonTarget.disabled = false
this.loginFormTarget.classList.remove("hidden") this.loginFormTarget.classList.remove("hidden")

View File

@@ -12,6 +12,9 @@ module Settings
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_public_key_primary_domain, type: :string,
default: ENV["NOSTR_PUBLIC_KEY_PRIMARY_DOMAIN"].presence
field :nostr_relay_url, type: :string, field :nostr_relay_url, type: :string,
default: ENV["NOSTR_RELAY_URL"].presence default: ENV["NOSTR_RELAY_URL"].presence

View File

@@ -30,7 +30,8 @@
<% Setting.available_services.each do |option| %> <% Setting.available_services.each do |option| %>
<div class="md:inline-block"> <div class="md:inline-block">
<%= f.check_box :default_services, <%= f.check_box :default_services,
{ multiple: true, checked: Setting.default_services.include?(option) }, { multiple: true, checked: Setting.default_services.include?(option),
class: "h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-600 mr-0.5" },
option, nil %> option, nil %>
<%= f.label "default_services_#{option.parameterize}", service_human_name(option) %> <%= f.label "default_services_#{option.parameterize}", service_human_name(option) %>
</div> </div>

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_public_key_primary_domain,
title: "Public key for primary domain (NIP-05)",
description: "(optional) A different pubkey to announce for the _@#{Setting.primary_domain} Nostr address"
) %>
<%= render FormElements::FieldsetResettableSettingComponent.new( <%= render FormElements::FieldsetResettableSettingComponent.new(
key: :nostr_relay_url, key: :nostr_relay_url,
title: "Relay URL", title: "Relay URL",

View File

@@ -184,7 +184,7 @@
<td>XMPP (ejabberd)</td> <td>XMPP (ejabberd)</td>
<td> <td>
<%= render FormElements::ToggleComponent.new( <%= render FormElements::ToggleComponent.new(
enabled: @services_enabled.include?("xmpp"), enabled: @services_enabled.include?("ejabberd"),
input_enabled: false input_enabled: false
) %> ) %>
</td> </td>

245
deno.lock generated Normal file
View File

@@ -0,0 +1,245 @@
{
"version": "3",
"packages": {
"specifiers": {
"jsr:@deno/cache-dir@0.8": "jsr:@deno/cache-dir@0.8.0",
"jsr:@deno/emit": "jsr:@deno/emit@0.45.0",
"jsr:@luca/esbuild-deno-loader@0.9": "jsr:@luca/esbuild-deno-loader@0.9.0",
"jsr:@std/assert@^0.213.1": "jsr:@std/assert@0.213.1",
"jsr:@std/assert@^0.218.2": "jsr:@std/assert@0.218.2",
"jsr:@std/assert@^0.223.0": "jsr:@std/assert@0.223.0",
"jsr:@std/bytes@^0.218.2": "jsr:@std/bytes@0.218.2",
"jsr:@std/encoding@0.213": "jsr:@std/encoding@0.213.1",
"jsr:@std/fmt@^0.218.2": "jsr:@std/fmt@0.218.2",
"jsr:@std/fs@^0.218.2": "jsr:@std/fs@0.218.2",
"jsr:@std/io@^0.218.2": "jsr:@std/io@0.218.2",
"jsr:@std/jsonc@0.213": "jsr:@std/jsonc@0.213.1",
"jsr:@std/path@0.213": "jsr:@std/path@0.213.1",
"jsr:@std/path@^0.218.2": "jsr:@std/path@0.218.2",
"jsr:@std/path@^0.223.0": "jsr:@std/path@0.223.0",
"npm:esbuild@0.20": "npm:esbuild@0.20.2"
},
"jsr": {
"@deno/cache-dir@0.8.0": {
"integrity": "e87e80a404958f6350d903e6238b72afb92468378b0b32111f7a1e4916ac7fe7",
"dependencies": [
"jsr:@std/fmt@^0.218.2",
"jsr:@std/fs@^0.218.2",
"jsr:@std/io@^0.218.2",
"jsr:@std/path@^0.218.2"
]
},
"@deno/emit@0.45.0": {
"integrity": "b59d632e61dbe4be7e9e61235f02ad08ff124c714c31deb080c4de778da1894d",
"dependencies": [
"jsr:@deno/cache-dir@0.8",
"jsr:@std/path@^0.223.0"
]
},
"@luca/esbuild-deno-loader@0.9.0": {
"integrity": "288bbcede5c8a6f97e635f8fa4df779b13440ee0c0506d9e478fb6537789dc93",
"dependencies": [
"jsr:@std/encoding@0.213",
"jsr:@std/jsonc@0.213",
"jsr:@std/path@0.213",
"npm:esbuild@0.20"
]
},
"@std/assert@0.213.1": {
"integrity": "24c28178b30c8e0782c18e8e94ea72b16282207569cdd10ffb9d1d26f2edebfe"
},
"@std/assert@0.218.2": {
"integrity": "7f0a5a1a8cf86607cd6c2c030584096e1ffad27fc9271429a8cb48cfbdee5eaf"
},
"@std/assert@0.223.0": {
"integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24"
},
"@std/bytes@0.218.2": {
"integrity": "91fe54b232dcca73856b79a817247f4a651dbb60d51baafafb6408c137241670"
},
"@std/encoding@0.213.1": {
"integrity": "fcbb6928713dde941a18ca5db88ca1544d0755ec8fb20fe61e2dc8144b390c62"
},
"@std/fmt@0.218.2": {
"integrity": "99526449d2505aa758b6cbef81e7dd471d8b28ec0dcb1491d122b284c548788a"
},
"@std/fs@0.218.2": {
"integrity": "dd9431453f7282e8c577cc22c9e6d036055a9a980b5549f887d6012969fabcca"
},
"@std/io@0.218.2": {
"integrity": "c64fbfa087b7c9d4d386c5672f291f607d88cb7d44fc299c20c713e345f2785f",
"dependencies": [
"jsr:@std/assert@^0.218.2",
"jsr:@std/bytes@^0.218.2"
]
},
"@std/jsonc@0.213.1": {
"integrity": "5578f21aa583b7eb7317eed077ffcde47b294f1056bdbb9aacec407758637bfe",
"dependencies": [
"jsr:@std/assert@^0.213.1"
]
},
"@std/path@0.213.1": {
"integrity": "f187bf278a172752e02fcbacf6bd78a335ed320d080a7ed3a5a59c3e88abc673",
"dependencies": [
"jsr:@std/assert@^0.213.1"
]
},
"@std/path@0.218.2": {
"integrity": "b568fd923d9e53ad76d17c513e7310bda8e755a3e825e6289a0ce536404e2662",
"dependencies": [
"jsr:@std/assert@^0.218.2"
]
},
"@std/path@0.223.0": {
"integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989",
"dependencies": [
"jsr:@std/assert@^0.223.0"
]
}
},
"npm": {
"@esbuild/aix-ppc64@0.20.2": {
"integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
"dependencies": {}
},
"@esbuild/android-arm64@0.20.2": {
"integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
"dependencies": {}
},
"@esbuild/android-arm@0.20.2": {
"integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
"dependencies": {}
},
"@esbuild/android-x64@0.20.2": {
"integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
"dependencies": {}
},
"@esbuild/darwin-arm64@0.20.2": {
"integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
"dependencies": {}
},
"@esbuild/darwin-x64@0.20.2": {
"integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
"dependencies": {}
},
"@esbuild/freebsd-arm64@0.20.2": {
"integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
"dependencies": {}
},
"@esbuild/freebsd-x64@0.20.2": {
"integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
"dependencies": {}
},
"@esbuild/linux-arm64@0.20.2": {
"integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
"dependencies": {}
},
"@esbuild/linux-arm@0.20.2": {
"integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
"dependencies": {}
},
"@esbuild/linux-ia32@0.20.2": {
"integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
"dependencies": {}
},
"@esbuild/linux-loong64@0.20.2": {
"integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
"dependencies": {}
},
"@esbuild/linux-mips64el@0.20.2": {
"integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
"dependencies": {}
},
"@esbuild/linux-ppc64@0.20.2": {
"integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
"dependencies": {}
},
"@esbuild/linux-riscv64@0.20.2": {
"integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
"dependencies": {}
},
"@esbuild/linux-s390x@0.20.2": {
"integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
"dependencies": {}
},
"@esbuild/linux-x64@0.20.2": {
"integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
"dependencies": {}
},
"@esbuild/netbsd-x64@0.20.2": {
"integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
"dependencies": {}
},
"@esbuild/openbsd-x64@0.20.2": {
"integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
"dependencies": {}
},
"@esbuild/sunos-x64@0.20.2": {
"integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
"dependencies": {}
},
"@esbuild/win32-arm64@0.20.2": {
"integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
"dependencies": {}
},
"@esbuild/win32-ia32@0.20.2": {
"integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
"dependencies": {}
},
"@esbuild/win32-x64@0.20.2": {
"integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
"dependencies": {}
},
"esbuild@0.20.2": {
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
"dependencies": {
"@esbuild/aix-ppc64": "@esbuild/aix-ppc64@0.20.2",
"@esbuild/android-arm": "@esbuild/android-arm@0.20.2",
"@esbuild/android-arm64": "@esbuild/android-arm64@0.20.2",
"@esbuild/android-x64": "@esbuild/android-x64@0.20.2",
"@esbuild/darwin-arm64": "@esbuild/darwin-arm64@0.20.2",
"@esbuild/darwin-x64": "@esbuild/darwin-x64@0.20.2",
"@esbuild/freebsd-arm64": "@esbuild/freebsd-arm64@0.20.2",
"@esbuild/freebsd-x64": "@esbuild/freebsd-x64@0.20.2",
"@esbuild/linux-arm": "@esbuild/linux-arm@0.20.2",
"@esbuild/linux-arm64": "@esbuild/linux-arm64@0.20.2",
"@esbuild/linux-ia32": "@esbuild/linux-ia32@0.20.2",
"@esbuild/linux-loong64": "@esbuild/linux-loong64@0.20.2",
"@esbuild/linux-mips64el": "@esbuild/linux-mips64el@0.20.2",
"@esbuild/linux-ppc64": "@esbuild/linux-ppc64@0.20.2",
"@esbuild/linux-riscv64": "@esbuild/linux-riscv64@0.20.2",
"@esbuild/linux-s390x": "@esbuild/linux-s390x@0.20.2",
"@esbuild/linux-x64": "@esbuild/linux-x64@0.20.2",
"@esbuild/netbsd-x64": "@esbuild/netbsd-x64@0.20.2",
"@esbuild/openbsd-x64": "@esbuild/openbsd-x64@0.20.2",
"@esbuild/sunos-x64": "@esbuild/sunos-x64@0.20.2",
"@esbuild/win32-arm64": "@esbuild/win32-arm64@0.20.2",
"@esbuild/win32-ia32": "@esbuild/win32-ia32@0.20.2",
"@esbuild/win32-x64": "@esbuild/win32-x64@0.20.2"
}
}
}
},
"remote": {
"https://deno.land/x/denoflate@1.2.1/mod.ts": "f5628e44b80b3d80ed525afa2ba0f12408e3849db817d47a883b801f9ce69dd6",
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate.js": "b9f9ad9457d3f12f28b1fb35c555f57443427f74decb403113d67364e4f2caf4",
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate_bg.wasm.js": "d581956245407a2115a3d7e8d85a9641c032940a8e810acbd59ca86afd34d44d",
"https://deno.land/x/esbuild@v0.20.1/mod.js": "d50e500b53ce67e31116beba3916b0f9275c0e1cc20bc5cadc0fc1b7a3b06fd9"
},
"workspace": {
"packageJson": {
"dependencies": [
"npm:@jsr/nostrify__nostrify",
"npm:@tailwindcss/forms@^0.5.3",
"npm:autoprefixer@^10.4.13",
"npm:postcss-flexbugs-fixes@^5.0.2",
"npm:postcss-import@^15.0.1",
"npm:postcss-nested@^6.0.0",
"npm:postcss-preset-env@^7.8.3",
"npm:postcss@^8.4.19",
"npm:tailwindcss@^3.2.4"
]
}
}
}

14
lib/tasks/deno.rake Normal file
View File

@@ -0,0 +1,14 @@
namespace :deno do
desc "Download and prepare a Deno package for importmap"
task :prepare, [:package, :version] => :environment do |t, args|
unless args[:package] && args[:version]
raise "Usage: rake deno:prepare[package-name,version]"
end
# Build the package
system "deno run -A scripts/build_deno_package.ts #{args[:package]} #{args[:version]}"
# Pin the package using importmap
# system "bin/importmap pin #{args[:package]} --to vendor/javascript/#{args[:package]}/build.js"
end
end

View File

@@ -2,6 +2,7 @@
"name": "akkounts", "name": "akkounts",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@nostrify/nostrify": "npm:@jsr/nostrify__nostrify",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"postcss": "^8.4.19", "postcss": "^8.4.19",
@@ -11,7 +12,7 @@
"postcss-preset-env": "^7.8.3", "postcss-preset-env": "^7.8.3",
"tailwindcss": "^3.2.4" "tailwindcss": "^3.2.4"
}, },
"version": "0.9.0", "version": "0.10.0",
"scripts": { "scripts": {
"build:css:tailwind": "tailwindcss --postcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css", "build:css:tailwind": "tailwindcss --postcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css",
"build:css": "yarn run build:css:tailwind" "build:css": "yarn run build:css:tailwind"

18
scripts/build_deno_package.ts Executable file
View File

@@ -0,0 +1,18 @@
import { bundle } from "jsr:@deno/emit";
const [packageName, version] = Deno.args;
if (!packageName || !version) {
console.error('Usage: deno run -A build_deno_package.ts <package-name> <version>');
process.exit(1);
}
const result = await bundle(
new URL(`https://jsr.io/${packageName}/${version}/mod.ts`),
);
const { code } = result;
const buildFolder = `vendor/javascript/${packageName}`;
const buildFile = `${buildFolder}/build.js`
await Deno.mkdir(buildFolder, { recursive: true });
Deno.writeTextFileSync(buildFile, code);

View File

@@ -92,7 +92,13 @@ RSpec.describe "WebFinger", type: :request do
expect(rs_link["href"]).to eql("#{Setting.rs_storage_url}/tony") 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"] oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"]
expect(oauth_url).to eql("http://www.example.com/rs/oauth/tony") expect(oauth_url).to eql("http://accounts.kosmos.org/rs/oauth/tony")
end
it "returns CORS headers" do
get "/.well-known/nostr.json?name=bobdylan"
expect(response.headers['Access-Control-Allow-Origin']).to eq("*")
expect(response.headers['Access-Control-Allow-Methods']).to eq('GET')
end end
end end

View File

@@ -46,6 +46,12 @@ RSpec.describe "Well-known URLs", type: :request do
expect(res["names"]["bobdylan"]).to eq(user.nostr_pubkey) expect(res["names"]["bobdylan"]).to eq(user.nostr_pubkey)
end end
it "returns CORS headers" do
get "/.well-known/nostr.json?name=bobdylan"
expect(response.headers['Access-Control-Allow-Origin']).to eq("*")
expect(response.headers['Access-Control-Allow-Methods']).to eq('GET')
end
context "without relay configured" do context "without relay configured" do
before do before do
Setting.nostr_relay_url = "" Setting.nostr_relay_url = ""
@@ -73,10 +79,36 @@ RSpec.describe "Well-known URLs", type: :request do
end end
describe "placeholder username for domain's own pubkey" do describe "placeholder username for domain's own pubkey" do
it "returns the configured nostr pubkey" do describe "for primary domain" do
get "/.well-known/nostr.json?name=_" context "no different pubkey configured for primary domain" do
res = JSON.parse(response.body) it "returns the akkounts nostr pubkey" do
expect(res["names"]["_"]).to eq(Setting.nostr_public_key) get "/.well-known/nostr.json?name=_"
res = JSON.parse(response.body)
expect(res["names"]["_"]).to eq("bdd76ce2934b2f591f9fad2ebe9da18f20d2921de527494ba00eeaa0a0efadcf")
end
end
context "different pubkey configured for primary domain" do
before do
Setting.nostr_public_key_primary_domain = "b3e8f62fbe41217ffc0aa1e178d297339932d8ba4f46d9c7df3b61575e78fecc"
end
it "returns the primary domain's nostr pubkey" do
get "/.well-known/nostr.json?name=_"
res = JSON.parse(response.body)
expect(res["names"]["_"]).to eq("b3e8f62fbe41217ffc0aa1e178d297339932d8ba4f46d9c7df3b61575e78fecc")
end
end
end
describe "for akkounts domain" do
it "returns the configured nostr pubkey" do
headers = { "X-Forwarded-Host" => "accounts.kosmos.org" }
get "/.well-known/nostr.json?name=_"
res = JSON.parse(response.body)
expect(res["names"]["_"]).to eq("bdd76ce2934b2f591f9fad2ebe9da18f20d2921de527494ba00eeaa0a0efadcf")
end
end end
context "with relay configured" do context "with relay configured" do

178
yarn.lock
View File

@@ -108,6 +108,90 @@
resolved "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz" resolved "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz"
integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg== integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==
"@jsr/nostrify__types@^0.35.0":
version "0.35.0"
resolved "https://npm.jsr.io/~/11/@jsr/nostrify__types/0.35.0.tgz#449D2F6DAE75E5FF660595CF3C45437D14409AF4"
integrity sha512-dukOLFxyF7JwDvORLvb3PwMFs1HOBIkTyiewkujiGPaQ7FjvvGMiqY/QxbG0qZX5AmTtS65c/lLlg/ni1flrGQ==
"@jsr/std__assert@^0.224.0":
version "0.224.0"
resolved "https://npm.jsr.io/~/11/@jsr/std__assert/0.224.0.tgz#B6D7D05F367C7991EC67B19758EDB5BD0D86B385"
integrity sha512-RB0p0ydybgKSfTba6kHWytfpEJ0CBPi+byxZikLYa51L9uLINW52/j6n4KuiLFoh2cdFfpNZSNMY/dzQPW90DQ==
dependencies:
"@jsr/std__fmt" "^0.224.0"
"@jsr/std__internal" "^0.224.0"
"@jsr/std__crypto@^0.224.0":
version "0.224.0"
resolved "https://npm.jsr.io/~/11/@jsr/std__crypto/0.224.0.tgz#FA994A4B99E2D48B983E40B25D65A57BB405A04B"
integrity sha512-qzZWI8VnH215FS7hmQsAeNafjLMkmSl1OOvexorVUEf1Zl9omHSN87MwIjtmyVXGLtpGRLzIhKXbeup1xO69Zw==
dependencies:
"@jsr/std__assert" "^0.224.0"
"@jsr/std__encoding" "^0.224.0"
"@jsr/std__encoding@^0.224.0", "@jsr/std__encoding@^0.224.1":
version "0.224.3"
resolved "https://npm.jsr.io/~/11/@jsr/std__encoding/0.224.3.tgz#ADBBF3F2EFA8C4F7A9063CFEF679AFF46B984FF0"
integrity sha512-zAuX2QV1zwJ5RSmrnDGVerAtN3pBXpYYNlGzhERW9AiQ1UJd2/xruyB3i5NdTWy2OK2pjETswOj+0+prYTPlxQ==
"@jsr/std__fmt@^0.224.0":
version "0.224.0"
resolved "https://npm.jsr.io/~/11/@jsr/std__fmt/0.224.0.tgz#8079EB480C2BE2414430ECCF98F24C1C325B1277"
integrity sha512-lyrH5LesMB897QW0NIbZlGp72Ucopj2hMZW2wqB0NyZhuXfLH2sPBIUpCSf87kRKTGnx90JV905w4iTp0TD+Sg==
"@jsr/std__internal@^0.224.0":
version "0.224.0"
resolved "https://npm.jsr.io/~/11/@jsr/std__internal/0.224.0.tgz#939D6DE44B7340EB097C464AFD7E7476E814B6BE"
integrity sha512-inYzKOGAFK2tyy1D4NfwlbPiqEcSaXfOms3Tm4Y+1LmKSYOeB9wjqWHF4y/BJuYj8XUv61F7eaHaIw6NIlhBWg==
dependencies:
"@jsr/std__fmt" "^0.224.0"
"@noble/ciphers@^0.5.1":
version "0.5.3"
resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.5.3.tgz#48b536311587125e0d0c1535f73ec8375cd76b23"
integrity sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==
"@noble/curves@1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35"
integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==
dependencies:
"@noble/hashes" "1.3.2"
"@noble/curves@~1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d"
integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==
dependencies:
"@noble/hashes" "1.3.1"
"@noble/curves@~1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b"
integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==
dependencies:
"@noble/hashes" "1.5.0"
"@noble/hashes@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9"
integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==
"@noble/hashes@1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
"@noble/hashes@1.5.0", "@noble/hashes@~1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0"
integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==
"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@@ -129,6 +213,66 @@
"@nodelib/fs.scandir" "2.1.5" "@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0" fastq "^1.6.0"
"@nostrify/nostrify@npm:@jsr/nostrify__nostrify":
version "0.36.0"
resolved "https://npm.jsr.io/~/11/@jsr/nostrify__nostrify/0.36.0.tgz#9A94131A51DCAA501C2AA69878DEE453E5796653"
integrity sha512-8M/VHxP0qS1+nrt+GiDRBu3AtDaZhlOuPMH/BkqPtIyp1tAqBXAb6yCrAhxw/iORGUUronJpet1U8bEQz9K0xg==
dependencies:
"@jsr/nostrify__types" "^0.35.0"
"@jsr/std__crypto" "^0.224.0"
"@jsr/std__encoding" "^0.224.1"
"@scure/base" "^1.1.6"
"@scure/bip32" "^1.4.0"
"@scure/bip39" "^1.3.0"
lru-cache "^10.2.0"
nostr-tools "^2.7.0"
websocket-ts "^2.1.5"
zod "^3.23.8"
"@scure/base@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
"@scure/base@^1.1.6", "@scure/base@~1.1.0", "@scure/base@~1.1.7", "@scure/base@~1.1.8":
version "1.1.9"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1"
integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==
"@scure/bip32@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10"
integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==
dependencies:
"@noble/curves" "~1.1.0"
"@noble/hashes" "~1.3.1"
"@scure/base" "~1.1.0"
"@scure/bip32@^1.4.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.5.0.tgz#dd4a2e1b8a9da60e012e776d954c4186db6328e6"
integrity sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==
dependencies:
"@noble/curves" "~1.6.0"
"@noble/hashes" "~1.5.0"
"@scure/base" "~1.1.7"
"@scure/bip39@1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a"
integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==
dependencies:
"@noble/hashes" "~1.3.0"
"@scure/base" "~1.1.0"
"@scure/bip39@^1.3.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.4.0.tgz#664d4f851564e2e1d4bffa0339f9546ea55960a6"
integrity sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==
dependencies:
"@noble/hashes" "~1.5.0"
"@scure/base" "~1.1.8"
"@tailwindcss/forms@^0.5.3": "@tailwindcss/forms@^0.5.3":
version "0.5.3" version "0.5.3"
resolved "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz" resolved "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz"
@@ -399,6 +543,11 @@ lilconfig@^2.0.5, lilconfig@^2.0.6:
resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz" resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz"
integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==
lru-cache@^10.2.0:
version "10.4.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
merge2@^1.3.0: merge2@^1.3.0:
version "1.4.1" version "1.4.1"
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
@@ -450,6 +599,25 @@ normalize-range@^0.1.2:
resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz"
integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
nostr-tools@^2.7.0:
version "2.7.2"
resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-2.7.2.tgz#74a6ff543a81da1dcce9563b9317faa17221acce"
integrity sha512-Bq3Ug0SZFtgtL1+0wCnAe8AJtI7yx/00/a2nUug9SkhfOwlKS92Tef12iCK9FdwXw+oFZWMtRnSwcLayQso+xA==
dependencies:
"@noble/ciphers" "^0.5.1"
"@noble/curves" "1.2.0"
"@noble/hashes" "1.3.1"
"@scure/base" "1.1.1"
"@scure/bip32" "1.3.1"
"@scure/bip39" "1.2.1"
optionalDependencies:
nostr-wasm v0.1.0
nostr-wasm@v0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/nostr-wasm/-/nostr-wasm-0.1.0.tgz#17af486745feb2b7dd29503fdd81613a24058d94"
integrity sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==
object-hash@^3.0.0: object-hash@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz"
@@ -901,6 +1069,11 @@ util-deprecate@^1.0.2:
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
websocket-ts@^2.1.5:
version "2.1.5"
resolved "https://registry.yarnpkg.com/websocket-ts/-/websocket-ts-2.1.5.tgz#b6b51f0afca89d6bc7ff71c9e74540f19ae0262c"
integrity sha512-rCNl9w6Hsir1azFm/pbjBEFzLD/gi7Th5ZgOxMifB6STUfTSovYAzryWw0TRvSZ1+Qu1Z5Plw4z42UfTNA9idA==
xtend@^4.0.2: xtend@^4.0.2:
version "4.0.2" version "4.0.2"
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz"
@@ -910,3 +1083,8 @@ yaml@^1.10.2:
version "1.10.2" version "1.10.2"
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
zod@^3.23.8:
version "3.23.8"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==