mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-03 01:41:44 +00:00
feature/1115 execute ucan token (#1177)
- **deps: remove tigerbeetle-go dependency** - **refactor: remove unused landing page components and models** - **feat: add pin and publish vault handlers** - **refactor: move payment and credential services to webui browser package** - **refactor: remove unused credentials management components** - **feat: add landing page components and middleware for credentials and payments** - **refactor: remove unused imports in vault config** - **refactor: remove unused bank, DID, and DWN gRPC clients** - **refactor: rename client files and improve code structure** - **feat: add session middleware helpers and landing page components** - **feat: add user profile registration flow** - **feat: Implement WebAuthn registration flow** - **feat: add error view for users without WebAuthn devices** - **chore: update htmx to include extensions** - **refactor: rename pin handler to claim handler and update routes** - **chore: update import paths after moving UI components and styles** - **fix: address potential server errors by handling and logging them properly** - **refactor: move vault config to gateway package and update related dependencies** - **style: simplify form styling and remove unnecessary components** - **feat: improve UI design for registration flow** - **feat: implement passkey-based authentication** - **refactor: migrate registration forms to use reusable form components** - **refactor: remove tailwindcss setup and use CDN instead** - **style: update submit button style to use outline variant** - **refactor: refactor server and IPFS client, remove MPC encryption** - **refactor: Abstract keyshare functionality and improve message encoding** - **refactor: improve keyset JSON marshaling and error handling** - **feat: add support for digital signatures using MPC keys** - **fix: Refactor MarshalJSON to use standard json.Marshal for Message serialization** - **fix: Encode messages before storing in keyshare structs** - **style: update form input styles for improved user experience** - **refactor: improve code structure in registration handlers** - **refactor: consolidate signer middleware and IPFS interaction** - **refactor: rename MPC signing and refresh protocol functions** - **refactor: update hway configuration loading mechanism** - **feat: integrate database support for sessions and users** - **refactor: remove devnet infrastructure and simplify build process** - **docs(guides): add Sonr DID module guide** - **feat: integrate progress bar into registration form** - **refactor: migrate WebAuthn dependencies to protocol package** - **feat: enhance user registration with passkey integration and improved form styling** - **refactor: move gateway view handlers to internal pages package** - **refactor: Move address package to MPC module** - **feat: integrate turnstile for registration** - **style: remove unnecessary size attribute from buttons** - **refactor: rename cookie package to session/cookie** - **refactor: remove unnecessary types.Session dependency** - **refactor: rename pkg/core to pkg/chain** - **refactor: simplify deployment process by removing testnet-specific Taskfile and devbox configuration** - **feat: add error redirect functionality and improve routes** - **feat: implement custom error handling for gateway** - **chore: update version number to 0.0.7 in template** - **feat: add IPFS client implementation** - **feat: Implement full IPFS client interface with comprehensive methods** - **refactor: improve IPFS client path handling** - **refactor: Move UCAN middleware to controller package** - **feat: add UCAN middleware to motr** - **refactor: update libp2p dependency** - **docs: add UCAN specification document** - **refactor: move UCAN controller logic to common package** - **refactor: rename exports.go to common.go** - **feat: add UCAN token support** - **refactor: migrate UCAN token parsing to dedicated package** - **refactor: improve CometBFT and app config initialization** - **refactor: improve deployment scripts and documentation** - **feat: integrate IPFS and producer middleware** - **refactor: rename agent directory to aider** - **fix: correct libp2p import path** - **refactor: remove redundant dependency** - **cleanup: remove unnecessary test files** - **refactor: move attention types to crypto/ucan package** - **feat: expand capabilities and resource types for UCANs** - **refactor: rename sonr.go to codec.go and update related imports** - **feat: add IPFS-based token store** - **feat: Implement IPFS-based token store with caching and UCAN integration** - **feat: Add dynamic attenuation constructor for UCAN presets** - **fix: Handle missing or invalid attenuation data with EmptyAttenuation** - **fix: Update UCAN attenuation tests with correct capability types** - **feat: integrate UCAN-based authorization into the producer middleware** - **refactor: remove unused dependency on go-ucan** - **refactor: Move address handling logic to DID module** - **feat: Add support for compressed and uncompressed Secp256k1 public keys in didkey** - **test: Add test for generating DID key from MPC keyshares** - **feat: Add methods for extracting compressed and uncompressed public keys in share types** - **feat: Add BaseKeyshare struct with public key conversion methods** - **refactor: Use compressed and uncompressed public keys in keyshare, fix public key usage in tests and verification** - **feat: add support for key generation policy type** - **fix: correct typo in VaultPermissions constant** - **refactor: move JWT related code to ucan package** - **refactor: move UCAN JWT and source code to spec package**
This commit is contained in:
@@ -6,10 +6,10 @@ import (
|
||||
"cosmossdk.io/core/header"
|
||||
"cosmossdk.io/core/store"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/core/branch"
|
||||
"github.com/onsonr/sonr/pkg/core/log"
|
||||
"github.com/onsonr/sonr/pkg/core/router"
|
||||
"github.com/onsonr/sonr/pkg/core/transaction"
|
||||
"github.com/onsonr/sonr/pkg/chain/branch"
|
||||
"github.com/onsonr/sonr/pkg/chain/log"
|
||||
"github.com/onsonr/sonr/pkg/chain/router"
|
||||
"github.com/onsonr/sonr/pkg/chain/transaction"
|
||||
)
|
||||
|
||||
// Environment is used to get all services to their respective module.
|
||||
@@ -3,7 +3,7 @@ package router
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/core/transaction"
|
||||
"github.com/onsonr/sonr/pkg/chain/transaction"
|
||||
)
|
||||
|
||||
// Service is the interface that wraps the basic methods for a router.
|
||||
@@ -1,36 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
)
|
||||
|
||||
// UCANConfig defines the configuration for UCAN middleware
|
||||
type UCANConfig struct {
|
||||
// Skipper defines a function to skip middleware
|
||||
Skipper func(c echo.Context) bool
|
||||
|
||||
// KeySource provides the source for validating UCANs
|
||||
KeySource mpc.KeyshareSource
|
||||
|
||||
// TokenLookup is a string in the form of "<source>:<name>" that is used
|
||||
// to extract token from the request.
|
||||
// Optional. Default value "header:Authorization".
|
||||
// Possible values:
|
||||
// - "header:<name>"
|
||||
// - "query:<name>"
|
||||
// - "param:<name>"
|
||||
// - "cookie:<name>"
|
||||
TokenLookup string
|
||||
|
||||
// AuthScheme to be used in the Authorization header.
|
||||
// Optional. Default value "Bearer".
|
||||
AuthScheme string
|
||||
}
|
||||
|
||||
// DefaultUCANConfig is the default UCAN middleware config
|
||||
var DefaultUCANConfig = UCANConfig{
|
||||
Skipper: nil,
|
||||
TokenLookup: "header:Authorization",
|
||||
AuthScheme: "Bearer",
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type Option func(c *UCANConfig)
|
||||
|
||||
func WithSkipper(skipper func(c echo.Context) bool) Option {
|
||||
return func(c *UCANConfig) {
|
||||
c.Skipper = skipper
|
||||
}
|
||||
}
|
||||
|
||||
func WithAuthScheme(scheme string) Option {
|
||||
return func(c *UCANConfig) {
|
||||
c.AuthScheme = scheme
|
||||
}
|
||||
}
|
||||
|
||||
// WithTokenLookup sets the token lookup strategy
|
||||
func WithTokenLookup(lookup string) Option {
|
||||
return func(c *UCANConfig) {
|
||||
c.TokenLookup = lookup
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/gateway/config"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type ClientsContext struct {
|
||||
echo.Context
|
||||
addr string
|
||||
}
|
||||
|
||||
func GetClientConn(c echo.Context) (*grpc.ClientConn, error) {
|
||||
cc, ok := c.(*ClientsContext)
|
||||
if !ok {
|
||||
return nil, echo.NewHTTPError(http.StatusInternalServerError, "ClientsContext not found")
|
||||
}
|
||||
grpcConn, err := grpc.NewClient(cc.addr, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to dial gRPC")
|
||||
}
|
||||
return grpcConn, nil
|
||||
}
|
||||
|
||||
func Middleware(env config.Env) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
cc := &ClientsContext{Context: c, addr: env.GetSonrGrpcUrl()}
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
"github.com/labstack/echo/v4"
|
||||
didv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
dwnv1 "github.com/onsonr/sonr/api/dwn/v1"
|
||||
svcv1 "github.com/onsonr/sonr/api/svc/v1"
|
||||
)
|
||||
|
||||
func BankQueryClient(c echo.Context) (bankv1beta1.QueryClient, error) {
|
||||
conn, err := GetClientConn(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bankv1beta1.NewQueryClient(conn), nil
|
||||
}
|
||||
|
||||
func DIDQueryClient(c echo.Context) (didv1.QueryClient, error) {
|
||||
conn, err := GetClientConn(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return didv1.NewQueryClient(conn), nil
|
||||
}
|
||||
|
||||
func DWNQueryClient(c echo.Context) (dwnv1.QueryClient, error) {
|
||||
conn, err := GetClientConn(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dwnv1.NewQueryClient(conn), nil
|
||||
}
|
||||
|
||||
func SVCQueryClient(c echo.Context) (svcv1.QueryClient, error) {
|
||||
conn, err := GetClientConn(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return svcv1.NewQueryClient(conn), nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
type LargeBlob struct {
|
||||
Support string `json:"support"`
|
||||
Write string `json:"write"`
|
||||
}
|
||||
|
||||
type BrowserName string
|
||||
|
||||
const (
|
||||
BrowserNameUnknown BrowserName = " Not A;Brand"
|
||||
BrowserNameChromium BrowserName = "Chromium"
|
||||
)
|
||||
|
||||
func (n BrowserName) String() string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
type PeerRole string
|
||||
|
||||
const (
|
||||
RoleUnknown PeerRole = "none"
|
||||
RoleHway PeerRole = "hway"
|
||||
RoleMotr PeerRole = "motr"
|
||||
)
|
||||
|
||||
func (r PeerRole) Is(role PeerRole) bool {
|
||||
return r == role
|
||||
}
|
||||
|
||||
func (r PeerRole) String() string {
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func Base64Encode(data []byte) string {
|
||||
return base64.RawURLEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
func Base64Decode(data string) ([]byte, error) {
|
||||
return base64.RawURLEncoding.DecodeString(data)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/crypto/ucan/spec"
|
||||
)
|
||||
|
||||
// ControllerConfig defines the configuration for UCAN middleware
|
||||
type ControllerConfig struct {
|
||||
// Skipper defines a function to skip middleware
|
||||
Skipper func(c echo.Context) bool
|
||||
|
||||
// KeySource provides the source for validating UCANs
|
||||
KeySource spec.KeyshareSource
|
||||
|
||||
// TokenLookup is a string in the form of "<source>:<name>" that is used
|
||||
// to extract token from the request.
|
||||
// Optional. Default value "header:Authorization".
|
||||
// Possible values:
|
||||
// - "header:<name>"
|
||||
// - "query:<name>"
|
||||
// - "param:<name>"
|
||||
// - "cookie:<name>"
|
||||
TokenLookup string
|
||||
|
||||
// AuthScheme to be used in the Authorization header.
|
||||
// Optional. Default value "Bearer".
|
||||
AuthScheme string
|
||||
}
|
||||
|
||||
// DefaultControllerConfig is the default UCAN middleware config
|
||||
var DefaultControllerConfig = ControllerConfig{
|
||||
Skipper: nil,
|
||||
TokenLookup: "header:Authorization",
|
||||
AuthScheme: "Bearer",
|
||||
}
|
||||
|
||||
type Option func(c *ControllerConfig)
|
||||
|
||||
func WithSkipper(skipper func(c echo.Context) bool) Option {
|
||||
return func(c *ControllerConfig) {
|
||||
c.Skipper = skipper
|
||||
}
|
||||
}
|
||||
|
||||
func WithAuthScheme(scheme string) Option {
|
||||
return func(c *ControllerConfig) {
|
||||
c.AuthScheme = scheme
|
||||
}
|
||||
}
|
||||
|
||||
// WithTokenLookup sets the token lookup strategy
|
||||
func WithTokenLookup(lookup string) Option {
|
||||
return func(c *ControllerConfig) {
|
||||
c.TokenLookup = lookup
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,37 @@
|
||||
package auth
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/crypto/ucan/spec"
|
||||
)
|
||||
|
||||
// UCAN returns middleware to validate UCAN tokens
|
||||
func UCAN(source mpc.KeyshareSource, opts ...Option) echo.MiddlewareFunc {
|
||||
c := DefaultUCANConfig
|
||||
// Middleware returns middleware to validate Middleware tokens
|
||||
func Middleware(source spec.KeyshareSource, opts ...Option) echo.MiddlewareFunc {
|
||||
c := DefaultControllerConfig
|
||||
for _, opt := range opts {
|
||||
opt(&c)
|
||||
}
|
||||
c.KeySource = source
|
||||
return UCANWithConfig(c)
|
||||
return initWithConfig(c)
|
||||
}
|
||||
|
||||
// UCANWithConfig returns UCAN middleware with custom config
|
||||
func UCANWithConfig(config UCANConfig) echo.MiddlewareFunc {
|
||||
// initWithConfig returns UCAN middleware with custom config
|
||||
func initWithConfig(config ControllerConfig) echo.MiddlewareFunc {
|
||||
// Defaults
|
||||
if config.Skipper == nil {
|
||||
config.Skipper = DefaultUCANConfig.Skipper
|
||||
config.Skipper = DefaultControllerConfig.Skipper
|
||||
}
|
||||
if config.TokenLookup == "" {
|
||||
config.TokenLookup = DefaultUCANConfig.TokenLookup
|
||||
config.TokenLookup = DefaultControllerConfig.TokenLookup
|
||||
}
|
||||
if config.AuthScheme == "" {
|
||||
config.AuthScheme = DefaultUCANConfig.AuthScheme
|
||||
config.AuthScheme = DefaultControllerConfig.AuthScheme
|
||||
}
|
||||
|
||||
// Initialize
|
||||
@@ -1,35 +0,0 @@
|
||||
package cookie
|
||||
|
||||
// Key is a type alias for string.
|
||||
type Key string
|
||||
|
||||
const (
|
||||
// SessionID is the key for the session ID cookie.
|
||||
SessionID Key = "session.id"
|
||||
|
||||
// SessionChallenge is the key for the session challenge cookie.
|
||||
SessionChallenge Key = "session.challenge"
|
||||
|
||||
// SessionRole is the key for the session role cookie.
|
||||
SessionRole Key = "session.role"
|
||||
|
||||
// SonrAddress is the key for the Sonr address cookie.
|
||||
SonrAddress Key = "sonr.address"
|
||||
|
||||
// SonrDID is the key for the Sonr DID cookie.
|
||||
SonrDID Key = "sonr.did"
|
||||
|
||||
// UserHandle is the key for the User Handle cookie.
|
||||
UserHandle Key = "user.handle"
|
||||
|
||||
// VaultCID is the key for the Vault CID cookie.
|
||||
VaultCID Key = "vault.cid"
|
||||
|
||||
// VaultSchema is the key for the Vault schema cookie.
|
||||
VaultSchema Key = "vault.schema"
|
||||
)
|
||||
|
||||
// String returns the string representation of the CookieKey.
|
||||
func (c Key) String() string {
|
||||
return string(c)
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package cookie
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func Exists(c echo.Context, key Key) bool {
|
||||
ck, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return ck != nil
|
||||
}
|
||||
|
||||
func Read(c echo.Context, key Key) (string, error) {
|
||||
cookie, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
// Cookie not found or other error
|
||||
return "", err
|
||||
}
|
||||
if cookie == nil || cookie.Value == "" {
|
||||
// Cookie is empty
|
||||
return "", http.ErrNoCookie
|
||||
}
|
||||
return cookie.Value, nil
|
||||
}
|
||||
|
||||
func ReadBytes(c echo.Context, key Key) ([]byte, error) {
|
||||
cookie, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
// Cookie not found or other error
|
||||
return nil, err
|
||||
}
|
||||
if cookie == nil || cookie.Value == "" {
|
||||
// Cookie is empty
|
||||
return nil, http.ErrNoCookie
|
||||
}
|
||||
return base64.RawURLEncoding.DecodeString(cookie.Value)
|
||||
}
|
||||
|
||||
func ReadUnsafe(c echo.Context, key Key) string {
|
||||
ck, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return ck.Value
|
||||
}
|
||||
|
||||
func Write(c echo.Context, key Key, value string) error {
|
||||
cookie := &http.Cookie{
|
||||
Name: key.String(),
|
||||
Value: value,
|
||||
Expires: time.Now().Add(24 * time.Hour),
|
||||
HttpOnly: true,
|
||||
Path: "/",
|
||||
// Add Secure and SameSite attributes as needed
|
||||
}
|
||||
c.SetCookie(cookie)
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteBytes(c echo.Context, key Key, value []byte) error {
|
||||
cookie := &http.Cookie{
|
||||
Name: key.String(),
|
||||
Value: base64.RawURLEncoding.EncodeToString(value),
|
||||
Expires: time.Now().Add(24 * time.Hour),
|
||||
HttpOnly: true,
|
||||
Path: "/",
|
||||
// Add Secure and SameSite attributes as needed
|
||||
}
|
||||
c.SetCookie(cookie)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// CookieKey is a type alias for string.
|
||||
type CookieKey string
|
||||
|
||||
const (
|
||||
// SessionID is the key for the session ID cookie.
|
||||
SessionID CookieKey = "session.id"
|
||||
|
||||
// SessionChallenge is the key for the session challenge cookie.
|
||||
SessionChallenge CookieKey = "session.challenge"
|
||||
|
||||
// SessionRole is the key for the session role cookie.
|
||||
SessionRole CookieKey = "session.role"
|
||||
|
||||
// SonrAddress is the key for the Sonr address cookie.
|
||||
SonrAddress CookieKey = "sonr.address"
|
||||
|
||||
// SonrDID is the key for the Sonr DID cookie.
|
||||
SonrDID CookieKey = "sonr.did"
|
||||
|
||||
// UserAvatar is the key for the User Avatar cookie.
|
||||
UserAvatar CookieKey = "user.avatar"
|
||||
|
||||
// UserHandle is the key for the User Handle cookie.
|
||||
UserHandle CookieKey = "user.handle"
|
||||
|
||||
// UserName is the key for the User Name cookie.
|
||||
UserName CookieKey = "user.full_name"
|
||||
|
||||
// VaultAddress is the key for the Vault address cookie.
|
||||
VaultAddress CookieKey = "vault.address"
|
||||
|
||||
// VaultCID is the key for the Vault CID cookie.
|
||||
VaultCID CookieKey = "vault.cid"
|
||||
|
||||
// VaultSchema is the key for the Vault schema cookie.
|
||||
VaultSchema CookieKey = "vault.schema"
|
||||
)
|
||||
|
||||
// String returns the string representation of the CookieKey.
|
||||
func (c CookieKey) String() string {
|
||||
return string(c)
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Utility Methods │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func CookieExists(c echo.Context, key CookieKey) bool {
|
||||
ck, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return ck != nil
|
||||
}
|
||||
|
||||
func ReadCookie(c echo.Context, key CookieKey) (string, error) {
|
||||
cookie, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
// Cookie not found or other error
|
||||
return "", err
|
||||
}
|
||||
if cookie == nil || cookie.Value == "" {
|
||||
// Cookie is empty
|
||||
return "", http.ErrNoCookie
|
||||
}
|
||||
return cookie.Value, nil
|
||||
}
|
||||
|
||||
func ReadCookieBytes(c echo.Context, key CookieKey) ([]byte, error) {
|
||||
cookie, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
// Cookie not found or other error
|
||||
return nil, err
|
||||
}
|
||||
if cookie == nil || cookie.Value == "" {
|
||||
// Cookie is empty
|
||||
return nil, http.ErrNoCookie
|
||||
}
|
||||
return base64.RawURLEncoding.DecodeString(cookie.Value)
|
||||
}
|
||||
|
||||
func ReadCookieUnsafe(c echo.Context, key CookieKey) string {
|
||||
ck, err := c.Cookie(key.String())
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return ck.Value
|
||||
}
|
||||
|
||||
func WriteCookie(c echo.Context, key CookieKey, value string) error {
|
||||
cookie := &http.Cookie{
|
||||
Name: key.String(),
|
||||
Value: value,
|
||||
Expires: time.Now().Add(24 * time.Hour),
|
||||
HttpOnly: true,
|
||||
Path: "/",
|
||||
// Add Secure and SameSite attributes as needed
|
||||
}
|
||||
c.SetCookie(cookie)
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteCookieBytes(c echo.Context, key CookieKey, value []byte) error {
|
||||
cookie := &http.Cookie{
|
||||
Name: key.String(),
|
||||
Value: base64.RawURLEncoding.EncodeToString(value),
|
||||
Expires: time.Now().Add(24 * time.Hour),
|
||||
HttpOnly: true,
|
||||
Path: "/",
|
||||
// Add Secure and SameSite attributes as needed
|
||||
}
|
||||
c.SetCookie(cookie)
|
||||
return nil
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package header
|
||||
|
||||
type Key string
|
||||
|
||||
const (
|
||||
Authorization Key = "Authorization"
|
||||
|
||||
// User Agent
|
||||
Architecture Key = "Sec-CH-UA-Arch"
|
||||
Bitness Key = "Sec-CH-UA-Bitness"
|
||||
FullVersionList Key = "Sec-CH-UA-Full-Version-List"
|
||||
Mobile Key = "Sec-CH-UA-Mobile"
|
||||
Model Key = "Sec-CH-UA-Model"
|
||||
Platform Key = "Sec-CH-UA-Platform"
|
||||
PlatformVersion Key = "Sec-CH-UA-Platform-Version"
|
||||
UserAgent Key = "Sec-CH-UA"
|
||||
|
||||
// Sonr Injected
|
||||
SonrAPIURL Key = "X-Sonr-API"
|
||||
SonrgRPCURL Key = "X-Sonr-GRPC"
|
||||
SonrRPCURL Key = "X-Sonr-RPC"
|
||||
SonrWSURL Key = "X-Sonr-WS"
|
||||
)
|
||||
|
||||
func (h Key) String() string {
|
||||
return string(h)
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package header
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func Equals(c echo.Context, key Key, value string) bool {
|
||||
return c.Response().Header().Get(key.String()) == value
|
||||
}
|
||||
|
||||
// Exists returns true if the request has the header Key.
|
||||
func Exists(c echo.Context, key Key) bool {
|
||||
return c.Response().Header().Get(key.String()) != ""
|
||||
}
|
||||
|
||||
// Read returns the header value for the Key.
|
||||
func Read(c echo.Context, key Key) string {
|
||||
return c.Response().Header().Get(key.String())
|
||||
}
|
||||
|
||||
// Write sets the header value for the Key.
|
||||
func Write(c echo.Context, key Key, value string) {
|
||||
c.Response().Header().Set(key.String(), value)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package common
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
type HeaderKey string
|
||||
|
||||
const (
|
||||
Authorization HeaderKey = "Authorization"
|
||||
|
||||
// User Agent
|
||||
Architecture HeaderKey = "Sec-CH-UA-Arch"
|
||||
Bitness HeaderKey = "Sec-CH-UA-Bitness"
|
||||
FullVersionList HeaderKey = "Sec-CH-UA-Full-Version-List"
|
||||
Mobile HeaderKey = "Sec-CH-UA-Mobile"
|
||||
Model HeaderKey = "Sec-CH-UA-Model"
|
||||
Platform HeaderKey = "Sec-CH-UA-Platform"
|
||||
PlatformVersion HeaderKey = "Sec-CH-UA-Platform-Version"
|
||||
UserAgent HeaderKey = "Sec-CH-UA"
|
||||
|
||||
// Sonr Injected
|
||||
SonrAPIURL HeaderKey = "X-Sonr-API"
|
||||
SonrgRPCURL HeaderKey = "X-Sonr-GRPC"
|
||||
SonrRPCURL HeaderKey = "X-Sonr-RPC"
|
||||
SonrWSURL HeaderKey = "X-Sonr-WS"
|
||||
)
|
||||
|
||||
func (h HeaderKey) String() string {
|
||||
return string(h)
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Utility Methods │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func HeaderEquals(c echo.Context, key HeaderKey, value string) bool {
|
||||
return c.Response().Header().Get(key.String()) == value
|
||||
}
|
||||
|
||||
// HeaderExists returns true if the request has the header Key.
|
||||
func HeaderExists(c echo.Context, key HeaderKey) bool {
|
||||
return c.Response().Header().Get(key.String()) != ""
|
||||
}
|
||||
|
||||
// HeaderRead returns the header value for the Key.
|
||||
func HeaderRead(c echo.Context, key HeaderKey) string {
|
||||
return c.Response().Header().Get(key.String())
|
||||
}
|
||||
|
||||
// HeaderWrite sets the header value for the Key.
|
||||
func HeaderWrite(c echo.Context, key HeaderKey, value string) {
|
||||
c.Response().Header().Set(key.String(), value)
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package ipfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
api *rpc.HttpApi
|
||||
}
|
||||
|
||||
func NewClient() (Client, error) {
|
||||
api, err := rpc.NewLocalApi()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &client{api: api}, nil
|
||||
}
|
||||
|
||||
func (c *client) Add(data []byte) (string, error) {
|
||||
file := files.NewBytesFile(data)
|
||||
cidFile, err := c.api.Unixfs().Add(context.Background(), file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cidFile.String(), nil
|
||||
}
|
||||
|
||||
func (c *client) Get(cid string) ([]byte, error) {
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := c.api.Unixfs().Get(context.Background(), p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, ok := node.(files.File)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected node type: %T", node)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err := io.Copy(buf, file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (c *client) IsPublished(ipns string) (bool, error) {
|
||||
_, err := c.api.Name().Resolve(context.Background(), ipns)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *client) Exists(cid string) (bool, error) {
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, err = c.api.Block().Stat(context.Background(), p)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *client) Pin(cid string) error {
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.api.Pin().Add(context.Background(), p)
|
||||
}
|
||||
|
||||
func (c *client) Unpin(cid string) error {
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.api.Pin().Rm(context.Background(), p)
|
||||
}
|
||||
|
||||
func (c *client) Publish(cid string, name string) (string, error) {
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result, err := c.api.Name().Publish(context.Background(), p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.String(), nil
|
||||
}
|
||||
|
||||
func (c *client) Ls(cid string) ([]string, error) {
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := c.api.Unixfs().Ls(context.Background(), p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var files []string
|
||||
for entry := range node {
|
||||
files = append(files, entry.Name)
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package ipfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
)
|
||||
|
||||
type file struct {
|
||||
files.File
|
||||
name string
|
||||
}
|
||||
|
||||
func (f *file) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func NewFile(name string, data []byte) File {
|
||||
return &file{File: files.NewBytesFile(data), name: name}
|
||||
}
|
||||
|
||||
func (c *client) AddFile(file File) (string, error) {
|
||||
cidFile, err := c.api.Unixfs().Add(context.Background(), file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cidFile.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package ipfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
)
|
||||
|
||||
type Folder = files.Directory
|
||||
|
||||
func NewFolder(fs ...File) Folder {
|
||||
return files.NewMapDirectory(convertFilesToMap(fs))
|
||||
}
|
||||
|
||||
func (c *client) AddFolder(folder Folder) (string, error) {
|
||||
cidFile, err := c.api.Unixfs().Add(context.Background(), folder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cidFile.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package ipfs
|
||||
|
||||
import "github.com/ipfs/boxo/files"
|
||||
|
||||
type Client interface {
|
||||
Add(data []byte) (string, error)
|
||||
AddFile(file File) (string, error)
|
||||
AddFolder(folder Folder) (string, error)
|
||||
Get(cid string) ([]byte, error)
|
||||
IsPublished(ipns string) (bool, error)
|
||||
Exists(cid string) (bool, error)
|
||||
Pin(cid string) error
|
||||
Unpin(cid string) error
|
||||
Publish(cid string, name string) (string, error)
|
||||
Ls(cid string) ([]string, error)
|
||||
}
|
||||
|
||||
type File interface {
|
||||
files.File
|
||||
Name() string
|
||||
}
|
||||
|
||||
func convertFilesToMap(vs []File) map[string]files.Node {
|
||||
m := make(map[string]files.Node)
|
||||
for _, f := range vs {
|
||||
m[f.Name()] = f
|
||||
}
|
||||
return m
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
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"
|
||||
)
|
||||
|
||||
type ProducerContext struct {
|
||||
echo.Context
|
||||
// TokenParser is the attentuations assigned to the producer service
|
||||
TokenParser *ucan.TokenParser
|
||||
|
||||
// TokenStore is the token store used to store and retrieve tokens
|
||||
TokenStore store.IPFSTokenStore
|
||||
|
||||
// IPFSClient is the IPFS client used to resolve the UCAN
|
||||
IPFSClient ipfs.Client
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package producer
|
||||
|
||||
import (
|
||||
"github.com/onsonr/sonr/crypto/ucan"
|
||||
"github.com/onsonr/sonr/crypto/ucan/store"
|
||||
"github.com/onsonr/sonr/pkg/common/ipfs"
|
||||
|
||||
"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 {
|
||||
// Setup token store and parser
|
||||
store := store.NewIPFSTokenStore(ipfs)
|
||||
parser := ucan.NewTokenParser(perms.GetConstructor(), store, store)
|
||||
|
||||
// Return middleware
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
ctx := ProducerContext{
|
||||
Context: c,
|
||||
IPFSClient: ipfs,
|
||||
TokenParser: parser,
|
||||
TokenStore: store,
|
||||
}
|
||||
return next(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package producer
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
)
|
||||
|
||||
func NewKeyset(c echo.Context) (mpc.Keyset, error) {
|
||||
ks, err := mpc.NewKeyset()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ks, nil
|
||||
}
|
||||
|
||||
//
|
||||
// func GetKeyset(c echo.Context) (mpc.Keyset, error) {
|
||||
// cc, ok := c.(*SignerContext)
|
||||
// if !ok {
|
||||
// return nil, errors.New("not an SignerContext")
|
||||
// }
|
||||
// if !cc.hasKeyset {
|
||||
// return nil, fmt.Errorf("keyset not found")
|
||||
// }
|
||||
// if cc.keyset == nil {
|
||||
// return nil, fmt.Errorf("keyset is nil")
|
||||
// }
|
||||
// return cc.keyset, nil
|
||||
// }
|
||||
//
|
||||
// func NewSource(c echo.Context) (mpc.KeyshareSource, error) {
|
||||
// cc, ok := c.(*SignerContext)
|
||||
// if !ok {
|
||||
// return nil, errors.New("not an SignerContext")
|
||||
// }
|
||||
// if !cc.hasKeyset {
|
||||
// return nil, fmt.Errorf("keyset not found")
|
||||
// }
|
||||
// if cc.keyset == nil {
|
||||
// return nil, fmt.Errorf("keyset is nil")
|
||||
// }
|
||||
// src, err := mpc.NewSource(cc.keyset)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// cc.signer = src
|
||||
// cc.hasSigner = true
|
||||
// return src, nil
|
||||
// }
|
||||
//
|
||||
// func GetSource(c echo.Context) (mpc.KeyshareSource, error) {
|
||||
// cc, ok := c.(*SignerContext)
|
||||
// if !ok {
|
||||
// return nil, errors.New("not an SignerContext")
|
||||
// }
|
||||
// if !cc.hasSigner {
|
||||
// return nil, fmt.Errorf("signer not found")
|
||||
// }
|
||||
// if cc.signer == nil {
|
||||
// return nil, fmt.Errorf("signer is nil")
|
||||
// }
|
||||
// return cc.signer, nil
|
||||
// }
|
||||
@@ -1 +0,0 @@
|
||||
package request
|
||||
@@ -1 +0,0 @@
|
||||
package request
|
||||
@@ -1 +0,0 @@
|
||||
package request
|
||||
@@ -1 +0,0 @@
|
||||
package request
|
||||
@@ -1 +0,0 @@
|
||||
package response
|
||||
@@ -1 +0,0 @@
|
||||
package response
|
||||
@@ -0,0 +1,18 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func RedirectOnError(target string) echo.HTTPErrorHandler {
|
||||
return func(err error, c echo.Context) {
|
||||
if he, ok := err.(*echo.HTTPError); ok {
|
||||
// Log the error if needed
|
||||
c.Logger().Errorf("Error: %v", he.Message)
|
||||
}
|
||||
// Redirect to main site
|
||||
c.Redirect(http.StatusFound, target)
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package response
|
||||
@@ -10,10 +10,10 @@ func RedirectLanding(c echo.Context) error {
|
||||
return c.Redirect(http.StatusFound, "http://localhost:3000")
|
||||
}
|
||||
|
||||
func RedirectVaultCID(c echo.Context, cid string) error {
|
||||
func RedirectIPFS(c echo.Context, cid string) error {
|
||||
return c.Redirect(http.StatusFound, cid)
|
||||
}
|
||||
|
||||
func RedirectVaultIPNS(c echo.Context, ipns string) error {
|
||||
return c.Redirect(http.StatusFound, ipns)
|
||||
func RedirectAuth(c echo.Context) error {
|
||||
return c.Redirect(http.StatusFound, "http://auth.localhost:3000")
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/common/types"
|
||||
)
|
||||
|
||||
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 SessionCtx interface {
|
||||
ID() string
|
||||
|
||||
LoginOptions(credentials []CredDescriptor) *LoginOptions
|
||||
RegisterOptions(subject string) *RegisterOptions
|
||||
|
||||
GetData() *types.Session
|
||||
}
|
||||
|
||||
type (
|
||||
CredDescriptor = protocol.CredentialDescriptor
|
||||
LoginOptions = protocol.PublicKeyCredentialRequestOptions
|
||||
RegisterOptions = protocol.PublicKeyCredentialCreationOptions
|
||||
)
|
||||
|
||||
type BrowserName string
|
||||
|
||||
const (
|
||||
BrowserNameUnknown BrowserName = " Not A;Brand"
|
||||
BrowserNameChromium BrowserName = "Chromium"
|
||||
)
|
||||
|
||||
func (n BrowserName) String() string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
type PeerRole string
|
||||
|
||||
const (
|
||||
RoleUnknown PeerRole = "none"
|
||||
RoleHway PeerRole = "hway"
|
||||
RoleMotr PeerRole = "motr"
|
||||
)
|
||||
|
||||
func (r PeerRole) Is(role PeerRole) bool {
|
||||
return r == role
|
||||
}
|
||||
|
||||
func (r PeerRole) String() string {
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func Base64Encode(data []byte) string {
|
||||
return base64.RawURLEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
func Base64Decode(data string) ([]byte, error) {
|
||||
return base64.RawURLEncoding.DecodeString(data)
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/common/types"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
// Context keys
|
||||
const (
|
||||
DataContextKey contextKey = "http_session_data"
|
||||
)
|
||||
|
||||
type Context = common.SessionCtx
|
||||
|
||||
// Get returns the session.Context from the echo context.
|
||||
func Get(c echo.Context) (Context, error) {
|
||||
ctx, ok := c.(*HTTPContext)
|
||||
if !ok {
|
||||
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Session Context not found")
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
// WithData sets the session data in the context
|
||||
func WithData(ctx context.Context, data *types.Session) context.Context {
|
||||
return context.WithValue(ctx, DataContextKey, data)
|
||||
}
|
||||
|
||||
// GetData gets the session data from any context type
|
||||
func GetData(ctx interface{}) *types.Session {
|
||||
switch c := ctx.(type) {
|
||||
case *HTTPContext:
|
||||
if c != nil {
|
||||
return c.sessionData
|
||||
}
|
||||
case context.Context:
|
||||
if c != nil {
|
||||
if val := c.Value(DataContextKey); val != nil {
|
||||
if httpCtx, ok := val.(*types.Session); ok {
|
||||
return httpCtx
|
||||
}
|
||||
}
|
||||
}
|
||||
case echo.Context:
|
||||
if c != nil {
|
||||
if httpCtx, ok := c.(*HTTPContext); ok && httpCtx != nil {
|
||||
return httpCtx.sessionData
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return empty session rather than nil to prevent nil pointer panics
|
||||
return &types.Session{}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/common/cookie"
|
||||
"github.com/onsonr/sonr/pkg/common/header"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
// TODO: Returns fixed chain ID for testing.
|
||||
func GetChainID(c echo.Context) string {
|
||||
return "sonr-testnet-1"
|
||||
}
|
||||
|
||||
// GetVaultConfig returns the default vault config
|
||||
func GetVaultConfig(c echo.Context, addr string, ucanCID string) *types.Config {
|
||||
return &types.Config{
|
||||
MotrToken: ucanCID,
|
||||
MotrAddress: addr,
|
||||
IpfsGatewayUrl: "http://localhost:80",
|
||||
SonrApiUrl: "http://localhost:1317",
|
||||
SonrRpcUrl: "http://localhost:26657",
|
||||
SonrChainId: GetChainID(c),
|
||||
VaultSchema: GetVaultSchema(c),
|
||||
}
|
||||
}
|
||||
|
||||
// GetVaultSchema returns the default vault schema
|
||||
func GetVaultSchema(c echo.Context) *types.Schema {
|
||||
return types.DefaultSchema()
|
||||
}
|
||||
|
||||
// SetVaultAddress sets the address of the vault
|
||||
func SetVaultAddress(c echo.Context, address string) error {
|
||||
return cookie.Write(c, cookie.SonrAddress, address)
|
||||
}
|
||||
|
||||
// SetVaultAuthorization sets the UCAN CID of the vault
|
||||
func SetVaultAuthorization(c echo.Context, ucanCID string) error {
|
||||
header.Write(c, header.Authorization, formatAuth(ucanCID))
|
||||
return nil
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/common/cookie"
|
||||
"github.com/onsonr/sonr/pkg/common/header"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
// HwayMiddleware establishes a Session Cookie.
|
||||
func HwayMiddleware() echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
cc := injectSession(c, common.RoleHway)
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MotrMiddleware establishes a Session Cookie.
|
||||
func MotrMiddleware(config *types.Config) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
err := injectConfig(c, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cc := injectSession(c, common.RoleMotr)
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func injectConfig(c echo.Context, config *types.Config) error {
|
||||
header.Write(c, header.SonrAPIURL, config.SonrApiUrl)
|
||||
header.Write(c, header.SonrRPCURL, config.SonrRpcUrl)
|
||||
|
||||
cookie.Write(c, cookie.SonrAddress, config.MotrAddress)
|
||||
schemaBz, err := json.Marshal(config.VaultSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cookie.WriteBytes(c, cookie.VaultSchema, schemaBz)
|
||||
return nil
|
||||
}
|
||||
|
||||
// injectSession returns the session injectSession from the cookies.
|
||||
func injectSession(c echo.Context, role common.PeerRole) *HTTPContext {
|
||||
if c == nil {
|
||||
return initHTTPContext(nil)
|
||||
}
|
||||
|
||||
cookie.Write(c, cookie.SessionRole, role.String())
|
||||
|
||||
// Continue even if there are errors, just ensure we have valid session data
|
||||
if err := loadOrGenKsuid(c); err != nil {
|
||||
// Log error but continue
|
||||
}
|
||||
if err := loadOrGenChallenge(c); err != nil {
|
||||
// Log error but continue
|
||||
}
|
||||
|
||||
return initHTTPContext(c)
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/common/cookie"
|
||||
"github.com/onsonr/sonr/pkg/common/types"
|
||||
)
|
||||
|
||||
// HTTPContext is the context for HTTP endpoints.
|
||||
type HTTPContext struct {
|
||||
echo.Context
|
||||
role common.PeerRole
|
||||
sessionData *types.Session
|
||||
}
|
||||
|
||||
// Ensure HTTPContext implements context.Context
|
||||
func (s *HTTPContext) Deadline() (deadline time.Time, ok bool) {
|
||||
return s.Context.Request().Context().Deadline()
|
||||
}
|
||||
|
||||
func (s *HTTPContext) Done() <-chan struct{} {
|
||||
return s.Context.Request().Context().Done()
|
||||
}
|
||||
|
||||
func (s *HTTPContext) Err() error {
|
||||
return s.Context.Request().Context().Err()
|
||||
}
|
||||
|
||||
func (s *HTTPContext) Value(key interface{}) interface{} {
|
||||
return s.Context.Request().Context().Value(key)
|
||||
}
|
||||
|
||||
// initHTTPContext loads the headers from the request.
|
||||
func initHTTPContext(c echo.Context) *HTTPContext {
|
||||
if c == nil {
|
||||
return &HTTPContext{
|
||||
sessionData: &types.Session{},
|
||||
}
|
||||
}
|
||||
|
||||
sessionData := injectSessionData(c)
|
||||
if sessionData == nil {
|
||||
sessionData = &types.Session{}
|
||||
}
|
||||
|
||||
cc := &HTTPContext{
|
||||
Context: c,
|
||||
role: common.PeerRole(cookie.ReadUnsafe(c, cookie.SessionRole)),
|
||||
sessionData: sessionData,
|
||||
}
|
||||
|
||||
// Set the session data in both contexts
|
||||
c.SetRequest(c.Request().WithContext(WithData(c.Request().Context(), sessionData)))
|
||||
return cc
|
||||
}
|
||||
|
||||
func (s *HTTPContext) ID() string {
|
||||
return s.GetData().Id
|
||||
}
|
||||
|
||||
func (s *HTTPContext) LoginOptions(credentials []common.CredDescriptor) *common.LoginOptions {
|
||||
ch, _ := common.Base64Decode(s.GetData().Challenge)
|
||||
return &common.LoginOptions{
|
||||
Challenge: ch,
|
||||
Timeout: 10000,
|
||||
AllowedCredentials: credentials,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HTTPContext) RegisterOptions(subject string) *common.RegisterOptions {
|
||||
ch, _ := common.Base64Decode(s.GetData().Challenge)
|
||||
opts := baseRegisterOptions()
|
||||
opts.Challenge = ch
|
||||
opts.User = buildUserEntity(subject)
|
||||
return opts
|
||||
}
|
||||
|
||||
func (s *HTTPContext) GetData() *types.Session {
|
||||
return s.sessionData
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.hway.Ctx`. DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/apple/pkl-go/pkl"
|
||||
)
|
||||
|
||||
type Ctx struct {
|
||||
}
|
||||
|
||||
// LoadFromPath loads the pkl module at the given path and evaluates it into a Ctx
|
||||
func LoadFromPath(ctx context.Context, path string) (ret *Ctx, err error) {
|
||||
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Ctx
|
||||
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (*Ctx, error) {
|
||||
var ret Ctx
|
||||
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.hway.Ctx`. DO NOT EDIT.
|
||||
package types
|
||||
|
||||
type Session struct {
|
||||
Id string `pkl:"id" json:"id,omitempty"`
|
||||
|
||||
Challenge string `pkl:"challenge" json:"challenge,omitempty"`
|
||||
|
||||
BrowserName string `pkl:"browserName" json:"browserName,omitempty"`
|
||||
|
||||
BrowserVersion string `pkl:"browserVersion" json:"browserVersion,omitempty"`
|
||||
|
||||
UserArchitecture string `pkl:"userArchitecture" json:"userArchitecture,omitempty"`
|
||||
|
||||
Platform string `pkl:"platform" json:"platform,omitempty"`
|
||||
|
||||
PlatformVersion string `pkl:"platformVersion" json:"platformVersion,omitempty"`
|
||||
|
||||
DeviceModel string `pkl:"deviceModel" json:"deviceModel,omitempty"`
|
||||
|
||||
IsMobile bool `pkl:"isMobile" json:"isMobile,omitempty"`
|
||||
|
||||
VaultAddress string `pkl:"vaultAddress" json:"vaultAddress,omitempty"`
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.hway.Ctx`. DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import "github.com/apple/pkl-go/pkl"
|
||||
|
||||
func init() {
|
||||
pkl.RegisterMapping("sonr.hway.Ctx", Ctx{})
|
||||
pkl.RegisterMapping("sonr.hway.Ctx#Session", Session{})
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// Code generated from Pkl module `sonr.hway.Env`. DO NOT EDIT.
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/apple/pkl-go/pkl"
|
||||
)
|
||||
|
||||
type Env interface {
|
||||
GetServePort() int
|
||||
|
||||
GetConfigDir() string
|
||||
|
||||
GetSqliteFile() string
|
||||
|
||||
GetChainId() string
|
||||
|
||||
GetIpfsGatewayUrl() string
|
||||
|
||||
GetSonrApiUrl() string
|
||||
|
||||
GetSonrGrpcUrl() string
|
||||
|
||||
GetSonrRpcUrl() string
|
||||
|
||||
GetTurnstileSiteKey() string
|
||||
}
|
||||
|
||||
var _ Env = (*EnvImpl)(nil)
|
||||
|
||||
type EnvImpl struct {
|
||||
ServePort int `pkl:"servePort"`
|
||||
|
||||
ConfigDir string `pkl:"configDir"`
|
||||
|
||||
SqliteFile string `pkl:"sqliteFile"`
|
||||
|
||||
ChainId string `pkl:"chainId"`
|
||||
|
||||
IpfsGatewayUrl string `pkl:"ipfsGatewayUrl"`
|
||||
|
||||
SonrApiUrl string `pkl:"sonrApiUrl"`
|
||||
|
||||
SonrGrpcUrl string `pkl:"sonrGrpcUrl"`
|
||||
|
||||
SonrRpcUrl string `pkl:"sonrRpcUrl"`
|
||||
|
||||
TurnstileSiteKey string `pkl:"turnstileSiteKey"`
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetServePort() int {
|
||||
return rcv.ServePort
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetConfigDir() string {
|
||||
return rcv.ConfigDir
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetSqliteFile() string {
|
||||
return rcv.SqliteFile
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetChainId() string {
|
||||
return rcv.ChainId
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetIpfsGatewayUrl() string {
|
||||
return rcv.IpfsGatewayUrl
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetSonrApiUrl() string {
|
||||
return rcv.SonrApiUrl
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetSonrGrpcUrl() string {
|
||||
return rcv.SonrGrpcUrl
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetSonrRpcUrl() string {
|
||||
return rcv.SonrRpcUrl
|
||||
}
|
||||
|
||||
func (rcv *EnvImpl) GetTurnstileSiteKey() string {
|
||||
return rcv.TurnstileSiteKey
|
||||
}
|
||||
|
||||
// LoadFromPath loads the pkl module at the given path and evaluates it into a Env
|
||||
func LoadFromPath(ctx context.Context, path string) (ret Env, err error) {
|
||||
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Env
|
||||
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (Env, error) {
|
||||
var ret EnvImpl
|
||||
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/apple/pkl-go/pkl"
|
||||
)
|
||||
|
||||
// LoadFromBytes loads the environment from the given bytes
|
||||
func LoadFromBytes(data []byte) (Env, error) {
|
||||
text := string(data)
|
||||
return LoadFromString(text)
|
||||
}
|
||||
|
||||
// LoadFromString loads the environment from the given string
|
||||
func LoadFromString(text string) (Env, error) {
|
||||
evaluator, err := pkl.NewEvaluator(context.Background(), pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err := Load(context.Background(), evaluator, pkl.TextSource(text))
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// LoadFromURL loads the environment from the given URL
|
||||
func LoadFromURL(url string) (Env, error) {
|
||||
evaluator, err := pkl.NewEvaluator(context.Background(), pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err := Load(context.Background(), evaluator, pkl.UriSource(url))
|
||||
return ret, err
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Code generated from Pkl module `sonr.hway.Env`. DO NOT EDIT.
|
||||
package config
|
||||
|
||||
import "github.com/apple/pkl-go/pkl"
|
||||
|
||||
func init() {
|
||||
pkl.RegisterMapping("sonr.hway.Env", EnvImpl{})
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package embed
|
||||
package internal
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
@@ -1,7 +1,9 @@
|
||||
package types
|
||||
package config
|
||||
|
||||
func NewWebManifest() WebManifest {
|
||||
return baseWebManifest
|
||||
import "encoding/json"
|
||||
|
||||
func newWebManifestBytes() ([]byte, error) {
|
||||
return json.Marshal(baseWebManifest)
|
||||
}
|
||||
|
||||
var baseWebManifest = WebManifest{
|
||||
@@ -120,18 +122,3 @@ type ServiceWorker struct {
|
||||
Src string `json:"src"`
|
||||
UseCache bool `json:"use_cache"`
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
// manifest := WebManifest{
|
||||
// Name: "My Amazing App",
|
||||
// ShortName: "MyApp",
|
||||
// StartURL: "/",
|
||||
// Display: "standalone",
|
||||
// Icons: []IconDefinition{
|
||||
// {
|
||||
// Src: "/icons/icon-192x192.png",
|
||||
// Sizes: "192x192",
|
||||
// Type: "image/png",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
@@ -1,17 +1,16 @@
|
||||
package types
|
||||
package config
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common/models"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
const SchemaVersion = 1
|
||||
|
||||
// DefaultSchema returns the default schema
|
||||
func DefaultSchema() *Schema {
|
||||
return &Schema{
|
||||
func DefaultSchema() *types.Schema {
|
||||
return &types.Schema{
|
||||
Version: SchemaVersion,
|
||||
Account: getSchema(&models.Account{}),
|
||||
Asset: getSchema(&models.Asset{}),
|
||||
@@ -0,0 +1,50 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/onsonr/sonr/pkg/gateway/config/internal"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
const SchemaVersion = 1
|
||||
const (
|
||||
AppManifestFileName = "app.webmanifest"
|
||||
DWNConfigFileName = "dwn.json"
|
||||
IndexHTMLFileName = "index.html"
|
||||
MainJSFileName = "main.js"
|
||||
ServiceWorkerFileName = "sw.js"
|
||||
)
|
||||
|
||||
// spawnVaultDirectory creates a new directory with the default files
|
||||
func NewFS(cfg *types.Config) (files.Directory, error) {
|
||||
manifestBz, err := newWebManifestBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cnfBz, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files.NewMapDirectory(map[string]files.Node{
|
||||
AppManifestFileName: files.NewBytesFile(manifestBz),
|
||||
DWNConfigFileName: files.NewBytesFile(cnfBz),
|
||||
IndexHTMLFileName: files.NewBytesFile(internal.IndexHTML),
|
||||
MainJSFileName: files.NewBytesFile(internal.MainJS),
|
||||
ServiceWorkerFileName: files.NewBytesFile(internal.WorkerJS),
|
||||
}), nil
|
||||
}
|
||||
|
||||
// GetVaultConfig returns the default vault config
|
||||
func GetVaultConfig(addr string, ucanCID string) *types.Config {
|
||||
return &types.Config{
|
||||
MotrToken: ucanCID,
|
||||
MotrAddress: addr,
|
||||
IpfsGatewayUrl: "http://localhost:80",
|
||||
SonrApiUrl: "http://localhost:1317",
|
||||
SonrRpcUrl: "http://localhost:26657",
|
||||
SonrChainId: "sonr-testnet-1",
|
||||
VaultSchema: DefaultSchema(),
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package embed
|
||||
|
||||
import (
|
||||
"github.com/ipfs/boxo/files"
|
||||
)
|
||||
|
||||
const (
|
||||
AppManifestFileName = "app.webmanifest"
|
||||
DWNConfigFileName = "dwn.json"
|
||||
IndexHTMLFileName = "index.html"
|
||||
MainJSFileName = "main.js"
|
||||
ServiceWorkerFileName = "sw.js"
|
||||
)
|
||||
|
||||
// spawnVaultDirectory creates a new directory with the default files
|
||||
func NewFS(cfgBz []byte, manifestBz []byte) files.Directory {
|
||||
return files.NewMapDirectory(map[string]files.Node{
|
||||
AppManifestFileName: files.NewBytesFile(manifestBz),
|
||||
DWNConfigFileName: files.NewBytesFile(cfgBz),
|
||||
IndexHTMLFileName: files.NewBytesFile(IndexHTML),
|
||||
MainJSFileName: files.NewBytesFile(MainJS),
|
||||
ServiceWorkerFileName: files.NewBytesFile(WorkerJS),
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/common/response"
|
||||
"github.com/onsonr/sonr/pkg/gateway/internal/pages/index"
|
||||
"github.com/onsonr/sonr/pkg/gateway/internal/session"
|
||||
)
|
||||
|
||||
func HandleIndex(c echo.Context) error {
|
||||
if isInitial(c) {
|
||||
return response.TemplEcho(c, index.InitialView())
|
||||
}
|
||||
if isExpired(c) {
|
||||
return response.TemplEcho(c, index.ReturningView())
|
||||
}
|
||||
return c.Render(http.StatusOK, "index.templ", nil)
|
||||
}
|
||||
|
||||
// ╭─────────────────────────────────────────────────────────╮
|
||||
// │ Utility Functions │
|
||||
// ╰─────────────────────────────────────────────────────────╯
|
||||
|
||||
// Initial users have no authorization, user handle, or vault address
|
||||
func isInitial(c echo.Context) bool {
|
||||
noAuth := !session.HasAuthorization(c)
|
||||
noUserHandle := !session.HasUserHandle(c)
|
||||
noVaultAddress := !session.HasVaultAddress(c)
|
||||
return noUserHandle && noVaultAddress && noAuth
|
||||
}
|
||||
|
||||
// Expired users have either a user handle or vault address
|
||||
func isExpired(c echo.Context) bool {
|
||||
noAuth := !session.HasAuthorization(c)
|
||||
hasUserHandle := session.HasUserHandle(c)
|
||||
hasVaultAddress := session.HasVaultAddress(c)
|
||||
return noAuth && hasUserHandle || noAuth && hasVaultAddress
|
||||
}
|
||||
|
||||
// Returning users have a valid authorization, and either a user handle or vault address
|
||||
func isReturning(c echo.Context) bool {
|
||||
hasAuth := session.HasAuthorization(c)
|
||||
hasUserHandle := session.HasUserHandle(c)
|
||||
hasVaultAddress := session.HasVaultAddress(c)
|
||||
return hasAuth && (hasUserHandle || hasVaultAddress)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package handlers
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func HandleLogin(c echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// func LoginHandler(c echo.Context) error {
|
||||
// options := PublicKeyCredentialRequestOptions{
|
||||
// Challenge: "your-challenge-base64url",
|
||||
// RpID: "yourdomain.com",
|
||||
// Timeout: 60000,
|
||||
// AllowCredentials: []CredentialDescriptor{
|
||||
// {
|
||||
// Type: "public-key",
|
||||
// ID: "credential-id-base64url",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// return GetCredentials(c, options)
|
||||
// }
|
||||
@@ -1,11 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func PinVault(c echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func PublishVault(c echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/cosmos/btcutil/bech32"
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/go-webauthn/webauthn/protocol/webauthncose"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/common/response"
|
||||
"github.com/onsonr/sonr/pkg/gateway/config"
|
||||
"github.com/onsonr/sonr/pkg/gateway/internal/pages/register"
|
||||
"github.com/onsonr/sonr/pkg/gateway/internal/session"
|
||||
)
|
||||
|
||||
func HandleRegisterView(env config.Env) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
return response.TemplEcho(c, register.ProfileFormView(env.GetTurnstileSiteKey()))
|
||||
}
|
||||
}
|
||||
|
||||
func HandleRegisterStart(c echo.Context) error {
|
||||
firstName := c.FormValue("first_name")
|
||||
lastName := c.FormValue("last_name")
|
||||
handle := c.FormValue("handle")
|
||||
|
||||
if firstName == "" || lastName == "" || handle == "" {
|
||||
return response.RedirectLanding(c)
|
||||
}
|
||||
|
||||
ks, err := mpc.NewKeyset()
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
adr, err := bech32.Encode("idx", ks.Val().GetPublicKey())
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
req := getLinkCredentialRequest(c, adr, handle, ks.UserJSON())
|
||||
return response.TemplEcho(c, register.LinkCredentialView(req))
|
||||
}
|
||||
|
||||
func HandleRegisterFinish(c echo.Context) error {
|
||||
// cred := c.FormValue("credential")
|
||||
return response.TemplEcho(c, register.LoadingVaultView())
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Registration Components │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func getLinkCredentialRequest(c echo.Context, addr string, handle string, userKSJSON string) register.LinkCredentialRequest {
|
||||
cc, err := session.Get(c)
|
||||
if err != nil {
|
||||
return register.LinkCredentialRequest{
|
||||
Handle: handle,
|
||||
Address: addr,
|
||||
RegisterOptions: buildRegisterOptions(buildUserEntity(addr, handle), buildLargeBlob(userKSJSON), buildServiceEntity(c)),
|
||||
}
|
||||
}
|
||||
usr := buildUserEntity(addr, handle)
|
||||
blob := buildLargeBlob(userKSJSON)
|
||||
service := buildServiceEntity(c)
|
||||
|
||||
return register.LinkCredentialRequest{
|
||||
Platform: cc.BrowserName(),
|
||||
Handle: handle,
|
||||
DeviceModel: cc.BrowserVersion(),
|
||||
Address: addr,
|
||||
RegisterOptions: buildRegisterOptions(usr, blob, service),
|
||||
}
|
||||
}
|
||||
|
||||
func buildRegisterOptions(user protocol.UserEntity, blob common.LargeBlob, service protocol.RelyingPartyEntity) protocol.PublicKeyCredentialCreationOptions {
|
||||
return protocol.PublicKeyCredentialCreationOptions{
|
||||
Timeout: 10000,
|
||||
Attestation: protocol.PreferDirectAttestation,
|
||||
AuthenticatorSelection: protocol.AuthenticatorSelection{
|
||||
AuthenticatorAttachment: "platform",
|
||||
ResidentKey: protocol.ResidentKeyRequirementPreferred,
|
||||
UserVerification: "preferred",
|
||||
},
|
||||
RelyingParty: service,
|
||||
User: user,
|
||||
Extensions: protocol.AuthenticationExtensions{
|
||||
"largeBlob": blob,
|
||||
},
|
||||
Parameters: []protocol.CredentialParameter{
|
||||
{
|
||||
Type: "public-key",
|
||||
Algorithm: webauthncose.AlgES256,
|
||||
},
|
||||
{
|
||||
Type: "public-key",
|
||||
Algorithm: webauthncose.AlgES256K,
|
||||
},
|
||||
{
|
||||
Type: "public-key",
|
||||
Algorithm: webauthncose.AlgEdDSA,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func buildLargeBlob(userKeyshareJSON string) common.LargeBlob {
|
||||
return common.LargeBlob{
|
||||
Support: "required",
|
||||
Write: userKeyshareJSON,
|
||||
}
|
||||
}
|
||||
|
||||
func buildUserEntity(userAddress string, userHandle string) protocol.UserEntity {
|
||||
return protocol.UserEntity{
|
||||
ID: userAddress,
|
||||
DisplayName: userHandle,
|
||||
CredentialEntity: protocol.CredentialEntity{
|
||||
Name: userAddress,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func buildServiceEntity(c echo.Context) protocol.RelyingPartyEntity {
|
||||
return protocol.RelyingPartyEntity{
|
||||
CredentialEntity: protocol.CredentialEntity{
|
||||
Name: "Sonr.ID",
|
||||
},
|
||||
ID: c.Request().Host,
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/pkg/common/session"
|
||||
"github.com/onsonr/sonr/pkg/gateway/embed"
|
||||
"github.com/onsonr/sonr/pkg/gateway/middleware"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
func SpawnVault(c echo.Context) error {
|
||||
ipfs, err := middleware.GetIPFSClient(c)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
ks, err := mpc.NewKeyset()
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
src, err := mpc.NewSource(ks)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
tk, err := src.OriginToken()
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
// Create the vault keyshare auth token
|
||||
kscid, err := tk.CID()
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
// Create the vault config
|
||||
cfg := session.GetVaultConfig(c, src.Address(), kscid.String())
|
||||
cnf, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
// Create the vault app manifest
|
||||
manifest := types.NewWebManifest()
|
||||
manifestBz, err := json.Marshal(manifest)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
dir := embed.NewFS(cnf, manifestBz)
|
||||
path, err := ipfs.Unixfs().Add(c.Request().Context(), dir)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return c.Redirect(http.StatusFound, path.String())
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package handlers
|
||||
|
||||
//
|
||||
// type SpawnVaultRequest struct {
|
||||
// Name string `json:"name"`
|
||||
// }
|
||||
//
|
||||
// func SpawnVault(c echo.Context) error {
|
||||
// ks, err := mpc.NewKeyset()
|
||||
// if err != nil {
|
||||
// return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
// }
|
||||
// src, err := mpc.NewSource(ks)
|
||||
// if err != nil {
|
||||
// return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
// }
|
||||
// tk, err := src.OriginToken()
|
||||
// if err != nil {
|
||||
// return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
// }
|
||||
// // Create the vault keyshare auth token
|
||||
// kscid, err := tk.CID()
|
||||
// if err != nil {
|
||||
// return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
// }
|
||||
// // Create the vault config
|
||||
// dir, err := config.NewFS(config.GetVaultConfig(src.Address(), kscid.String()))
|
||||
// path, err := clients.IPFSAdd(c, dir)
|
||||
// if err != nil {
|
||||
// return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
// }
|
||||
// return c.Redirect(http.StatusFound, path)
|
||||
// }
|
||||
@@ -0,0 +1,16 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
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")
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/gateway/config"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DatabaseContext struct {
|
||||
echo.Context
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func Middleware(env config.Env) echo.MiddlewareFunc {
|
||||
cc := initDB(env.GetSqliteFile())
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
cc.Context = c
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DatabaseContext) HasDB() bool {
|
||||
return c.db != nil
|
||||
}
|
||||
|
||||
func initDB(path string) *DatabaseContext {
|
||||
cc := new(DatabaseContext)
|
||||
db, err := gorm.Open(sqlite.Open(path), &gorm.Config{})
|
||||
if err != nil {
|
||||
cc.db = nil
|
||||
return cc
|
||||
}
|
||||
// Migrate the schema
|
||||
db.AutoMigrate(&Session{})
|
||||
db.AutoMigrate(&User{})
|
||||
|
||||
return &DatabaseContext{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func formatDBPath(path string) string {
|
||||
home := os.Getenv("HOME")
|
||||
if home == "" {
|
||||
home = os.Getenv("USERPROFILE")
|
||||
}
|
||||
if home == "" {
|
||||
home = "."
|
||||
}
|
||||
return filepath.Join(home, ".config", "hway", path)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package database
|
||||
|
||||
type Session struct {
|
||||
ID string `json:"id"`
|
||||
BrowserName string `json:"browserName"`
|
||||
BrowserVersion string `json:"browserVersion"`
|
||||
UserArchitecture string `json:"userArchitecture"`
|
||||
Platform string `json:"platform"`
|
||||
PlatformVersion string `json:"platformVersion"`
|
||||
DeviceModel string `json:"deviceModel"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Address string `json:"address"`
|
||||
Handle string `json:"handle"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
VaultCID string `json:"vaultCID"`
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package index
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
templ NoWebauthnErrorView() {
|
||||
@layout.Root("Error | Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
No WebAuthn Devices
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
You don't have any WebAuthn devices connected to your computer.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// 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/pkg/styles/layout"
|
||||
|
||||
func NoWebauthnErrorView() 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_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">No WebAuthn Devices</h1><p class=\"text-lg text-zinc-500\">You don't have any WebAuthn devices connected to your computer.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</button></div></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Error | 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
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,36 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"github.com/onsonr/sonr/pkg/styles/layout"
|
||||
"github.com/onsonr/sonr/pkg/styles/text"
|
||||
)
|
||||
|
||||
templ InitialView() {
|
||||
@layout.Root("Welcome | Sonr.ID") {
|
||||
@layout.Container() {
|
||||
@text.Header("Sonr.ID", "The decentralized identity layer for the web.")
|
||||
<div class="pt-3 flex flex-col items-center justify-center h-full">
|
||||
<sl-button hx-target="#container" hx-get="/register" type="button">
|
||||
<sl-icon slot="prefix" library="sonr" name="sonr"></sl-icon>
|
||||
Get Started
|
||||
<sl-icon slot="suffix" library="sonr" name="arrow-right"></sl-icon>
|
||||
</sl-button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
templ ReturningView() {
|
||||
@layout.Root("Login | Sonr.ID") {
|
||||
@layout.Container() {
|
||||
@text.Header("Welcome Back!", "Continue with your existing Sonr.ID.")
|
||||
<div class="pt-3 flex flex-col items-center justify-center h-full">
|
||||
<sl-button hx-target="#container" hx-get="/register" type="button">
|
||||
<sl-icon slot="prefix" library="sonr" name="sonr"></sl-icon>
|
||||
Log back in
|
||||
<sl-icon slot="suffix" library="sonr" name="arrow-right"></sl-icon>
|
||||
</sl-button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// 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/pkg/styles/layout"
|
||||
"github.com/onsonr/sonr/pkg/styles/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.Header("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(" <div class=\"pt-3 flex flex-col items-center justify-center h-full\"><sl-button hx-target=\"#container\" hx-get=\"/register\" type=\"button\"><sl-icon slot=\"prefix\" library=\"sonr\" name=\"sonr\"></sl-icon> Get Started <sl-icon slot=\"suffix\" library=\"sonr\" name=\"arrow-right\"></sl-icon></sl-button></div>")
|
||||
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.Root("Welcome | 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.Header("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(" <div class=\"pt-3 flex flex-col items-center justify-center h-full\"><sl-button hx-target=\"#container\" hx-get=\"/register\" type=\"button\"><sl-icon slot=\"prefix\" library=\"sonr\" name=\"sonr\"></sl-icon> Log back in <sl-icon slot=\"suffix\" library=\"sonr\" name=\"arrow-right\"></sl-icon></sl-button></div>")
|
||||
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.Root("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
|
||||
@@ -0,0 +1,24 @@
|
||||
package login
|
||||
|
||||
type LoginRequest struct {
|
||||
Subject string
|
||||
Action string
|
||||
Origin string
|
||||
Status string
|
||||
Ping string
|
||||
BlockSpeed string
|
||||
BlockHeight string
|
||||
}
|
||||
|
||||
type PublicKeyCredentialRequestOptions struct {
|
||||
Challenge string `json:"challenge"`
|
||||
RpID string `json:"rpId"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
UserVerification string `json:"userVerification,omitempty"`
|
||||
AllowCredentials []CredentialDescriptor `json:"allowCredentials,omitempty"`
|
||||
}
|
||||
|
||||
type CredentialDescriptor struct {
|
||||
Type string `json:"type"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package register
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
)
|
||||
|
||||
type LinkCredentialRequest struct {
|
||||
Platform string `json:"platform"`
|
||||
Handle string `json:"handle"`
|
||||
DeviceModel string `json:"deviceModel"`
|
||||
Architecture string `json:"architecture"`
|
||||
Address string `json:"address"`
|
||||
RegisterOptions protocol.PublicKeyCredentialCreationOptions `json:"registerOptions"`
|
||||
}
|
||||
|
||||
func (r LinkCredentialRequest) GetCredentialOptions() string {
|
||||
opts, _ := templ.JSONString(r.RegisterOptions)
|
||||
return opts
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package register
|
||||
|
||||
import (
|
||||
"github.com/onsonr/sonr/pkg/styles/details"
|
||||
"github.com/onsonr/sonr/pkg/styles/form"
|
||||
"github.com/onsonr/sonr/pkg/styles/layout"
|
||||
"github.com/onsonr/sonr/pkg/styles/text"
|
||||
)
|
||||
|
||||
templ ProfileFormView(turnstileSiteKey string) {
|
||||
@layout.Root("Sonr.ID") {
|
||||
@layout.Container() {
|
||||
@text.Header("Create a Profile", "Enter some basic information about yourself.")
|
||||
<br/>
|
||||
@form.Form("/register/start", "POST", form.Submit("Continue"), "25", true) {
|
||||
@form.NameInput()
|
||||
<br/>
|
||||
@form.HandleInput()
|
||||
@form.TurnstileWidget(turnstileSiteKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
templ LinkCredentialView(req LinkCredentialRequest) {
|
||||
@layout.Root("Sonr.ID") {
|
||||
@layout.Container() {
|
||||
@text.Header("Link a PassKey", "This will be used to login to your vault.")
|
||||
<br/>
|
||||
@form.Form("/register/finish", "POST", form.PasskeyInput("passkey"), "65", false) {
|
||||
@details.PropertyList() {
|
||||
@details.Property("Address", req.Address, "wallet")
|
||||
@details.Property("Handle", req.Handle, "at-sign")
|
||||
@details.Property("Platform", req.Platform, "device-iphone")
|
||||
@details.Property("Model", req.DeviceModel, "laptop")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
templ LoadingVaultView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
@layout.Container() {
|
||||
@text.Header("Loading Vault", "This will be used to login to your vault.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
// 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/pkg/styles/details"
|
||||
"github.com/onsonr/sonr/pkg/styles/form"
|
||||
"github.com/onsonr/sonr/pkg/styles/layout"
|
||||
"github.com/onsonr/sonr/pkg/styles/text"
|
||||
)
|
||||
|
||||
func ProfileFormView(turnstileSiteKey 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_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.Header("Create a Profile", "Enter some basic information about yourself.").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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 = form.NameInput().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = form.HandleInput().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.TurnstileWidget(turnstileSiteKey).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = form.Form("/register/start", "POST", form.Submit("Continue"), "25", true).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), 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.Root("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(req LinkCredentialRequest) 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_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(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_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 {
|
||||
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.Header("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(" <br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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 = details.Property("Address", req.Address, "wallet").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 = details.Property("Handle", req.Handle, "at-sign").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 = details.Property("Platform", req.Platform, "device-iphone").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 = details.Property("Model", req.DeviceModel, "laptop").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = details.PropertyList().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 = form.Form("/register/finish", "POST", form.PasskeyInput("passkey"), "65", false).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.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), 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_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_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_Err = text.Header("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_Var12), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var11), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,46 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
// Context keys
|
||||
const (
|
||||
DataContextKey contextKey = "http_session_data"
|
||||
)
|
||||
|
||||
type SessionCtx interface {
|
||||
ID() string
|
||||
BrowserName() string
|
||||
BrowserVersion() string
|
||||
}
|
||||
|
||||
// Get returns the session.Context from the echo context.
|
||||
func Get(c echo.Context) (SessionCtx, error) {
|
||||
ctx, ok := c.(*HTTPContext)
|
||||
if !ok {
|
||||
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Session Context not found")
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
// TODO: Returns fixed chain ID for testing.
|
||||
func GetChainID(c echo.Context) string {
|
||||
return "sonr-testnet-1"
|
||||
}
|
||||
|
||||
// SetVaultAddress sets the address of the vault
|
||||
func SetVaultAddress(c echo.Context, address string) error {
|
||||
return common.WriteCookie(c, common.SonrAddress, address)
|
||||
}
|
||||
|
||||
// SetVaultAuthorization sets the UCAN CID of the vault
|
||||
func SetVaultAuthorization(c echo.Context, ucanCID string) error {
|
||||
common.HeaderWrite(c, common.Authorization, formatAuth(ucanCID))
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/gateway/config"
|
||||
)
|
||||
|
||||
// Middleware establishes a Session Cookie.
|
||||
func Middleware(env config.Env) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
cc := injectSession(c, common.RoleHway)
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// injectSession returns the session injectSession from the cookies.
|
||||
func injectSession(c echo.Context, role common.PeerRole) *HTTPContext {
|
||||
if c == nil {
|
||||
return initHTTPContext(nil)
|
||||
}
|
||||
|
||||
common.WriteCookie(c, common.SessionRole, role.String())
|
||||
|
||||
// Continue even if there are errors, just ensure we have valid session data
|
||||
if err := loadOrGenKsuid(c); err != nil {
|
||||
// Log error but continue
|
||||
}
|
||||
|
||||
return initHTTPContext(c)
|
||||
}
|
||||
|
||||
// HasAuthorization checks if the request has an authorization header
|
||||
func HasAuthorization(c echo.Context) bool {
|
||||
return common.HeaderExists(c, common.Authorization)
|
||||
}
|
||||
|
||||
// HasUserHandle checks if the request has a user handle cookie
|
||||
func HasUserHandle(c echo.Context) bool {
|
||||
return common.CookieExists(c, common.UserHandle)
|
||||
}
|
||||
|
||||
// HasVaultAddress checks if the request has a vault address cookie
|
||||
func HasVaultAddress(c echo.Context) bool {
|
||||
return common.CookieExists(c, common.SonrAddress)
|
||||
}
|
||||
@@ -10,50 +10,58 @@ import (
|
||||
"github.com/segmentio/ksuid"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/common/cookie"
|
||||
"github.com/onsonr/sonr/pkg/common/header"
|
||||
"github.com/onsonr/sonr/pkg/common/types"
|
||||
)
|
||||
|
||||
const kWebAuthnTimeout = 6000
|
||||
|
||||
// HTTPContext is the context for HTTP endpoints.
|
||||
type HTTPContext struct {
|
||||
echo.Context
|
||||
role common.PeerRole
|
||||
id string
|
||||
chal string
|
||||
bn string
|
||||
bv string
|
||||
}
|
||||
|
||||
// initHTTPContext loads the headers from the request.
|
||||
func initHTTPContext(c echo.Context) *HTTPContext {
|
||||
if c == nil {
|
||||
return &HTTPContext{}
|
||||
}
|
||||
|
||||
id, chal := extractPeerInfo(c)
|
||||
bn, bv := extractBrowserInfo(c)
|
||||
|
||||
cc := &HTTPContext{
|
||||
Context: c,
|
||||
role: common.PeerRole(common.ReadCookieUnsafe(c, common.SessionRole)),
|
||||
id: id,
|
||||
chal: chal,
|
||||
bn: bn,
|
||||
bv: bv,
|
||||
}
|
||||
|
||||
// Set the session data in both contexts
|
||||
return cc
|
||||
}
|
||||
|
||||
func (s *HTTPContext) ID() string {
|
||||
return s.id
|
||||
}
|
||||
|
||||
func (s *HTTPContext) BrowserName() string {
|
||||
return s.bn
|
||||
}
|
||||
|
||||
func (s *HTTPContext) BrowserVersion() string {
|
||||
return s.bv
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Initialization │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func loadOrGenChallenge(c echo.Context) error {
|
||||
var (
|
||||
chal protocol.URLEncodedBase64
|
||||
chalRaw []byte
|
||||
err error
|
||||
)
|
||||
|
||||
// Setup genChal function
|
||||
genChal := func() []byte {
|
||||
ch, _ := protocol.CreateChallenge()
|
||||
bz, _ := ch.MarshalJSON()
|
||||
return bz
|
||||
}
|
||||
|
||||
// Check if there is a session challenge cookie
|
||||
if !cookie.Exists(c, cookie.SessionChallenge) {
|
||||
chalRaw = genChal()
|
||||
cookie.WriteBytes(c, cookie.SessionChallenge, chalRaw)
|
||||
} else {
|
||||
chalRaw, err = cookie.ReadBytes(c, cookie.SessionChallenge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to read the session challenge from the "session" cookie
|
||||
err = chal.UnmarshalJSON(chalRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadOrGenKsuid(c echo.Context) error {
|
||||
var (
|
||||
sessionID string
|
||||
@@ -66,15 +74,15 @@ func loadOrGenKsuid(c echo.Context) error {
|
||||
}
|
||||
|
||||
// Attempt to read the session ID from the "session" cookie
|
||||
if ok := cookie.Exists(c, cookie.SessionID); !ok {
|
||||
if ok := common.CookieExists(c, common.SessionID); !ok {
|
||||
sessionID = genKsuid()
|
||||
} else {
|
||||
sessionID, err = cookie.Read(c, cookie.SessionID)
|
||||
sessionID, err = common.ReadCookie(c, common.SessionID)
|
||||
if err != nil {
|
||||
sessionID = genKsuid()
|
||||
}
|
||||
}
|
||||
cookie.Write(c, cookie.SessionID, sessionID)
|
||||
common.WriteCookie(c, common.SessionID, sessionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -82,40 +90,24 @@ func loadOrGenKsuid(c echo.Context) error {
|
||||
// │ Extraction │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func injectSessionData(c echo.Context) *types.Session {
|
||||
id, chal := extractPeerInfo(c)
|
||||
bn, bv := extractBrowserInfo(c)
|
||||
return &types.Session{
|
||||
Id: id,
|
||||
Challenge: chal,
|
||||
BrowserName: bn,
|
||||
BrowserVersion: bv,
|
||||
UserArchitecture: header.Read(c, header.Architecture),
|
||||
Platform: header.Read(c, header.Platform),
|
||||
PlatformVersion: header.Read(c, header.PlatformVersion),
|
||||
DeviceModel: header.Read(c, header.Model),
|
||||
IsMobile: header.Equals(c, header.Mobile, "?1"),
|
||||
}
|
||||
}
|
||||
|
||||
func extractPeerInfo(c echo.Context) (string, string) {
|
||||
var chal protocol.URLEncodedBase64
|
||||
id, _ := cookie.Read(c, cookie.SessionID)
|
||||
chalRaw, _ := cookie.ReadBytes(c, cookie.SessionChallenge)
|
||||
id, _ := common.ReadCookie(c, common.SessionID)
|
||||
chalRaw, _ := common.ReadCookieBytes(c, common.SessionChallenge)
|
||||
chal.UnmarshalJSON(chalRaw)
|
||||
|
||||
return id, common.Base64Encode(chal)
|
||||
}
|
||||
|
||||
func extractBrowserInfo(c echo.Context) (string, string) {
|
||||
secCHUA := header.Read(c, header.UserAgent)
|
||||
secCHUA := common.HeaderRead(c, common.UserAgent)
|
||||
|
||||
// If header is empty, return empty BrowserInfo
|
||||
// If common.is empty, return empty BrowserInfo
|
||||
if secCHUA == "" {
|
||||
return "N/A", "-1"
|
||||
}
|
||||
|
||||
// Split the header into individual browser entries
|
||||
// Split the common.into individual browser entries
|
||||
var (
|
||||
name string
|
||||
ver string
|
||||
@@ -161,7 +153,7 @@ func buildUserEntity(userID string) protocol.UserEntity {
|
||||
}
|
||||
|
||||
// returns the base options for registering a new user without challenge or user entity.
|
||||
func baseRegisterOptions() *common.RegisterOptions {
|
||||
func baseRegisterOptions() *protocol.PublicKeyCredentialCreationOptions {
|
||||
return &protocol.PublicKeyCredentialCreationOptions{
|
||||
Timeout: kWebAuthnTimeout,
|
||||
Attestation: protocol.PreferDirectAttestation,
|
||||
@@ -1,132 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type IPFSContext struct {
|
||||
echo.Context
|
||||
ipfs *rpc.HttpApi
|
||||
}
|
||||
|
||||
func IPFSMiddleware(client *rpc.HttpApi) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
cc := &IPFSContext{
|
||||
Context: c,
|
||||
ipfs: client,
|
||||
}
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetIPFSClient(c echo.Context) (*rpc.HttpApi, error) {
|
||||
cc, ok := c.(*IPFSContext)
|
||||
if !ok {
|
||||
return nil, errors.New("not an IPFSContext")
|
||||
}
|
||||
if cc.ipfs == nil {
|
||||
return nil, errors.New("no IPFS client")
|
||||
}
|
||||
return cc.ipfs, nil
|
||||
}
|
||||
|
||||
func getContentType(path string, defaultType string) string {
|
||||
ext := strings.ToLower(filepath.Ext(path))
|
||||
switch ext {
|
||||
case ".html", ".htm":
|
||||
return "text/html"
|
||||
case ".css":
|
||||
return "text/css"
|
||||
case ".js":
|
||||
return "application/javascript"
|
||||
case ".jpg", ".jpeg":
|
||||
return "image/jpeg"
|
||||
case ".png":
|
||||
return "image/png"
|
||||
case ".gif":
|
||||
return "image/gif"
|
||||
case ".svg":
|
||||
return "image/svg+xml"
|
||||
case ".json":
|
||||
return "application/json"
|
||||
case ".xml":
|
||||
return "application/xml"
|
||||
case ".pdf":
|
||||
return "application/pdf"
|
||||
case ".zip":
|
||||
return "application/zip"
|
||||
case ".mp4":
|
||||
return "video/mp4"
|
||||
case ".mp3":
|
||||
return "audio/mpeg"
|
||||
case ".woff":
|
||||
return "font/woff"
|
||||
case ".woff2":
|
||||
return "font/woff2"
|
||||
case ".ttf":
|
||||
return "font/ttf"
|
||||
default:
|
||||
return defaultType
|
||||
}
|
||||
}
|
||||
|
||||
func streamFile(c echo.Context, file files.File, cid string, filePath string) error {
|
||||
// Get file size if possible
|
||||
stat, err := file.Size()
|
||||
if err == nil {
|
||||
c.Response().Header().Set("Content-Length", fmt.Sprintf("%d", stat))
|
||||
}
|
||||
|
||||
// Set content type based on file extension first
|
||||
contentType := getContentType(filePath, "")
|
||||
|
||||
// If no content type found by extension, detect from content
|
||||
if contentType == "" {
|
||||
buffer := make([]byte, 512)
|
||||
_, err = file.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
contentType = http.DetectContentType(buffer)
|
||||
|
||||
// Reset file pointer after reading for content type detection
|
||||
if seeker, ok := file.(io.Seeker); ok {
|
||||
_, err = seeker.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set headers
|
||||
c.Response().Header().Set("Content-Type", contentType)
|
||||
c.Response().Header().Set("ETag", fmt.Sprintf(`"%s"`, cid))
|
||||
c.Response().Header().Set("Cache-Control", "public, max-age=29030400, immutable")
|
||||
c.Response().Header().Set("X-Content-Type-Options", "nosniff")
|
||||
c.Response().Header().Set("X-Frame-Options", "DENY")
|
||||
c.Response().Header().Set("X-XSS-Protection", "1; mode=block")
|
||||
|
||||
// Stream the file
|
||||
return c.Stream(http.StatusOK, contentType, file)
|
||||
}
|
||||
|
||||
func redirectOnError(c echo.Context) error {
|
||||
return c.Redirect(http.StatusFound, "http://localhost:3000")
|
||||
}
|
||||
|
||||
func looksLikeCID(s string) bool {
|
||||
return strings.HasPrefix(s, "Qm") || // v0 CID
|
||||
strings.HasPrefix(s, "bafy") || // v1 CID
|
||||
strings.HasPrefix(s, "b") // other base32 v1 CIDs
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package middleware
|
||||
+16
-14
@@ -1,23 +1,25 @@
|
||||
// Package gateway provides the default routes for the Sonr hway.
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/common/response"
|
||||
"github.com/onsonr/sonr/pkg/gateway/config"
|
||||
"github.com/onsonr/sonr/pkg/gateway/handlers"
|
||||
"github.com/onsonr/sonr/pkg/gateway/internal/database"
|
||||
"github.com/onsonr/sonr/pkg/gateway/internal/session"
|
||||
)
|
||||
|
||||
func RegisterRoutes(e *echo.Echo) {
|
||||
func RegisterRoutes(e *echo.Echo, env config.Env) {
|
||||
// Custom error handler for gateway
|
||||
e.HTTPErrorHandler = func(err error, c echo.Context) {
|
||||
if he, ok := err.(*echo.HTTPError); ok {
|
||||
// Log the error if needed
|
||||
c.Logger().Errorf("Gateway error: %v", he.Message)
|
||||
}
|
||||
// Redirect to main site
|
||||
c.Redirect(http.StatusFound, "http://localhost:3000")
|
||||
}
|
||||
e.POST("/spawn", handlers.SpawnVault)
|
||||
e.POST("/pin", handlers.PinVault)
|
||||
e.POST("/publish", handlers.PublishVault)
|
||||
e.HTTPErrorHandler = response.RedirectOnError("http://localhost:3000")
|
||||
|
||||
// Inject session middleware
|
||||
e.Use(session.Middleware(env))
|
||||
e.Use(database.Middleware(env))
|
||||
// Register routes
|
||||
e.GET("/", handlers.HandleIndex)
|
||||
e.GET("/register", handlers.HandleRegisterView(env))
|
||||
e.POST("/register/start", handlers.HandleRegisterStart)
|
||||
e.POST("/register/finish", handlers.HandleRegisterFinish)
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.hway.Gate`. DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/apple/pkl-go/pkl"
|
||||
)
|
||||
|
||||
type Gate struct {
|
||||
}
|
||||
|
||||
// LoadFromPath loads the pkl module at the given path and evaluates it into a Gate
|
||||
func LoadFromPath(ctx context.Context, path string) (ret *Gate, err error) {
|
||||
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Gate
|
||||
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (*Gate, error) {
|
||||
var ret Gate
|
||||
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
@@ -4,6 +4,5 @@ package types
|
||||
import "github.com/apple/pkl-go/pkl"
|
||||
|
||||
func init() {
|
||||
pkl.RegisterMapping("sonr.hway.Gate", Gate{})
|
||||
pkl.RegisterMapping("sonr.hway.Gate#Config", Config{})
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// CreateCredentials initiates the credential creation process
|
||||
func CreateCredentials(c echo.Context, options PublicKeyCredentialCreationOptions) error {
|
||||
return CreateCredential(options).Render(c.Request().Context(), c.Response().Writer)
|
||||
}
|
||||
|
||||
// GetCredentials initiates the credential retrieval process
|
||||
func GetCredentials(c echo.Context, options PublicKeyCredentialRequestOptions) error {
|
||||
return GetCredential(options).Render(c.Request().Context(), c.Response().Writer)
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
func RegisterHandler(c echo.Context) error {
|
||||
options := PublicKeyCredentialCreationOptions{
|
||||
Challenge: "your-challenge-base64url",
|
||||
RpName: "Your App",
|
||||
RpID: "yourdomain.com",
|
||||
UserID: "user-id-base64url",
|
||||
UserName: "username",
|
||||
UserDisplayName: "User Display Name",
|
||||
Timeout: 60000,
|
||||
AttestationType: "none",
|
||||
}
|
||||
|
||||
return CreateCredentials(c, options)
|
||||
}
|
||||
|
||||
func LoginHandler(c echo.Context) error {
|
||||
options := PublicKeyCredentialRequestOptions{
|
||||
Challenge: "your-challenge-base64url",
|
||||
RpID: "yourdomain.com",
|
||||
Timeout: 60000,
|
||||
AllowCredentials: []CredentialDescriptor{
|
||||
{
|
||||
Type: "public-key",
|
||||
ID: "credential-id-base64url",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return GetCredentials(c, options)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package credentials
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
type CredentialsManager interface {
|
||||
Create(c echo.Context) error
|
||||
Get(c echo.Context) error
|
||||
List(c echo.Context) error
|
||||
HasWebAuthn(c echo.Context) error
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package credentials
|
||||
|
||||
type Config struct {
|
||||
RpName string
|
||||
RpID string
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
// payments/payments.go
|
||||
|
||||
package payments
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Constants for supported payment methods
|
||||
const (
|
||||
MethodCard = "basic-card"
|
||||
MethodGooglePay = "https://google.com/pay"
|
||||
MethodApplePay = "https://apple.com/apple-pay"
|
||||
MethodSonrWallet = "https://sonr.id/wallet"
|
||||
)
|
||||
|
||||
// InitiatePayment starts the payment request flow
|
||||
func InitiatePayment(c echo.Context, request PaymentRequest) error {
|
||||
return StartPayment(request).Render(c.Request().Context(), c.Response().Writer)
|
||||
}
|
||||
|
||||
// Helper functions to create payment requests
|
||||
func NewBasicCardPayment(amount float64, currency string, label string) PaymentRequest {
|
||||
return PaymentRequest{
|
||||
MethodData: []PaymentMethodData{
|
||||
{
|
||||
SupportedMethods: MethodCard,
|
||||
Data: map[string]any{
|
||||
"supportedNetworks": []string{"visa", "mastercard"},
|
||||
"supportedTypes": []string{"credit", "debit"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Details: PaymentDetails{
|
||||
Total: PaymentItem{
|
||||
Label: label,
|
||||
Amount: Money{
|
||||
Currency: currency,
|
||||
Value: formatAmount(amount),
|
||||
},
|
||||
},
|
||||
},
|
||||
Options: PaymentOptions{
|
||||
RequestPayerName: true,
|
||||
RequestPayerEmail: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
func PaymentHandler(c echo.Context) error {
|
||||
request := NewBasicCardPayment(99.99, "USD", "Product Purchase")
|
||||
|
||||
// Add display items
|
||||
request.Details.DisplayItems = []PaymentItem{
|
||||
{
|
||||
Label: "Product Price",
|
||||
Amount: Money{
|
||||
Currency: "USD",
|
||||
Value: "89.99",
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "Tax",
|
||||
Amount: Money{
|
||||
Currency: "USD",
|
||||
Value: "10.00",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Add shipping options
|
||||
request.Details.ShippingOptions = []ShippingOption{
|
||||
{
|
||||
ID: "standard",
|
||||
Label: "Standard Shipping",
|
||||
Amount: Money{
|
||||
Currency: "USD",
|
||||
Value: "0.00",
|
||||
},
|
||||
Selected: true,
|
||||
},
|
||||
{
|
||||
ID: "express",
|
||||
Label: "Express Shipping",
|
||||
Amount: Money{
|
||||
Currency: "USD",
|
||||
Value: "10.00",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return InitiatePayment(c, request)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package payments
|
||||
|
||||
import "fmt"
|
||||
|
||||
func formatAmount(amount float64) string {
|
||||
return fmt.Sprintf("%.2f", amount)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package resolver
|
||||
|
||||
type DID string
|
||||
|
||||
func (d DID) String() string {
|
||||
return string(d)
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -36,7 +36,7 @@ func Primary(href string, text string) templ.Component {
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(href)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/button/default.templ`, Line: 5, Col: 124}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/button/default.templ`, Line: 5, Col: 124}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -49,7 +49,7 @@ func Primary(href string, text string) templ.Component {
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/button/default.templ`, Line: 6, Col: 9}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/button/default.templ`, Line: 6, Col: 9}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -91,7 +91,7 @@ func Secondary(href string, text string) templ.Component {
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/button/default.templ`, Line: 13, Col: 175}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/button/default.templ`, Line: 13, Col: 175}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -0,0 +1,46 @@
|
||||
package details
|
||||
|
||||
import "strings"
|
||||
|
||||
// Helper function to shorten address
|
||||
func shortenAddress(address string) string {
|
||||
if len(address) <= 12 {
|
||||
return address
|
||||
}
|
||||
return address[:8] + "..." + address[len(address)-4:]
|
||||
}
|
||||
|
||||
func formatValue(value string) string {
|
||||
if value == "" {
|
||||
return "N/A"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
templ Property(name string, value string, icon string) {
|
||||
<div class="flex items-center w-full gap-4">
|
||||
<div class="flex items-center gap-1">
|
||||
<sl-icon name={ icon } library="sonr"></sl-icon>
|
||||
<span class="min-w-[64px]">{ name }</span>
|
||||
</div>
|
||||
<div class="w-[40px] border-b border-dotted border-gray-400"></div>
|
||||
<span>
|
||||
<sl-badge variant="neutral" class="ml-2 text-right flex-grow" pill>
|
||||
<p class="font-mono">
|
||||
if strings.HasPrefix(strings.ToLower(name), "address") {
|
||||
{ shortenAddress(value) }
|
||||
<sl-copy-button value={ value }></sl-copy-button>
|
||||
} else {
|
||||
{ formatValue(value) }
|
||||
}
|
||||
</p>
|
||||
</sl-badge>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ PropertyList() {
|
||||
<div class="flex flex-col space-y-4 w-full">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package details
|
||||
|
||||
//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 "strings"
|
||||
|
||||
// Helper function to shorten address
|
||||
func shortenAddress(address string) string {
|
||||
if len(address) <= 12 {
|
||||
return address
|
||||
}
|
||||
return address[:8] + "..." + address[len(address)-4:]
|
||||
}
|
||||
|
||||
func formatValue(value string) string {
|
||||
if value == "" {
|
||||
return "N/A"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func Property(name string, value string, icon 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("<div class=\"flex items-center w-full gap-4\"><div class=\"flex items-center gap-1\"><sl-icon name=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(icon)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/details/property.templ`, Line: 23, Col: 23}
|
||||
}
|
||||
_, 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("\" library=\"sonr\"></sl-icon> <span class=\"min-w-[64px]\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/details/property.templ`, Line: 24, Col: 36}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></div><div class=\"w-[40px] border-b border-dotted border-gray-400\"></div><span><sl-badge variant=\"neutral\" class=\"ml-2 text-right flex-grow\" pill><p class=\"font-mono\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if strings.HasPrefix(strings.ToLower(name), "address") {
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(shortenAddress(value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/details/property.templ`, Line: 31, Col: 29}
|
||||
}
|
||||
_, 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(" <sl-copy-button value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/details/property.templ`, Line: 32, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></sl-copy-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(formatValue(value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/details/property.templ`, Line: 34, Col: 26}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></sl-badge></span></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func PropertyList() 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_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col space-y-4 w-full\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var7.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,76 @@
|
||||
package form
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
// Form is a standard form styled like a card
|
||||
templ Form(action string, method string, submit templ.Component, progress string, enableCancel bool) {
|
||||
<form action={ templ.SafeURL(action) } method={ method }>
|
||||
<sl-card class="card-form gap-4 max-w-lg">
|
||||
<div slot="header">
|
||||
<div class="w-full py-1">
|
||||
<sl-progress-bar value={ progress }></sl-progress-bar>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
<div slot="footer">
|
||||
if enableCancel {
|
||||
<sl-button href="/" outline>
|
||||
<sl-icon slot="prefix" name="arrow-left" library="sonr"></sl-icon>
|
||||
Cancel
|
||||
</sl-button>
|
||||
}
|
||||
@submit
|
||||
</div>
|
||||
<style>
|
||||
.card-form [slot='footer'] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</sl-card>
|
||||
</form>
|
||||
}
|
||||
|
||||
templ NameInput() {
|
||||
@layout.Rows() {
|
||||
<sl-input name="first_name" placeholder="Steve" type="text" label="First Name" required autofocus></sl-input>
|
||||
<sl-input name="last_name" placeholder="J" maxlength="1" type="text" label="Last Initial"></sl-input>
|
||||
}
|
||||
}
|
||||
|
||||
templ HandleInput() {
|
||||
<sl-input name="handle" placeholder="thoughtdiff" type="text" label="Handle" minlength="4" maxlength="12" required>
|
||||
<div slot="prefix">
|
||||
<sl-icon name="at-sign" library="sonr"></sl-icon>
|
||||
</div>
|
||||
</sl-input>
|
||||
}
|
||||
|
||||
templ CodeInput(id string) {
|
||||
<sl-input id={ id } placeholder="●" type="text" maxlength="1" pill class="w-min"></sl-input>
|
||||
}
|
||||
|
||||
// Hidden input and button which calls a javascript function to generate a passkey
|
||||
templ PasskeyInput(id string) {
|
||||
@CredentialsScripts()
|
||||
<sl-button type="submit" pill style="width: 100%;">
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 20px;"></sl-icon>
|
||||
Create PassKey
|
||||
<sl-icon slot="suffix" name="arrow-right" library="sonr" style="font-size: 20px;"></sl-icon>
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ TurnstileWidget(sitekey string) {
|
||||
if sitekey != "" {
|
||||
<br/>
|
||||
<div class="cf-turnstile" data-sitekey={ sitekey }></div>
|
||||
}
|
||||
}
|
||||
|
||||
templ Submit(text string) {
|
||||
<sl-button type="submit">
|
||||
{ text }
|
||||
<sl-icon slot="suffix" name="arrow-right" library="sonr"></sl-icon>
|
||||
</sl-button>
|
||||
}
|
||||
@@ -1,25 +1,17 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package layout
|
||||
package form
|
||||
|
||||
//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"
|
||||
|
||||
const (
|
||||
PublicOrigin = "https://cdn.sonr.id"
|
||||
)
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
var (
|
||||
stylesHandle = templ.NewOnceHandle()
|
||||
alpineHandle = templ.NewOnceHandle()
|
||||
dexieHandle = templ.NewOnceHandle()
|
||||
htmxHandle = templ.NewOnceHandle()
|
||||
)
|
||||
|
||||
func Styles() templ.Component {
|
||||
// Form is a standard form styled like a card
|
||||
func Form(action string, method string, submit templ.Component, progress string, enableCancel 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 {
|
||||
@@ -40,75 +32,64 @@ func Styles() templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<link href=\"")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form action=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("https://cdn.sonr.id/css/styles.css")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/layout/scripts.templ`, Line: 15, Col: 50}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL(action)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" rel=\"stylesheet\"><script src=\"https://kit.fontawesome.com/9909219bb5.js\" crossorigin=\"anonymous\"></script>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" method=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Alpine() 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
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(method)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/form/form.templ`, Line: 7, Col: 55}
|
||||
}
|
||||
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
|
||||
}
|
||||
}()
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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("<script src=\"")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><sl-card class=\"card-form gap-4 max-w-lg\"><div slot=\"header\"><div class=\"w-full py-1\"><sl-progress-bar value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs("https://cdn.sonr.id/js/alpine-focus.min.js")
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(progress)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/layout/scripts.templ`, Line: 20, Col: 59}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/form/form.templ`, Line: 11, Col: 38}
|
||||
}
|
||||
_, 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("\" defer></script><script src=\"")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></sl-progress-bar></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs("https://cdn.sonr.id/js/alpine.min.js")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/layout/scripts.templ`, Line: 21, Col: 53}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
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("\" defer></script>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div slot=\"footer\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if enableCancel {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-button href=\"/\" outline><sl-icon slot=\"prefix\" name=\"arrow-left\" library=\"sonr\"></sl-icon> Cancel</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = submit.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><style>\n \t\t.card-form [slot='footer'] {\n \t\tdisplay: flex;\n \t\tjustify-content: space-between;\n \t\talign-items: center;\n \t\t}\n\t\t</style></sl-card></form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -116,7 +97,7 @@ func Alpine() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func Dexie() templ.Component {
|
||||
func NameInput() 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 {
|
||||
@@ -132,25 +113,30 @@ func Dexie() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script src=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
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 = templ_7745c5c3_Buffer.WriteString("<sl-input name=\"first_name\" placeholder=\"Steve\" type=\"text\" label=\"First Name\" required autofocus></sl-input> <sl-input name=\"last_name\" placeholder=\"J\" maxlength=\"1\" type=\"text\" label=\"Last Initial\"></sl-input>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs("https://cdn.sonr.id/js/dexie.min.js")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/layout/scripts.templ`, Line: 25, Col: 52}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></script>")
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Rows().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -158,7 +144,36 @@ func Dexie() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func Htmx() templ.Component {
|
||||
func HandleInput() 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_Err = templ_7745c5c3_Buffer.WriteString("<sl-input name=\"handle\" placeholder=\"thoughtdiff\" type=\"text\" label=\"Handle\" minlength=\"4\" maxlength=\"12\" required><div slot=\"prefix\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon></div></sl-input>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func CodeInput(id 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 {
|
||||
@@ -179,20 +194,20 @@ func Htmx() templ.Component {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script src=\"")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-input id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs("https://cdn.sonr.id/js/htmx.min.js")
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(id)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/layout/scripts.templ`, Line: 29, Col: 51}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/form/form.templ`, Line: 51, Col: 18}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></script>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" placeholder=\"●\" type=\"text\" maxlength=\"1\" pill class=\"w-min\"></sl-input>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -200,7 +215,8 @@ func Htmx() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func WebAwesome() templ.Component {
|
||||
// Hidden input and button which calls a javascript function to generate a passkey
|
||||
func PasskeyInput(id 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 {
|
||||
@@ -221,7 +237,11 @@ func WebAwesome() templ.Component {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script type=\"module\" src=\"https://early.webawesome.com/webawesome@3.0.0-alpha.4/dist/webawesome.loader.js\"></script><link rel=\"stylesheet\" href=\"https://early.webawesome.com/webawesome@3.0.0-alpha.4/dist/themes/default.css\">")
|
||||
templ_7745c5c3_Err = CredentialsScripts().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-button type=\"submit\" pill style=\"width: 100%;\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 20px;\"></sl-icon> Create PassKey <sl-icon slot=\"suffix\" name=\"arrow-right\" library=\"sonr\" style=\"font-size: 20px;\"></sl-icon></sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -229,7 +249,7 @@ func WebAwesome() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func Toaster() templ.Component {
|
||||
func TurnstileWidget(sitekey 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 {
|
||||
@@ -250,15 +270,64 @@ func Toaster() templ.Component {
|
||||
templ_7745c5c3_Var11 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div x-data=\"{ \n title: 'Default Toast Notification', \n description: '',\n type: 'default',\n position: 'top-center',\n expanded: false,\n popToast (custom){\n let html = '';\n if(typeof custom != 'undefined'){\n html = custom;\n }\n toast(this.title, { description: this.description, type: this.type, position: this.position, html: html })\n }\n }\" x-init=\"\n window.toast = function(message, options = {}){\n let description = '';\n let type = 'default';\n let position = 'top-center';\n let html = '';\n if(typeof options.description != 'undefined') description = options.description;\n if(typeof options.type != 'undefined') type = options.type;\n if(typeof options.position != 'undefined') position = options.position;\n if(typeof options.html != 'undefined') html = options.html;\n window.dispatchEvent(new CustomEvent('toast-show', { detail : { type: type, message: message, description: description, position : position, html: html }}));\n }\n \">")
|
||||
if sitekey != "" {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<br><div class=\"cf-turnstile\" data-sitekey=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(sitekey)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/form/form.templ`, Line: 67, Col: 50}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Submit(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_Var13 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var13 == nil {
|
||||
templ_7745c5c3_Var13 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-button type=\"submit\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var11.Render(ctx, templ_7745c5c3_Buffer)
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/form/form.templ`, Line: 73, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <sl-icon slot=\"suffix\" name=\"arrow-right\" library=\"sonr\"></sl-icon></sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -1,32 +1,9 @@
|
||||
package credentials
|
||||
package form
|
||||
|
||||
import "github.com/go-webauthn/webauthn/protocol"
|
||||
|
||||
var credentialsHandle = templ.NewOnceHandle()
|
||||
|
||||
// Types for credential data
|
||||
type PublicKeyCredentialCreationOptions struct {
|
||||
Challenge string `json:"challenge"`
|
||||
RpName string `json:"rpName"`
|
||||
RpID string `json:"rpId"`
|
||||
UserID string `json:"userId"`
|
||||
UserName string `json:"userName"`
|
||||
UserDisplayName string `json:"userDisplayName"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
AttestationType string `json:"attestationType,omitempty"`
|
||||
}
|
||||
|
||||
type PublicKeyCredentialRequestOptions struct {
|
||||
Challenge string `json:"challenge"`
|
||||
RpID string `json:"rpId"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
UserVerification string `json:"userVerification,omitempty"`
|
||||
AllowCredentials []CredentialDescriptor `json:"allowCredentials,omitempty"`
|
||||
}
|
||||
|
||||
type CredentialDescriptor struct {
|
||||
Type string `json:"type"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// Base credentials script template
|
||||
templ CredentialsScripts() {
|
||||
@credentialsHandle.Once() {
|
||||
@@ -142,8 +119,15 @@ templ CredentialsScripts() {
|
||||
}
|
||||
}
|
||||
|
||||
script CreatePasskey(id string) {
|
||||
function createPasskey(id) {
|
||||
const passkey = document.getElementById(id);
|
||||
passkey.value = window.crypto.getRandomValues(new Uint8Array(32)).join('');
|
||||
}
|
||||
}
|
||||
|
||||
// Template for creating credentials
|
||||
templ CreateCredential(options PublicKeyCredentialCreationOptions) {
|
||||
templ CreateCredential(options *protocol.PublicKeyCredentialCreationOptions) {
|
||||
@CredentialsScripts()
|
||||
<script>
|
||||
(async () => {
|
||||
@@ -167,7 +151,7 @@ templ CreateCredential(options PublicKeyCredentialCreationOptions) {
|
||||
}
|
||||
|
||||
// Template for getting credentials
|
||||
templ GetCredential(options PublicKeyCredentialRequestOptions) {
|
||||
templ GetCredential(options *protocol.PublicKeyCredentialRequestOptions) {
|
||||
@CredentialsScripts()
|
||||
<script>
|
||||
(async () => {
|
||||
@@ -1,40 +1,17 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package credentials
|
||||
package form
|
||||
|
||||
//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/go-webauthn/webauthn/protocol"
|
||||
|
||||
var credentialsHandle = templ.NewOnceHandle()
|
||||
|
||||
// Types for credential data
|
||||
type PublicKeyCredentialCreationOptions struct {
|
||||
Challenge string `json:"challenge"`
|
||||
RpName string `json:"rpName"`
|
||||
RpID string `json:"rpId"`
|
||||
UserID string `json:"userId"`
|
||||
UserName string `json:"userName"`
|
||||
UserDisplayName string `json:"userDisplayName"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
AttestationType string `json:"attestationType,omitempty"`
|
||||
}
|
||||
|
||||
type PublicKeyCredentialRequestOptions struct {
|
||||
Challenge string `json:"challenge"`
|
||||
RpID string `json:"rpId"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
UserVerification string `json:"userVerification,omitempty"`
|
||||
AllowCredentials []CredentialDescriptor `json:"allowCredentials,omitempty"`
|
||||
}
|
||||
|
||||
type CredentialDescriptor struct {
|
||||
Type string `json:"type"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// Base credentials script template
|
||||
func CredentialsScripts() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
@@ -83,8 +60,21 @@ func CredentialsScripts() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func CreatePasskey(id string) templ.ComponentScript {
|
||||
return templ.ComponentScript{
|
||||
Name: `__templ_CreatePasskey_df39`,
|
||||
Function: `function __templ_CreatePasskey_df39(id){function createPasskey(id) {
|
||||
const passkey = document.getElementById(id);
|
||||
passkey.value = window.crypto.getRandomValues(new Uint8Array(32)).join('');
|
||||
}
|
||||
}`,
|
||||
Call: templ.SafeScript(`__templ_CreatePasskey_df39`, id),
|
||||
CallInline: templ.SafeScriptInline(`__templ_CreatePasskey_df39`, id),
|
||||
}
|
||||
}
|
||||
|
||||
// Template for creating credentials
|
||||
func CreateCredential(options PublicKeyCredentialCreationOptions) templ.Component {
|
||||
func CreateCredential(options *protocol.PublicKeyCredentialCreationOptions) 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 {
|
||||
@@ -118,7 +108,7 @@ func CreateCredential(options PublicKeyCredentialCreationOptions) templ.Componen
|
||||
}
|
||||
|
||||
// Template for getting credentials
|
||||
func GetCredential(options PublicKeyCredentialRequestOptions) templ.Component {
|
||||
func GetCredential(options *protocol.PublicKeyCredentialRequestOptions) 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 {
|
||||
@@ -1,8 +1,27 @@
|
||||
package layout
|
||||
|
||||
// Columns is a component that renders a flex container with a gap of 3 and a max width of 100%
|
||||
templ Columns() {
|
||||
<div class="flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Container() {
|
||||
<div id="container" class="flex fixed inset-0 z-[99] w-screen h-screen">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
// Rows is a component that renders a flex container with a gap of 2 and a max width of 100%
|
||||
templ Rows() {
|
||||
<div class="flex flex-row w-full gap-2 md:gap-4">
|
||||
<div class="flex flex-row w-full gap-2 md:gap-4 max-w-fit">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
@@ -16,14 +35,7 @@ templ Separator(text string) {
|
||||
<div class="relative py-6">
|
||||
<div class="absolute inset-0 flex items-center"><span class="w-full border-t"></span></div>
|
||||
<div class="relative flex justify-center text-xs uppercase">
|
||||
<span class="px-2 bg-white text-neutral-500">{ text }</span>
|
||||
<span class="px-2 text-neutral-500">{ text }</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
// Columns is a component that renders a flex container with a gap of 3 and a max width of 100%
|
||||
templ Columns() {
|
||||
<div class="flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
@@ -8,8 +8,8 @@ package layout
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
// Rows is a component that renders a flex container with a gap of 2 and a max width of 100%
|
||||
func Rows() templ.Component {
|
||||
// Columns is a component that renders a flex container with a gap of 3 and a max width of 100%
|
||||
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 {
|
||||
@@ -30,7 +30,7 @@ func Rows() templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-row w-full gap-2 md:gap-4\">")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -46,6 +46,81 @@ func Rows() 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 {
|
||||
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("<div id=\"container\" class=\"flex fixed inset-0 z-[99] w-screen h-screen\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\">")
|
||||
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("</div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
// Rows is a component that renders a flex container with a gap of 2 and a max width of 100%
|
||||
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_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("<div class=\"flex flex-row w-full gap-2 md:gap-4 max-w-fit\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
// Spacer is a component that renders a <br/> tag
|
||||
func Spacer() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
@@ -63,9 +138,9 @@ func Spacer() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
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("<br>")
|
||||
@@ -92,21 +167,21 @@ func Separator(text string) 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_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative py-6\"><div class=\"absolute inset-0 flex items-center\"><span class=\"w-full border-t\"></span></div><div class=\"relative flex justify-center text-xs uppercase\"><span class=\"px-2 bg-white text-neutral-500\">")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative py-6\"><div class=\"absolute inset-0 flex items-center\"><span class=\"w-full border-t\"></span></div><div class=\"relative flex justify-center text-xs uppercase\"><span class=\"px-2 text-neutral-500\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/webui/styles/layout/ui.templ`, Line: 19, Col: 54}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/layout/container.templ`, Line: 38, Col: 45}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -118,42 +193,4 @@ func Separator(text string) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
// Columns is a component that renders a flex container with a gap of 3 and a max width of 100%
|
||||
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_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var5.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,75 @@
|
||||
package layout
|
||||
|
||||
type (
|
||||
Alignment templ.Attributes
|
||||
ScreenWidth templ.Attributes
|
||||
)
|
||||
|
||||
var (
|
||||
AlignCenter = Alignment{
|
||||
"class": "flex items-center justify-center",
|
||||
}
|
||||
AlignEnd = Alignment{
|
||||
"class": "flex items-end justify-center",
|
||||
}
|
||||
MaxWidthSmall = ScreenWidth{
|
||||
"class": "max-w-screen-sm",
|
||||
}
|
||||
MaxWidthMedium = ScreenWidth{
|
||||
"class": "max-w-screen-md",
|
||||
}
|
||||
MaxWidthFull = ScreenWidth{
|
||||
"class": "w-full",
|
||||
}
|
||||
)
|
||||
|
||||
// Layout is a component that renders the general layout of the application
|
||||
templ Root(title string) {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@Head(title, "0.0.7")
|
||||
<body class="flex items-center justify-center h-full lg:p-24 md:16 p-4 no-scrollbar">
|
||||
<main class="flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3">
|
||||
{ children... }
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
templ Head(title string, nebulaVersion string) {
|
||||
<head>
|
||||
@Turnstile()
|
||||
@Tailwind()
|
||||
@Alpine()
|
||||
@Htmx()
|
||||
@Dexie()
|
||||
@Nebula(nebulaVersion)
|
||||
<meta charset="UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>{ title }</title>
|
||||
<!-- Sets the status bar style to transparent -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
||||
<link rel="icon" type="image/png" href="https://cdn.sonr.id/favicon.png"/>
|
||||
{ children... }
|
||||
</head>
|
||||
}
|
||||
|
||||
templ Body(align Alignment, screenWidth ScreenWidth) {
|
||||
<body class="flex items-center justify-center h-full lg:p-24 md:16 p-4 no-scrollbar">
|
||||
<main class="flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3">
|
||||
{ children... }
|
||||
</main>
|
||||
</body>
|
||||
}
|
||||
|
||||
func Clsx(attrs ...templ.Attributes) templ.Attributes {
|
||||
merged := templ.Attributes{}
|
||||
for _, attr := range attrs {
|
||||
for k, v := range attr {
|
||||
merged[k] = v
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
// 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"
|
||||
|
||||
type (
|
||||
Alignment templ.Attributes
|
||||
ScreenWidth templ.Attributes
|
||||
)
|
||||
|
||||
var (
|
||||
AlignCenter = Alignment{
|
||||
"class": "flex items-center justify-center",
|
||||
}
|
||||
AlignEnd = Alignment{
|
||||
"class": "flex items-end justify-center",
|
||||
}
|
||||
MaxWidthSmall = ScreenWidth{
|
||||
"class": "max-w-screen-sm",
|
||||
}
|
||||
MaxWidthMedium = ScreenWidth{
|
||||
"class": "max-w-screen-md",
|
||||
}
|
||||
MaxWidthFull = ScreenWidth{
|
||||
"class": "w-full",
|
||||
}
|
||||
)
|
||||
|
||||
// Layout is a component that renders the general layout of the application
|
||||
func Root(title 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("<!doctype html><html lang=\"en\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = Head(title, "0.0.7").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"flex items-center justify-center h-full lg:p-24 md:16 p-4 no-scrollbar\"><main class=\"flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3\">")
|
||||
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("</main></body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
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_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("<head>")
|
||||
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("<meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/styles/layout/layout.templ`, Line: 50, Col: 16}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title><!-- Sets the status bar style to transparent --><meta name=\"apple-mobile-web-app-capable\" content=\"yes\"><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\"><link rel=\"icon\" type=\"image/png\" href=\"https://cdn.sonr.id/favicon.png\">")
|
||||
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("</head>")
|
||||
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("<body class=\"flex items-center justify-center h-full lg:p-24 md:16 p-4 no-scrollbar\"><main class=\"flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var4.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</main></body>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Clsx(attrs ...templ.Attributes) templ.Attributes {
|
||||
merged := templ.Attributes{}
|
||||
for _, attr := range attrs {
|
||||
for k, v := range attr {
|
||||
merged[k] = v
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,83 @@
|
||||
package layout
|
||||
|
||||
import "fmt"
|
||||
|
||||
var (
|
||||
nebulaHandle = templ.NewOnceHandle()
|
||||
tailwindHandle = templ.NewOnceHandle()
|
||||
alpineHandle = templ.NewOnceHandle()
|
||||
dexieHandle = templ.NewOnceHandle()
|
||||
htmxHandle = templ.NewOnceHandle()
|
||||
turnstileHandle = templ.NewOnceHandle()
|
||||
)
|
||||
|
||||
// ╭──────────────────────────────────────────────────────────╮
|
||||
// │ 3rd Party Libraries │
|
||||
// ╰──────────────────────────────────────────────────────────╯
|
||||
|
||||
// Tailwind css dependencies
|
||||
templ Tailwind() {
|
||||
@tailwindHandle.Once() {
|
||||
<script src="https://cdn.tailwindcss.com?plugins=typography,aspect-ratio,line-clamp,container-queries"></script>
|
||||
<script src="https://kit.fontawesome.com/9909219bb5.js" crossorigin="anonymous"></script>
|
||||
}
|
||||
}
|
||||
|
||||
// Turnstile is used for cloudflare challenges
|
||||
templ Turnstile() {
|
||||
@turnstileHandle.Once() {
|
||||
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
|
||||
}
|
||||
}
|
||||
|
||||
// Alpine is a component that renders the Alpine.js library
|
||||
templ Alpine() {
|
||||
@alpineHandle.Once() {
|
||||
<script src={ jsDelivrURL("alpinejs", "3.14.6", "dist/cdn.min.js") }></script>
|
||||
<script src={ jsDelivrURL("@alpinejs/focus", "3.14.6", "dist/cdn.min.js") }></script>
|
||||
}
|
||||
}
|
||||
|
||||
// Dexie is a component that renders the Dexie.js library
|
||||
templ Dexie() {
|
||||
@dexieHandle.Once() {
|
||||
<script src={ jsDelivrURL("dexie", "4.0.10", "dist/dexie.min.js") }></script>
|
||||
<script src={ jsDelivrURL("dexie-export-import", "4.1.4", "dist/dexie-export-import.min.js") }></script>
|
||||
}
|
||||
}
|
||||
|
||||
// Htmx is a component that renders the Htmx.js library
|
||||
templ Htmx() {
|
||||
@htmxHandle.Once() {
|
||||
<script src={ jsDelivrURL("htmx.org", "1.9.12", "dist/htmx.min.js") }></script>
|
||||
<script src={ jsDelivrURL("htmx-ext-include-vals", "2.0.0", "include-vals.min.js") }></script>
|
||||
<script src={ jsDelivrURL("htmx-ext-path-params", "2.0.0", "path-params.min.js") }></script>
|
||||
<script src={ jsDelivrURL("htmx-ext-alpine-morph", "2.0.0", "alpine-morph.min.js") }></script>
|
||||
}
|
||||
}
|
||||
|
||||
// Nebula is a component that renders the Nebula.js library
|
||||
templ Nebula(version string) {
|
||||
<link
|
||||
rel="stylesheet"
|
||||
media="(prefers-color-scheme:light)"
|
||||
href={ jsDelivrURL("@onsonr/nebula", version, "cdn/themes/light.css") }
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
media="(prefers-color-scheme:dark)"
|
||||
href={ jsDelivrURL("@onsonr/nebula", version, "cdn/themes/dark.css") }
|
||||
onload="document.documentElement.classList.add('sl-theme-dark');"
|
||||
/>
|
||||
@nebulaHandle.Once() {
|
||||
<script type="module" src={ jsDelivrURL("@onsonr/nebula", version, "cdn/shoelace-autoloader.js") }></script>
|
||||
}
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Helper Functions │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func jsDelivrURL(pkg string, version string, path string) string {
|
||||
return fmt.Sprintf("https://cdn.jsdelivr.net/npm/%s@%s/%s", pkg, version, path)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user