From ee12bf684e811b85e721cff07c8ef63d3948fcb1 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Wed, 11 Dec 2024 17:46:18 -0500 Subject: [PATCH 1/3] fix: Correct regular expression for version tags in release workflow --- .github/workflows/scheduled-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/scheduled-release.yml b/.github/workflows/scheduled-release.yml index b03d92698..312f00eb6 100644 --- a/.github/workflows/scheduled-release.yml +++ b/.github/workflows/scheduled-release.yml @@ -2,7 +2,8 @@ name: Versioned Release on: push: - tags: ["v*"] + tags: + - "v[0-9]+.[0-9]+.[0-9]+" branches: ["develop"] workflow_dispatch: From ac8c153b2898b29f24e59a5ee4193960ba10f90c Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Fri, 13 Dec 2024 15:10:27 -0500 Subject: [PATCH 2/3] feature/1120 leverage service authorization (#1188) * refactor: remove redundant branch trigger for scheduled releases * refactor: simplify process-compose commands and improve logging * refactor: remove redundant command * refactor: remove unused error variables and simplify database configuration * feat: introduce task runner for project automation * refactor: Remove hardcoded action and method from form components * refactor: move server setup to main.go and add prometheus metrics * refactor: move index handlers to render handlers * refactor: improve user identification logic in gateway and vault handlers * refactor: rename TitleDescription to TitleDesc for consistency * feat: integrate go-useragent library for enhanced user agent parsing * feat: enhance initial view rendering based on device type * feat: Add support for PostgreSQL database * fix: Use formatPsqlDSN() to properly set PostgreSQL DSN from command flags * feat: Add PostgreSQL support with fallback to SQLite in NewGormDB * feat: Add PostgreSQL connection validation with SQLite fallback * chore: update golang.org/x/crypto dependency to v0.31.0 * feat: add PKL-based configuration initialization * refactor: improve file naming consistency in cmd/sonrd * refactor: Improve init-pkl command with safer config file generation and error handling * fix: add logging for pkl evaluation results * refactor: Move credential handling to gateway context * refactor: Migrate session models to gateway package * refactor: rename models and update User model * chore: initial commit for address and pubkey functionality * refactor: move pubkey package to keys package * refactor: Rename models and add resolver service * feat: add gRPC clients for bank, DID, DWN, and SVC modules * refactor: Migrate title and description components from text package to hero package * refactor: improve file naming conventions * feat: add user credential validation * refactor: rename registration handlers and routes for clarity * * refactor: Decouple database and IPFS interactions from server setup * refactor: Migrate configuration from class-based to TOML-based structure * refactor: move network configuration files to sonr.net module * feature/1120-leverage-service-authorization * fix: correct DID identifier creation function name * feat: add compressed and uncompressed public keys to keyset * refactor: move address packages to crypto/address * feat: implement pubkey verification * refactor: remove ECDSA-related functions from keyshare and protocol modules * feat: Implement ECDSA signature serialization * * feat: add vault service for IPFS token storage * refactor: update ucan codec to use new DID generation method * refactor: refactor key management and move address parsers to keys package * refactor: rename key parsers and move to parsers package * fix: resolved import issues with the new spec * feat: improve user onboarding experience by updating button text and functionality * refactor: update point marshaling and unmarshaling methods to use JSON * refactor: remove unnecessary DID method from PubKey * refactor: Rename and refactor MPC key generation functions * test: Add comprehensive test suite for keyshare generation and validation * test: Fix keyshare role validation and encoding tests * feat: Update key share role tests with enclave initialization validation * test(mpc): refactor tests to focus on public API and remove internal role checks * refactor: Remove unnecessary role check in initKeyEnclave function * fix: Enforce strict order for validator and user keyshares in enclave initialization * fix: Update codec_test to match latest codec implementation * refactor: Update KeyEnclave to use string-based key shares and improve error handling * fix: Refactor MPC enclave to use string-based encoding and simplify key management * refactor: Remove redundant keyshare decoding tests in codec_test.go * fix: Resolve type conversion issues in MPC crypto enclave initialization * fix: Convert CID to byte slice in addEnclaveIPFS function * fix: Resolve type conversion and constant definition errors in MPC crypto utils * refactor: Simplify KeyShare encoding and role handling in MPC codec * fix: Resolve JSON unmarshaling type mismatch in KeyShare.Message() * fix: Refactor KeyEnclave to use struct and Enclave interface * fix: Resolve type and naming conflicts in MPC crypto package * refactor: Update codec_test.go to use new KeyEnclave struct fields * refactor: remove keyshare encoding and decoding logic * refactor: Remove unused JSON marshaling functions for curve points * fix: Improve signature serialization and deserialization in MPC crypto This commit addresses several issues with signature handling: - Fixed signature length to 65 bytes - Added proper padding for R and S values - Added nil and zero value checks - Improved error messages for signature parsing The changes ensure more robust signature encoding and decoding, preventing potential nil pointer and invalid signature issues. * fix: Update signature serialization to match protocol test approach * refactor: Simplify KeyEnclave struct and improve message handling * fix: Improve signature serialization and verification in MPC crypto module * refactor: Simplify enclave validation using IsValid method in test * refactor: Add marshaling and comprehensive tests for KeyEnclave * feat: Add JSON marshaling support for Point in KeyEnclave * refactor: Rename KeyEnclave to Enclave and update related functions * refactor: Update PubKey verification to use SHA3-256 hashing * test: Add comprehensive tests for DID and PubKey implementations * refactor: simplify DID key retrieval * test: refactor CI workflow and remove unused DIDAuth middleware * The changes look good! The updated workflows will now: 1. Run tests on push to master 2. Bump the version if the commit doesn't already start with 'bump:' 3. Trigger a release workflow automatically with the new version tag 4. Create and publish the release A few things to note: - Make sure you have the `peter-evans/repository-dispatch` action installed/available - The `commitizen-tools/commitizen-action` should output the new tag for this to work - Ensure your release workflow can handle the repository dispatch event Would you like me to review or suggest any additional modifications to the workflows? * ci(github actions): add build stage dependency for tests * fix(workflow): update workflow to trigger on PR edits * test: Update unit test dependencies * ci: Add GoReleaser dry-run check for merge group events * test: remove unnecessary dependencies between test jobs * ci: Make race and coverage tests depend on build tests --- .github/workflows/checks.yml | 122 +++ .github/workflows/label-pr.yml | 2 +- .github/workflows/run-tests.yml | 59 -- .github/workflows/scheduled-release.yml | 3 +- .github/workflows/version-bump.yml | 18 +- .gitignore | 3 - Makefile | 11 +- cmd/hway/cmds.go | 68 +- cmd/hway/main.go | 55 ++ cmd/motr/main.go | 4 +- cmd/sonrd/initpkl.go | 101 +++ cmd/sonrd/main.go | 2 +- crypto/core/curves/bls12377_curve.go | 8 +- crypto/core/curves/bls12381_curve.go | 8 +- crypto/core/curves/curve.go | 4 +- crypto/core/curves/ed25519_curve.go | 4 +- crypto/core/curves/k256_curve.go | 4 +- crypto/core/curves/p256_bench_test.go | 4 +- crypto/core/curves/p256_curve.go | 4 +- crypto/core/curves/pallas_curve.go | 4 +- crypto/keys/didkey.go | 157 ++++ crypto/keys/methods.go | 17 + crypto/keys/parsers/btc_parser.go | 1 + crypto/keys/parsers/cosmos_parser.go | 12 + crypto/keys/parsers/eth_parser.go | 1 + crypto/keys/parsers/fil_parser.go | 1 + .../key.go => keys/parsers/key_parser.go} | 32 +- crypto/keys/parsers/sol_parser.go | 1 + crypto/keys/parsers/ton_parser.go | 1 + crypto/keys/pubkey.go | 62 ++ crypto/keys/utils.go | 46 ++ crypto/mpc/codec.go | 22 + crypto/mpc/codec_test.go | 105 +++ crypto/mpc/enclave.go | 151 ++++ crypto/mpc/keyset.go | 61 -- crypto/mpc/keyshare.go | 71 -- crypto/mpc/protocol.go | 148 +--- crypto/mpc/share.go | 150 ---- crypto/mpc/spec/jwt.go | 83 ++ crypto/{ucan => mpc}/spec/source.go | 64 +- crypto/{ucan => mpc}/spec/ucan.go | 19 +- crypto/mpc/utils.go | 124 +++ crypto/ucan/attns/capability/capability.go | 1 - crypto/ucan/attns/resourcetype/resource.go | 33 - crypto/ucan/codec.go | 7 +- crypto/ucan/didkey/key_test.go | 86 -- crypto/ucan/spec/jwt.go | 98 --- crypto/ucan/token.go | 22 +- go.mod | 25 +- go.sum | 69 +- internal/gateway/context/context.go | 80 +- internal/gateway/context/middleware.go | 26 +- internal/gateway/context/session.go | 168 ---- internal/gateway/context/store.go | 58 ++ internal/gateway/handlers/index/data.go | 36 - internal/gateway/handlers/index/handlers.go | 13 - internal/gateway/handlers/index/views.templ | 48 -- .../gateway/handlers/index/views_templ.go | 155 ---- .../gateway/handlers/register/forms.templ | 51 -- .../gateway/handlers/register/forms_templ.go | 233 ------ .../gateway/handlers/register/views.templ | 33 - internal/gateway/handlers/render_index.go | 21 + .../handlers.go => render_register.go} | 29 +- .../gateway/handlers/validate_credential.go | 11 + internal/gateway/handlers/validate_profile.go | 8 + internal/gateway/models/db_orm.go | 37 + internal/gateway/models/form_data.go | 15 + internal/gateway/models/resolver.go | 1 + .../register/data.go => models/webauthn.go} | 52 +- internal/gateway/routes.go | 68 +- internal/gateway/services/resolver_service.go | 59 ++ internal/gateway/services/user_service.go | 7 + internal/gateway/services/vault_service.go | 18 + internal/gateway/views/initial_view.templ | 39 + .../initial_view_templ.go} | 130 ++- internal/gateway/views/register_view.templ | 69 ++ internal/gateway/views/register_view_templ.go | 501 ++++++++++++ internal/nebula/card/container.templ | 13 - internal/nebula/card/sonr_profile.templ | 2 +- internal/nebula/card/sonr_profile_templ.go | 2 +- internal/nebula/hero/social_buttons.templ | 15 + .../social_buttons_templ.go} | 14 +- internal/nebula/hero/start_button.templ | 11 + internal/nebula/hero/start_button_templ.go | 40 + internal/nebula/{text => hero}/titles.templ | 4 +- .../nebula/{text => hero}/titles_templ.go | 8 +- internal/nebula/input/input_handle.templ | 12 +- internal/nebula/input/input_handle_templ.go | 2 +- ...der_isHuman.templ => slider_isHuman.templ} | 0 ...Human_templ.go => slider_isHuman_templ.go} | 2 +- internal/nebula/layout/container.templ | 27 +- internal/nebula/layout/container_templ.go | 87 +- internal/nebula/layout/grid.templ | 24 + internal/nebula/layout/grid_templ.go | 129 +++ .../layout/{scripts.templ => head.templ} | 50 ++ .../{scripts_templ.go => head_templ.go} | 226 ++++-- internal/nebula/layout/layout.templ | 50 -- internal/nebula/layout/layout_templ.go | 82 +- .../handlers/{auth/handlers.go => auth.go} | 0 .../handlers/{authz/handlers.go => authz.go} | 0 .../handlers/{feeds/handlers.go => feeds.go} | 2 +- .../handlers/{index/handlers.go => index.go} | 12 +- .../{profile/handlers.go => profile.go} | 0 .../{search/handlers.go => search.go} | 0 .../{wallet/handlers.go => wallet.go} | 0 pkg/config/hway/Hway.pkl.go | 18 +- pkg/config/hway/init.pkl.go | 4 +- pkg/config/motr/Config.pkl.go | 2 +- pkg/config/motr/Environment.pkl.go | 2 +- pkg/config/motr/Motr.pkl.go | 2 +- pkg/config/motr/Schema.pkl.go | 2 +- pkg/config/motr/init.pkl.go | 10 +- pkg/database/sessions/models.go | 42 - pkg/database/sessions/sqlite.go | 42 - pkg/didauth/controller/config.go | 2 +- pkg/didauth/controller/middleware.go | 2 +- pkg/didauth/producer/context.go | 7 +- pkg/didauth/producer/middleware.go | 13 +- pkg/{common/ipfs => ipfsapi}/client.go | 2 +- pkg/{common/ipfs => ipfsapi}/file.go | 2 +- pkg/{common/ipfs => ipfsapi}/folder.go | 2 +- pkg/{common/ipfs/ipfs.go => ipfsapi/iface.go} | 2 +- .../store/ipfs.go => pkg/ipfsapi/ucans.go | 35 +- pkl/sonr.chain/App.pkl | 89 --- pkl/sonr.chain/Config.pkl | 154 ---- pkl/sonr.chain/Genesis.pkl | 747 ------------------ pkl/sonr.chain/PklProject | 22 - pkl/sonr.conf/PklProject.deps.json | 4 - pkl/{sonr.conf => sonr.net}/Hway.pkl | 5 +- pkl/{sonr.conf => sonr.net}/Motr.pkl | 2 +- pkl/{sonr.conf => sonr.net}/PklProject | 2 +- .../PklProject.deps.json | 0 132 files changed, 2818 insertions(+), 3336 deletions(-) create mode 100644 .github/workflows/checks.yml delete mode 100644 .github/workflows/run-tests.yml create mode 100644 cmd/sonrd/initpkl.go create mode 100644 crypto/keys/didkey.go create mode 100644 crypto/keys/methods.go create mode 100644 crypto/keys/parsers/btc_parser.go create mode 100644 crypto/keys/parsers/cosmos_parser.go create mode 100644 crypto/keys/parsers/eth_parser.go create mode 100644 crypto/keys/parsers/fil_parser.go rename crypto/{ucan/didkey/key.go => keys/parsers/key_parser.go} (86%) create mode 100644 crypto/keys/parsers/sol_parser.go create mode 100644 crypto/keys/parsers/ton_parser.go create mode 100644 crypto/keys/pubkey.go create mode 100644 crypto/keys/utils.go create mode 100644 crypto/mpc/codec.go create mode 100644 crypto/mpc/codec_test.go create mode 100644 crypto/mpc/enclave.go delete mode 100644 crypto/mpc/keyset.go delete mode 100644 crypto/mpc/keyshare.go delete mode 100644 crypto/mpc/share.go create mode 100644 crypto/mpc/spec/jwt.go rename crypto/{ucan => mpc}/spec/source.go (70%) rename crypto/{ucan => mpc}/spec/ucan.go (82%) create mode 100644 crypto/mpc/utils.go delete mode 100644 crypto/ucan/attns/capability/capability.go delete mode 100644 crypto/ucan/attns/resourcetype/resource.go delete mode 100644 crypto/ucan/didkey/key_test.go delete mode 100644 crypto/ucan/spec/jwt.go delete mode 100644 internal/gateway/context/session.go create mode 100644 internal/gateway/context/store.go delete mode 100644 internal/gateway/handlers/index/data.go delete mode 100644 internal/gateway/handlers/index/handlers.go delete mode 100644 internal/gateway/handlers/index/views.templ delete mode 100644 internal/gateway/handlers/index/views_templ.go delete mode 100644 internal/gateway/handlers/register/forms.templ delete mode 100644 internal/gateway/handlers/register/forms_templ.go delete mode 100644 internal/gateway/handlers/register/views.templ create mode 100644 internal/gateway/handlers/render_index.go rename internal/gateway/handlers/{register/handlers.go => render_register.go} (54%) create mode 100644 internal/gateway/handlers/validate_credential.go create mode 100644 internal/gateway/handlers/validate_profile.go create mode 100644 internal/gateway/models/db_orm.go create mode 100644 internal/gateway/models/form_data.go create mode 100644 internal/gateway/models/resolver.go rename internal/gateway/{handlers/register/data.go => models/webauthn.go} (52%) create mode 100644 internal/gateway/services/resolver_service.go create mode 100644 internal/gateway/services/user_service.go create mode 100644 internal/gateway/services/vault_service.go create mode 100644 internal/gateway/views/initial_view.templ rename internal/gateway/{handlers/register/views_templ.go => views/initial_view_templ.go} (61%) create mode 100644 internal/gateway/views/register_view.templ create mode 100644 internal/gateway/views/register_view_templ.go delete mode 100644 internal/nebula/card/container.templ create mode 100644 internal/nebula/hero/social_buttons.templ rename internal/nebula/{card/container_templ.go => hero/social_buttons_templ.go} (66%) create mode 100644 internal/nebula/hero/start_button.templ create mode 100644 internal/nebula/hero/start_button_templ.go rename internal/nebula/{text => hero}/titles.templ (79%) rename internal/nebula/{text => hero}/titles_templ.go (93%) rename internal/nebula/input/{input_slider_isHuman.templ => slider_isHuman.templ} (100%) rename internal/nebula/input/{input_slider_isHuman_templ.go => slider_isHuman_templ.go} (97%) create mode 100644 internal/nebula/layout/grid.templ create mode 100644 internal/nebula/layout/grid_templ.go rename internal/nebula/layout/{scripts.templ => head.templ} (71%) rename internal/nebula/layout/{scripts_templ.go => head_templ.go} (72%) rename internal/vault/handlers/{auth/handlers.go => auth.go} (100%) rename internal/vault/handlers/{authz/handlers.go => authz.go} (100%) rename internal/vault/handlers/{feeds/handlers.go => feeds.go} (75%) rename internal/vault/handlers/{index/handlers.go => index.go} (80%) rename internal/vault/handlers/{profile/handlers.go => profile.go} (100%) rename internal/vault/handlers/{search/handlers.go => search.go} (100%) rename internal/vault/handlers/{wallet/handlers.go => wallet.go} (100%) delete mode 100644 pkg/database/sessions/models.go delete mode 100644 pkg/database/sessions/sqlite.go rename pkg/{common/ipfs => ipfsapi}/client.go (99%) rename pkg/{common/ipfs => ipfsapi}/file.go (96%) rename pkg/{common/ipfs => ipfsapi}/folder.go (95%) rename pkg/{common/ipfs/ipfs.go => ipfsapi/iface.go} (97%) rename crypto/ucan/store/ipfs.go => pkg/ipfsapi/ucans.go (66%) delete mode 100644 pkl/sonr.chain/App.pkl delete mode 100644 pkl/sonr.chain/Config.pkl delete mode 100644 pkl/sonr.chain/Genesis.pkl delete mode 100644 pkl/sonr.chain/PklProject delete mode 100644 pkl/sonr.conf/PklProject.deps.json rename pkl/{sonr.conf => sonr.net}/Hway.pkl (86%) rename pkl/{sonr.conf => sonr.net}/Motr.pkl (97%) rename pkl/{sonr.conf => sonr.net}/PklProject (97%) rename pkl/{sonr.chain => sonr.net}/PklProject.deps.json (100%) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 000000000..925b0e543 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,122 @@ +name: Run All Checks + +on: + pull_request: + merge_group: + +jobs: + test-builds: + runs-on: ubuntu-latest + name: Run Build Tests + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: onsonr/sonr + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + - name: Run Sonrd Build + run: make build + - name: Run Hway Build + run: make build-hway + - name: Run Motr Build + run: make build-motr + + test-unit: + needs: [test-builds] + runs-on: ubuntu-latest + name: Run Unit Tests + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: onsonr/sonr + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + - run: make test-unit + + test-race: + runs-on: ubuntu-latest + needs: [test-builds] + name: Run Race Tests + continue-on-error: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: onsonr/sonr + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + - run: make test-race + + test-cover: + runs-on: ubuntu-latest + needs: [test-builds] + name: Run Coverage Tests + continue-on-error: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: onsonr/sonr + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + - run: make test-cover + + goreleaser-check: + if: github.event_name == 'merge_group' + needs: [test-unit] + runs-on: ubuntu-latest + name: Check GoReleaser Config + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: onsonr/sonr + fetch-depth: 0 + fetch-tags: true + + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + + - name: Check GoReleaser Config + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser-pro + version: latest + args: check + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} + + - name: GoReleaser Dry Run + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser-pro + version: latest + args: release --snapshot --clean --skip=publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/label-pr.yml b/.github/workflows/label-pr.yml index a5e0d6924..45788f43f 100644 --- a/.github/workflows/label-pr.yml +++ b/.github/workflows/label-pr.yml @@ -1,7 +1,7 @@ name: PR Labeler on: pull_request: - types: [opened] + types: [opened, edited] permissions: contents: read diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml deleted file mode 100644 index 23b76ef00..000000000 --- a/.github/workflows/run-tests.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Run Tests - -on: - pull_request: - merge_group: - -jobs: - test-unit: - runs-on: ubuntu-latest - name: Run Unit Tests - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - repository: onsonr/sonr - fetch-depth: 0 - fetch-tags: true - - - uses: actions/setup-go@v5 - with: - go-version: "1.23" - check-latest: true - - run: make test-unit - - test-race: - runs-on: ubuntu-latest - name: Run Race Tests - continue-on-error: true - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - repository: onsonr/sonr - fetch-depth: 0 - fetch-tags: true - - - uses: actions/setup-go@v5 - with: - go-version: "1.23" - check-latest: true - - run: make test-race - - test-cover: - runs-on: ubuntu-latest - name: Run Coverage Tests - continue-on-error: true - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - repository: onsonr/sonr - fetch-depth: 0 - fetch-tags: true - - - uses: actions/setup-go@v5 - with: - go-version: "1.23" - check-latest: true - - run: make test-cover diff --git a/.github/workflows/scheduled-release.yml b/.github/workflows/scheduled-release.yml index 312f00eb6..833a75b55 100644 --- a/.github/workflows/scheduled-release.yml +++ b/.github/workflows/scheduled-release.yml @@ -4,8 +4,9 @@ on: push: tags: - "v[0-9]+.[0-9]+.[0-9]+" - branches: ["develop"] workflow_dispatch: + repository_dispatch: + types: [trigger-release] permissions: contents: write diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index b8bf8e5e4..77133d9df 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -1,4 +1,4 @@ -name: Update Version +name: Update Version and Release on: push: @@ -27,13 +27,29 @@ jobs: runs-on: ubuntu-latest name: "Bump Version" if: ${{ !startsWith(github.event.head_commit.message, 'bump:') }} + outputs: + new_tag: ${{ steps.bump.outputs.new_tag }} steps: - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - name: Create bump and changelog + id: bump uses: commitizen-tools/commitizen-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} increment: "PATCH" + + trigger-release: + needs: [bump-version] + if: needs.bump-version.outputs.new_tag != '' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Trigger release workflow + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + event-type: trigger-release + client-payload: '{"tag": "${{ needs.bump-version.outputs.new_tag }}"}' diff --git a/.gitignore b/.gitignore index fb5218d21..9a864a977 100644 --- a/.gitignore +++ b/.gitignore @@ -61,9 +61,6 @@ override.tf.json .terraformrc terraform.rc -Taskfile.yml - -!deploy/**/Taskfile.yml # Misc .DS_Store diff --git a/Makefile b/Makefile index 47246cd08..cabbee6c1 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,6 @@ format: format-tools mod-tidy: go mod tidy - cd interchaintest && go mod tidy .PHONY: format-tools lint format mod-tidy @@ -312,8 +311,8 @@ sh-testnet: mod-tidy gen-pkl: init-env pkl-gen-go pkl/sonr.orm/UCAN.pkl pkl-gen-go pkl/sonr.orm/Models.pkl - pkl-gen-go pkl/sonr.conf/Hway.pkl - pkl-gen-go pkl/sonr.conf/Motr.pkl + pkl-gen-go pkl/sonr.net/Hway.pkl + pkl-gen-go pkl/sonr.net/Motr.pkl gen-templ: init-env templ generate @@ -343,9 +342,6 @@ logs-sonr: init-env .PHONY: deploy start start-tui start-uds stop stop-uds restart status start: build-hway init-env - bin/process-compose up --port $(PC_PORT_NUM) --log-file $(PC_LOG_FILE) --detached -f deploy/process-compose.yaml - -start-tui: build-hway init-env bin/process-compose up --port $(PC_PORT_NUM) --log-file $(PC_LOG_FILE) -f deploy/process-compose.yaml start-uds: build-hway init-env @@ -359,6 +355,9 @@ stop-uds: init-env status: init-env bin/process-compose project state --port $(PC_PORT_NUM) + +status-uds: init-env + bin/process-compose project state --use-uds --unix-socket $(PC_SOCKET_PATH) ############################################################################### ### help ### ############################################################################### diff --git a/cmd/hway/cmds.go b/cmd/hway/cmds.go index 1c90b34d3..e942cb7ed 100644 --- a/cmd/hway/cmds.go +++ b/cmd/hway/cmds.go @@ -6,27 +6,23 @@ import ( "net/http" "os" - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" - "github.com/onsonr/sonr/crypto/ucan" - "github.com/onsonr/sonr/internal/gateway" - "github.com/onsonr/sonr/pkg/common/ipfs" - config "github.com/onsonr/sonr/pkg/config/hway" - "github.com/onsonr/sonr/pkg/database/sessions" - "github.com/onsonr/sonr/pkg/didauth/producer" "github.com/spf13/cobra" ) // Command line flags var ( servePort int // Gateway http entry point (default 3000) - configDir string // Hway config directory (default hway) - sqliteFile string // SQLite database file (default hway.db) chainID string // Current chain ID (default sonr-testnet-1) ipfsGatewayURL string // IPFS gateway URL (default localhost:8080) sonrAPIURL string // Sonr API URL (default localhost:1317) sonrGrpcURL string // Sonr gRPC URL (default localhost:9090) sonrRPCURL string // Sonr RPC URL (default localhost:26657) + + sqliteFile string // SQLite database file (default hway.db) + psqlHost string // PostgresSQL Host Flag + psqlUser string // PostgresSQL User Flag + psqlPass string // PostgresSQL Password Flag + psqlDB string // PostgresSQL Database Flag ) func rootCmd() *cobra.Command { @@ -38,7 +34,11 @@ func rootCmd() *cobra.Command { if err != nil { panic(err) } - e, err := setupServer(env) + db, ipc, err := initDeps(env) + if err != nil { + panic(err) + } + e, err := setupServer(env, db, ipc) if err != nil { panic(err) } @@ -50,50 +50,22 @@ func rootCmd() *cobra.Command { }, } cmd.Flags().IntVar(&servePort, "serve-port", 3000, "Port to serve the gateway on") - cmd.Flags().StringVar(&configDir, "config-dir", "hway", "Directory to store config files") - cmd.Flags().StringVar(&sqliteFile, "sqlite-file", "hway.db", "File to store sqlite database") cmd.Flags().StringVar(&chainID, "chain-id", "sonr-testnet-1", "Chain ID") cmd.Flags().StringVar(&ipfsGatewayURL, "ipfs-gateway-url", "localhost:8080", "IPFS gateway URL") cmd.Flags().StringVar(&sonrAPIURL, "sonr-api-url", "localhost:1317", "Sonr API URL") cmd.Flags().StringVar(&sonrGrpcURL, "sonr-grpc-url", "localhost:9090", "Sonr gRPC URL") cmd.Flags().StringVar(&sonrRPCURL, "sonr-rpc-url", "localhost:26657", "Sonr RPC URL") + cmd.Flags().StringVar(&sqliteFile, "sqlite-file", "hway.db", "File to store sqlite database") + cmd.Flags().StringVar(&psqlHost, "psql-host", "", "PostgresSQL Host") + cmd.Flags().StringVar(&psqlUser, "psql-user", "", "PostgresSQL User") + cmd.Flags().StringVar(&psqlPass, "psql-pass", "", "PostgresSQL Password") + cmd.Flags().StringVar(&psqlDB, "psql-db", "", "PostgresSQL Database") return cmd } -func loadEnvImplFromArgs(args []string) (config.Hway, error) { - cmd := rootCmd() - if err := cmd.ParseFlags(args); err != nil { - return nil, err - } - - env := &config.HwayImpl{ - ServePort: servePort, - ConfigDir: configDir, - SqliteFile: sqliteFile, - ChainId: chainID, - IpfsGatewayUrl: ipfsGatewayURL, - SonrApiUrl: sonrAPIURL, - SonrGrpcUrl: sonrGrpcURL, - SonrRpcUrl: sonrRPCURL, - } - return env, nil -} - -// setupServer sets up the server -func setupServer(env config.Hway) (*echo.Echo, error) { - ipc, err := ipfs.NewClient() - if err != nil { - return nil, err - } - db, err := sessions.NewGormDB(env) - if err != nil { - return nil, err +func formatPsqlDSN() string { + if psqlHost == "" { + return "" } - e := echo.New() - e.IPExtractor = echo.ExtractIPDirect() - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - e.Use(producer.Middleware(ipc, ucan.ServicePermissions)) - gateway.RegisterRoutes(e, env, db) - return e, nil + return fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", psqlHost, psqlUser, psqlPass, psqlDB) } diff --git a/cmd/hway/main.go b/cmd/hway/main.go index 8e4da3a13..faa812dbb 100644 --- a/cmd/hway/main.go +++ b/cmd/hway/main.go @@ -4,6 +4,16 @@ import ( _ "embed" "fmt" "os" + + "github.com/labstack/echo-contrib/echoprometheus" + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + "github.com/onsonr/sonr/crypto/ucan" + "github.com/onsonr/sonr/internal/gateway" + config "github.com/onsonr/sonr/pkg/config/hway" + "github.com/onsonr/sonr/pkg/didauth/producer" + "github.com/onsonr/sonr/pkg/ipfsapi" + "gorm.io/gorm" ) // main is the entry point for the application @@ -15,3 +25,48 @@ func main() { } os.Exit(0) } + +func initDeps(env config.Hway) (*gorm.DB, ipfsapi.Client, error) { + db, err := gateway.NewDB(env) + if err != nil { + return nil, nil, err + } + + ipc, err := ipfsapi.NewClient() + if err != nil { + return nil, nil, err + } + + return db, ipc, nil +} + +func loadEnvImplFromArgs(args []string) (config.Hway, error) { + cmd := rootCmd() + if err := cmd.ParseFlags(args); err != nil { + return nil, err + } + + env := &config.HwayImpl{ + ServePort: servePort, + SqliteFile: sqliteFile, + ChainId: chainID, + IpfsGatewayUrl: ipfsGatewayURL, + SonrApiUrl: sonrAPIURL, + SonrGrpcUrl: sonrGrpcURL, + SonrRpcUrl: sonrRPCURL, + PsqlDSN: formatPsqlDSN(), + } + return env, nil +} + +// setupServer sets up the server +func setupServer(env config.Hway, db *gorm.DB, ipc ipfsapi.Client) (*echo.Echo, error) { + e := echo.New() + e.Use(echoprometheus.NewMiddleware("hway")) + e.IPExtractor = echo.ExtractIPDirect() + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + e.Use(producer.Middleware(ipc, ucan.ServicePermissions)) + gateway.RegisterRoutes(e, env, db) + return e, nil +} diff --git a/cmd/motr/main.go b/cmd/motr/main.go index e368eb866..c9e30c41c 100644 --- a/cmd/motr/main.go +++ b/cmd/motr/main.go @@ -11,7 +11,7 @@ import ( "github.com/onsonr/sonr/internal/vault" "github.com/onsonr/sonr/pkg/common/wasm" "github.com/onsonr/sonr/pkg/config/motr" - "github.com/onsonr/sonr/pkg/didauth/controller" + // "github.com/onsonr/sonr/pkg/didauth/controller" ) var ( @@ -49,7 +49,7 @@ func main() { e := echo.New() e.Use(wasm.ContextMiddleware) - e.Use(controller.Middleware(nil)) + // e.Use(controller.Middleware(nil)) vault.RegisterRoutes(e, config) wasm.ServeFetch(e) } diff --git a/cmd/sonrd/initpkl.go b/cmd/sonrd/initpkl.go new file mode 100644 index 000000000..b2bb624ba --- /dev/null +++ b/cmd/sonrd/initpkl.go @@ -0,0 +1,101 @@ +package main + +import ( + "context" + "log" + "os" + "path/filepath" + + "github.com/apple/pkl-go/pkl" + "github.com/spf13/cobra" +) + +var configDir string + +func newPklInitCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "init-pkl", + Short: "Initialize the Sonrd configuration using PKL", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions) + if err != nil { + return err + } + defer evaluator.Close() + + appPath := formatConfigPath(cmd, "app.toml") + configPath := formatConfigPath(cmd, "config.toml") + + // Create app.toml + if err := createAppToml(evaluator, appPath); err != nil { + cmd.PrintErrf("Failed to create app.toml: %v\n", err) + return err + } + cmd.Printf("Successfully created %s\n", appPath) + + // Create config.toml + if err := createConfigToml(evaluator, configPath); err != nil { + cmd.PrintErrf("Failed to create config.toml: %v\n", err) + return err + } + cmd.Printf("Successfully created %s\n", configPath) + + return nil + }, + } + cmd.Flags().StringVar(&configDir, "config-dir", "~/.sonr/config", "Path to where pkl files should be output") + return cmd +} + +func createAppToml(evaluator pkl.Evaluator, path string) error { + appSource := pkl.UriSource("https://pkl.sh/sonr.chain/0.0.2/App.pkl") + res, err := evaluator.EvaluateOutputText(context.Background(), appSource) + if err != nil { + return err + } + log.Printf("res: %s", res) + return writeConfigFile(path, res) +} + +func createConfigToml(evaluator pkl.Evaluator, path string) error { + configSource := pkl.UriSource("https://pkl.sh/sonr.chain/0.0.2/Config.pkl") + res, err := evaluator.EvaluateOutputText(context.Background(), configSource) + if err != nil { + return err + } + log.Printf("res: %s", res) + return writeConfigFile(path, res) +} + +func formatConfigPath(cmd *cobra.Command, fileName string) string { + configDir := cmd.Flag("config-dir").Value.String() + // Expand home directory if needed + if configDir[:2] == "~/" { + home, err := os.UserHomeDir() + if err == nil { + configDir = filepath.Join(home, configDir[2:]) + } + } + return filepath.Join(configDir, fileName) +} + +func writeConfigFile(path string, content string) error { + // Create the directory path if it doesn't exist + dir := filepath.Dir(path) + if err := os.MkdirAll(dir, 0o755); err != nil { + return err + } + + // Check if file already exists + if _, err := os.Stat(path); err == nil { + // File exists, create backup + backupPath := path + ".backup" + if err := os.Rename(path, backupPath); err != nil { + return err + } + } + + // Write the new config file + return os.WriteFile(path, []byte(content), 0o644) +} diff --git a/cmd/sonrd/main.go b/cmd/sonrd/main.go index 7080ac6d8..56513c66e 100644 --- a/cmd/sonrd/main.go +++ b/cmd/sonrd/main.go @@ -12,7 +12,7 @@ import ( func main() { rootCmd := NewRootCmd() - + rootCmd.AddCommand(newPklInitCmd()) if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { log.NewLogger(rootCmd.OutOrStderr()).Error("failure when running app", "err", err) os.Exit(1) diff --git a/crypto/core/curves/bls12377_curve.go b/crypto/core/curves/bls12377_curve.go index 8a41422f4..5fdf01552 100755 --- a/crypto/core/curves/bls12377_curve.go +++ b/crypto/core/curves/bls12377_curve.go @@ -601,11 +601,11 @@ func (p *PointBls12377G1) UnmarshalText(input []byte) error { } func (p *PointBls12377G1) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointBls12377G1) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } @@ -874,11 +874,11 @@ func (p *PointBls12377G2) UnmarshalText(input []byte) error { } func (p *PointBls12377G2) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointBls12377G2) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/core/curves/bls12381_curve.go b/crypto/core/curves/bls12381_curve.go index 5fa0910a3..2be154f42 100755 --- a/crypto/core/curves/bls12381_curve.go +++ b/crypto/core/curves/bls12381_curve.go @@ -573,11 +573,11 @@ func (p *PointBls12381G1) UnmarshalText(input []byte) error { } func (p *PointBls12381G1) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointBls12381G1) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } @@ -823,11 +823,11 @@ func (p *PointBls12381G2) UnmarshalText(input []byte) error { } func (p *PointBls12381G2) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointBls12381G2) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/core/curves/curve.go b/crypto/core/curves/curve.go index af497eee2..d06fb7f91 100755 --- a/crypto/core/curves/curve.go +++ b/crypto/core/curves/curve.go @@ -336,14 +336,14 @@ func pointUnmarshalText(input []byte) (Point, error) { return curve.Point.FromAffineCompressed(buffer) } -func pointMarshalJson(point Point) ([]byte, error) { +func pointMarshalJSON(point Point) ([]byte, error) { m := make(map[string]string, 2) m["type"] = point.CurveName() m["value"] = hex.EncodeToString(point.ToAffineCompressed()) return json.Marshal(m) } -func pointUnmarshalJson(input []byte) (Point, error) { +func pointUnmarshalJSON(input []byte) (Point, error) { var m map[string]string err := json.Unmarshal(input, &m) diff --git a/crypto/core/curves/ed25519_curve.go b/crypto/core/curves/ed25519_curve.go index 5b101e91b..9c31d7a5b 100755 --- a/crypto/core/curves/ed25519_curve.go +++ b/crypto/core/curves/ed25519_curve.go @@ -682,11 +682,11 @@ func (p *PointEd25519) UnmarshalText(input []byte) error { } func (p *PointEd25519) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointEd25519) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/core/curves/k256_curve.go b/crypto/core/curves/k256_curve.go index 70132dc39..3be001d32 100755 --- a/crypto/core/curves/k256_curve.go +++ b/crypto/core/curves/k256_curve.go @@ -653,11 +653,11 @@ func (p *PointK256) UnmarshalText(input []byte) error { } func (p *PointK256) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointK256) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/core/curves/p256_bench_test.go b/crypto/core/curves/p256_bench_test.go index 3799c3cc3..6fe7f8bce 100755 --- a/crypto/core/curves/p256_bench_test.go +++ b/crypto/core/curves/p256_bench_test.go @@ -701,11 +701,11 @@ func (p *BenchPointP256) UnmarshalText(input []byte) error { } func (p *BenchPointP256) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *BenchPointP256) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/core/curves/p256_curve.go b/crypto/core/curves/p256_curve.go index 363515557..2225bdb6b 100755 --- a/crypto/core/curves/p256_curve.go +++ b/crypto/core/curves/p256_curve.go @@ -651,11 +651,11 @@ func (p *PointP256) UnmarshalText(input []byte) error { } func (p *PointP256) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointP256) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/core/curves/pallas_curve.go b/crypto/core/curves/pallas_curve.go index b0cd1de7b..29f8424e6 100755 --- a/crypto/core/curves/pallas_curve.go +++ b/crypto/core/curves/pallas_curve.go @@ -669,11 +669,11 @@ func (p *PointPallas) UnmarshalText(input []byte) error { } func (p *PointPallas) MarshalJSON() ([]byte, error) { - return pointMarshalJson(p) + return pointMarshalJSON(p) } func (p *PointPallas) UnmarshalJSON(input []byte) error { - pt, err := pointUnmarshalJson(input) + pt, err := pointUnmarshalJSON(input) if err != nil { return err } diff --git a/crypto/keys/didkey.go b/crypto/keys/didkey.go new file mode 100644 index 000000000..ad4d0ec89 --- /dev/null +++ b/crypto/keys/didkey.go @@ -0,0 +1,157 @@ +package keys + +import ( + "crypto/ed25519" + "crypto/rsa" + "crypto/x509" + "fmt" + "strings" + + "github.com/libp2p/go-libp2p/core/crypto" + mb "github.com/multiformats/go-multibase" + varint "github.com/multiformats/go-varint" +) + +const ( + // KeyPrefix indicates a decentralized identifier that uses the key method + KeyPrefix = "did:key" + // MulticodecKindRSAPubKey rsa-x509-pub https://github.com/multiformats/multicodec/pull/226 + MulticodecKindRSAPubKey = 0x1205 + // MulticodecKindEd25519PubKey ed25519-pub + MulticodecKindEd25519PubKey = 0xed + // MulticodecKindSecp256k1PubKey secp256k1-pub + MulticodecKindSecp256k1PubKey = 0x1206 +) + +// DID is a DID:key identifier +type DID struct { + crypto.PubKey +} + +// NewDID constructs an Identifier from a public key +func NewDID(pub crypto.PubKey) (DID, error) { + switch pub.Type() { + case crypto.Ed25519, crypto.RSA, crypto.Secp256k1: + return DID{PubKey: pub}, nil + default: + return DID{}, fmt.Errorf("unsupported key type: %s", pub.Type()) + } +} + +// MulticodecType indicates the type for this multicodec +func (id DID) MulticodecType() uint64 { + switch id.Type() { + case crypto.RSA: + return MulticodecKindRSAPubKey + case crypto.Ed25519: + return MulticodecKindEd25519PubKey + case crypto.Secp256k1: + return MulticodecKindSecp256k1PubKey + default: + panic("unexpected crypto type") + } +} + +// String returns this did:key formatted as a string +func (id DID) String() string { + raw, err := id.Raw() + if err != nil { + return "" + } + + t := id.MulticodecType() + size := varint.UvarintSize(t) + data := make([]byte, size+len(raw)) + n := varint.PutUvarint(data, t) + copy(data[n:], raw) + + b58BKeyStr, err := mb.Encode(mb.Base58BTC, data) + if err != nil { + return "" + } + + return fmt.Sprintf("%s:%s", KeyPrefix, b58BKeyStr) +} + +// VerifyKey returns the backing implementation for a public key, one of: +// *rsa.PublicKey, ed25519.PublicKey +func (id DID) VerifyKey() (interface{}, error) { + rawPubBytes, err := id.Raw() + if err != nil { + return nil, err + } + switch id.Type() { + case crypto.RSA: + verifyKeyiface, err := x509.ParsePKIXPublicKey(rawPubBytes) + if err != nil { + return nil, err + } + verifyKey, ok := verifyKeyiface.(*rsa.PublicKey) + if !ok { + return nil, fmt.Errorf("public key is not an RSA key. got type: %T", verifyKeyiface) + } + return verifyKey, nil + case crypto.Ed25519: + return ed25519.PublicKey(rawPubBytes), nil + case crypto.Secp256k1: + // Handle both compressed and uncompressed Secp256k1 public keys + if len(rawPubBytes) == 65 || len(rawPubBytes) == 33 { + return rawPubBytes, nil + } + return nil, fmt.Errorf("invalid Secp256k1 public key length: %d", len(rawPubBytes)) + default: + return nil, fmt.Errorf("unrecognized Public Key type: %s", id.Type()) + } +} + +// Parse turns a string into a key method ID +func Parse(keystr string) (DID, error) { + var id DID + if !strings.HasPrefix(keystr, KeyPrefix) { + return id, fmt.Errorf("decentralized identifier is not a 'key' type") + } + + keystr = strings.TrimPrefix(keystr, KeyPrefix+":") + + enc, data, err := mb.Decode(keystr) + if err != nil { + return id, fmt.Errorf("decoding multibase: %w", err) + } + + if enc != mb.Base58BTC { + return id, fmt.Errorf("unexpected multibase encoding: %s", mb.EncodingToStr[enc]) + } + + keyType, n, err := varint.FromUvarint(data) + if err != nil { + return id, err + } + + switch keyType { + case MulticodecKindRSAPubKey: + pub, err := crypto.UnmarshalRsaPublicKey(data[n:]) + if err != nil { + return id, err + } + return DID{pub}, nil + case MulticodecKindEd25519PubKey: + pub, err := crypto.UnmarshalEd25519PublicKey(data[n:]) + if err != nil { + return id, err + } + return DID{pub}, nil + case MulticodecKindSecp256k1PubKey: + // Handle both compressed and uncompressed formats + keyData := data[n:] + if len(keyData) != 33 && len(keyData) != 65 { + return id, fmt.Errorf("invalid Secp256k1 public key length: %d", len(keyData)) + } + pub, err := crypto.UnmarshalSecp256k1PublicKey(keyData) + if err != nil { + return id, fmt.Errorf("failed to unmarshal Secp256k1 key: %w", err) + } + return DID{pub}, nil + } + + return id, fmt.Errorf("unrecognized key type multicodec prefix: %x", data[0]) +} diff --git a/crypto/keys/methods.go b/crypto/keys/methods.go new file mode 100644 index 000000000..7c972e8a6 --- /dev/null +++ b/crypto/keys/methods.go @@ -0,0 +1,17 @@ +package keys + +type DIDMethod string + +const ( + DIDMethodKey DIDMethod = "key" + DIDMethodSonr DIDMethod = "sonr" + DIDMehthodBitcoin DIDMethod = "btcr" + DIDMethodEthereum DIDMethod = "ethr" + DIDMethodCbor DIDMethod = "cbor" + DIDMethodCID DIDMethod = "cid" + DIDMethodIPFS DIDMethod = "ipfs" +) + +func (d DIDMethod) String() string { + return string(d) +} diff --git a/crypto/keys/parsers/btc_parser.go b/crypto/keys/parsers/btc_parser.go new file mode 100644 index 000000000..3ece6e2d4 --- /dev/null +++ b/crypto/keys/parsers/btc_parser.go @@ -0,0 +1 @@ +package parsers diff --git a/crypto/keys/parsers/cosmos_parser.go b/crypto/keys/parsers/cosmos_parser.go new file mode 100644 index 000000000..a66145cea --- /dev/null +++ b/crypto/keys/parsers/cosmos_parser.go @@ -0,0 +1,12 @@ +package parsers + +type CosmosPrefix string + +const ( + ATOMPrefix CosmosPrefix = "cosmos" + AXELARPrefix CosmosPrefix = "axelar" + EVMOSPrefix CosmosPrefix = "evmos" + OSMOPrefix CosmosPrefix = "osmo" + SONRPrefix CosmosPrefix = "idx" + STARSPrefix CosmosPrefix = "stars" +) diff --git a/crypto/keys/parsers/eth_parser.go b/crypto/keys/parsers/eth_parser.go new file mode 100644 index 000000000..3ece6e2d4 --- /dev/null +++ b/crypto/keys/parsers/eth_parser.go @@ -0,0 +1 @@ +package parsers diff --git a/crypto/keys/parsers/fil_parser.go b/crypto/keys/parsers/fil_parser.go new file mode 100644 index 000000000..3ece6e2d4 --- /dev/null +++ b/crypto/keys/parsers/fil_parser.go @@ -0,0 +1 @@ +package parsers diff --git a/crypto/ucan/didkey/key.go b/crypto/keys/parsers/key_parser.go similarity index 86% rename from crypto/ucan/didkey/key.go rename to crypto/keys/parsers/key_parser.go index 712237f1f..3a307cbc2 100644 --- a/crypto/ucan/didkey/key.go +++ b/crypto/keys/parsers/key_parser.go @@ -1,4 +1,4 @@ -package didkey +package parsers import ( "crypto/ed25519" @@ -23,23 +23,23 @@ const ( MulticodecKindSecp256k1PubKey = 0x1206 ) -// ID is a DID:key identifier -type ID struct { +// DIDKey is a DID:key identifier +type DIDKey struct { crypto.PubKey } -// NewID constructs an Identifier from a public key -func NewID(pub crypto.PubKey) (ID, error) { +// NewKeyDID constructs an Identifier from a public key +func NewKeyDID(pub crypto.PubKey) (DIDKey, error) { switch pub.Type() { case crypto.Ed25519, crypto.RSA, crypto.Secp256k1: - return ID{PubKey: pub}, nil + return DIDKey{PubKey: pub}, nil default: - return ID{}, fmt.Errorf("unsupported key type: %s", pub.Type()) + return DIDKey{}, fmt.Errorf("unsupported key type: %s", pub.Type()) } } // MulticodecType indicates the type for this multicodec -func (id ID) MulticodecType() uint64 { +func (id DIDKey) MulticodecType() uint64 { switch id.Type() { case crypto.RSA: return MulticodecKindRSAPubKey @@ -53,7 +53,7 @@ func (id ID) MulticodecType() uint64 { } // String returns this did:key formatted as a string -func (id ID) String() string { +func (id DIDKey) String() string { raw, err := id.Raw() if err != nil { return "" @@ -75,7 +75,7 @@ func (id ID) String() string { // VerifyKey returns the backing implementation for a public key, one of: // *rsa.PublicKey, ed25519.PublicKey -func (id ID) VerifyKey() (interface{}, error) { +func (id DIDKey) VerifyKey() (interface{}, error) { rawPubBytes, err := id.PubKey.Raw() if err != nil { return nil, err @@ -100,13 +100,13 @@ func (id ID) VerifyKey() (interface{}, error) { } return nil, fmt.Errorf("invalid Secp256k1 public key length: %d", len(rawPubBytes)) default: - return nil, fmt.Errorf("unrecognized Public Key type: %s", id.PubKey.Type()) + return nil, fmt.Errorf("unrecognized Public Key type: %s", id.Type()) } } // Parse turns a string into a key method ID -func Parse(keystr string) (ID, error) { - var id ID +func Parse(keystr string) (DIDKey, error) { + var id DIDKey if !strings.HasPrefix(keystr, KeyPrefix) { return id, fmt.Errorf("decentralized identifier is not a 'key' type") } @@ -133,13 +133,13 @@ func Parse(keystr string) (ID, error) { if err != nil { return id, err } - return ID{pub}, nil + return DIDKey{pub}, nil case MulticodecKindEd25519PubKey: pub, err := crypto.UnmarshalEd25519PublicKey(data[n:]) if err != nil { return id, err } - return ID{pub}, nil + return DIDKey{pub}, nil case MulticodecKindSecp256k1PubKey: // Handle both compressed and uncompressed formats keyData := data[n:] @@ -150,7 +150,7 @@ func Parse(keystr string) (ID, error) { if err != nil { return id, fmt.Errorf("failed to unmarshal Secp256k1 key: %w", err) } - return ID{pub}, nil + return DIDKey{pub}, nil } return id, fmt.Errorf("unrecognized key type multicodec prefix: %x", data[0]) diff --git a/crypto/keys/parsers/sol_parser.go b/crypto/keys/parsers/sol_parser.go new file mode 100644 index 000000000..3ece6e2d4 --- /dev/null +++ b/crypto/keys/parsers/sol_parser.go @@ -0,0 +1 @@ +package parsers diff --git a/crypto/keys/parsers/ton_parser.go b/crypto/keys/parsers/ton_parser.go new file mode 100644 index 000000000..3ece6e2d4 --- /dev/null +++ b/crypto/keys/parsers/ton_parser.go @@ -0,0 +1 @@ +package parsers diff --git a/crypto/keys/pubkey.go b/crypto/keys/pubkey.go new file mode 100644 index 000000000..b682f7f82 --- /dev/null +++ b/crypto/keys/pubkey.go @@ -0,0 +1,62 @@ +package keys + +import ( + "crypto/ecdsa" + "encoding/hex" + + "github.com/onsonr/sonr/crypto/core/curves" + "golang.org/x/crypto/sha3" +) + +type PubKey interface { + Bytes() []byte + Type() string + Hex() string + Verify(msg []byte, sig []byte) (bool, error) +} + +type pubKey struct { + publicPoint curves.Point + method string +} + +func NewPubKey(pk curves.Point) PubKey { + return &pubKey{ + publicPoint: pk, + } +} + +func (p pubKey) Bytes() []byte { + return p.publicPoint.ToAffineCompressed() +} + +func (p pubKey) Hex() string { + return hex.EncodeToString(p.publicPoint.ToAffineCompressed()) +} + +func (p pubKey) Type() string { + return "secp256k1" +} + +func (p pubKey) Verify(data []byte, sigBz []byte) (bool, error) { + sig, err := deserializeSignature(sigBz) + if err != nil { + return false, err + } + pp, err := getEcdsaPoint(p.Bytes()) + if err != nil { + return false, err + } + pk := &ecdsa.PublicKey{ + Curve: pp.Curve, + X: pp.X, + Y: pp.Y, + } + + // Hash the message using SHA3-256 + hash := sha3.New256() + hash.Write(data) + digest := hash.Sum(nil) + + return ecdsa.Verify(pk, digest, sig.R, sig.S), nil +} diff --git a/crypto/keys/utils.go b/crypto/keys/utils.go new file mode 100644 index 000000000..60e817119 --- /dev/null +++ b/crypto/keys/utils.go @@ -0,0 +1,46 @@ +package keys + +import ( + "errors" + "fmt" + "math/big" + + "github.com/onsonr/sonr/crypto/core/curves" +) + +// getEcdsaPoint builds an elliptic curve point from a compressed byte slice +func getEcdsaPoint(pubKey []byte) (*curves.EcPoint, error) { + crv := curves.K256() + x := new(big.Int).SetBytes(pubKey[1:33]) + y := new(big.Int).SetBytes(pubKey[33:]) + ecCurve, err := crv.ToEllipticCurve() + if err != nil { + return nil, fmt.Errorf("error converting curve: %v", err) + } + return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil +} + +// SerializeSecp256k1Signature serializes an ECDSA signature into a byte slice +func serializeSignature(sig *curves.EcdsaSignature) ([]byte, error) { + rBytes := sig.R.Bytes() + sBytes := sig.S.Bytes() + + sigBytes := make([]byte, 66) // V (1 byte) + R (32 bytes) + S (32 bytes) + sigBytes[0] = byte(sig.V) + copy(sigBytes[33-len(rBytes):33], rBytes) + copy(sigBytes[66-len(sBytes):66], sBytes) + return sigBytes, nil +} + +// DeserializeSecp256k1Signature deserializes an ECDSA signature from a byte slice +func deserializeSignature(sigBytes []byte) (*curves.EcdsaSignature, error) { + if len(sigBytes) != 66 { + return nil, errors.New("malformed signature: not the correct size") + } + sig := &curves.EcdsaSignature{ + V: int(sigBytes[0]), + R: new(big.Int).SetBytes(sigBytes[1:33]), + S: new(big.Int).SetBytes(sigBytes[33:66]), + } + return sig, nil +} diff --git a/crypto/mpc/codec.go b/crypto/mpc/codec.go new file mode 100644 index 000000000..bbe8fdfc0 --- /dev/null +++ b/crypto/mpc/codec.go @@ -0,0 +1,22 @@ +package mpc + +import ( + "github.com/onsonr/sonr/crypto/core/curves" + "github.com/onsonr/sonr/crypto/core/protocol" + "github.com/onsonr/sonr/crypto/tecdsa/dklsv1/dkg" +) + +// ╭───────────────────────────────────────────────────────────╮ +// │ Exported Generics │ +// ╰───────────────────────────────────────────────────────────╯ + +type ( + AliceOut *dkg.AliceOutput + BobOut *dkg.BobOutput + Point curves.Point + Role string // Role is the type for the role + Message *protocol.Message // Message is the protocol.Message that is used for MPC + Signature *curves.EcdsaSignature // Signature is the type for the signature + RefreshFunc interface{ protocol.Iterator } // RefreshFunc is the type for the refresh function + SignFunc interface{ protocol.Iterator } // SignFunc is the type for the sign function +) diff --git a/crypto/mpc/codec_test.go b/crypto/mpc/codec_test.go new file mode 100644 index 000000000..ac2a15ba4 --- /dev/null +++ b/crypto/mpc/codec_test.go @@ -0,0 +1,105 @@ +package mpc + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestKeyShareGeneration(t *testing.T) { + t.Run("Generate Valid Enclave", func(t *testing.T) { + // Generate enclave + enclave, err := GenEnclave() + require.NoError(t, err) + require.NotNil(t, enclave) + + // Validate enclave contents + assert.True(t, enclave.IsValid()) + }) +} + +func TestEnclaveOperations(t *testing.T) { + t.Run("Signing and Verification", func(t *testing.T) { + // Generate valid enclave + enclave, err := GenEnclave() + require.NoError(t, err) + + // Test signing + testData := []byte("test message") + signature, err := enclave.Sign(testData) + require.NoError(t, err) + require.NotNil(t, signature) + + // Verify the signature + valid, err := enclave.Verify(testData, signature) + require.NoError(t, err) + assert.True(t, valid) + + // Test invalid data verification + invalidData := []byte("wrong message") + valid, err = enclave.Verify(invalidData, signature) + require.NoError(t, err) + assert.False(t, valid) + }) + + t.Run("Address and Public Key", func(t *testing.T) { + enclave, err := GenEnclave() + require.NoError(t, err) + + // Test Address + addr := enclave.Address() + assert.NotEmpty(t, addr) + assert.True(t, strings.HasPrefix(addr, "idx")) + + // Test Public Key + pubKey := enclave.PubKey() + assert.NotNil(t, pubKey) + assert.NotEmpty(t, pubKey.Bytes()) + }) + + t.Run("Refresh Operation", func(t *testing.T) { + enclave, err := GenEnclave() + require.NoError(t, err) + + // Test refresh + refreshedEnclave, err := enclave.Refresh() + require.NoError(t, err) + require.NotNil(t, refreshedEnclave) + + // Verify refreshed enclave is valid + assert.True(t, refreshedEnclave.IsValid()) + + // Verify it maintains the same address + assert.Equal(t, enclave.Address(), refreshedEnclave.Address()) + }) +} + +func TestEnclaveSerialization(t *testing.T) { + t.Run("Marshal and Unmarshal", func(t *testing.T) { + // Generate original enclave + original, err := GenEnclave() + require.NoError(t, err) + require.NotNil(t, original) + + // Marshal + keyEnclave, ok := original.(*KeyEnclave) + require.True(t, ok) + + data, err := keyEnclave.Marshal() + require.NoError(t, err) + require.NotEmpty(t, data) + + // Unmarshal + restored := &KeyEnclave{} + err = restored.Unmarshal(data) + require.NoError(t, err) + + // Verify restored enclave + assert.Equal(t, keyEnclave.Addr, restored.Addr) + assert.True(t, keyEnclave.PubPoint.Equal(restored.PubPoint)) + assert.Equal(t, keyEnclave.VaultCID, restored.VaultCID) + assert.True(t, restored.IsValid()) + }) +} diff --git a/crypto/mpc/enclave.go b/crypto/mpc/enclave.go new file mode 100644 index 000000000..197d7d36f --- /dev/null +++ b/crypto/mpc/enclave.go @@ -0,0 +1,151 @@ +package mpc + +import ( + "crypto/ecdsa" + "encoding/json" + + "github.com/onsonr/sonr/crypto/core/curves" + "github.com/onsonr/sonr/crypto/core/protocol" + "github.com/onsonr/sonr/crypto/keys" + "github.com/onsonr/sonr/crypto/tecdsa/dklsv1" + "golang.org/x/crypto/sha3" +) + +// Enclave defines the interface for key management operations +type Enclave interface { + Address() string + IsValid() bool + PubKey() keys.PubKey + Refresh() (Enclave, error) + Sign(data []byte) ([]byte, error) + Verify(data []byte, sig []byte) (bool, error) +} + +// KeyEnclave implements the Enclave interface +type KeyEnclave struct { + Addr string `json:"address"` + PubPoint curves.Point `json:"-"` + PubBytes []byte `json:"pub_key"` + ValShare Message `json:"val_share"` + UserShare Message `json:"user_share"` + VaultCID string `json:"vault_cid,omitempty"` +} + +// Marshal returns the JSON encoding of KeyEnclave +func (k *KeyEnclave) Marshal() ([]byte, error) { + // Store compressed public point bytes before marshaling + k.PubBytes = k.PubPoint.ToAffineCompressed() + return json.Marshal(k) +} + +// Unmarshal parses the JSON-encoded data and stores the result +func (k *KeyEnclave) Unmarshal(data []byte) error { + if err := json.Unmarshal(data, k); err != nil { + return err + } + // Reconstruct Point from bytes + curve := curves.K256() + point, err := curve.NewIdentityPoint().FromAffineCompressed(k.PubBytes) + if err != nil { + return err + } + k.PubPoint = point + return nil +} + +func (k *KeyEnclave) IsValid() bool { + return k.PubPoint != nil && k.ValShare != nil && k.UserShare != nil && k.Addr != "" +} + +func initKeyEnclave(valShare, userShare Message) (*KeyEnclave, error) { + pubPoint, err := getAlicePubPoint(valShare) + if err != nil { + return nil, err + } + + addr, err := computeSonrAddr(pubPoint) + if err != nil { + return nil, err + } + return &KeyEnclave{ + Addr: addr, + PubPoint: pubPoint, + ValShare: valShare, + UserShare: userShare, + }, nil +} + +func (k *KeyEnclave) Address() string { + return k.Addr +} + +func (k *KeyEnclave) PubKey() keys.PubKey { + return keys.NewPubKey(k.PubPoint) +} + +func (k *KeyEnclave) Refresh() (Enclave, error) { + refreshFuncVal, err := k.valRefreshFunc() + if err != nil { + return nil, err + } + refreshFuncUser, err := k.userRefreshFunc() + if err != nil { + return nil, err + } + return ExecuteRefresh(refreshFuncVal, refreshFuncUser) +} + +func (k *KeyEnclave) Sign(data []byte) ([]byte, error) { + userSign, err := k.userSignFunc(data) + if err != nil { + return nil, err + } + valSign, err := k.valSignFunc(data) + if err != nil { + return nil, err + } + return ExecuteSigning(valSign, userSign) +} + +func (k *KeyEnclave) Verify(data []byte, sig []byte) (bool, error) { + edSig, err := deserializeSignature(sig) + if err != nil { + return false, err + } + ePub, err := getEcdsaPoint(k.PubPoint.ToAffineUncompressed()) + if err != nil { + return false, err + } + pk := &ecdsa.PublicKey{ + Curve: ePub.Curve, + X: ePub.X, + Y: ePub.Y, + } + + // Hash the message using SHA3-256 + hash := sha3.New256() + hash.Write(data) + digest := hash.Sum(nil) + + return ecdsa.Verify(pk, digest, edSig.R, edSig.S), nil +} + +func (k *KeyEnclave) userSignFunc(bz []byte) (SignFunc, error) { + curve := curves.K256() + return dklsv1.NewBobSign(curve, sha3.New256(), bz, k.UserShare, protocol.Version1) +} + +func (k *KeyEnclave) userRefreshFunc() (RefreshFunc, error) { + curve := curves.K256() + return dklsv1.NewBobRefresh(curve, k.UserShare, protocol.Version1) +} + +func (k *KeyEnclave) valSignFunc(bz []byte) (SignFunc, error) { + curve := curves.K256() + return dklsv1.NewAliceSign(curve, sha3.New256(), bz, k.ValShare, protocol.Version1) +} + +func (k *KeyEnclave) valRefreshFunc() (RefreshFunc, error) { + curve := curves.K256() + return dklsv1.NewAliceRefresh(curve, k.ValShare, protocol.Version1) +} diff --git a/crypto/mpc/keyset.go b/crypto/mpc/keyset.go deleted file mode 100644 index 074fe0a18..000000000 --- a/crypto/mpc/keyset.go +++ /dev/null @@ -1,61 +0,0 @@ -package mpc - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/types/bech32" -) - -type ( - ExportedKeyset = []byte -) - -type Keyset interface { - Address() string - Val() *ValKeyshare - ValJSON() string - User() *UserKeyshare - UserJSON() string -} - -type keyset struct { - val *ValKeyshare - user *UserKeyshare - addr string -} - -func (k keyset) Address() string { - return k.addr -} - -func (k keyset) Val() *ValKeyshare { - return k.val -} - -func (k keyset) User() *UserKeyshare { - return k.user -} - -func (k keyset) ValJSON() string { - return k.val.String() -} - -func (k keyset) UserJSON() string { - return k.user.String() -} - -func ComputeIssuerDID(pk []byte) (string, string, error) { - addr, err := ComputeSonrAddr(pk) - if err != nil { - return "", "", err - } - return fmt.Sprintf("did:sonr:%s", addr), addr, nil -} - -func ComputeSonrAddr(pk []byte) (string, error) { - sonrAddr, err := bech32.ConvertAndEncode("idx", pk) - if err != nil { - return "", err - } - return sonrAddr, nil -} diff --git a/crypto/mpc/keyshare.go b/crypto/mpc/keyshare.go deleted file mode 100644 index 241c9acdb..000000000 --- a/crypto/mpc/keyshare.go +++ /dev/null @@ -1,71 +0,0 @@ -package mpc - -import ( - "crypto/ecdsa" - - "github.com/onsonr/sonr/crypto/core/protocol" - "github.com/onsonr/sonr/crypto/tecdsa/dklsv1/dkg" -) - -// BaseKeyshare contains common fields and methods for both validator and user keyshares -type BaseKeyshare struct { - Message *protocol.Message `json:"message"` - Role int `json:"role"` - UncompressedPubKey []byte `json:"public_key"` - CompressedPubKey []byte `json:"compressed_public_key"` -} - -func initFromAlice(aliceOut *dkg.AliceOutput, originalMsg *protocol.Message) BaseKeyshare { - return BaseKeyshare{ - Message: originalMsg, - Role: 1, - UncompressedPubKey: aliceOut.PublicKey.ToAffineUncompressed(), - CompressedPubKey: aliceOut.PublicKey.ToAffineCompressed(), - } -} - -func initFromBob(bobOut *dkg.BobOutput, originalMsg *protocol.Message) BaseKeyshare { - return BaseKeyshare{ - Message: originalMsg, - Role: 2, - UncompressedPubKey: bobOut.PublicKey.ToAffineUncompressed(), - CompressedPubKey: bobOut.PublicKey.ToAffineCompressed(), - } -} - -func (b *BaseKeyshare) GetPayloads() map[string][]byte { - return b.Message.Payloads -} - -func (b *BaseKeyshare) GetMetadata() map[string]string { - return b.Message.Metadata -} - -func (b *BaseKeyshare) GetPublicKey() []byte { - return b.UncompressedPubKey -} - -func (b *BaseKeyshare) GetProtocol() string { - return b.Message.Protocol -} - -func (b *BaseKeyshare) GetRole() int32 { - return int32(b.Role) -} - -func (b *BaseKeyshare) GetVersion() uint32 { - return uint32(b.Message.Version) -} - -func (b *BaseKeyshare) ECDSAPublicKey() (*ecdsa.PublicKey, error) { - return ComputeEcdsaPublicKey(b.UncompressedPubKey) -} - -func (b *BaseKeyshare) ExtractMessage() *protocol.Message { - return &protocol.Message{ - Payloads: b.GetPayloads(), - Metadata: b.GetMetadata(), - Protocol: b.GetProtocol(), - Version: uint(b.GetVersion()), - } -} diff --git a/crypto/mpc/protocol.go b/crypto/mpc/protocol.go index 14ddddc93..aff0036c5 100644 --- a/crypto/mpc/protocol.go +++ b/crypto/mpc/protocol.go @@ -1,20 +1,14 @@ package mpc import ( - "crypto/ecdsa" - genericecdsa "crypto/ecdsa" - "errors" - "fmt" - "math/big" - + "github.com/ipfs/kubo/client/rpc" "github.com/onsonr/sonr/crypto/core/curves" "github.com/onsonr/sonr/crypto/core/protocol" "github.com/onsonr/sonr/crypto/tecdsa/dklsv1" - "golang.org/x/crypto/sha3" ) -// NewKeyshareSource generates a new MPC keyshare -func NewKeyset() (Keyset, error) { +// GenEnclave generates a new MPC keyshare +func GenEnclave() (Enclave, error) { curve := curves.K256() valKs := dklsv1.NewAliceDkg(curve, protocol.Version1) userKs := dklsv1.NewBobDkg(curve, protocol.Version1) @@ -26,27 +20,39 @@ func NewKeyset() (Keyset, error) { if err != nil { return nil, err } - valShare, err := NewValKeyshare(valRes) + userRes, err := userKs.Result(protocol.Version1) if err != nil { return nil, err } - userRes, err := userKs.Result(protocol.Version1) + return initKeyEnclave(valRes, userRes) +} + +// GenEnclaveIPFS generates a new MPC keyshare +func GenEnclaveIPFS(ipc *rpc.HttpApi) (Enclave, error) { + curve := curves.K256() + valKs := dklsv1.NewAliceDkg(curve, protocol.Version1) + userKs := dklsv1.NewBobDkg(curve, protocol.Version1) + aErr, bErr := RunProtocol(userKs, valKs) + if err := checkIteratedErrors(aErr, bErr); err != nil { + return nil, err + } + valRes, err := valKs.Result(protocol.Version1) if err != nil { return nil, err } - userShare, err := NewUserKeyshare(userRes) + userRes, err := userKs.Result(protocol.Version1) if err != nil { return nil, err } - addr, err := computeSonrAddr(valShare.CompressedPublicKey()) + e, err := initKeyEnclave(valRes, userRes) if err != nil { return nil, err } - return keyset{val: valShare, user: userShare, addr: addr}, nil + return addEnclaveIPFS(e, ipc) } // ExecuteSigning runs the MPC signing protocol -func ExecuteSigning(signFuncVal SignFunc, signFuncUser SignFunc) (Signature, error) { +func ExecuteSigning(signFuncVal SignFunc, signFuncUser SignFunc) ([]byte, error) { aErr, bErr := RunProtocol(signFuncVal, signFuncUser) if err := checkIteratedErrors(aErr, bErr); err != nil { return nil, err @@ -55,11 +61,19 @@ func ExecuteSigning(signFuncVal SignFunc, signFuncUser SignFunc) (Signature, err if err != nil { return nil, err } - return dklsv1.DecodeSignature(out) + s, err := dklsv1.DecodeSignature(out) + if err != nil { + return nil, err + } + sig, err := serializeSignature(s) + if err != nil { + return nil, err + } + return sig, nil } // ExecuteRefresh runs the MPC refresh protocol -func ExecuteRefresh(refreshFuncVal RefreshFunc, refreshFuncUser RefreshFunc) (Keyset, error) { +func ExecuteRefresh(refreshFuncVal RefreshFunc, refreshFuncUser RefreshFunc) (*KeyEnclave, error) { aErr, bErr := RunProtocol(refreshFuncVal, refreshFuncUser) if err := checkIteratedErrors(aErr, bErr); err != nil { return nil, err @@ -68,53 +82,11 @@ func ExecuteRefresh(refreshFuncVal RefreshFunc, refreshFuncUser RefreshFunc) (Ke if err != nil { return nil, err } - valShare, err := NewValKeyshare(valRefreshResult) - if err != nil { - return nil, err - } userRefreshResult, err := refreshFuncUser.Result(protocol.Version1) if err != nil { return nil, err } - userShare, err := NewUserKeyshare(userRefreshResult) - if err != nil { - return nil, err - } - addr, err := computeSonrAddr(valShare.CompressedPublicKey()) - if err != nil { - return nil, err - } - return keyset{val: valShare, user: userShare, addr: addr}, nil -} - -// SerializeSecp256k1Signature serializes an ECDSA signature into a byte slice -func SerializeSignature(sig Signature) ([]byte, error) { - rBytes := sig.R.Bytes() - sBytes := sig.S.Bytes() - - sigBytes := make([]byte, 66) // V (1 byte) + R (32 bytes) + S (32 bytes) - sigBytes[0] = byte(sig.V) - copy(sigBytes[33-len(rBytes):33], rBytes) - copy(sigBytes[66-len(sBytes):66], sBytes) - return sigBytes, nil -} - -// DeserializeSecp256k1Signature deserializes an ECDSA signature from a byte slice -func DeserializeSignature(sigBytes []byte) (Signature, error) { - if len(sigBytes) != 66 { - return nil, errors.New("malformed signature: not the correct size") - } - sig := &curves.EcdsaSignature{ - V: int(sigBytes[0]), - R: new(big.Int).SetBytes(sigBytes[1:33]), - S: new(big.Int).SetBytes(sigBytes[33:66]), - } - return sig, nil -} - -// VerifyMPCSignature verifies an MPC signature -func VerifyMPCSignature(sig Signature, msg []byte, publicKey *ecdsa.PublicKey) bool { - return ecdsa.Verify(publicKey, msg, sig.R, sig.S) + return initKeyEnclave(valRefreshResult, userRefreshResult) } // For DKG bob starts first. For refresh and sign, Alice starts first. @@ -139,59 +111,3 @@ func RunProtocol(firstParty protocol.Iterator, secondParty protocol.Iterator) (e } return aErr, bErr } - -// ComputeEcPoint builds an elliptic curve point from a compressed byte slice -func ComputeEcPoint(pubKey []byte) (*curves.EcPoint, error) { - crv := curves.K256() - x := new(big.Int).SetBytes(pubKey[1:33]) - y := new(big.Int).SetBytes(pubKey[33:]) - ecCurve, err := crv.ToEllipticCurve() - if err != nil { - return nil, fmt.Errorf("error converting curve: %v", err) - } - return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil -} - -func ComputeEcdsaPublicKey(pubKey []byte) (*genericecdsa.PublicKey, error) { - pk, err := ComputeEcPoint(pubKey) - if err != nil { - return nil, err - } - return &genericecdsa.PublicKey{ - Curve: pk.Curve, - X: pk.X, - Y: pk.Y, - }, nil -} - -// VerifySignature verifies the signature of a message -func VerifySignature(pk []byte, msg []byte, sig []byte) (bool, error) { - pp, err := ComputeEcPoint(pk) - if err != nil { - return false, err - } - sigEd, err := DeserializeSignature(sig) - if err != nil { - return false, err - } - hash := sha3.New256() - _, err = hash.Write(msg) - if err != nil { - return false, err - } - digest := hash.Sum(nil) - return curves.VerifyEcdsa(pp, digest[:], sigEd), nil -} - -func checkIteratedErrors(aErr, bErr error) error { - if aErr == protocol.ErrProtocolFinished && bErr == protocol.ErrProtocolFinished { - return nil - } - if aErr != protocol.ErrProtocolFinished { - return aErr - } - if bErr != protocol.ErrProtocolFinished { - return bErr - } - return nil -} diff --git a/crypto/mpc/share.go b/crypto/mpc/share.go deleted file mode 100644 index e8685a640..000000000 --- a/crypto/mpc/share.go +++ /dev/null @@ -1,150 +0,0 @@ -package mpc - -import ( - "errors" - - "github.com/cosmos/cosmos-sdk/types/bech32" - "github.com/onsonr/sonr/crypto/core/curves" - "github.com/onsonr/sonr/crypto/core/protocol" - "github.com/onsonr/sonr/crypto/tecdsa/dklsv1" - "golang.org/x/crypto/sha3" -) - -var ErrInvalidKeyshareRole = errors.New("invalid keyshare role") - -type Role int - -const ( - RoleUnknown Role = iota - RoleUser - RoleValidator -) - -func (r Role) IsUser() bool { - return r == RoleUser -} - -func (r Role) IsValidator() bool { - return r == RoleValidator -} - -// Message is the protocol.Message that is used for MPC -type Message *protocol.Message - -type Signature *curves.EcdsaSignature - -// RefreshFunc is the type for the refresh function -type RefreshFunc interface { - protocol.Iterator -} - -// SignFunc is the type for the sign function -type SignFunc interface { - protocol.Iterator -} - -type ValKeyshare struct { - BaseKeyshare - encoded string -} - -func computeSonrAddr(pk []byte) (string, error) { - sonrAddr, err := bech32.ConvertAndEncode("idx", pk) - if err != nil { - return "", err - } - return sonrAddr, nil -} - -func NewValKeyshare(msg *protocol.Message) (*ValKeyshare, error) { - vks := new(ValKeyshare) - encoded, err := protocol.EncodeMessage(msg) - if err != nil { - return nil, err - } - valShare, err := dklsv1.DecodeAliceDkgResult(msg) - if err != nil { - return nil, err - } - - vks.BaseKeyshare = initFromAlice(valShare, msg) - vks.encoded = encoded - return vks, nil -} - -func (v *ValKeyshare) RefreshFunc() (RefreshFunc, error) { - curve := curves.K256() - return dklsv1.NewAliceRefresh(curve, v.ExtractMessage(), protocol.Version1) -} - -func (v *ValKeyshare) SignFunc(msg []byte) (SignFunc, error) { - curve := curves.K256() - return dklsv1.NewAliceSign(curve, sha3.New256(), msg, v.ExtractMessage(), protocol.Version1) -} - -func (v *ValKeyshare) String() string { - return v.encoded -} - -// PublicKey returns the uncompressed public key (65 bytes) -func (v *ValKeyshare) PublicKey() []byte { - return v.UncompressedPubKey -} - -// CompressedPublicKey returns the compressed public key (33 bytes) -func (v *ValKeyshare) CompressedPublicKey() []byte { - return v.CompressedPubKey -} - -type UserKeyshare struct { - BaseKeyshare - encoded string -} - -func NewUserKeyshare(msg *protocol.Message) (*UserKeyshare, error) { - uks := new(UserKeyshare) - encoded, err := protocol.EncodeMessage(msg) - if err != nil { - return nil, err - } - out, err := dklsv1.DecodeBobDkgResult(msg) - if err != nil { - return nil, err - } - - uks.BaseKeyshare = initFromBob(out, msg) - uks.encoded = encoded - return uks, nil -} - -func (u *UserKeyshare) RefreshFunc() (RefreshFunc, error) { - curve := curves.K256() - return dklsv1.NewBobRefresh(curve, u.ExtractMessage(), protocol.Version1) -} - -func (u *UserKeyshare) SignFunc(msg []byte) (SignFunc, error) { - curve := curves.K256() - return dklsv1.NewBobSign(curve, sha3.New256(), msg, u.ExtractMessage(), protocol.Version1) -} - -func (u *UserKeyshare) String() string { - return u.encoded -} - -// PublicKey returns the uncompressed public key (65 bytes) -func (u *UserKeyshare) PublicKey() []byte { - return u.UncompressedPubKey -} - -// CompressedPublicKey returns the compressed public key (33 bytes) -func (u *UserKeyshare) CompressedPublicKey() []byte { - return u.CompressedPubKey -} - -func encodeMessage(m *protocol.Message) (string, error) { - return protocol.EncodeMessage(m) -} - -func decodeMessage(s string) (*protocol.Message, error) { - return protocol.DecodeMessage(s) -} diff --git a/crypto/mpc/spec/jwt.go b/crypto/mpc/spec/jwt.go new file mode 100644 index 000000000..7090fb605 --- /dev/null +++ b/crypto/mpc/spec/jwt.go @@ -0,0 +1,83 @@ +package spec + +import ( + "crypto/sha256" + + "github.com/golang-jwt/jwt" +) + +// MPCSigningMethod implements the SigningMethod interface for MPC-based signing +type MPCSigningMethod struct { + Name string + ks ucanKeyshare +} + +// NewJWTSigningMethod creates a new MPC signing method with the given keyshare source +func NewJWTSigningMethod(name string, ks ucanKeyshare) *MPCSigningMethod { + return &MPCSigningMethod{ + Name: name, + ks: ks, + } +} + +// Alg returns the signing method's name +func (m *MPCSigningMethod) Alg() string { + return m.Name +} + +// Verify verifies the signature using the MPC public key +func (m *MPCSigningMethod) Verify(signingString, signature string, key interface{}) error { + // // Decode the signature + // sig, err := base64.RawURLEncoding.DecodeString(signature) + // if err != nil { + // return err + // } + // + // // Hash the signing string + // hasher := sha256.New() + // hasher.Write([]byte(signingString)) + // digest := hasher.Sum(nil) + // valid, err := m.ks.valShare.PublicKey().Verify(digest, sig) + // if !valid || err != nil { + // return fmt.Errorf("invalid signature") + // } + return nil +} + +// Sign signs the data using MPC +func (m *MPCSigningMethod) Sign(signingString string, key interface{}) (string, error) { + // Hash the signing string + hasher := sha256.New() + hasher.Write([]byte(signingString)) + // digest := hasher.Sum(nil) + // + // // Create signing functions + // signFunc, err := m.ks.userShare.SignFunc(digest) + // if err != nil { + // return "", fmt.Errorf("failed to create sign function: %w", err) + // } + // + // valSignFunc, err := m.ks.valShare.SignFunc(digest) + // if err != nil { + // return "", fmt.Errorf("failed to create validator sign function: %w", err) + // } + + // // Run the signing protocol + // sig, err := mpc.ExecuteSigning(valSignFunc, signFunc) + // if err != nil { + // return "", fmt.Errorf("failed to run sign protocol: %w", err) + // } + + // Encode the signature + // encoded := base64.RawURLEncoding.EncodeToString(sig) + return "", nil +} + +func init() { + // Register the MPC signing method + jwt.RegisterSigningMethod("MPC256", func() jwt.SigningMethod { + return &MPCSigningMethod{ + Name: "MPC256", + } + }) +} diff --git a/crypto/ucan/spec/source.go b/crypto/mpc/spec/source.go similarity index 70% rename from crypto/ucan/spec/source.go rename to crypto/mpc/spec/source.go index 8e73c4d04..d1452ada4 100644 --- a/crypto/ucan/spec/source.go +++ b/crypto/mpc/spec/source.go @@ -5,9 +5,8 @@ import ( "fmt" "time" - "github.com/onsonr/sonr/crypto/mpc" + "github.com/onsonr/sonr/crypto/keys" "github.com/onsonr/sonr/crypto/ucan" - "github.com/onsonr/sonr/crypto/ucan/didkey" "lukechampine.com/blake3" ) @@ -23,21 +22,18 @@ type KeyshareSource interface { UCANParser() *ucan.TokenParser } -func NewSource(ks mpc.Keyset) (KeyshareSource, error) { - val := ks.Val() - user := ks.User() - iss, addr, err := ComputeIssuerDID(val.GetPublicKey()) - if err != nil { - return nil, err - } - return ucanKeyshare{ - userShare: user, - valShare: val, - addr: addr, - issuerDID: iss, - }, nil -} - +// func NewSource(ks mpc.KeyEnclave) (KeyshareSource, error) { +// iss, addr, err := getIssuerDID(val.PublicKey()) +// if err != nil { +// return nil, err +// } +// +// return ucanKeyshare{ +// issuerDID: iss, +// addr: addr, +// }, nil +// } +// // Address returns the address of the keyshare func (k ucanKeyshare) Address() string { return k.addr @@ -67,27 +63,25 @@ func (k ucanKeyshare) OriginToken() (*Token, error) { } func (k ucanKeyshare) SignData(data []byte) ([]byte, error) { - // Create signing functions - signFunc, err := k.userShare.SignFunc(data) - if err != nil { - return nil, fmt.Errorf("failed to create sign function: %w", err) - } - - valSignFunc, err := k.valShare.SignFunc(data) - if err != nil { - return nil, fmt.Errorf("failed to create validator sign function: %w", err) - } + // // Create signing functions + // signFunc, err := k.userShare.SignFunc(data) + // if err != nil { + // return nil, fmt.Errorf("failed to create sign function: %w", err) + // } + // + // valSignFunc, err := k.valShare.SignFunc(data) + // if err != nil { + // return nil, fmt.Errorf("failed to create validator sign function: %w", err) + // } // Run the signing protocol - sig, err := mpc.ExecuteSigning(valSignFunc, signFunc) - if err != nil { - return nil, fmt.Errorf("failed to run sign protocol: %w", err) - } - return mpc.SerializeSignature(sig) + // return mpc.ExecuteSigning(valSignFunc, signFunc) + return nil, nil } func (k ucanKeyshare) VerifyData(data []byte, sig []byte) (bool, error) { - return mpc.VerifySignature(k.userShare.PublicKey(), data, sig) + return false, nil + // return k.valShare.PublicKey().Verify(data, sig) } // TokenParser returns a token parser that can be used to parse tokens @@ -127,6 +121,6 @@ func (k ucanKeyshare) UCANParser() *ucan.TokenParser { type customDIDPubKeyResolver struct{} // ResolveDIDKey extracts a public key from a did:key string -func (customDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (didkey.ID, error) { - return didkey.Parse(didStr) +func (customDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (keys.DID, error) { + return keys.Parse(didStr) } diff --git a/crypto/ucan/spec/ucan.go b/crypto/mpc/spec/ucan.go similarity index 82% rename from crypto/ucan/spec/ucan.go rename to crypto/mpc/spec/ucan.go index 1d0576711..df5c24a2d 100644 --- a/crypto/ucan/spec/ucan.go +++ b/crypto/mpc/spec/ucan.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/bech32" "github.com/golang-jwt/jwt" - "github.com/onsonr/sonr/crypto/mpc" + "github.com/onsonr/sonr/crypto/keys" "github.com/onsonr/sonr/crypto/ucan" ) @@ -30,9 +30,6 @@ var ( ) type ucanKeyshare struct { - userShare *mpc.UserKeyshare - valShare *mpc.ValKeyshare - addr string issuerDID string } @@ -97,20 +94,10 @@ func (k ucanKeyshare) newToken(audienceDID string, prf []Proof, att Attenuations }, nil } -// ComputeIssuerDID computes the issuer DID from a public key -func ComputeIssuerDID(pk []byte) (string, string, error) { - addr, err := ComputeSonrAddr(pk) +func getIssuerDID(pk keys.PubKey) (string, string, error) { + addr, err := bech32.ConvertAndEncode("idx", pk.Bytes()) if err != nil { return "", "", err } return fmt.Sprintf("did:sonr:%s", addr), addr, nil } - -// ComputeSonrAddr computes the Sonr address from a public key -func ComputeSonrAddr(pk []byte) (string, error) { - sonrAddr, err := bech32.ConvertAndEncode("idx", pk) - if err != nil { - return "", err - } - return sonrAddr, nil -} diff --git a/crypto/mpc/utils.go b/crypto/mpc/utils.go new file mode 100644 index 000000000..c3c0b3317 --- /dev/null +++ b/crypto/mpc/utils.go @@ -0,0 +1,124 @@ +package mpc + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + + "github.com/cosmos/cosmos-sdk/types/bech32" + "github.com/ipfs/boxo/files" + "github.com/ipfs/kubo/client/rpc" + "github.com/onsonr/sonr/crypto/core/curves" + "github.com/onsonr/sonr/crypto/core/protocol" + "github.com/onsonr/sonr/crypto/tecdsa/dklsv1" +) + +func addEnclaveIPFS(enclave *KeyEnclave, ipc *rpc.HttpApi) (Enclave, error) { + jsonEnclave, err := json.Marshal(enclave) + if err != nil { + return nil, err + } + // Save enclave to IPFS + cid, err := ipc.Unixfs().Add(context.Background(), files.NewBytesFile(jsonEnclave)) + if err != nil { + return nil, err + } + enclave.VaultCID = cid.String() + return enclave, nil +} + +func checkIteratedErrors(aErr, bErr error) error { + if aErr == protocol.ErrProtocolFinished && bErr == protocol.ErrProtocolFinished { + return nil + } + if aErr != protocol.ErrProtocolFinished { + return aErr + } + if bErr != protocol.ErrProtocolFinished { + return bErr + } + return nil +} + +func computeSonrAddr(pp Point) (string, error) { + pk := pp.ToAffineCompressed() + sonrAddr, err := bech32.ConvertAndEncode("idx", pk) + if err != nil { + return "", err + } + return sonrAddr, nil +} + +func getAliceOut(msg *protocol.Message) (AliceOut, error) { + return dklsv1.DecodeAliceDkgResult(msg) +} + +func getAlicePubPoint(msg *protocol.Message) (Point, error) { + out, err := dklsv1.DecodeAliceDkgResult(msg) + if err != nil { + return nil, err + } + return out.PublicKey, nil +} + +func getBobOut(msg *protocol.Message) (BobOut, error) { + return dklsv1.DecodeBobDkgResult(msg) +} + +func getBobPubPoint(msg *protocol.Message) (Point, error) { + out, err := dklsv1.DecodeBobDkgResult(msg) + if err != nil { + return nil, err + } + return out.PublicKey, nil +} + +// getEcdsaPoint builds an elliptic curve point from a compressed byte slice +func getEcdsaPoint(pubKey []byte) (*curves.EcPoint, error) { + crv := curves.K256() + x := new(big.Int).SetBytes(pubKey[1:33]) + y := new(big.Int).SetBytes(pubKey[33:]) + ecCurve, err := crv.ToEllipticCurve() + if err != nil { + return nil, fmt.Errorf("error converting curve: %v", err) + } + return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil +} + +func serializeSignature(sig *curves.EcdsaSignature) ([]byte, error) { + if sig == nil { + return nil, errors.New("nil signature") + } + + rBytes := sig.R.Bytes() + sBytes := sig.S.Bytes() + + // Ensure both components are 32 bytes + rPadded := make([]byte, 32) + sPadded := make([]byte, 32) + copy(rPadded[32-len(rBytes):], rBytes) + copy(sPadded[32-len(sBytes):], sBytes) + + // Concatenate R and S + result := make([]byte, 64) + copy(result[0:32], rPadded) + copy(result[32:64], sPadded) + + return result, nil +} + +func deserializeSignature(sigBytes []byte) (*curves.EcdsaSignature, error) { + if len(sigBytes) != 64 { + return nil, fmt.Errorf("invalid signature length: expected 64 bytes, got %d", len(sigBytes)) + } + + r := new(big.Int).SetBytes(sigBytes[:32]) + s := new(big.Int).SetBytes(sigBytes[32:]) + + return &curves.EcdsaSignature{ + R: r, + S: s, + }, nil +} diff --git a/crypto/ucan/attns/capability/capability.go b/crypto/ucan/attns/capability/capability.go deleted file mode 100644 index bf4d0e392..000000000 --- a/crypto/ucan/attns/capability/capability.go +++ /dev/null @@ -1 +0,0 @@ -package capability diff --git a/crypto/ucan/attns/resourcetype/resource.go b/crypto/ucan/attns/resourcetype/resource.go deleted file mode 100644 index 9c1057ed1..000000000 --- a/crypto/ucan/attns/resourcetype/resource.go +++ /dev/null @@ -1,33 +0,0 @@ -package resourcetype - -// Resource is a unique identifier for a thing, usually stored state. Resources -// are organized by string types -type Resource interface { - Type() ResourceType - Value() string - Contains(b Resource) bool -} - -type stringResource struct { - t ResourceType - v string -} - -func (r stringResource) Type() ResourceType { - return r.t -} - -func (r stringResource) Value() string { - return r.v -} - -func (r stringResource) Contains(b Resource) bool { - return r.Type() == b.Type() && len(r.Value()) <= len(b.Value()) -} - -func NewResource(typ ResourceType, val string) Resource { - return stringResource{ - t: typ, - v: val, - } -} diff --git a/crypto/ucan/codec.go b/crypto/ucan/codec.go index 8728107be..8a757a1f7 100644 --- a/crypto/ucan/codec.go +++ b/crypto/ucan/codec.go @@ -98,12 +98,9 @@ func ServiceCapabilities() []string { // NewVault creates default attenuations for a smart account func NewVault( - kss mpc.Keyset, + kss mpc.KeyEnclave, ) Attenuations { - accountAddr, err := mpc.ComputeSonrAddr(kss.User().GetPublicKey()) - if err != nil { - return nil - } + accountAddr := kss.Address() caps := VaultPermissions.GetCapabilities() return Attenuations{ // Owner capabilities diff --git a/crypto/ucan/didkey/key_test.go b/crypto/ucan/didkey/key_test.go deleted file mode 100644 index 442ce742c..000000000 --- a/crypto/ucan/didkey/key_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package didkey - -import ( - "log" - "testing" - - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/onsonr/sonr/crypto/mpc" -) - -func TestID_Parse(t *testing.T) { - keyStrED := "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" - id, err := Parse(keyStrED) - if err != nil { - t.Fatal(err) - } - - if id.String() != keyStrED { - t.Errorf("string mismatch.\nwant: %q\ngot: %q", keyStrED, id.String()) - } - - keyStrRSA := "did:key:z2MGw4gk84USotaWf4AkJ83DcnrfgGaceF86KQXRYMfQ7xqnUFp38UZ6Le8JPfkb4uCLGjHBzKpjEXb9hx9n2ftecQWCHXKtKszkke4FmENdTZ7i9sqRmL3pLnEEJ774r3HMuuC7tNRQ6pqzrxatXx2WinCibdhUmvh3FobnA9ygeqkSGtV6WLa7NVFw9cAvnv8Y6oHcaoZK7fNP4ASGs6AHmSC6ydSR676aKYMe95QmEAj4xJptDsSxG7zLAGzAdwCgm56M4fTno8GdWNmU6Pdghnuf6fWyYus9ASwdfwyaf3SDf4uo5T16PRJssHkQh6DJHfK4Rka7RNQLjzfGBPjFLHbUSvmf4EdbHasbVaveAArD68ZfazRCCvjdovQjWr6uyLCwSAQLPUFZBTT8mW" - - id, err = Parse(keyStrRSA) - if err != nil { - t.Fatal(err) - } - - if id.String() != keyStrRSA { - t.Errorf("string mismatch.\nwant: %q\ngot: %q", keyStrRSA, id.String()) - } -} - -func TestID_FromMPCKey(t *testing.T) { - // Generate new MPC keyset - ks, err := mpc.NewKeyset() - if err != nil { - t.Fatalf("failed to generate MPC keyset: %v", err) - } - - // Get public key from validator share - pubKey := ks.Val().PublicKey() - if len(pubKey) != 65 { - t.Fatalf("expected 65-byte uncompressed public key, got %d bytes", len(pubKey)) - } - - // Create crypto.PubKey from raw bytes - cryptoPubKey, err := crypto.UnmarshalSecp256k1PublicKey(pubKey) - if err != nil { - t.Fatalf("failed to unmarshal public key: %v", err) - } - - // Create DID Key ID - id, err := NewID(cryptoPubKey) - if err != nil { - t.Fatalf("failed to create DID Key ID: %v", err) - } - log.Printf("%s\n", id.String()) - - // Verify the key can be parsed back - parsed, err := Parse(id.String()) - if err != nil { - t.Fatalf("failed to parse DID Key string: %v", err) - } - - // Verify the parsed key matches original - if parsed.String() != id.String() { - t.Errorf("parsed key doesn't match original.\nwant: %q\ngot: %q", - id.String(), parsed.String()) - } - - // Verify we can get back a valid verify key - verifyKey, err := id.VerifyKey() - if err != nil { - t.Fatalf("failed to get verify key: %v", err) - } - - // Verify the key is the right type and length - rawKey, ok := verifyKey.([]byte) - if !ok { - t.Fatalf("expected []byte verify key, got %T", verifyKey) - } - if len(rawKey) != 65 && len(rawKey) != 33 { - t.Errorf("invalid key length %d, expected 65 or 33 bytes", len(rawKey)) - } -} diff --git a/crypto/ucan/spec/jwt.go b/crypto/ucan/spec/jwt.go deleted file mode 100644 index cfcf050f4..000000000 --- a/crypto/ucan/spec/jwt.go +++ /dev/null @@ -1,98 +0,0 @@ -package spec - -import ( - "crypto/sha256" - "encoding/base64" - "fmt" - - "github.com/golang-jwt/jwt" - "github.com/onsonr/sonr/crypto/mpc" -) - -// MPCSigningMethod implements the SigningMethod interface for MPC-based signing -type MPCSigningMethod struct { - Name string - ks ucanKeyshare -} - -// NewJWTSigningMethod creates a new MPC signing method with the given keyshare source -func NewJWTSigningMethod(name string, ks ucanKeyshare) *MPCSigningMethod { - return &MPCSigningMethod{ - Name: name, - ks: ks, - } -} - -// Alg returns the signing method's name -func (m *MPCSigningMethod) Alg() string { - return m.Name -} - -// Verify verifies the signature using the MPC public key -func (m *MPCSigningMethod) Verify(signingString, signature string, key interface{}) error { - // Decode the signature - sig, err := base64.RawURLEncoding.DecodeString(signature) - if err != nil { - return err - } - - // Hash the signing string - hasher := sha256.New() - hasher.Write([]byte(signingString)) - digest := hasher.Sum(nil) - - // Verify using the keyshare's public key - valid, err := mpc.VerifySignature(m.ks.valShare.PublicKey(), digest, sig) - if err != nil { - return fmt.Errorf("failed to verify signature: %w", err) - } - if !valid { - return fmt.Errorf("invalid signature") - } - - return nil -} - -// Sign signs the data using MPC -func (m *MPCSigningMethod) Sign(signingString string, key interface{}) (string, error) { - // Hash the signing string - hasher := sha256.New() - hasher.Write([]byte(signingString)) - digest := hasher.Sum(nil) - - // Create signing functions - signFunc, err := m.ks.userShare.SignFunc(digest) - if err != nil { - return "", fmt.Errorf("failed to create sign function: %w", err) - } - - valSignFunc, err := m.ks.valShare.SignFunc(digest) - if err != nil { - return "", fmt.Errorf("failed to create validator sign function: %w", err) - } - - // Run the signing protocol - sig, err := mpc.ExecuteSigning(valSignFunc, signFunc) - if err != nil { - return "", fmt.Errorf("failed to run sign protocol: %w", err) - } - - // Serialize the signature - sigBytes, err := mpc.SerializeSignature(sig) - if err != nil { - return "", fmt.Errorf("failed to serialize signature: %w", err) - } - - // Encode the signature - encoded := base64.RawURLEncoding.EncodeToString(sigBytes) - return encoded, nil -} - -func init() { - // Register the MPC signing method - jwt.RegisterSigningMethod("MPC256", func() jwt.SigningMethod { - return &MPCSigningMethod{ - Name: "MPC256", - } - }) -} diff --git a/crypto/ucan/token.go b/crypto/ucan/token.go index ad4fef3a9..fc24f3063 100644 --- a/crypto/ucan/token.go +++ b/crypto/ucan/token.go @@ -21,7 +21,7 @@ import ( "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p/core/crypto" mh "github.com/multiformats/go-multihash" - "github.com/onsonr/sonr/crypto/ucan/didkey" + "github.com/onsonr/sonr/crypto/keys" ) // ErrInvalidToken indicates an access token is invalid @@ -47,8 +47,8 @@ const ( type Token struct { // Entire UCAN as a signed JWT string Raw string - Issuer didkey.ID - Audience didkey.ID + Issuer keys.DID + Audience keys.DID // the "inputs" to this token, a chain UCAN tokens with broader scopes & // deadlines than this token Proofs []Proof `json:"prf,omitempty"` @@ -261,12 +261,12 @@ func (a *pkSource) newToken(audienceDID string, prf []Proof, att Attenuations, f // DIDPubKeyResolver turns did:key Decentralized IDentifiers into a public key, // possibly using a network request type DIDPubKeyResolver interface { - ResolveDIDKey(ctx context.Context, did string) (didkey.ID, error) + ResolveDIDKey(ctx context.Context, did string) (keys.DID, error) } // DIDStringFromPublicKey creates a did:key identifier string from a public key func DIDStringFromPublicKey(pub crypto.PubKey) (string, error) { - id, err := didkey.NewID(pub) + id, err := keys.NewDID(pub) if err != nil { return "", err } @@ -279,8 +279,8 @@ func DIDStringFromPublicKey(pub crypto.PubKey) (string, error) { type StringDIDPubKeyResolver struct{} // ResolveDIDKey extracts a public key from a did:key string -func (StringDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (didkey.ID, error) { - return didkey.Parse(didStr) +func (StringDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (keys.DID, error) { + return keys.Parse(didStr) } // TokenParser parses a raw string into a Token @@ -315,11 +315,11 @@ func (p *TokenParser) parseAndVerify(ctx context.Context, raw string, child *Tok return nil, fmt.Errorf("parser fail") } - var iss didkey.ID + var iss keys.DID // TODO(b5): we're double parsing here b/c the jwt lib we're using doesn't expose // an API (that I know of) for storing parsed issuer / audience if issStr, ok := mc["iss"].(string); ok { - iss, err = didkey.Parse(issStr) + iss, err = keys.Parse(issStr) if err != nil { return nil, err } @@ -327,11 +327,11 @@ func (p *TokenParser) parseAndVerify(ctx context.Context, raw string, child *Tok return nil, fmt.Errorf(`"iss" key is not in claims`) } - var aud didkey.ID + var aud keys.DID // TODO(b5): we're double parsing here b/c the jwt lib we're using doesn't expose // an API (that I know of) for storing parsed issuer / audience if audStr, ok := mc["aud"].(string); ok { - aud, err = didkey.Parse(audStr) + aud, err = keys.Parse(audStr) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index f739b27e6..ff8be065d 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/bwesterb/go-ristretto v1.2.3 github.com/cometbft/cometbft v0.38.12 - github.com/consensys/gnark-crypto v0.12.1 + github.com/consensys/gnark-crypto v0.14.0 github.com/cosmos/btcutil v1.0.5 github.com/cosmos/cosmos-db v1.0.2 github.com/cosmos/cosmos-proto v1.0.0-beta.5 @@ -74,8 +74,10 @@ require ( github.com/ipfs/go-cid v0.4.1 github.com/ipfs/kubo v0.32.1 github.com/joho/godotenv v1.5.1 - github.com/labstack/echo/v4 v4.10.2 + github.com/labstack/echo-contrib v0.17.1 + github.com/labstack/echo/v4 v4.12.0 github.com/libp2p/go-libp2p v0.37.2 + github.com/medama-io/go-useragent v1.0.1 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 @@ -91,11 +93,12 @@ require ( github.com/strangelove-ventures/poa v0.50.0 github.com/strangelove-ventures/tokenfactory v0.50.0 github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.30.0 + golang.org/x/crypto v0.31.0 golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.2 + gorm.io/driver/postgres v1.5.11 gorm.io/driver/sqlite v1.5.6 gorm.io/gorm v1.25.12 lukechampine.com/blake3 v1.3.0 @@ -116,9 +119,10 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect - github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/bits-and-blooms/bitset v1.19.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/btcsuite/btcd v0.20.1-beta // indirect + github.com/boyter/go-string v1.0.5 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/caddyserver/certmagic v0.21.4 // indirect github.com/caddyserver/zerossl v0.1.3 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect @@ -133,7 +137,7 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v0.11.0 // indirect - github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/bavard v0.1.24 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.1.2 // indirect @@ -145,6 +149,7 @@ require ( github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect @@ -152,7 +157,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/dot v1.6.1 // indirect - github.com/ethereum/go-ethereum v1.14.6 // indirect + github.com/ethereum/go-ethereum v1.14.12 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -230,6 +235,10 @@ require ( github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect github.com/ipshipyard/p2p-forge v0.0.2 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.1 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect @@ -242,7 +251,7 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/labstack/gommon v0.4.0 // indirect + github.com/labstack/gommon v0.4.2 // indirect github.com/lib/pq v1.10.7 // indirect github.com/libdns/libdns v0.2.2 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect diff --git a/go.sum b/go.sum index d1f614469..a45f36d32 100644 --- a/go.sum +++ b/go.sum @@ -885,7 +885,6 @@ github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vc github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= @@ -958,30 +957,25 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= -github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.19.1 h1:mv2yVhy96D2CuskLPXnc58oJNMs5PCWjAZuyYU0p12M= +github.com/bits-and-blooms/bitset v1.19.1/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boyter/go-string v1.0.5 h1:/xcOlWdgelLYLVkUU0xBLfioGjZ9KIMUMI/RXG138YY= +github.com/boyter/go-string v1.0.5/go.mod h1:Mww9cDld2S2cdJ0tQffBhsZFMQRA2OJdcjWYZXvZ4Ss= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= @@ -1073,12 +1067,14 @@ github.com/cometbft/cometbft v0.38.12/go.mod h1:GPHp3/pehPqgX1930HmK1BpBLZPxB75v github.com/cometbft/cometbft-db v0.11.0 h1:M3Lscmpogx5NTbb1EGyGDaFRdsoLWrUWimFEyf7jej8= github.com/cometbft/cometbft-db v0.11.0/go.mod h1:GDPJAC/iFHNjmZZPN8V8C1yr/eyityhi2W1hz2MGKSc= github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/bavard v0.1.24 h1:Lfe+bjYbpaoT7K5JTFoMi5wo9V4REGLvQQbHmatoN2I= +github.com/consensys/bavard v0.1.24/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= +github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -1142,7 +1138,6 @@ github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -1152,8 +1147,9 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= @@ -1232,8 +1228,8 @@ github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHj github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= -github.com/ethereum/go-ethereum v1.14.6 h1:ZTxnErSopkDyxdvB8zW/KcK+/AVrdil/TzoWXVKaaC8= -github.com/ethereum/go-ethereum v1.14.6/go.mod h1:hglUZo/5pVIYXNyYjWzsAUDpT/zI+WbWo/Nih7ot+G0= +github.com/ethereum/go-ethereum v1.14.12 h1:8hl57x77HSUo+cXExrURjU/w1VhL+ShCTJrTwcCQSe4= +github.com/ethereum/go-ethereum v1.14.12/go.mod h1:RAC2gVMWJ6FkxSPESfbshrcKpIokgQKsVKmAuqdekDY= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -1770,6 +1766,14 @@ github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbk github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= +github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= @@ -1780,7 +1784,6 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -1796,7 +1799,6 @@ github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -1823,7 +1825,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -1863,15 +1864,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo-contrib v0.17.1 h1:7I/he7ylVKsDUieaGRZ9XxxTYOjfQwVzHzUYrNykfCU= +github.com/labstack/echo-contrib v0.17.1/go.mod h1:SnsCZtwHBAZm5uBSAtQtXQHI3wqEA73hvTn0bYMKnZA= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= -github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= +github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= +github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= @@ -1942,7 +1946,6 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -1975,6 +1978,8 @@ github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpe github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/medama-io/go-useragent v1.0.1 h1:staHGaZKIRpGI7sPVnyjYVT0SMRlQmp0L21rKYusi8Y= +github.com/medama-io/go-useragent v1.0.1/go.mod h1:H9GYWth4IN8vAFZh5LeARza7VwM4jK9uk7Tb9huVzLw= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw= @@ -2081,7 +2086,6 @@ github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DV github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= @@ -2090,7 +2094,6 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= @@ -2559,7 +2562,6 @@ go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZM go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -2597,8 +2599,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2910,7 +2912,6 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -3484,6 +3485,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= +gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= diff --git a/internal/gateway/context/context.go b/internal/gateway/context/context.go index 709e083d3..199aa5029 100644 --- a/internal/gateway/context/context.go +++ b/internal/gateway/context/context.go @@ -1,33 +1,30 @@ package context import ( - "regexp" - "strings" - - "github.com/labstack/echo/v4" + "github.com/onsonr/sonr/internal/gateway/models" "github.com/onsonr/sonr/pkg/common" - "github.com/onsonr/sonr/pkg/database/sessions" "github.com/segmentio/ksuid" ) -// InitSession initializes or loads an existing session -func (s *HTTPContext) InitSession() error { +// initSession initializes or loads an existing session +func (s *HTTPContext) initSession() error { sessionID := s.getOrCreateSessionID() // Try to load existing session - var sess sessions.Session + var sess models.Session result := s.db.Where("id = ?", sessionID).First(&sess) if result.Error != nil { // Create new session if not found - bn, bv, arch, plat, platVer, model := extractBrowserInfo(s.Context) - sess = sessions.Session{ - ID: sessionID, - BrowserName: bn, - BrowserVersion: bv, - UserArchitecture: arch, - Platform: plat, - PlatformVersion: platVer, - DeviceModel: model, + sess = models.Session{ + ID: sessionID, + BrowserName: s.GetBrowser(), + BrowserVersion: s.GetMajorVersion(), + Platform: s.GetOS(), + IsMobile: s.IsMobile(), + IsTablet: s.IsTablet(), + IsDesktop: s.IsDesktop(), + IsBot: s.IsBot(), + IsTV: s.IsTV(), } if err := s.db.Create(&sess).Error; err != nil { return err @@ -51,52 +48,3 @@ func (s *HTTPContext) getOrCreateSessionID() string { } return sessionID } - -func extractBrowserInfo(c echo.Context) (string, string, string, string, string, string) { - // Extract all relevant headers - browserName := common.HeaderRead(c, common.UserAgent) - arch := common.HeaderRead(c, common.Architecture) - platform := common.HeaderRead(c, common.Platform) - platformVer := common.HeaderRead(c, common.PlatformVersion) - model := common.HeaderRead(c, common.Model) - fullVersionList := common.HeaderRead(c, common.FullVersionList) - - // Default values if headers are empty - if browserName == "" { - browserName = "N/A" - } - if arch == "" { - arch = "unknown" - } - if platform == "" { - platform = "unknown" - } - if platformVer == "" { - platformVer = "unknown" - } - if model == "" { - model = "unknown" - } - - // Extract browser version from full version list - version := "-1" - if fullVersionList != "" { - entries := strings.Split(strings.TrimSpace(fullVersionList), ",") - for _, entry := range entries { - entry = strings.TrimSpace(entry) - re := regexp.MustCompile(`"([^"]+)";v="([^"]+)"`) - matches := re.FindStringSubmatch(entry) - - if len(matches) == 3 { - browserName = matches[1] - version = matches[2] - if browserName != "Not.A/Brand" && - browserName != "Chromium" { - break - } - } - } - } - - return browserName, version, arch, platform, platformVer, model -} diff --git a/internal/gateway/context/middleware.go b/internal/gateway/context/middleware.go index 7c7d26a90..c4377b688 100644 --- a/internal/gateway/context/middleware.go +++ b/internal/gateway/context/middleware.go @@ -4,17 +4,21 @@ import ( "net/http" "github.com/labstack/echo/v4" + "github.com/medama-io/go-useragent" + "github.com/onsonr/sonr/internal/gateway/models" + "github.com/onsonr/sonr/internal/gateway/services" config "github.com/onsonr/sonr/pkg/config/hway" - "github.com/onsonr/sonr/pkg/database/sessions" "gorm.io/gorm" ) // Middleware creates a new session middleware func Middleware(db *gorm.DB, env config.Hway) echo.MiddlewareFunc { + ua := useragent.NewParser() return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { - cc := NewHTTPContext(c, db) - if err := cc.InitSession(); err != nil { + agent := ua.Parse(c.Request().UserAgent()) + cc := NewHTTPContext(c, db, agent, env.GetSonrGrpcUrl()) + if err := cc.initSession(); err != nil { return err } return next(cc) @@ -25,9 +29,12 @@ func Middleware(db *gorm.DB, env config.Hway) echo.MiddlewareFunc { // HTTPContext is the context for HTTP endpoints. type HTTPContext struct { echo.Context + *services.ResolverService db *gorm.DB - sess *sessions.Session + sess *models.Session + user *models.User env config.Hway + useragent.UserAgent } // Get returns the HTTPContext from the echo context @@ -40,14 +47,17 @@ func Get(c echo.Context) (*HTTPContext, error) { } // NewHTTPContext creates a new session context -func NewHTTPContext(c echo.Context, db *gorm.DB) *HTTPContext { +func NewHTTPContext(c echo.Context, db *gorm.DB, a useragent.UserAgent, grpcAddr string) *HTTPContext { + rsv := services.NewResolverService(grpcAddr) return &HTTPContext{ - Context: c, - db: db, + Context: c, + db: db, + ResolverService: rsv, + UserAgent: a, } } // Session returns the current session -func (s *HTTPContext) Session() *sessions.Session { +func (s *HTTPContext) Session() *models.Session { return s.sess } diff --git a/internal/gateway/context/session.go b/internal/gateway/context/session.go deleted file mode 100644 index f312bdfb6..000000000 --- a/internal/gateway/context/session.go +++ /dev/null @@ -1,168 +0,0 @@ -package context - -import ( - "github.com/labstack/echo/v4" - "github.com/onsonr/sonr/pkg/database/sessions" -) - -// ╭───────────────────────────────────────────────────────╮ -// │ DB Setter Functions │ -// ╰───────────────────────────────────────────────────────╯ - -// SetUserHandle sets the user handle in the session -func SetUserHandle(c echo.Context, handle string) error { - sess, err := Get(c) - if err != nil { - return err - } - sess.Session().UserHandle = handle - return sess.db.Save(sess.Session()).Error -} - -// SetFirstName sets the first name in the session -func SetFirstName(c echo.Context, name string) error { - sess, err := Get(c) - if err != nil { - return err - } - sess.Session().FirstName = name - return sess.db.Save(sess.Session()).Error -} - -// SetLastInitial sets the last initial in the session -func SetLastInitial(c echo.Context, initial string) error { - sess, err := Get(c) - if err != nil { - return err - } - sess.Session().LastInitial = initial - return sess.db.Save(sess.Session()).Error -} - -// SetVaultAddress sets the vault address in the session -func SetVaultAddress(c echo.Context, address string) error { - sess, err := Get(c) - if err != nil { - return err - } - sess.Session().VaultAddress = address - return sess.db.Save(sess.Session()).Error -} - -// ╭───────────────────────────────────────────────────────╮ -// │ DB Getter Functions │ -// ╰───────────────────────────────────────────────────────╯ - -// GetID returns the session ID -func GetID(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().ID, nil -} - -// GetBrowserName returns the browser name -func GetBrowserName(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().BrowserName, nil -} - -// GetBrowserVersion returns the browser version -func GetBrowserVersion(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().BrowserVersion, nil -} - -// GetUserArchitecture returns the user architecture -func GetUserArchitecture(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().UserArchitecture, nil -} - -// GetPlatform returns the platform -func GetPlatform(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().Platform, nil -} - -// GetPlatformVersion returns the platform version -func GetPlatformVersion(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().PlatformVersion, nil -} - -// GetDeviceModel returns the device model -func GetDeviceModel(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().DeviceModel, nil -} - -// GetUserHandle returns the user handle -func GetUserHandle(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().UserHandle, nil -} - -// GetFirstName returns the first name -func GetFirstName(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().FirstName, nil -} - -// GetLastInitial returns the last initial -func GetLastInitial(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().LastInitial, nil -} - -// GetVaultAddress returns the vault address -func GetVaultAddress(c echo.Context) (string, error) { - sess, err := Get(c) - if err != nil { - return "", err - } - return sess.Session().VaultAddress, nil -} - -// HandleExists checks if a handle already exists in any session -func HandleExists(c echo.Context, handle string) (bool, error) { - sess, err := Get(c) - if err != nil { - return false, err - } - - var count int64 - if err := sess.db.Model(&sessions.Session{}).Where("user_handle = ?", handle).Count(&count).Error; err != nil { - return false, err - } - - return count > 0, nil -} diff --git a/internal/gateway/context/store.go b/internal/gateway/context/store.go new file mode 100644 index 000000000..14459c0d5 --- /dev/null +++ b/internal/gateway/context/store.go @@ -0,0 +1,58 @@ +package context + +import ( + "fmt" + + "github.com/labstack/echo/v4" + "github.com/onsonr/sonr/internal/gateway/models" +) + +func InsertCredential(c echo.Context, handle string, cred *models.CredentialDescriptor) error { + sess, err := Get(c) + if err != nil { + return err + } + return sess.db.Save(cred.ToDBModel(handle, c.Request().Host)).Error +} + +func InsertProfile(c echo.Context) error { + sess, err := Get(c) + if err != nil { + return err + } + handle := c.FormValue("handle") + firstName := c.FormValue("first_name") + lastName := c.FormValue("last_name") + return sess.db.Save(&models.User{ + Handle: handle, + Name: fmt.Sprintf("%s %s", firstName, lastName), + }).Error +} + +// ╭───────────────────────────────────────────────────────╮ +// │ DB Getter Functions │ +// ╰───────────────────────────────────────────────────────╯ + +// SessionID returns the session ID +func SessionID(c echo.Context) (string, error) { + sess, err := Get(c) + if err != nil { + return "", err + } + return sess.Session().ID, nil +} + +// HandleExists checks if a handle already exists in any session +func HandleExists(c echo.Context, handle string) (bool, error) { + sess, err := Get(c) + if err != nil { + return false, err + } + + var count int64 + if err := sess.db.Model(&models.User{}).Where("handle = ?", handle).Count(&count).Error; err != nil { + return false, err + } + + return count > 0, nil +} diff --git a/internal/gateway/handlers/index/data.go b/internal/gateway/handlers/index/data.go deleted file mode 100644 index 09b3077a5..000000000 --- a/internal/gateway/handlers/index/data.go +++ /dev/null @@ -1,36 +0,0 @@ -package index - -import ( - "github.com/labstack/echo/v4" - "github.com/onsonr/sonr/internal/gateway/context" -) - -// Initial users have no authorization, user handle, or vault address -func isInitial(c echo.Context) bool { - sess, err := context.Get(c) - if err != nil { - return false - } - data := sess.Session() - return data.UserHandle == "" && data.VaultAddress == "" -} - -// Expired users have either a user handle or vault address -func isExpired(c echo.Context) bool { - sess, err := context.Get(c) - if err != nil { - return false - } - data := sess.Session() - return data.UserHandle != "" || data.VaultAddress != "" -} - -// Returning users have a valid authorization, and either a user handle or vault address -func isReturning(c echo.Context) bool { - sess, err := context.Get(c) - if err != nil { - return false - } - data := sess.Session() - return data.UserHandle != "" && data.VaultAddress != "" -} diff --git a/internal/gateway/handlers/index/handlers.go b/internal/gateway/handlers/index/handlers.go deleted file mode 100644 index 1a56d8aa0..000000000 --- a/internal/gateway/handlers/index/handlers.go +++ /dev/null @@ -1,13 +0,0 @@ -package index - -import ( - "github.com/labstack/echo/v4" - "github.com/onsonr/sonr/pkg/common/response" -) - -func Handler(c echo.Context) error { - if isExpired(c) { - return response.TemplEcho(c, ReturningView()) - } - return response.TemplEcho(c, InitialView()) -} diff --git a/internal/gateway/handlers/index/views.templ b/internal/gateway/handlers/index/views.templ deleted file mode 100644 index f44f04ef2..000000000 --- a/internal/gateway/handlers/index/views.templ +++ /dev/null @@ -1,48 +0,0 @@ -package index - -import ( - "github.com/onsonr/sonr/internal/nebula/card" - "github.com/onsonr/sonr/internal/nebula/layout" - "github.com/onsonr/sonr/internal/nebula/text" -) - -templ InitialView() { - @layout.View("Sonr.ID") { - @card.Container() { - @text.TitleDescription("Sonr.ID", "The decentralized identity layer for the web.") -
- - - Get Started - - -
-
- - - - - - - - - -
- } - } -} - -templ ReturningView() { - @layout.View("Login | Sonr.ID") { - @card.Container() { - @text.TitleDescription("Welcome Back!", "Continue with your existing Sonr.ID.") -
- - - Log back in - - -
- } - } -} diff --git a/internal/gateway/handlers/index/views_templ.go b/internal/gateway/handlers/index/views_templ.go deleted file mode 100644 index 8a26cb929..000000000 --- a/internal/gateway/handlers/index/views_templ.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.2.793 -package index - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import ( - "github.com/onsonr/sonr/internal/nebula/card" - "github.com/onsonr/sonr/internal/nebula/layout" - "github.com/onsonr/sonr/internal/nebula/text" -) - -func InitialView() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = text.TitleDescription("Sonr.ID", "The decentralized identity layer for the web.").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Get Started
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = card.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = layout.View("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -func ReturningView() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var4 := templ.GetChildren(ctx) - if templ_7745c5c3_Var4 == nil { - templ_7745c5c3_Var4 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = text.TitleDescription("Welcome Back!", "Continue with your existing Sonr.ID.").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Log back in
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = card.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = layout.View("Login | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/gateway/handlers/register/forms.templ b/internal/gateway/handlers/register/forms.templ deleted file mode 100644 index 6c8609902..000000000 --- a/internal/gateway/handlers/register/forms.templ +++ /dev/null @@ -1,51 +0,0 @@ -package register - -import ( - "github.com/onsonr/sonr/internal/nebula/card" - "github.com/onsonr/sonr/internal/nebula/form" - "github.com/onsonr/sonr/internal/nebula/input" -) - -templ formCreateProfile(action string, method string, data CreateProfileData) { - @form.Root(action, method, "create-profile") { - @form.Body() { - @form.Header() { - - } - @input.Name() - @input.Handle() - @input.HumanSlider(data.FirstNumber, data.LastNumber) - @form.Footer() { - @form.CancelButton() - @form.SubmitButton("Next") - } - } - } -} - -templ formRegisterPasskey(action, method string, data RegisterPasskeyData) { -
- - -
-
- @card.SonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock) -
-
- @input.CoinSelect() -
- @input.Passkey(data.Address, data.Handle, data.Challenge) - - - Cancel - -
- -
-
-} diff --git a/internal/gateway/handlers/register/forms_templ.go b/internal/gateway/handlers/register/forms_templ.go deleted file mode 100644 index 3e13c1479..000000000 --- a/internal/gateway/handlers/register/forms_templ.go +++ /dev/null @@ -1,233 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.2.793 -package register - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import ( - "github.com/onsonr/sonr/internal/nebula/card" - "github.com/onsonr/sonr/internal/nebula/form" - "github.com/onsonr/sonr/internal/nebula/input" -) - -func formCreateProfile(action string, method string, data CreateProfileData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = form.Header().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = input.Name().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = input.Handle().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = input.HumanSlider(data.FirstNumber, data.LastNumber).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = form.CancelButton().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = form.SubmitButton("Next").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = form.Footer().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = form.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = form.Root(action, method, "create-profile").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -func formRegisterPasskey(action, method string, data RegisterPasskeyData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templ.GetChildren(ctx) - if templ_7745c5c3_Var6 == nil { - templ_7745c5c3_Var6 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = card.SonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = input.CoinSelect().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = input.Passkey(data.Address, data.Handle, data.Challenge).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" Cancel
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/gateway/handlers/register/views.templ b/internal/gateway/handlers/register/views.templ deleted file mode 100644 index bb9ea9215..000000000 --- a/internal/gateway/handlers/register/views.templ +++ /dev/null @@ -1,33 +0,0 @@ -package register - -import ( - "github.com/onsonr/sonr/internal/nebula/card" - "github.com/onsonr/sonr/internal/nebula/layout" - "github.com/onsonr/sonr/internal/nebula/text" -) - -templ ProfileFormView(data CreateProfileData) { - @layout.View("New Profile | Sonr.ID") { - @card.Container() { - @text.TitleDescription("Basic Info", "Tell us a little about yourself.") - @formCreateProfile("/register/start", "POST", data) - } - } -} - -templ LinkCredentialView(data RegisterPasskeyData) { - @layout.View("Register | Sonr.ID") { - @card.Container() { - @text.TitleDescription("Link a PassKey", "This will be used to login to your vault.") - @formRegisterPasskey("/register/finish", "POST", data) - } - } -} - -templ LoadingVaultView() { - @layout.View("Loading... | Sonr.ID") { - @card.Container() { - @text.TitleDescription("Loading Vault", "This will be used to login to your vault.") - } - } -} diff --git a/internal/gateway/handlers/render_index.go b/internal/gateway/handlers/render_index.go new file mode 100644 index 000000000..5fd086e77 --- /dev/null +++ b/internal/gateway/handlers/render_index.go @@ -0,0 +1,21 @@ +package handlers + +import ( + "github.com/labstack/echo/v4" + "github.com/onsonr/sonr/internal/gateway/context" + "github.com/onsonr/sonr/internal/gateway/views" + "github.com/onsonr/sonr/pkg/common/response" +) + +func RenderIndex(c echo.Context) error { + return response.TemplEcho(c, views.InitialView(isUnavailableDevice(c))) +} + +// isUnavailableDevice returns true if the device is unavailable +func isUnavailableDevice(c echo.Context) bool { + s, err := context.Get(c) + if err != nil { + return true + } + return s.IsBot() || s.IsTV() +} diff --git a/internal/gateway/handlers/register/handlers.go b/internal/gateway/handlers/render_register.go similarity index 54% rename from internal/gateway/handlers/register/handlers.go rename to internal/gateway/handlers/render_register.go index c04dff73f..8b9e23ea4 100644 --- a/internal/gateway/handlers/register/handlers.go +++ b/internal/gateway/handlers/render_register.go @@ -1,4 +1,4 @@ -package register +package handlers import ( "fmt" @@ -7,43 +7,48 @@ import ( "github.com/go-webauthn/webauthn/protocol" "github.com/labstack/echo/v4" "github.com/onsonr/sonr/crypto/mpc" + "github.com/onsonr/sonr/internal/gateway/models" + "github.com/onsonr/sonr/internal/gateway/views" "github.com/onsonr/sonr/pkg/common/response" + "golang.org/x/exp/rand" ) -func HandleCreateProfile(c echo.Context) error { - d := randomCreateProfileData() - return response.TemplEcho(c, ProfileFormView(d)) +func RenderProfileCreate(c echo.Context) error { + d := models.CreateProfileData{ + FirstNumber: rand.Intn(5) + 1, + LastNumber: rand.Intn(4) + 1, + } + return response.TemplEcho(c, views.CreateProfileForm(d)) } -func HandlePasskeyStart(c echo.Context) error { +func RenderPasskeyCreate(c echo.Context) error { challenge, _ := protocol.CreateChallenge() handle := c.FormValue("handle") firstName := c.FormValue("first_name") lastName := c.FormValue("last_name") - ks, err := mpc.NewKeyset() + ks, err := mpc.GenEnclave() if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - dat := RegisterPasskeyData{ + dat := models.CreatePasskeyData{ Address: ks.Address(), Handle: handle, Name: fmt.Sprintf("%s %s", firstName, lastName), Challenge: challenge.String(), CreationBlock: "00001", } - return response.TemplEcho(c, LinkCredentialView(dat)) + return response.TemplEcho(c, views.CreatePasskeyForm(dat)) } -func HandlePasskeyFinish(c echo.Context) error { - // Get the raw credential JSON string +func RenderVaultLoading(c echo.Context) error { credentialJSON := c.FormValue("credential") if credentialJSON == "" { return echo.NewHTTPError(http.StatusBadRequest, "missing credential data") } - _, err := extractCredentialDescriptor(credentialJSON) + _, err := models.ExtractCredentialDescriptor(credentialJSON) if err != nil { return err } - return response.TemplEcho(c, LoadingVaultView()) + return response.TemplEcho(c, views.LoadingVaultView()) } diff --git a/internal/gateway/handlers/validate_credential.go b/internal/gateway/handlers/validate_credential.go new file mode 100644 index 000000000..6e5090013 --- /dev/null +++ b/internal/gateway/handlers/validate_credential.go @@ -0,0 +1,11 @@ +package handlers + +import ( + "github.com/labstack/echo/v4" +) + +// ValidateCredentialSubmit finds the user credential and validates it against the +// session challenge +func ValidateCredentialSubmit(c echo.Context) error { + return nil +} diff --git a/internal/gateway/handlers/validate_profile.go b/internal/gateway/handlers/validate_profile.go new file mode 100644 index 000000000..44a00c8a3 --- /dev/null +++ b/internal/gateway/handlers/validate_profile.go @@ -0,0 +1,8 @@ +package handlers + +import "github.com/labstack/echo/v4" + +// ValidateProfileHandle finds the chosen handle and verifies it is unique +func ValidateProfileSubmit(c echo.Context) error { + return nil +} diff --git a/internal/gateway/models/db_orm.go b/internal/gateway/models/db_orm.go new file mode 100644 index 000000000..dadac6a45 --- /dev/null +++ b/internal/gateway/models/db_orm.go @@ -0,0 +1,37 @@ +package models + +import ( + "gorm.io/gorm" +) + +type Credential struct { + gorm.Model + Handle string `json:"handle"` + ID string `json:"id"` + Origin string `json:"origin"` + Type string `json:"type"` + Transports string `json:"transports"` +} + +type Session struct { + gorm.Model + ID string `json:"id" gorm:"primaryKey"` + BrowserName string `json:"browserName"` + BrowserVersion string `json:"browserVersion"` + Platform string `json:"platform"` + IsDesktop bool `json:"isDesktop"` + IsMobile bool `json:"isMobile"` + IsTablet bool `json:"isTablet"` + IsTV bool `json:"isTV"` + IsBot bool `json:"isBot"` + Challenge string `json:"challenge"` +} + +type User struct { + gorm.Model + Address string `json:"address"` + Handle string `json:"handle"` + Origin string `json:"origin"` + Name string `json:"name"` + CID string `json:"cid"` +} diff --git a/internal/gateway/models/form_data.go b/internal/gateway/models/form_data.go new file mode 100644 index 000000000..6613755f7 --- /dev/null +++ b/internal/gateway/models/form_data.go @@ -0,0 +1,15 @@ +package models + +type CreatePasskeyData struct { + Address string + Handle string + Name string + Challenge string + CreationBlock string +} + +type CreateProfileData struct { + TurnstileSiteKey string + FirstNumber int + LastNumber int +} diff --git a/internal/gateway/models/resolver.go b/internal/gateway/models/resolver.go new file mode 100644 index 000000000..2640e7f93 --- /dev/null +++ b/internal/gateway/models/resolver.go @@ -0,0 +1 @@ +package models diff --git a/internal/gateway/handlers/register/data.go b/internal/gateway/models/webauthn.go similarity index 52% rename from internal/gateway/handlers/register/data.go rename to internal/gateway/models/webauthn.go index 502cf9a8d..c44ff2524 100644 --- a/internal/gateway/handlers/register/data.go +++ b/internal/gateway/models/webauthn.go @@ -1,17 +1,12 @@ -package register +package models import ( "encoding/json" "fmt" - "net/http" - - "github.com/labstack/echo/v4" - "golang.org/x/exp/rand" ) // Define the credential structure matching our frontend data -type Credential struct { - Handle string `json:"handle"` +type CredentialDescriptor struct { ID string `json:"id"` RawID string `json:"rawId"` Type string `json:"type"` @@ -24,40 +19,32 @@ type Credential struct { } `json:"response"` } -type CreateProfileData struct { - TurnstileSiteKey string - FirstNumber int - LastNumber int -} - -type RegisterPasskeyData struct { - Address string - Handle string - Name string - Challenge string - CreationBlock string -} - -func (d CreateProfileData) IsHumanLabel() string { - return fmt.Sprintf("What is %d + %d?", d.FirstNumber, d.LastNumber) +func (c *CredentialDescriptor) ToDBModel(handle, origin string) *Credential { + return &Credential{ + Handle: handle, + Origin: origin, + ID: c.ID, + Type: c.Type, + Transports: c.Transports, + } } -func extractCredentialDescriptor(jsonString string) (*Credential, error) { - cred := &Credential{} +func ExtractCredentialDescriptor(jsonString string) (*CredentialDescriptor, error) { + cred := &CredentialDescriptor{} // Unmarshal the credential JSON if err := json.Unmarshal([]byte(jsonString), cred); err != nil { - return nil, echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("invalid credential format: %v", err)) + return nil, err } // Validate required fields if cred.ID == "" || cred.RawID == "" { - return nil, echo.NewHTTPError(http.StatusBadRequest, "missing credential ID") + return nil, fmt.Errorf("missing credential ID") } if cred.Type != "public-key" { - return nil, echo.NewHTTPError(http.StatusBadRequest, "invalid credential type") + return nil, fmt.Errorf("invalid credential type") } if cred.Response.AttestationObject == "" || cred.Response.ClientDataJSON == "" { - return nil, echo.NewHTTPError(http.StatusBadRequest, "missing attestation data") + return nil, fmt.Errorf("missing attestation data") } // Log detailed credential information @@ -75,10 +62,3 @@ func extractCredentialDescriptor(jsonString string) (*Credential, error) { ) return cred, nil } - -func randomCreateProfileData() CreateProfileData { - return CreateProfileData{ - FirstNumber: rand.Intn(5) + 1, - LastNumber: rand.Intn(4) + 1, - } -} diff --git a/internal/gateway/routes.go b/internal/gateway/routes.go index 59d941e07..7bbee58fe 100644 --- a/internal/gateway/routes.go +++ b/internal/gateway/routes.go @@ -2,12 +2,18 @@ package gateway import ( + "os" + "path/filepath" + "strings" + "github.com/labstack/echo/v4" "github.com/onsonr/sonr/internal/gateway/context" - "github.com/onsonr/sonr/internal/gateway/handlers/index" - "github.com/onsonr/sonr/internal/gateway/handlers/register" + "github.com/onsonr/sonr/internal/gateway/handlers" + "github.com/onsonr/sonr/internal/gateway/models" "github.com/onsonr/sonr/pkg/common/response" config "github.com/onsonr/sonr/pkg/config/hway" + "gorm.io/driver/postgres" + "gorm.io/driver/sqlite" "gorm.io/gorm" ) @@ -18,10 +24,58 @@ func RegisterRoutes(e *echo.Echo, env config.Hway, db *gorm.DB) error { // Inject session middleware with database connection e.Use(context.Middleware(db, env)) - // Register routes - e.GET("/", index.Handler) - e.GET("/register", register.HandleCreateProfile) - e.POST("/register/start", register.HandlePasskeyStart) - e.POST("/register/finish", register.HandlePasskeyFinish) + // Register View Handlers + e.GET("/", handlers.RenderIndex) + e.GET("/register", handlers.RenderProfileCreate) + e.POST("/register/passkey", handlers.RenderPasskeyCreate) + e.POST("/register/loading", handlers.RenderVaultLoading) + + // Register Validation Handlers + e.PUT("/register/profile/submit", handlers.ValidateProfileSubmit) + e.PUT("/register/passkey/submit", handlers.ValidateCredentialSubmit) return nil } + +// NewGormDB initializes and returns a configured database connection +func NewDB(env config.Hway) (*gorm.DB, error) { + // Try PostgreSQL first if DSN is provided + if dsn := env.GetPsqlDSN(); dsn != "" && !strings.Contains(dsn, "password= ") { + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + if err == nil { + // Test the connection + sqlDB, err := db.DB() + if err == nil { + if err = sqlDB.Ping(); err == nil { + // Successfully connected to PostgreSQL + db.AutoMigrate(&models.Credential{}) + db.AutoMigrate(&models.Session{}) + db.AutoMigrate(&models.User{}) + return db, nil + } + } + } + } + + // Fall back to SQLite + path := formatDBPath(env.GetSqliteFile()) + db, err := gorm.Open(sqlite.Open(path), &gorm.Config{}) + if err != nil { + return nil, err + } + + // Migrate the schema + db.AutoMigrate(&models.Credential{}) + db.AutoMigrate(&models.Session{}) + db.AutoMigrate(&models.User{}) + return db, nil +} + +func formatDBPath(fileName string) string { + configDir := filepath.Join(os.Getenv("XDG_CONFIG_HOME"), "hway") + if err := os.MkdirAll(configDir, 0o755); err != nil { + // If we can't create the directory, fall back to current directory + return configDir + } + + return filepath.Join(configDir, fileName) +} diff --git a/internal/gateway/services/resolver_service.go b/internal/gateway/services/resolver_service.go new file mode 100644 index 000000000..26fc8c96c --- /dev/null +++ b/internal/gateway/services/resolver_service.go @@ -0,0 +1,59 @@ +package services + +import ( + bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" + didv1 "github.com/onsonr/sonr/api/did/v1" + dwnv1 "github.com/onsonr/sonr/api/dwn/v1" + svcv1 "github.com/onsonr/sonr/api/svc/v1" + "google.golang.org/grpc" +) + +type ResolverService struct { + grpcAddr string +} + +func NewResolverService(grpcAddr string) *ResolverService { + return &ResolverService{ + grpcAddr: grpcAddr, + } +} + +func (s *ResolverService) getClientConn() (*grpc.ClientConn, error) { + grpcConn, err := grpc.NewClient(s.grpcAddr, grpc.WithInsecure()) + if err != nil { + return nil, err + } + return grpcConn, nil +} + +func (s *ResolverService) BankQuery() (bankv1beta1.QueryClient, error) { + conn, err := s.getClientConn() + if err != nil { + return nil, err + } + return bankv1beta1.NewQueryClient(conn), nil +} + +func (s *ResolverService) DIDQuery() (didv1.QueryClient, error) { + conn, err := s.getClientConn() + if err != nil { + return nil, err + } + return didv1.NewQueryClient(conn), nil +} + +func (s *ResolverService) DWNQuery() (dwnv1.QueryClient, error) { + conn, err := s.getClientConn() + if err != nil { + return nil, err + } + return dwnv1.NewQueryClient(conn), nil +} + +func (s *ResolverService) SVCQuery() (svcv1.QueryClient, error) { + conn, err := s.getClientConn() + if err != nil { + return nil, err + } + return svcv1.NewQueryClient(conn), nil +} diff --git a/internal/gateway/services/user_service.go b/internal/gateway/services/user_service.go new file mode 100644 index 000000000..e2dacf460 --- /dev/null +++ b/internal/gateway/services/user_service.go @@ -0,0 +1,7 @@ +package services + +import "gorm.io/gorm" + +type UserService struct { + db *gorm.DB +} diff --git a/internal/gateway/services/vault_service.go b/internal/gateway/services/vault_service.go new file mode 100644 index 000000000..f97d8befc --- /dev/null +++ b/internal/gateway/services/vault_service.go @@ -0,0 +1,18 @@ +package services + +import ( + "github.com/onsonr/sonr/pkg/ipfsapi" + "gorm.io/gorm" +) + +type VaultService struct { + db *gorm.DB + tokenStore ipfsapi.IPFSTokenStore +} + +func NewVaultService(db *gorm.DB, ipc ipfsapi.Client) *VaultService { + return &VaultService{ + db: db, + tokenStore: ipfsapi.NewUCANStore(ipc), + } +} diff --git a/internal/gateway/views/initial_view.templ b/internal/gateway/views/initial_view.templ new file mode 100644 index 000000000..d16d74d85 --- /dev/null +++ b/internal/gateway/views/initial_view.templ @@ -0,0 +1,39 @@ +package views + +import ( + "github.com/onsonr/sonr/internal/nebula/hero" + "github.com/onsonr/sonr/internal/nebula/layout" +) + +templ InitialView(isUnavailable bool) { + if isUnavailable { + @layout.View("Sonr.ID") { + @layout.Container() { + @hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.") + @hero.SocialButtonsRow() + } + } + } + @layout.View("Sonr.ID") { + @layout.Container() { + @hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.") + @hero.StartButton() + @hero.SocialButtonsRow() + } + } +} + +templ ReturningView() { + @layout.View("Login | Sonr.ID") { + @layout.Container() { + @hero.TitleDesc("Welcome Back!", "Continue with your existing Sonr.ID.") +
+ + + Log back in + + +
+ } + } +} diff --git a/internal/gateway/handlers/register/views_templ.go b/internal/gateway/views/initial_view_templ.go similarity index 61% rename from internal/gateway/handlers/register/views_templ.go rename to internal/gateway/views/initial_view_templ.go index 2bcd252fb..019f002b3 100644 --- a/internal/gateway/handlers/register/views_templ.go +++ b/internal/gateway/views/initial_view_templ.go @@ -1,7 +1,7 @@ // Code generated by templ - DO NOT EDIT. // templ: version: v0.2.793 -package register +package views //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -9,12 +9,11 @@ import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" import ( - "github.com/onsonr/sonr/internal/nebula/card" + "github.com/onsonr/sonr/internal/nebula/hero" "github.com/onsonr/sonr/internal/nebula/layout" - "github.com/onsonr/sonr/internal/nebula/text" ) -func ProfileFormView(data CreateProfileData) templ.Component { +func InitialView(isUnavailable bool) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -35,19 +34,8 @@ func ProfileFormView(data CreateProfileData) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + if isUnavailable { + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -59,56 +47,44 @@ func ProfileFormView(data CreateProfileData) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = text.TitleDescription("Basic Info", "Tell us a little about yourself.").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { + templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = hero.SocialButtonsRow().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } return templ_7745c5c3_Err - } - templ_7745c5c3_Err = formCreateProfile("/register/start", "POST", data).Render(ctx, templ_7745c5c3_Buffer) + }) + templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = card.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = layout.View("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = layout.View("New Profile | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -func LinkCredentialView(data RegisterPasskeyData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var4 := templ.GetChildren(ctx) - if templ_7745c5c3_Var4 == nil { - templ_7745c5c3_Var4 = templ.NopComponent } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -120,7 +96,7 @@ func LinkCredentialView(data RegisterPasskeyData) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -132,7 +108,15 @@ func LinkCredentialView(data RegisterPasskeyData) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = text.TitleDescription("Link a PassKey", "This will be used to login to your vault.").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = hero.StartButton().Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -140,19 +124,19 @@ func LinkCredentialView(data RegisterPasskeyData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = formRegisterPasskey("/register/finish", "POST", data).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = hero.SocialButtonsRow().Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = card.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = layout.View("Register | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = layout.View("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -160,7 +144,7 @@ func LinkCredentialView(data RegisterPasskeyData) templ.Component { }) } -func LoadingVaultView() templ.Component { +func ReturningView() templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -176,12 +160,12 @@ func LoadingVaultView() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var7 := templ.GetChildren(ctx) - if templ_7745c5c3_Var7 == nil { - templ_7745c5c3_Var7 = templ.NopComponent + templ_7745c5c3_Var6 := templ.GetChildren(ctx) + if templ_7745c5c3_Var6 == nil { + templ_7745c5c3_Var6 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var7 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -193,7 +177,7 @@ func LoadingVaultView() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var9 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -205,19 +189,23 @@ func LoadingVaultView() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = text.TitleDescription("Loading Vault", "This will be used to login to your vault.").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = hero.TitleDesc("Welcome Back!", "Continue with your existing Sonr.ID.").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Log back in
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = card.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = layout.View("Loading... | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = layout.View("Login | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/gateway/views/register_view.templ b/internal/gateway/views/register_view.templ new file mode 100644 index 000000000..744badb4f --- /dev/null +++ b/internal/gateway/views/register_view.templ @@ -0,0 +1,69 @@ +package views + +import ( + "github.com/onsonr/sonr/internal/gateway/models" + "github.com/onsonr/sonr/internal/nebula/card" + "github.com/onsonr/sonr/internal/nebula/form" + "github.com/onsonr/sonr/internal/nebula/hero" + "github.com/onsonr/sonr/internal/nebula/input" + "github.com/onsonr/sonr/internal/nebula/layout" +) + +templ CreateProfileForm(data models.CreateProfileData) { + @layout.View("New Profile | Sonr.ID") { + @layout.Container() { + @hero.TitleDesc("Basic Info", "Tell us a little about yourself.") + @formCreateProfile(data) + } + } +} + +templ CreatePasskeyForm(data models.CreatePasskeyData) { + @layout.View("Register | Sonr.ID") { + @layout.Container() { + @hero.TitleDesc("Link a PassKey", "This will be used to login to your vault.") + @formCreatePasskey(data) + } + } +} + +templ LoadingVaultView() { + @layout.View("Loading... | Sonr.ID") { + @layout.Container() { + @hero.TitleDesc("Loading Vault", "This will be used to login to your vault.") + } + } +} + +templ formCreatePasskey(data models.CreatePasskeyData) { + @form.Root("/register/finish", "POST", "passkey-form") { + + @form.Body() { + @form.Header() { + @card.SonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock) + } + @input.CoinSelect() + @form.Footer() { + @input.Passkey(data.Address, data.Handle, data.Challenge) + @form.CancelButton() + } + } + } +} + +templ formCreateProfile(data models.CreateProfileData) { + @form.Root("/register/passkey", "POST", "create-profile") { + @form.Body() { + @form.Header() { + + } + @input.Name() + @input.Handle() + @input.HumanSlider(data.FirstNumber, data.LastNumber) + @form.Footer() { + @form.CancelButton() + @form.SubmitButton("Next") + } + } + } +} diff --git a/internal/gateway/views/register_view_templ.go b/internal/gateway/views/register_view_templ.go new file mode 100644 index 000000000..dce3686cf --- /dev/null +++ b/internal/gateway/views/register_view_templ.go @@ -0,0 +1,501 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.793 +package views + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +import ( + "github.com/onsonr/sonr/internal/gateway/models" + "github.com/onsonr/sonr/internal/nebula/card" + "github.com/onsonr/sonr/internal/nebula/form" + "github.com/onsonr/sonr/internal/nebula/hero" + "github.com/onsonr/sonr/internal/nebula/input" + "github.com/onsonr/sonr/internal/nebula/layout" +) + +func CreateProfileForm(data models.CreateProfileData) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = hero.TitleDesc("Basic Info", "Tell us a little about yourself.").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = formCreateProfile(data).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.View("New Profile | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func CreatePasskeyForm(data models.CreatePasskeyData) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = hero.TitleDesc("Link a PassKey", "This will be used to login to your vault.").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = formCreatePasskey(data).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.View("Register | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func LoadingVaultView() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var9 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = hero.TitleDesc("Loading Vault", "This will be used to login to your vault.").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.View("Loading... | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func formCreatePasskey(data models.CreatePasskeyData) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var10 := templ.GetChildren(ctx) + if templ_7745c5c3_Var10 == nil { + templ_7745c5c3_Var10 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var11 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var12 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var13 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = card.SonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Header().Render(templ.WithChildren(ctx, templ_7745c5c3_Var13), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = input.CoinSelect().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var14 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = input.Passkey(data.Address, data.Handle, data.Challenge).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = form.CancelButton().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Footer().Render(templ.WithChildren(ctx, templ_7745c5c3_Var14), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var12), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Root("/register/finish", "POST", "passkey-form").Render(templ.WithChildren(ctx, templ_7745c5c3_Var11), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func formCreateProfile(data models.CreateProfileData) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var15 := templ.GetChildren(ctx) + if templ_7745c5c3_Var15 == nil { + templ_7745c5c3_Var15 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var16 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var17 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var18 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Header().Render(templ.WithChildren(ctx, templ_7745c5c3_Var18), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = input.Name().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = input.Handle().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = input.HumanSlider(data.FirstNumber, data.LastNumber).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var19 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = form.CancelButton().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = form.SubmitButton("Next").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Footer().Render(templ.WithChildren(ctx, templ_7745c5c3_Var19), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var17), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = form.Root("/register/passkey", "POST", "create-profile").Render(templ.WithChildren(ctx, templ_7745c5c3_Var16), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/internal/nebula/card/container.templ b/internal/nebula/card/container.templ deleted file mode 100644 index a2091cf4e..000000000 --- a/internal/nebula/card/container.templ +++ /dev/null @@ -1,13 +0,0 @@ -package card - -templ Container() { -
-
-
-
- { children... } -
-
-
-
-} diff --git a/internal/nebula/card/sonr_profile.templ b/internal/nebula/card/sonr_profile.templ index 35463cdee..bfe943505 100644 --- a/internal/nebula/card/sonr_profile.templ +++ b/internal/nebula/card/sonr_profile.templ @@ -2,7 +2,7 @@ package card templ SonrProfile(addr, name, handle, creationBlock string) {
-
+

sonr-testnet-1

diff --git a/internal/nebula/card/sonr_profile_templ.go b/internal/nebula/card/sonr_profile_templ.go index 3d01b0dfc..2dfcb8f61 100644 --- a/internal/nebula/card/sonr_profile_templ.go +++ b/internal/nebula/card/sonr_profile_templ.go @@ -29,7 +29,7 @@ func SonrProfile(addr, name, handle, creationBlock string) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

sonr-testnet-1

") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

sonr-testnet-1

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/nebula/hero/social_buttons.templ b/internal/nebula/hero/social_buttons.templ new file mode 100644 index 000000000..1802b4484 --- /dev/null +++ b/internal/nebula/hero/social_buttons.templ @@ -0,0 +1,15 @@ +package hero + +templ SocialButtonsRow() { +

+ + + + + + + + + +
+} diff --git a/internal/nebula/card/container_templ.go b/internal/nebula/hero/social_buttons_templ.go similarity index 66% rename from internal/nebula/card/container_templ.go rename to internal/nebula/hero/social_buttons_templ.go index 2af9be2fb..bdb0fe6ce 100644 --- a/internal/nebula/card/container_templ.go +++ b/internal/nebula/hero/social_buttons_templ.go @@ -1,14 +1,14 @@ // Code generated by templ - DO NOT EDIT. // templ: version: v0.2.793 -package card +package hero //lint:file-ignore SA4006 This context is only used if a nested component is present. import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -func Container() templ.Component { +func SocialButtonsRow() templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -29,15 +29,7 @@ func Container() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/nebula/hero/start_button.templ b/internal/nebula/hero/start_button.templ new file mode 100644 index 000000000..64783b8df --- /dev/null +++ b/internal/nebula/hero/start_button.templ @@ -0,0 +1,11 @@ +package hero + +templ StartButton() { +
+ + + Create Vault + + +
+} diff --git a/internal/nebula/hero/start_button_templ.go b/internal/nebula/hero/start_button_templ.go new file mode 100644 index 000000000..ceaf6e6b2 --- /dev/null +++ b/internal/nebula/hero/start_button_templ.go @@ -0,0 +1,40 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.793 +package hero + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +func StartButton() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Create Vault
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/internal/nebula/text/titles.templ b/internal/nebula/hero/titles.templ similarity index 79% rename from internal/nebula/text/titles.templ rename to internal/nebula/hero/titles.templ index 2e8b9eb6c..19a16a6b8 100644 --- a/internal/nebula/text/titles.templ +++ b/internal/nebula/hero/titles.templ @@ -1,6 +1,6 @@ -package text +package hero -templ TitleDescription(title string, subtitle string) { +templ TitleDesc(title string, subtitle string) {

{ title } diff --git a/internal/nebula/text/titles_templ.go b/internal/nebula/hero/titles_templ.go similarity index 93% rename from internal/nebula/text/titles_templ.go rename to internal/nebula/hero/titles_templ.go index c103e2953..be11d0507 100644 --- a/internal/nebula/text/titles_templ.go +++ b/internal/nebula/hero/titles_templ.go @@ -1,14 +1,14 @@ // Code generated by templ - DO NOT EDIT. // templ: version: v0.2.793 -package text +package hero //lint:file-ignore SA4006 This context is only used if a nested component is present. import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -func TitleDescription(title string, subtitle string) templ.Component { +func TitleDesc(title string, subtitle string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -36,7 +36,7 @@ func TitleDescription(title string, subtitle string) templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/text/titles.templ`, Line: 6, Col: 10} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/hero/titles.templ`, Line: 6, Col: 10} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { @@ -49,7 +49,7 @@ func TitleDescription(title string, subtitle string) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/text/titles.templ`, Line: 9, Col: 13} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/hero/titles.templ`, Line: 9, Col: 13} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { diff --git a/internal/nebula/input/input_handle.templ b/internal/nebula/input/input_handle.templ index 232f09c84..586a0dfc2 100644 --- a/internal/nebula/input/input_handle.templ +++ b/internal/nebula/input/input_handle.templ @@ -13,11 +13,13 @@ func (s HandleState) string() string { } templ Handle() { - -
- -
-
+
+ +
+ +
+
+

} diff --git a/internal/nebula/input/input_handle_templ.go b/internal/nebula/input/input_handle_templ.go index f6e55cd60..fb3496700 100644 --- a/internal/nebula/input/input_handle_templ.go +++ b/internal/nebula/input/input_handle_templ.go @@ -41,7 +41,7 @@ func Handle() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/nebula/input/input_slider_isHuman.templ b/internal/nebula/input/slider_isHuman.templ similarity index 100% rename from internal/nebula/input/input_slider_isHuman.templ rename to internal/nebula/input/slider_isHuman.templ diff --git a/internal/nebula/input/input_slider_isHuman_templ.go b/internal/nebula/input/slider_isHuman_templ.go similarity index 97% rename from internal/nebula/input/input_slider_isHuman_templ.go rename to internal/nebula/input/slider_isHuman_templ.go index a22443344..505ec86fa 100644 --- a/internal/nebula/input/input_slider_isHuman_templ.go +++ b/internal/nebula/input/slider_isHuman_templ.go @@ -38,7 +38,7 @@ func HumanSlider(firstNumber int, lastNumber int) templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(formatHumanSliderLabel(firstNumber, lastNumber)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/input/input_slider_isHuman.templ`, Line: 6, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/input/slider_isHuman.templ`, Line: 6, Col: 82} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { diff --git a/internal/nebula/layout/container.templ b/internal/nebula/layout/container.templ index 4b2ef729b..58f616aa6 100644 --- a/internal/nebula/layout/container.templ +++ b/internal/nebula/layout/container.templ @@ -1,24 +1,13 @@ package layout -// Columns is a component that renders a responsive flex container that stacks on mobile -templ Columns() { -
- { children... } -
-} - -// Rows is a component that renders a responsive flex container that wraps on mobile -templ Rows() { -
- { children... } -
-} - -templ Separator(text string) { -
-
-
- { text } +templ Container() { +
+
+
+
+ { children... } +
+
} diff --git a/internal/nebula/layout/container_templ.go b/internal/nebula/layout/container_templ.go index 34a8679ee..c02d5ed6d 100644 --- a/internal/nebula/layout/container_templ.go +++ b/internal/nebula/layout/container_templ.go @@ -8,8 +8,7 @@ package layout import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -// Columns is a component that renders a responsive flex container that stacks on mobile -func Columns() templ.Component { +func Container() templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -30,7 +29,7 @@ func Columns() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -38,87 +37,7 @@ func Columns() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -// Rows is a component that renders a responsive flex container that wraps on mobile -func Rows() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var2 := templ.GetChildren(ctx) - if templ_7745c5c3_Var2 == nil { - templ_7745c5c3_Var2 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ_7745c5c3_Var2.Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -func Separator(text string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templ.GetChildren(ctx) - if templ_7745c5c3_Var3 == nil { - templ_7745c5c3_Var3 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/container.templ`, Line: 21, Col: 45} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/nebula/layout/grid.templ b/internal/nebula/layout/grid.templ new file mode 100644 index 000000000..4b2ef729b --- /dev/null +++ b/internal/nebula/layout/grid.templ @@ -0,0 +1,24 @@ +package layout + +// Columns is a component that renders a responsive flex container that stacks on mobile +templ Columns() { +
+ { children... } +
+} + +// Rows is a component that renders a responsive flex container that wraps on mobile +templ Rows() { +
+ { children... } +
+} + +templ Separator(text string) { +
+
+
+ { text } +
+
+} diff --git a/internal/nebula/layout/grid_templ.go b/internal/nebula/layout/grid_templ.go new file mode 100644 index 000000000..4db78d318 --- /dev/null +++ b/internal/nebula/layout/grid_templ.go @@ -0,0 +1,129 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.793 +package layout + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +// Columns is a component that renders a responsive flex container that stacks on mobile +func Columns() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// Rows is a component that renders a responsive flex container that wraps on mobile +func Rows() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var2 := templ.GetChildren(ctx) + if templ_7745c5c3_Var2 == nil { + templ_7745c5c3_Var2 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var2.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func Separator(text string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/grid.templ`, Line: 21, Col: 45} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/internal/nebula/layout/scripts.templ b/internal/nebula/layout/head.templ similarity index 71% rename from internal/nebula/layout/scripts.templ rename to internal/nebula/layout/head.templ index e7fbaf921..d42780a80 100644 --- a/internal/nebula/layout/scripts.templ +++ b/internal/nebula/layout/head.templ @@ -11,6 +11,56 @@ var ( turnstileHandle = templ.NewOnceHandle() ) +templ Head(title string, nebulaVersion string) { + + @Turnstile() + @Tailwind() + @Alpine() + @Htmx() + @Dexie() + @Nebula(nebulaVersion) + + + + { title } + + + + + + { children... } + +} + // ╭──────────────────────────────────────────────────────────╮ // │ 3rd Party Libraries │ // ╰──────────────────────────────────────────────────────────╯ diff --git a/internal/nebula/layout/scripts_templ.go b/internal/nebula/layout/head_templ.go similarity index 72% rename from internal/nebula/layout/scripts_templ.go rename to internal/nebula/layout/head_templ.go index 76c0b5823..fe6d98888 100644 --- a/internal/nebula/layout/scripts_templ.go +++ b/internal/nebula/layout/head_templ.go @@ -19,6 +19,84 @@ var ( turnstileHandle = templ.NewOnceHandle() ) +func Head(title string, nebulaVersion string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Turnstile().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Tailwind().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Alpine().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Htmx().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Dexie().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Nebula(nebulaVersion).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 25, Col: 16} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + // ╭──────────────────────────────────────────────────────────╮ // │ 3rd Party Libraries │ // ╰──────────────────────────────────────────────────────────╯ @@ -40,12 +118,12 @@ func Tailwind() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -63,7 +141,7 @@ func Tailwind() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = tailwindHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = tailwindHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -88,12 +166,12 @@ func Turnstile() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templ.GetChildren(ctx) - if templ_7745c5c3_Var3 == nil { - templ_7745c5c3_Var3 = templ.NopComponent + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -111,7 +189,7 @@ func Turnstile() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = turnstileHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = turnstileHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -136,12 +214,12 @@ func Alpine() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var5 := templ.GetChildren(ctx) - if templ_7745c5c3_Var5 == nil { - templ_7745c5c3_Var5 = templ.NopComponent + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -157,12 +235,12 @@ func Alpine() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("alpinejs", "3.14.6", "dist/cdn.min.js")) + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("alpinejs", "3.14.6", "dist/cdn.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 36, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 86, Col: 68} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -170,12 +248,12 @@ func Alpine() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@alpinejs/focus", "3.14.6", "dist/cdn.min.js")) + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("@alpinejs/focus", "3.14.6", "dist/cdn.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 37, Col: 75} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 87, Col: 75} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -185,7 +263,7 @@ func Alpine() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = alpineHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = alpineHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -210,12 +288,12 @@ func Dexie() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var9 := templ.GetChildren(ctx) - if templ_7745c5c3_Var9 == nil { - templ_7745c5c3_Var9 = templ.NopComponent + templ_7745c5c3_Var11 := templ.GetChildren(ctx) + if templ_7745c5c3_Var11 == nil { + templ_7745c5c3_Var11 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var10 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var12 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -231,12 +309,12 @@ func Dexie() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie", "4.0.10", "dist/dexie.min.js")) + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie", "4.0.10", "dist/dexie.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 44, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 94, Col: 67} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -244,12 +322,12 @@ func Dexie() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var12 string - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie-export-import", "4.1.4", "dist/dexie-export-import.min.js")) + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("dexie-export-import", "4.1.4", "dist/dexie-export-import.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 45, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 95, Col: 94} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -259,7 +337,7 @@ func Dexie() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = dexieHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var10), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = dexieHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var12), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -284,12 +362,12 @@ func Htmx() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var13 := templ.GetChildren(ctx) - if templ_7745c5c3_Var13 == nil { - templ_7745c5c3_Var13 = templ.NopComponent + templ_7745c5c3_Var15 := templ.GetChildren(ctx) + if templ_7745c5c3_Var15 == nil { + templ_7745c5c3_Var15 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var14 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var16 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -305,12 +383,12 @@ func Htmx() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var15 string - templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx.org", "1.9.12", "dist/htmx.min.js")) + var templ_7745c5c3_Var17 string + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx.org", "1.9.12", "dist/htmx.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 52, Col: 69} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 102, Col: 69} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -318,12 +396,12 @@ func Htmx() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var16 string - templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-include-vals", "2.0.0", "include-vals.min.js")) + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-include-vals", "2.0.0", "include-vals.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 53, Col: 84} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 103, Col: 84} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -331,12 +409,12 @@ func Htmx() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var17 string - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-path-params", "2.0.0", "path-params.min.js")) + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-path-params", "2.0.0", "path-params.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 54, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 104, Col: 82} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -344,12 +422,12 @@ func Htmx() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var18 string - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-alpine-morph", "2.0.0", "alpine-morph.min.js")) + var templ_7745c5c3_Var20 string + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(jsDelivrURL("htmx-ext-alpine-morph", "2.0.0", "alpine-morph.min.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/scripts.templ`, Line: 55, Col: 84} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/nebula/layout/head.templ`, Line: 105, Col: 84} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -359,7 +437,7 @@ func Htmx() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = htmxHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var14), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = htmxHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var16), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -384,21 +462,21 @@ func Nebula(version string) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var19 := templ.GetChildren(ctx) - if templ_7745c5c3_Var19 == nil { - templ_7745c5c3_Var19 = templ.NopComponent + templ_7745c5c3_Var21 := templ.GetChildren(ctx) + if templ_7745c5c3_Var21 == nil { + templ_7745c5c3_Var21 = templ.NopComponent } ctx = templ.ClearChildren(ctx) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" } -templ Head(title string, nebulaVersion string) { - - @Turnstile() - @Tailwind() - @Alpine() - @Htmx() - @Dexie() - @Nebula(nebulaVersion) - - - - { title } - - - - - - { children... } - -} - templ Body(align Alignment, screenWidth ScreenWidth) { ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ_7745c5c3_Var2.Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return templ_7745c5c3_Err - }) -} - -func Body(align Alignment, screenWidth ScreenWidth) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var4 := templ.GetChildren(ctx) - if templ_7745c5c3_Var4 == nil { - templ_7745c5c3_Var4 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ_7745c5c3_Var4.Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = templ_7745c5c3_Var2.Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/vault/handlers/auth/handlers.go b/internal/vault/handlers/auth.go similarity index 100% rename from internal/vault/handlers/auth/handlers.go rename to internal/vault/handlers/auth.go diff --git a/internal/vault/handlers/authz/handlers.go b/internal/vault/handlers/authz.go similarity index 100% rename from internal/vault/handlers/authz/handlers.go rename to internal/vault/handlers/authz.go diff --git a/internal/vault/handlers/feeds/handlers.go b/internal/vault/handlers/feeds.go similarity index 75% rename from internal/vault/handlers/feeds/handlers.go rename to internal/vault/handlers/feeds.go index a978d7f05..7f4621b14 100644 --- a/internal/vault/handlers/feeds/handlers.go +++ b/internal/vault/handlers/feeds.go @@ -6,6 +6,6 @@ import ( "github.com/labstack/echo/v4" ) -func Handler(c echo.Context) error { +func RenderFeeds(c echo.Context) error { return c.Render(http.StatusOK, "index.templ", nil) } diff --git a/internal/vault/handlers/index/handlers.go b/internal/vault/handlers/index.go similarity index 80% rename from internal/vault/handlers/index/handlers.go rename to internal/vault/handlers/index.go index e543a3a53..8656afb8d 100644 --- a/internal/vault/handlers/index/handlers.go +++ b/internal/vault/handlers/index.go @@ -7,9 +7,9 @@ import ( "github.com/onsonr/sonr/internal/vault/context" ) -func Handler(c echo.Context) error { +func RenderIndex(c echo.Context) error { // TODO: Create views - if isInitial(c) { + if isReturning(c) { // return response.TemplEcho(c, index.InitialView()) } // TODO: Add authorization check @@ -23,14 +23,6 @@ func Handler(c echo.Context) error { // │ Utility Functions │ // ╰─────────────────────────────────────────────────────────╯ -// Initial users have no authorization, user handle, or vault address -func isInitial(c echo.Context) bool { - noAuth := !context.HasAuthorization(c) - noUserHandle := !context.HasUserHandle(c) - noVaultAddress := !context.HasVaultAddress(c) - return noUserHandle && noVaultAddress && noAuth -} - // Expired users have either a user handle or vault address func isExpired(c echo.Context) bool { noAuth := !context.HasAuthorization(c) diff --git a/internal/vault/handlers/profile/handlers.go b/internal/vault/handlers/profile.go similarity index 100% rename from internal/vault/handlers/profile/handlers.go rename to internal/vault/handlers/profile.go diff --git a/internal/vault/handlers/search/handlers.go b/internal/vault/handlers/search.go similarity index 100% rename from internal/vault/handlers/search/handlers.go rename to internal/vault/handlers/search.go diff --git a/internal/vault/handlers/wallet/handlers.go b/internal/vault/handlers/wallet.go similarity index 100% rename from internal/vault/handlers/wallet/handlers.go rename to internal/vault/handlers/wallet.go diff --git a/pkg/config/hway/Hway.pkl.go b/pkg/config/hway/Hway.pkl.go index 7859e50e7..09c88ce2a 100644 --- a/pkg/config/hway/Hway.pkl.go +++ b/pkg/config/hway/Hway.pkl.go @@ -1,4 +1,4 @@ -// Code generated from Pkl module `sonr.conf.Hway`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Hway`. DO NOT EDIT. package hway import ( @@ -10,8 +10,6 @@ import ( type Hway interface { GetServePort() int - GetConfigDir() string - GetSqliteFile() string GetChainId() string @@ -23,6 +21,8 @@ type Hway interface { GetSonrGrpcUrl() string GetSonrRpcUrl() string + + GetPsqlDSN() string } var _ Hway = (*HwayImpl)(nil) @@ -30,8 +30,6 @@ var _ Hway = (*HwayImpl)(nil) type HwayImpl struct { ServePort int `pkl:"servePort"` - ConfigDir string `pkl:"configDir"` - SqliteFile string `pkl:"sqliteFile"` ChainId string `pkl:"chainId"` @@ -43,16 +41,14 @@ type HwayImpl struct { SonrGrpcUrl string `pkl:"sonrGrpcUrl"` SonrRpcUrl string `pkl:"sonrRpcUrl"` + + PsqlDSN string `pkl:"psqlDSN"` } func (rcv *HwayImpl) GetServePort() int { return rcv.ServePort } -func (rcv *HwayImpl) GetConfigDir() string { - return rcv.ConfigDir -} - func (rcv *HwayImpl) GetSqliteFile() string { return rcv.SqliteFile } @@ -77,6 +73,10 @@ func (rcv *HwayImpl) GetSonrRpcUrl() string { return rcv.SonrRpcUrl } +func (rcv *HwayImpl) GetPsqlDSN() string { + return rcv.PsqlDSN +} + // LoadFromPath loads the pkl module at the given path and evaluates it into a Hway func LoadFromPath(ctx context.Context, path string) (ret Hway, err error) { evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions) diff --git a/pkg/config/hway/init.pkl.go b/pkg/config/hway/init.pkl.go index d4ed3bee2..f8e5b2d88 100644 --- a/pkg/config/hway/init.pkl.go +++ b/pkg/config/hway/init.pkl.go @@ -1,8 +1,8 @@ -// Code generated from Pkl module `sonr.conf.Hway`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Hway`. DO NOT EDIT. package hway import "github.com/apple/pkl-go/pkl" func init() { - pkl.RegisterMapping("sonr.conf.Hway", HwayImpl{}) + pkl.RegisterMapping("sonr.net.Hway", HwayImpl{}) } diff --git a/pkg/config/motr/Config.pkl.go b/pkg/config/motr/Config.pkl.go index 2957560c9..4e20c6040 100644 --- a/pkg/config/motr/Config.pkl.go +++ b/pkg/config/motr/Config.pkl.go @@ -1,4 +1,4 @@ -// Code generated from Pkl module `sonr.conf.Motr`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT. package motr type Config struct { diff --git a/pkg/config/motr/Environment.pkl.go b/pkg/config/motr/Environment.pkl.go index 5824d6ecc..8235f7724 100644 --- a/pkg/config/motr/Environment.pkl.go +++ b/pkg/config/motr/Environment.pkl.go @@ -1,4 +1,4 @@ -// Code generated from Pkl module `sonr.conf.Motr`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT. package motr type Environment struct { diff --git a/pkg/config/motr/Motr.pkl.go b/pkg/config/motr/Motr.pkl.go index 35beff0b0..5aeb64bf0 100644 --- a/pkg/config/motr/Motr.pkl.go +++ b/pkg/config/motr/Motr.pkl.go @@ -1,4 +1,4 @@ -// Code generated from Pkl module `sonr.conf.Motr`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT. package motr import ( diff --git a/pkg/config/motr/Schema.pkl.go b/pkg/config/motr/Schema.pkl.go index 8ea43bd32..9a0e9742f 100644 --- a/pkg/config/motr/Schema.pkl.go +++ b/pkg/config/motr/Schema.pkl.go @@ -1,4 +1,4 @@ -// Code generated from Pkl module `sonr.conf.Motr`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT. package motr type Schema struct { diff --git a/pkg/config/motr/init.pkl.go b/pkg/config/motr/init.pkl.go index 0b9d6ee41..fac9199be 100644 --- a/pkg/config/motr/init.pkl.go +++ b/pkg/config/motr/init.pkl.go @@ -1,11 +1,11 @@ -// Code generated from Pkl module `sonr.conf.Motr`. DO NOT EDIT. +// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT. package motr import "github.com/apple/pkl-go/pkl" func init() { - pkl.RegisterMapping("sonr.conf.Motr", Motr{}) - pkl.RegisterMapping("sonr.conf.Motr#Config", Config{}) - pkl.RegisterMapping("sonr.conf.Motr#Schema", Schema{}) - pkl.RegisterMapping("sonr.conf.Motr#Environment", Environment{}) + pkl.RegisterMapping("sonr.net.Motr", Motr{}) + pkl.RegisterMapping("sonr.net.Motr#Config", Config{}) + pkl.RegisterMapping("sonr.net.Motr#Schema", Schema{}) + pkl.RegisterMapping("sonr.net.Motr#Environment", Environment{}) } diff --git a/pkg/database/sessions/models.go b/pkg/database/sessions/models.go deleted file mode 100644 index 4eeb7e235..000000000 --- a/pkg/database/sessions/models.go +++ /dev/null @@ -1,42 +0,0 @@ -package sessions - -import ( - "net/http" - - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -var ( - ErrInvalidCredentials = echo.NewHTTPError(http.StatusUnauthorized, "Invalid credentials") - ErrInvalidSubject = echo.NewHTTPError(http.StatusBadRequest, "Invalid subject") - ErrInvalidUser = echo.NewHTTPError(http.StatusBadRequest, "Invalid user") - - ErrUserAlreadyExists = echo.NewHTTPError(http.StatusConflict, "User already exists") - ErrUserNotFound = echo.NewHTTPError(http.StatusNotFound, "User not found") -) - -type User struct { - gorm.Model - Address string `json:"address"` - Handle string `json:"handle"` - Name string `json:"name"` - CID string `json:"cid"` -} - -type Session struct { - gorm.Model - ID string `json:"id" gorm:"primaryKey"` - BrowserName string `json:"browserName"` - BrowserVersion string `json:"browserVersion"` - UserArchitecture string `json:"userArchitecture"` - Platform string `json:"platform"` - PlatformVersion string `json:"platformVersion"` - DeviceModel string `json:"deviceModel"` - UserHandle string `json:"userHandle"` - FirstName string `json:"firstName"` - LastInitial string `json:"lastInitial"` - VaultAddress string `json:"vaultAddress"` - HumanSum int `json:"humanSum"` - Challenge string `json:"challenge"` -} diff --git a/pkg/database/sessions/sqlite.go b/pkg/database/sessions/sqlite.go deleted file mode 100644 index 109275a9f..000000000 --- a/pkg/database/sessions/sqlite.go +++ /dev/null @@ -1,42 +0,0 @@ -package sessions - -import ( - "os" - "path/filepath" - - config "github.com/onsonr/sonr/pkg/config/hway" - "gorm.io/driver/sqlite" - "gorm.io/gorm" -) - -// NewGormDB initializes and returns a configured database connection -func NewGormDB(env config.Hway) (*gorm.DB, error) { - path := formatDBPath(env.GetSqliteFile()) - db, err := gorm.Open(sqlite.Open(path), &gorm.Config{}) - if err != nil { - return nil, err - } - - // Migrate the schema - db.AutoMigrate(&Session{}) - db.AutoMigrate(&User{}) - return db, nil -} - -func formatDBPath(path string) string { - home := os.Getenv("HOME") - if home == "" { - home = os.Getenv("USERPROFILE") - } - if home == "" { - home = "." - } - - configDir := filepath.Join(home, ".config", "hway") - if err := os.MkdirAll(configDir, 0o755); err != nil { - // If we can't create the directory, fall back to current directory - return path - } - - return filepath.Join(configDir, path) -} diff --git a/pkg/didauth/controller/config.go b/pkg/didauth/controller/config.go index 7c86443fa..e76ece96f 100644 --- a/pkg/didauth/controller/config.go +++ b/pkg/didauth/controller/config.go @@ -2,7 +2,7 @@ package controller import ( "github.com/labstack/echo/v4" - "github.com/onsonr/sonr/crypto/ucan/spec" + "github.com/onsonr/sonr/crypto/mpc/spec" ) // ControllerConfig defines the configuration for UCAN middleware diff --git a/pkg/didauth/controller/middleware.go b/pkg/didauth/controller/middleware.go index 41bccac1e..3c88539a1 100644 --- a/pkg/didauth/controller/middleware.go +++ b/pkg/didauth/controller/middleware.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/labstack/echo/v4" - "github.com/onsonr/sonr/crypto/ucan/spec" + "github.com/onsonr/sonr/crypto/mpc/spec" ) // Middleware returns middleware to validate Middleware tokens diff --git a/pkg/didauth/producer/context.go b/pkg/didauth/producer/context.go index ae7ccbe2f..ba7311c1d 100644 --- a/pkg/didauth/producer/context.go +++ b/pkg/didauth/producer/context.go @@ -3,8 +3,7 @@ package producer import ( "github.com/labstack/echo/v4" "github.com/onsonr/sonr/crypto/ucan" - "github.com/onsonr/sonr/crypto/ucan/store" - "github.com/onsonr/sonr/pkg/common/ipfs" + "github.com/onsonr/sonr/pkg/ipfsapi" ) type ProducerContext struct { @@ -13,8 +12,8 @@ type ProducerContext struct { TokenParser *ucan.TokenParser // TokenStore is the token store used to store and retrieve tokens - TokenStore store.IPFSTokenStore + TokenStore ipfsapi.IPFSTokenStore // IPFSClient is the IPFS client used to resolve the UCAN - IPFSClient ipfs.Client + IPFSClient ipfsapi.Client } diff --git a/pkg/didauth/producer/middleware.go b/pkg/didauth/producer/middleware.go index f79b34255..82f59eb92 100644 --- a/pkg/didauth/producer/middleware.go +++ b/pkg/didauth/producer/middleware.go @@ -3,16 +3,15 @@ package producer import ( "github.com/onsonr/sonr/crypto/mpc" "github.com/onsonr/sonr/crypto/ucan" - "github.com/onsonr/sonr/crypto/ucan/store" - "github.com/onsonr/sonr/pkg/common/ipfs" + "github.com/onsonr/sonr/pkg/ipfsapi" "github.com/labstack/echo/v4" ) // Middleware returns middleware to spawn controllers and validate UCAN tokens -func Middleware(ipfs ipfs.Client, perms ucan.Permissions) echo.MiddlewareFunc { +func Middleware(ipc ipfsapi.Client, perms ucan.Permissions) echo.MiddlewareFunc { // Setup token store and parser - store := store.NewIPFSTokenStore(ipfs) + store := ipfsapi.NewUCANStore(ipc) parser := ucan.NewTokenParser(perms.GetConstructor(), store, store) // Return middleware @@ -20,7 +19,7 @@ func Middleware(ipfs ipfs.Client, perms ucan.Permissions) echo.MiddlewareFunc { return func(c echo.Context) error { ctx := ProducerContext{ Context: c, - IPFSClient: ipfs, + IPFSClient: ipc, TokenParser: parser, TokenStore: store, } @@ -29,8 +28,8 @@ func Middleware(ipfs ipfs.Client, perms ucan.Permissions) echo.MiddlewareFunc { } } -func NewKeyset(c echo.Context) (mpc.Keyset, error) { - ks, err := mpc.NewKeyset() +func NewKeyset(c echo.Context) (mpc.Enclave, error) { + ks, err := mpc.GenEnclave() if err != nil { return nil, err } diff --git a/pkg/common/ipfs/client.go b/pkg/ipfsapi/client.go similarity index 99% rename from pkg/common/ipfs/client.go rename to pkg/ipfsapi/client.go index 679536681..1425eb6be 100644 --- a/pkg/common/ipfs/client.go +++ b/pkg/ipfsapi/client.go @@ -1,4 +1,4 @@ -package ipfs +package ipfsapi import ( "bytes" diff --git a/pkg/common/ipfs/file.go b/pkg/ipfsapi/file.go similarity index 96% rename from pkg/common/ipfs/file.go rename to pkg/ipfsapi/file.go index e3f5d531a..3f1e0aa03 100644 --- a/pkg/common/ipfs/file.go +++ b/pkg/ipfsapi/file.go @@ -1,4 +1,4 @@ -package ipfs +package ipfsapi import ( "context" diff --git a/pkg/common/ipfs/folder.go b/pkg/ipfsapi/folder.go similarity index 95% rename from pkg/common/ipfs/folder.go rename to pkg/ipfsapi/folder.go index 4fbe0438c..511e2f03f 100644 --- a/pkg/common/ipfs/folder.go +++ b/pkg/ipfsapi/folder.go @@ -1,4 +1,4 @@ -package ipfs +package ipfsapi import ( "context" diff --git a/pkg/common/ipfs/ipfs.go b/pkg/ipfsapi/iface.go similarity index 97% rename from pkg/common/ipfs/ipfs.go rename to pkg/ipfsapi/iface.go index 2d0fa8bfe..63f4c0ef1 100644 --- a/pkg/common/ipfs/ipfs.go +++ b/pkg/ipfsapi/iface.go @@ -1,4 +1,4 @@ -package ipfs +package ipfsapi import "github.com/ipfs/boxo/files" diff --git a/crypto/ucan/store/ipfs.go b/pkg/ipfsapi/ucans.go similarity index 66% rename from crypto/ucan/store/ipfs.go rename to pkg/ipfsapi/ucans.go index c7e723fbc..9ca466a12 100644 --- a/crypto/ucan/store/ipfs.go +++ b/pkg/ipfsapi/ucans.go @@ -1,4 +1,4 @@ -package store +package ipfsapi import ( "context" @@ -8,34 +8,33 @@ import ( "github.com/golang-jwt/jwt" "github.com/ipfs/go-cid" + "github.com/onsonr/sonr/crypto/keys" "github.com/onsonr/sonr/crypto/ucan" - "github.com/onsonr/sonr/crypto/ucan/didkey" - "github.com/onsonr/sonr/pkg/common/ipfs" ) type IPFSTokenStore interface { ucan.TokenStore ResolveCIDBytes(ctx context.Context, id cid.Cid) ([]byte, error) - ResolveDIDKey(ctx context.Context, did string) (didkey.ID, error) + ResolveDIDKey(ctx context.Context, did string) (keys.DID, error) } -// ipfsTokenStore is a token store that uses IPFS to store tokens. It uses the memory store as a cache +// ipfsUCANStore is a token store that uses IPFS to store tokens. It uses the memory store as a cache // for CID strings to be used as keys for retrieving tokens. -type ipfsTokenStore struct { +type ipfsUCANStore struct { sync.Mutex - ipfs ipfs.Client + ipfs Client cache map[string]string } -// NewIPFSTokenStore creates a new IPFS-backed token store -func NewIPFSTokenStore(ipfsClient ipfs.Client) IPFSTokenStore { - return &ipfsTokenStore{ +// NewUCANStore creates a new IPFS-backed token store +func NewUCANStore(ipfsClient Client) IPFSTokenStore { + return &ipfsUCANStore{ ipfs: ipfsClient, cache: make(map[string]string), } } -func (st *ipfsTokenStore) PutToken(ctx context.Context, key string, raw string) error { +func (st *ipfsUCANStore) PutToken(ctx context.Context, key string, raw string) error { // Validate token format p := &jwt.Parser{ UseJSONNumber: true, @@ -58,7 +57,7 @@ func (st *ipfsTokenStore) PutToken(ctx context.Context, key string, raw string) return nil } -func (st *ipfsTokenStore) RawToken(ctx context.Context, key string) (string, error) { +func (st *ipfsUCANStore) RawToken(ctx context.Context, key string) (string, error) { st.Lock() cid, exists := st.cache[key] st.Unlock() @@ -76,7 +75,7 @@ func (st *ipfsTokenStore) RawToken(ctx context.Context, key string) (string, err return string(data), nil } -func (st *ipfsTokenStore) DeleteToken(ctx context.Context, key string) error { +func (st *ipfsUCANStore) DeleteToken(ctx context.Context, key string) error { st.Lock() defer st.Unlock() @@ -94,7 +93,7 @@ func (st *ipfsTokenStore) DeleteToken(ctx context.Context, key string) error { return nil } -func (st *ipfsTokenStore) ListTokens(ctx context.Context, offset, limit int) ([]ucan.RawToken, error) { +func (st *ipfsUCANStore) ListTokens(ctx context.Context, offset, limit int) ([]ucan.RawToken, error) { st.Lock() defer st.Unlock() @@ -126,7 +125,7 @@ func (st *ipfsTokenStore) ListTokens(ctx context.Context, offset, limit int) ([] return tokens[offset:end], nil } -func (st *ipfsTokenStore) ResolveCIDBytes(ctx context.Context, id cid.Cid) ([]byte, error) { +func (st *ipfsUCANStore) ResolveCIDBytes(ctx context.Context, id cid.Cid) ([]byte, error) { data, err := st.ipfs.Get(id.String()) if err != nil { return nil, fmt.Errorf("failed to resolve CID bytes: %w", err) @@ -134,10 +133,10 @@ func (st *ipfsTokenStore) ResolveCIDBytes(ctx context.Context, id cid.Cid) ([]by return data, nil } -func (st *ipfsTokenStore) ResolveDIDKey(ctx context.Context, did string) (didkey.ID, error) { - id, err := didkey.Parse(did) +func (st *ipfsUCANStore) ResolveDIDKey(ctx context.Context, did string) (keys.DID, error) { + id, err := keys.Parse(did) if err != nil { - return didkey.ID{}, fmt.Errorf("failed to parse DID: %w", err) + return keys.DID{}, fmt.Errorf("failed to parse DID: %w", err) } return id, nil } diff --git a/pkl/sonr.chain/App.pkl b/pkl/sonr.chain/App.pkl deleted file mode 100644 index 9ec0317c8..000000000 --- a/pkl/sonr.chain/App.pkl +++ /dev/null @@ -1,89 +0,0 @@ -open module sonr.chain.App - -import "package://pkg.pkl-lang.org/pkl-pantry/pkl.toml@1.0.0#/toml.pkl" - -class Chain { - `minimum-gas-prices`: String = "0stake" - `query-gas-limit`: String = "0" - pruning: String = "default" - `pruning-keep-recent`: String = "0" - `pruning-interval`: String = "0" - `halt-height`: Int = 0 - `halt-time`: Int = 0 - `min-retain-blocks`: Int = 0 - `inter-block-cache`: Boolean = true - `index-events`: Listing = new {} - `iavl-cache-size`: Int = 781250 - `iavl-disable-fastnode`: Boolean = false - `app-db-backend`: String = "" - telemetry: Telemetry = new {} - api: Api = new {} - grpc: Grpc = new {} - `grpc-web`: GrpcWeb = new {} - `state-sync`: StateSync = new {} - streaming: Streaming = new {} - mempool: Mempool = new {} -} - -class Telemetry { - `service-name`: String = "" - enabled: Boolean = true - `enable-hostname`: Boolean = false - `enable-hostname-label`: Boolean = false - `enable-service-label`: Boolean = false - `prometheus-retention-time`: Int = 60 - `global-labels`: Listing> = new { - new { - "chain_id" - "chain-NKlMbx" - } - } - `metrics-sink`: String = "" - `statsd-addr`: String = "" - `datadog-hostname`: String = "" -} - -class Api { - enable: Boolean = true - swagger: Boolean = false - address: String = "tcp://0.0.0.0:1317" - `max-open-connections`: Int = 1000 - `rpc-read-timeout`: Int = 10 - `rpc-write-timeout`: Int = 0 - `rpc-max-body-bytes`: Int = 1000000 - `enabled-unsafe-cors`: Boolean = false -} - -class Grpc { - enable: Boolean = true - address: String = "0.0.0.0:9090" - `max-recv-msg-size`: String = "10485760" - `max-send-msg-size`: String = "2147483647" -} - -class GrpcWeb { - enable: Boolean = true -} - -class StateSync { - `snapshot-interval`: Int = 0 - `snapshot-keep-recent`: Int = 2 -} - -class Streaming { - abci: Abci = new {} -} - -class Abci { - keys: Listing = new {} - plugin: String = "" - `stop-node-on-err`: Boolean = true -} - -class Mempool { - `max-txs`: Int = 5000 -} - -output { - renderer = new toml.Renderer {} -} diff --git a/pkl/sonr.chain/Config.pkl b/pkl/sonr.chain/Config.pkl deleted file mode 100644 index ee5e50c52..000000000 --- a/pkl/sonr.chain/Config.pkl +++ /dev/null @@ -1,154 +0,0 @@ -open module sonr.chain.Config - -import "package://pkg.pkl-lang.org/pkl-pantry/pkl.toml@1.0.0#/toml.pkl" - -class Chain { - version: String = "0.38.5" - proxy_app: String = "tcp://127.0.0.1:26658" - moniker: String = "node0" - db_backend: String = "goleveldb" - db_dir: String = "data" - log_level: String = "info" - log_format: String = "plain" - genesis_file: String = "config/genesis.json" - priv_validator_key_file: String = "config/priv_validator_key.json" - priv_validator_state_file: String = "data/priv_validator_state.json" - priv_validator_laddr: String = "" - node_key_file: String = "config/node_key.json" - abci: String = "socket" - filter_peers: Boolean = false - - rpc: Rpc = new {} - p2p: P2p = new {} - mempool: Mempool = new {} - statesync: StateSync = new {} - blocksync: BlockSync = new {} - consensus: Consensus = new {} - storage: Storage = new {} - tx_index: TxIndex = new {} - instrumentation: Instrumentation = new {} -} - -class Rpc { - laddr: String = "tcp://0.0.0.0:26657" - cors_allowed_origins: Listing = new {} - cors_allowed_methods: Listing = new { - "HEAD" - "GET" - "POST" - } - cors_allowed_headers: Listing = new { - "Origin" - "Accept" - "Content-Type" - "X-Requested-With" - "X-Server-Time" - } - grpc_laddr: String = "" - grpc_max_open_connections: Int = 900 - unsafe: Boolean = false - max_open_connections: Int = 900 - max_subscription_clients: Int = 100 - max_subscriptions_per_client: Int = 5 - experimental_subscription_buffer_size: Int = 200 - experimental_websocket_write_buffer_size: Int = 200 - experimental_close_on_slow_client: Boolean = false - timeout_broadcast_tx_commit: String = "10s" - max_body_bytes: Int = 1000000 - max_header_bytes: Int = 1048576 - tls_cert_file: String = "" - tls_key_file: String = "" - pprof_laddr: String = "localhost:6060" -} - -class P2p { - laddr: String = "tcp://0.0.0.0:26656" - external_address: String = "" - seeds: String = "" - persistent_peers: String = read("env:SONR_PERSISTENT_PEERS") ?? "" - addr_book_file: String = "config/addrbook.json" - addr_book_strict: Boolean = true - max_num_inbound_peers: Int = 40 - max_num_outbound_peers: Int = 10 - unconditional_peer_ids: String = "" - persistent_peers_max_dial_period: String = "0s" - flush_throttle_timeout: String = "100ms" - max_packet_msg_payload_size: Int = 1024 - send_rate: Int = 5120000 - recv_rate: Int = 5120000 - pex: Boolean = true - seed_mode: Boolean = false - private_peer_ids: String = "" - allow_duplicate_ip: Boolean = false - handshake_timeout: String = "20s" - dial_timeout: String = "3s" -} - -class Mempool { - type: String = "flood" - recheck: Boolean = true - broadcast: Boolean = true - wal_dir: String = "" - size: Int = 5000 - max_txs_bytes: Int = 1073741824 - cache_size: Int = 10000 - `keep-invalid-txs-in-cache`: Boolean = false - max_tx_bytes: Int = 1048576 - max_batch_bytes: Int = 0 - experimental_max_gossip_connections_to_persistent_peers: Int = 0 - experimental_max_gossip_connections_to_non_persistent_peers: Int = 0 -} - -class StateSync { - enable: Boolean = false - rpc_servers: String = "" - trust_height: Int = 0 - trust_hash: String = "" - trust_period: String = "168h0m0s" - discovery_time: String = "15s" - temp_dir: String = "" - chunk_request_timeout: String = "10s" - chunk_fetchers: String = "4" -} - -class BlockSync { - version: String = "v0" -} - -class Consensus { - wal_file: String = "data/cs.wal/wal" - timeout_propose: String = "3s" - timeout_propose_delta: String = "500ms" - timeout_prevote: String = "1s" - timeout_prevote_delta: String = "500ms" - timeout_precommit: String = "1s" - timeout_precommit_delta: String = "500ms" - timeout_commit: String = "5s" - double_sign_check_height: Int = 0 - skip_timeout_commit: Boolean = false - create_empty_blocks: Boolean = true - create_empty_blocks_interval: String = "0s" - peer_gossip_sleep_duration: String = "100ms" - peer_query_maj23_sleep_duration: String = "2s" -} - -class Storage { - discard_abci_responses: Boolean = false -} - -class TxIndex { - indexer: String = "kv" - `psql-conn`: String = read("env:SONR_PSQL_CONN") ?? "" -} - -class Instrumentation { - prometheus: Boolean = false - prometheus_listen_addr: String = ":26660" - max_open_connections: Int = 3 - namespace: String = "cometbft" -} - - -output { - renderer = new toml.Renderer {} -} diff --git a/pkl/sonr.chain/Genesis.pkl b/pkl/sonr.chain/Genesis.pkl deleted file mode 100644 index 3247a1ea5..000000000 --- a/pkl/sonr.chain/Genesis.pkl +++ /dev/null @@ -1,747 +0,0 @@ -open module sonr.chain.Genesis - -app_name: String - -app_version: String - -genesis_time: String - -chain_id: String - -initial_height: Int - -app_hash: Any - -app_state: AppState - -consensus: Consensus - -class AppState { - `07-tendermint`: Any - - auth: Auth - - authz: Authz - - bank: Bank - - capability: Capability - - circuit: Circuit - - consensus: Any - - crisis: Crisis - - did: Did - - distribution: Distribution - - dwn: Dwn - - evidence: Evidence - - feegrant: Feegrant - - feeibc: Feeibc - - genutil: Genutil - - globalfee: Globalfee - - gov: Gov - - group: Group - - ibc: Ibc - - interchainaccounts: Interchainaccounts - - mint: Mint - - nft: Nft - - packetfowardmiddleware: Packetfowardmiddleware - - params: Any - - poa: Poa - - slashing: Slashing - - staking: Staking - - svc: Svc - - tokenfactory: Tokenfactory - - transfer: Transfer - - upgrade: Dynamic - - vesting: Dynamic -} - -class Auth { - params: Params - - accounts: Listing -} - -class Params { - max_memo_characters: String - - tx_sig_limit: String - - tx_size_cost_per_byte: String - - sig_verify_cost_ed25519: String - - sig_verify_cost_secp256k1: String -} - -class AccountsItem1 { - `@type`: String - - address: String - - pub_key: Any - - account_number: String - - sequence: String -} - -class Authz { - authorization: Listing -} - -class Bank { - params: BankParams - - balances: Listing - - supply: Listing - - denom_metadata: Listing - - send_enabled: Listing -} - -class BankParams { - send_enabled: Listing - - default_send_enabled: Boolean -} - -class BalancesItem1 { - address: String - - coins: Listing -} - -class ExpeditedMinDepositItem0 { - denom: String - - amount: String -} - -class Capability { - index: String - - owners: Listing -} - -class Circuit { - account_permissions: Listing - - disabled_type_urls: Listing -} - -class Crisis { - constant_fee: ExpeditedMinDepositItem0 -} - -class Did { - params: Dynamic -} - -class Distribution { - params: DistributionParams - - fee_pool: FeePool - - delegator_withdraw_infos: Listing - - previous_proposer: String - - outstanding_rewards: Listing - - validator_accumulated_commissions: Listing - - validator_historical_rewards: Listing - - validator_current_rewards: Listing - - delegator_starting_infos: Listing - - validator_slash_events: Listing -} - -class DistributionParams { - community_tax: String - - base_proposer_reward: String - - bonus_proposer_reward: String - - withdraw_addr_enabled: Boolean -} - -class FeePool { - community_pool: Listing -} - -class Dwn { - params: DwnParams -} - -class DwnParams { - allowed_public_keys: Dynamic - - conveyance_preference: String - - attestation_formats: Listing - - schema: Schema - - allowed_operators: Listing -} - -class Schema { - version: Int - - account: String - - asset: String - - chain: String - - credential: String - - did: String - - jwk: String - - grant: String - - keyshare: String - - profile: String -} - -class Evidence { - evidence: Listing -} - -class Feegrant { - allowances: Listing -} - -class Feeibc { - identified_fees: Listing - - fee_enabled_channels: Listing - - registered_payees: Listing - - registered_counterparty_payees: Listing - - forward_relayers: Listing -} - -class Genutil { - gen_txs: Listing -} - -class GenTxsItem0 { - body: Body - - auth_info: AuthInfo - - signatures: Listing -} - -class Body { - messages: Listing - - memo: String - - timeout_height: String - - extension_options: Listing - - non_critical_extension_options: Listing -} - -class MessagesItem0 { - `@type`: String - - description: Description - - commission: Commission - - min_self_delegation: String - - delegator_address: String - - validator_address: String - - pubkey: PublicKey - - value: ExpeditedMinDepositItem0 -} - -class Description { - moniker: String - - identity: String - - website: String - - security_contact: String - - details: String -} - -class Commission { - rate: String - - max_rate: String - - max_change_rate: String -} - -class PublicKey { - `@type`: String - - key: String -} - -class AuthInfo { - signer_infos: Listing - - fee: Fee - - tip: Any -} - -class SignerInfosItem0 { - public_key: PublicKey - - mode_info: ModeInfo - - sequence: String -} - -class ModeInfo { - single: Single -} - -class Single { - mode: String -} - -class Fee { - amount: Listing - - gas_limit: String - - payer: String - - granter: String -} - -class Globalfee { - params: GlobalfeeParams -} - -class GlobalfeeParams { - minimum_gas_prices: Listing -} - -class MinimumGasPricesItem0 { - amount: String - - denom: String -} - -class Gov { - starting_proposal_id: String - - deposits: Listing - - votes: Listing - - proposals: Listing - - deposit_params: Any - - voting_params: Any - - tally_params: Any - - params: GovParams - - constitution: String -} - -class GovParams { - min_deposit: Listing - - max_deposit_period: String - - voting_period: String - - quorum: String - - threshold: String - - veto_threshold: String - - min_initial_deposit_ratio: String - - proposal_cancel_ratio: String - - proposal_cancel_dest: String - - expedited_voting_period: String - - expedited_threshold: String - - expedited_min_deposit: Listing - - burn_vote_quorum: Boolean - - burn_proposal_deposit_prevote: Boolean - - burn_vote_veto: Boolean - - min_deposit_ratio: String -} - -class Group { - group_seq: String - - groups: Listing - - group_members: Listing - - group_policy_seq: String - - group_policies: Listing - - proposal_seq: String - - proposals: Listing - - votes: Listing -} - -class Ibc { - client_genesis: ClientGenesis - - connection_genesis: ConnectionGenesis - - channel_genesis: ChannelGenesis -} - -class ClientGenesis { - clients: Listing - - clients_consensus: Listing - - clients_metadata: Listing - - params: ClientGenesisParams - - create_localhost: Boolean - - next_client_sequence: String -} - -class ClientGenesisParams { - allowed_clients: Listing -} - -class ConnectionGenesis { - connections: Listing - - client_connection_paths: Listing - - next_connection_sequence: String - - params: ConnectionGenesisParams -} - -class ConnectionGenesisParams { - max_expected_time_per_block: String -} - -class ChannelGenesis { - channels: Listing - - acknowledgements: Listing - - commitments: Listing - - receipts: Listing - - send_sequences: Listing - - recv_sequences: Listing - - ack_sequences: Listing - - next_channel_sequence: String - - params: ChannelGenesisParams -} - -class ChannelGenesisParams { - upgrade_timeout: UpgradeTimeout -} - -class UpgradeTimeout { - height: Height - - timestamp: String -} - -class Height { - revision_number: String - - revision_height: String -} - -class Interchainaccounts { - controller_genesis_state: ControllerGenesisState - - host_genesis_state: HostGenesisState -} - -class ControllerGenesisState { - active_channels: Listing - - interchain_accounts: Listing - - ports: Listing - - params: ControllerGenesisStateParams -} - -class ControllerGenesisStateParams { - controller_enabled: Boolean -} - -class HostGenesisState { - active_channels: Listing - - interchain_accounts: Listing - - port: String - - params: HostGenesisStateParams -} - -class HostGenesisStateParams { - host_enabled: Boolean - - allow_messages: Listing -} - -class Mint { - minter: Minter - - params: MintParams -} - -class Minter { - inflation: String - - annual_provisions: String -} - -class MintParams { - mint_denom: String - - inflation_rate_change: String - - inflation_max: String - - inflation_min: String - - goal_bonded: String - - blocks_per_year: String -} - -class Nft { - classes: Listing - - entries: Listing -} - -class Packetfowardmiddleware { - params: PacketfowardmiddlewareParams - - in_flight_packets: Dynamic -} - -class PacketfowardmiddlewareParams { - fee_percentage: String -} - -class Poa { - params: PoaParams -} - -class PoaParams { - admins: Listing - - allow_validator_self_exit: Boolean -} - -class Slashing { - params: SlashingParams - - signing_infos: Listing - - missed_blocks: Listing -} - -class SlashingParams { - signed_blocks_window: String - - min_signed_per_window: String - - downtime_jail_duration: String - - slash_fraction_double_sign: String - - slash_fraction_downtime: String -} - -class Staking { - params: StakingParams - - last_total_power: String - - last_validator_powers: Listing - - validators: Listing - - delegations: Listing - - unbonding_delegations: Listing - - redelegations: Listing - - exported: Boolean -} - -class StakingParams { - unbonding_time: String - - max_validators: Int - - max_entries: Int - - historical_entries: Int - - bond_denom: String - - min_commission_rate: String -} - -class Svc { - params: SvcParams -} - -class SvcParams { - categories: Any - - types: Any -} - -class Tokenfactory { - params: TokenfactoryParams - - factory_denoms: Listing -} - -class TokenfactoryParams { - denom_creation_fee: Listing - - denom_creation_gas_consume: Int -} - -class Transfer { - port_id: String - - denom_traces: Listing - - params: TransferParams - - total_escrowed: Listing -} - -class TransferParams { - send_enabled: Boolean - - receive_enabled: Boolean -} - -class Consensus { - params: ConsensusParams -} - -class ConsensusParams { - block: Block - - evidence: ParamsEvidence - - validator: Validator - - version: Version - - abci: Abci -} - -class Block { - max_bytes: String - - max_gas: String -} - -class ParamsEvidence { - max_age_num_blocks: String - - max_age_duration: String - - max_bytes: String -} - -class Validator { - pub_key_types: Listing -} - -class Version { - app: String -} - -class Abci { - vote_extensions_enable_height: String -} - - diff --git a/pkl/sonr.chain/PklProject b/pkl/sonr.chain/PklProject deleted file mode 100644 index a5185f92b..000000000 --- a/pkl/sonr.chain/PklProject +++ /dev/null @@ -1,22 +0,0 @@ -//===----------------------------------------------------------------------===// -// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//===----------------------------------------------------------------------===// -/// Base configuration files for initializing a sonr chain -amends "../basePklProject.pkl" - -package { - name = "sonr.chain" - version = "0.0.2" -} diff --git a/pkl/sonr.conf/PklProject.deps.json b/pkl/sonr.conf/PklProject.deps.json deleted file mode 100644 index 836079aad..000000000 --- a/pkl/sonr.conf/PklProject.deps.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "schemaVersion": 1, - "resolvedDependencies": {} -} \ No newline at end of file diff --git a/pkl/sonr.conf/Hway.pkl b/pkl/sonr.net/Hway.pkl similarity index 86% rename from pkl/sonr.conf/Hway.pkl rename to pkl/sonr.net/Hway.pkl index de5223012..a0a70b4a0 100644 --- a/pkl/sonr.conf/Hway.pkl +++ b/pkl/sonr.net/Hway.pkl @@ -1,18 +1,17 @@ @go.Package { name = "github.com/onsonr/sonr/pkg/config/hway" } -open module sonr.conf.Hway +open module sonr.net.Hway import "package://pkg.pkl-lang.org/pkl-go/pkl.golang@0.5.0#/go.pkl" servePort: Int = 3000 -configDir: String = "~/.config/hway" sqliteFile: String = "hway.db" chainId: String = "sonr-testnet-1" ipfsGatewayUrl: String = "http://localhost:8080" sonrApiUrl: String = "http://localhost:1317" sonrGrpcUrl: String = "http://localhost:9090" sonrRpcUrl: String = "http://localhost:26657" - +psqlDSN: String diff --git a/pkl/sonr.conf/Motr.pkl b/pkl/sonr.net/Motr.pkl similarity index 97% rename from pkl/sonr.conf/Motr.pkl rename to pkl/sonr.net/Motr.pkl index 88d89a28f..2239e3e62 100644 --- a/pkl/sonr.conf/Motr.pkl +++ b/pkl/sonr.net/Motr.pkl @@ -1,6 +1,6 @@ @go.Package { name = "github.com/onsonr/sonr/pkg/config/motr" } -module sonr.conf.Motr +module sonr.net.Motr import "package://pkg.pkl-lang.org/pkl-go/pkl.golang@0.5.0#/go.pkl" diff --git a/pkl/sonr.conf/PklProject b/pkl/sonr.net/PklProject similarity index 97% rename from pkl/sonr.conf/PklProject rename to pkl/sonr.net/PklProject index 9aaf524d8..16362f342 100644 --- a/pkl/sonr.conf/PklProject +++ b/pkl/sonr.net/PklProject @@ -17,6 +17,6 @@ amends "../basePklProject.pkl" package { - name = "sonr.conf" + name = "sonr.net" version = "0.0.1" } diff --git a/pkl/sonr.chain/PklProject.deps.json b/pkl/sonr.net/PklProject.deps.json similarity index 100% rename from pkl/sonr.chain/PklProject.deps.json rename to pkl/sonr.net/PklProject.deps.json From 1388a673e5165cefdbbf33dc629c0201600b4abe Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Fri, 13 Dec 2024 15:21:54 -0500 Subject: [PATCH 3/3] ci: Implement comprehensive CI/CD workflow with build, unit, race, and coverage tests --- .github/workflows/checks.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 925b0e543..76ec4cc61 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -6,6 +6,7 @@ on: jobs: test-builds: + if: github.event_name == 'pull_request' runs-on: ubuntu-latest name: Run Build Tests steps: @@ -28,7 +29,7 @@ jobs: run: make build-motr test-unit: - needs: [test-builds] + if: github.event_name == 'pull_request' runs-on: ubuntu-latest name: Run Unit Tests steps: @@ -47,7 +48,7 @@ jobs: test-race: runs-on: ubuntu-latest - needs: [test-builds] + if: github.event_name == 'merge_group' name: Run Race Tests continue-on-error: true steps: @@ -66,9 +67,8 @@ jobs: test-cover: runs-on: ubuntu-latest - needs: [test-builds] + if: github.event_name == 'merge_group' name: Run Coverage Tests - continue-on-error: true steps: - name: Checkout repository uses: actions/checkout@v4 @@ -85,7 +85,6 @@ jobs: goreleaser-check: if: github.event_name == 'merge_group' - needs: [test-unit] runs-on: ubuntu-latest name: Check GoReleaser Config steps: @@ -102,7 +101,7 @@ jobs: check-latest: true - name: Check GoReleaser Config - uses: goreleaser/goreleaser-action@v5 + uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro version: latest @@ -112,7 +111,7 @@ jobs: GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - name: GoReleaser Dry Run - uses: goreleaser/goreleaser-action@v5 + uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro version: latest