mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-02 17:31:39 +00:00
(no commit message provided)
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package coins
|
||||
|
||||
// Coin represents a cryptocurrency
|
||||
type Coin interface {
|
||||
// FormatAddress formats a public key into an address
|
||||
FormatAddress(pubKey []byte) (string, error)
|
||||
|
||||
// GetIndex returns the coin type index
|
||||
GetIndex() int64
|
||||
|
||||
// GetPath returns the coin component path
|
||||
GetPath() uint32
|
||||
|
||||
// GetSymbol returns the coin symbol
|
||||
GetSymbol() string
|
||||
|
||||
// GetMethod returns the coin DID method
|
||||
GetMethod() string
|
||||
|
||||
// GetName returns the coin name
|
||||
GetName() string
|
||||
}
|
||||
|
||||
// DefaultCoins is a list of default coins used in the vault
|
||||
var DefaultCoins = []Coin{
|
||||
CoinBTC,
|
||||
CoinETH,
|
||||
CoinSNR,
|
||||
}
|
||||
|
||||
var (
|
||||
// Bitcoin mainnet
|
||||
CoinBTC = &coin{
|
||||
Name: "Bitcoin",
|
||||
Index: 0,
|
||||
Path: 0x80000000,
|
||||
Symbol: "BTC",
|
||||
Hrp: "bc",
|
||||
Method: "btcr",
|
||||
}
|
||||
|
||||
// Ethereum
|
||||
CoinETH = &coin{
|
||||
Name: "Ethereum",
|
||||
Index: 60,
|
||||
Path: 0x8000003c,
|
||||
Symbol: "ETH",
|
||||
Method: "ethr",
|
||||
}
|
||||
|
||||
// Sonr
|
||||
CoinSNR = &coin{
|
||||
Name: "Sonr",
|
||||
Index: 703,
|
||||
Path: 0x800002bf,
|
||||
Symbol: "SNR",
|
||||
Hrp: "idx",
|
||||
Method: "sonr",
|
||||
}
|
||||
)
|
||||
|
||||
// CoinBTCType is the coin type for BTC
|
||||
const CoinBTCType = int64(0)
|
||||
|
||||
// CoinETHType is the coin type for ETH
|
||||
const CoinETHType = int64(60)
|
||||
|
||||
// CoinSNRType is the coin type for SNR
|
||||
const CoinSNRType = int64(703)
|
||||
@@ -0,0 +1,54 @@
|
||||
package coins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
)
|
||||
|
||||
type coin struct {
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Hrp string `json:"hrp"`
|
||||
Method string `json:"method"`
|
||||
Index int64 `json:"index"`
|
||||
Path uint32 `json:"path"`
|
||||
}
|
||||
|
||||
// FormatAddress formats the address based on the coin
|
||||
func (c *coin) FormatAddress(pubKey []byte) (string, error) {
|
||||
if c.Hrp != "" {
|
||||
return bech32.ConvertAndEncode(c.Hrp, pubKey)
|
||||
}
|
||||
return "", fmt.Errorf("unsupported coin")
|
||||
}
|
||||
|
||||
// GetIndex returns the coin index
|
||||
func (c *coin) GetIndex() int64 {
|
||||
return c.Index
|
||||
}
|
||||
|
||||
// GetName returns the coin name
|
||||
func (c *coin) GetName() string {
|
||||
return c.Name
|
||||
}
|
||||
|
||||
// GetSymbol returns the coin symbol
|
||||
func (c *coin) GetSymbol() string {
|
||||
return c.Symbol
|
||||
}
|
||||
|
||||
// GetHrp returns the coin hrp
|
||||
func (c *coin) GetHrp() string {
|
||||
return c.Hrp
|
||||
}
|
||||
|
||||
// GetPath returns the coin path
|
||||
func (c *coin) GetPath() uint32 {
|
||||
return c.Path
|
||||
}
|
||||
|
||||
// GetMethod returns the DID method for the coin
|
||||
func (c *coin) GetMethod() string {
|
||||
return c.Method
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package did
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/hway/internal/orm"
|
||||
)
|
||||
|
||||
// Format.Credential formats a credential as a DID
|
||||
func (f formatter) Credential(c *orm.Credential) string {
|
||||
return fmt.Sprintf("did:web:%s@%s#%s", c.DisplayName, c.Origin, c.ID)
|
||||
}
|
||||
|
||||
// Format.Wallet formats a wallet as a DID
|
||||
func (f formatter) Wallet(w *orm.Wallet) string {
|
||||
return fmt.Sprintf("did:sonr:%s", w.Address)
|
||||
}
|
||||
|
||||
// Format is the formatter to use for DIDs
|
||||
var Format = formatter{}
|
||||
|
||||
type formatter struct{}
|
||||
@@ -0,0 +1 @@
|
||||
package did
|
||||
@@ -0,0 +1,9 @@
|
||||
package did
|
||||
|
||||
// VerificationMethod is an object that represents a verification method.
|
||||
type VerificationMethod struct {
|
||||
PublicKeyJwk map[string]interface{} `json:"publicKeyJwk"`
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Controller string `json:"controller"`
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package motor
|
||||
@@ -0,0 +1 @@
|
||||
package motor
|
||||
@@ -0,0 +1 @@
|
||||
package motor
|
||||
@@ -0,0 +1 @@
|
||||
package motor
|
||||
@@ -0,0 +1 @@
|
||||
package motor
|
||||
@@ -0,0 +1,107 @@
|
||||
package motor
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
"github.com/onsonr/hway/crypto/kss"
|
||||
"github.com/onsonr/hway/crypto/mpc"
|
||||
fs "github.com/onsonr/hway/internal/vfs"
|
||||
)
|
||||
|
||||
const kSonrHRP = "idx"
|
||||
|
||||
// vfd is the struct implementation of an IPFS file system
|
||||
type drive struct {
|
||||
kss kss.Set
|
||||
folder fs.Folder
|
||||
addr string
|
||||
}
|
||||
|
||||
// NewVFS creates a new virtual file system.
|
||||
func Spawn() (*drive, error) {
|
||||
kss, err := mpc.GenerateKss()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := bech32.ConvertAndEncode(kSonrHRP, kss.PublicKey().Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootDir, err := fs.NewVaultFolder(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &drive{
|
||||
folder: rootDir,
|
||||
addr: addr,
|
||||
kss: kss,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// // CreateFingerprint creates a fingerprint for the given database and public key
|
||||
// func CreateFingerprint(dir fs.Folder, db dwn.Database, publicKey crypto.PublicKey) error {
|
||||
// pk, err := secret.NewKey("credentials", publicKey)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// creds, err := db.ListCredentials()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// credIDStrs := make([]string, len(creds))
|
||||
// for i, c := range creds {
|
||||
// credIDStrs[i] = c.DID
|
||||
// }
|
||||
|
||||
// acc, err := pk.CreateAccumulator(credIDStrs...)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// bz, err := acc.MarshalBinary()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// _, err = dir.WriteFile("fingerprint", bz, os.ModePerm)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// // ValidateAndPurgeFingerprint validates the fingerprint and purges it if it's valid
|
||||
// func ValidateAndPurgeFingerprint(dir fs.Folder, witness []byte, publicKey crypto.PublicKey) (bool, error) {
|
||||
// pk, err := secret.NewKey("credentials", publicKey)
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
// creds := new(accumulator.Accumulator)
|
||||
// membership := new(accumulator.MembershipWitness)
|
||||
// err = membership.UnmarshalBinary(witness)
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
|
||||
// bz, err := dir.ReadFile("fingerprint")
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
|
||||
// err = creds.UnmarshalBinary(bz)
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
|
||||
// if err := pk.VerifyWitness(creds, membership); err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
|
||||
// err = dir.DeleteFile("fingerprint")
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
// return true, nil
|
||||
// }
|
||||
@@ -0,0 +1,41 @@
|
||||
package components
|
||||
|
||||
templ RootLayout() {
|
||||
<html>
|
||||
@head()
|
||||
<body>
|
||||
{ children... }
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
templ Container() {
|
||||
<html>
|
||||
@head()
|
||||
<body>
|
||||
<div class="pt-24 flex flex-col items-center">
|
||||
<sl-card class="card-basic max-w-xl min-w-lg">
|
||||
{ children... }
|
||||
</sl-card>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
templ Form(id, action, method string) {
|
||||
<form id={ id } class="flex flex-col gap-x-2 gap-y-4 pt-3" action={ templ.URL(action) } method={ method }>
|
||||
{ children... }
|
||||
</form>
|
||||
}
|
||||
|
||||
templ Rows() {
|
||||
<div class="pt-3 flex flex-row space-x-2">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Columns() {
|
||||
<div class="pt-3 flex flex-col space-y-4">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.731
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func RootLayout() 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
|
||||
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("<html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = head().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body>")
|
||||
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("</body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
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("<html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = head().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body><div class=\"pt-24 flex flex-col items-center\"><sl-card class=\"card-basic max-w-xl min-w-lg\">")
|
||||
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("</sl-card></div></body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Form(id, action, method 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
|
||||
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("<form id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(id)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/layout.templ`, Line: 26, Col: 14}
|
||||
}
|
||||
_, 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("\" class=\"flex flex-col gap-x-2 gap-y-4 pt-3\" action=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 templ.SafeURL = templ.URL(action)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" method=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(method)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/layout.templ`, Line: 26, Col: 104}
|
||||
}
|
||||
_, 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("\">")
|
||||
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("</form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
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=\"pt-3 flex flex-row space-x-2\">")
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
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_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"pt-3 flex flex-col space-y-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var8.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
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package components
|
||||
|
||||
templ Home(sessionID string) {
|
||||
@RootLayout() {
|
||||
@Container() {
|
||||
@Header("Sonr.ID", "The most secure crypto wallet ever made.")
|
||||
@Rows() {
|
||||
@SecondaryButton("Login", "/login")
|
||||
@PrimaryButton("Register", "/register")
|
||||
}
|
||||
}
|
||||
@footer(sessionID)
|
||||
}
|
||||
}
|
||||
|
||||
templ Login(sessionID string) {
|
||||
@RootLayout() {
|
||||
@Container() {
|
||||
@Header("Login", "Authenticate with your existing Sonr Identity.")
|
||||
This is the Login page.
|
||||
}
|
||||
@footer(sessionID)
|
||||
}
|
||||
}
|
||||
|
||||
templ Register(sessionID string, challenge string) {
|
||||
@RootLayout() {
|
||||
@Container() {
|
||||
@Header("Register", "Begin your Interchain Journey securely with a Sonr Identity.")
|
||||
@Form("register", "/api/register/finish", "POST") {
|
||||
@NameInput()
|
||||
@UsernameInput()
|
||||
@PasskeyButton("register")
|
||||
}
|
||||
}
|
||||
}
|
||||
@footer(sessionID)
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.731
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Home(sessionID 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
|
||||
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 = Header("Sonr.ID", "The most secure crypto wallet ever made.").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_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 = SecondaryButton("Login", "/login").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 = PrimaryButton("Register", "/register").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Rows().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 = Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), 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 = footer(sessionID).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = RootLayout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Login(sessionID 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
|
||||
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 = Header("Login", "Authenticate with your existing Sonr Identity.").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" This is the Login page.")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), 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 = footer(sessionID).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = RootLayout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Register(sessionID string, challenge 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
|
||||
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_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(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_Var10 := 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 = Header("Register", "Begin your Interchain Journey securely with a Sonr Identity.").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_Var11 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = NameInput().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 = UsernameInput().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 = PasskeyButton("register").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Form("register", "/api/register/finish", "POST").Render(templ.WithChildren(ctx, templ_7745c5c3_Var11), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var10), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = RootLayout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = footer(sessionID).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package components
|
||||
|
||||
templ head() {
|
||||
<head>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/themes/light.css"/>
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/shoelace-autoloader.js"></script>
|
||||
<link rel="stylesheet" href="https://i.icomoon.io/public/c5fe40a91e/OXYUI/style-svg.css"/>
|
||||
<script defer src="https://i.icomoon.io/public/c5fe40a91e/OXYUI/svgxuse.js"></script>
|
||||
</head>
|
||||
}
|
||||
|
||||
templ footer(sessionID string) {
|
||||
<footer class="absolute bottom-0 w-full">
|
||||
<div class="mx-auto max-w-7xl px-6 py-12 md:flex md:items-center md:justify-between lg:px-8">
|
||||
<div class="flex justify-center space-x-6 md:order-2">
|
||||
<p class="text-center text-xs leading-5 text-gray-800 font-mono">Session: { sessionID }</p>
|
||||
</div>
|
||||
<div class="mt-8 md:order-1 md:mt-0">
|
||||
<p class="text-center text-xs leading-5 text-gray-500">© 2024 diDAO. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.731
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func head() 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
|
||||
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("<head><script src=\"https://cdn.tailwindcss.com\"></script><link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/themes/light.css\"><script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/shoelace-autoloader.js\"></script><link rel=\"stylesheet\" href=\"https://i.icomoon.io/public/c5fe40a91e/OXYUI/style-svg.css\"><script defer src=\"https://i.icomoon.io/public/c5fe40a91e/OXYUI/svgxuse.js\"></script></head>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func footer(sessionID 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
|
||||
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("<footer class=\"absolute bottom-0 w-full\"><div class=\"mx-auto max-w-7xl px-6 py-12 md:flex md:items-center md:justify-between lg:px-8\"><div class=\"flex justify-center space-x-6 md:order-2\"><p class=\"text-center text-xs leading-5 text-gray-800 font-mono\">Session: ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(sessionID)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/styles.templ`, Line: 17, Col: 89}
|
||||
}
|
||||
_, 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("</p></div><div class=\"mt-8 md:order-1 md:mt-0\"><p class=\"text-center text-xs leading-5 text-gray-500\">© 2024 diDAO. All rights reserved.</p></div></div></footer>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package components
|
||||
|
||||
templ Header(title, description string) {
|
||||
<div class="flex flex-col gap-2">
|
||||
<h1 class="text-3xl font-bold">{ title }</h1>
|
||||
<p class="text-gray-600">{ description }</p>
|
||||
</div>
|
||||
<sl-divider></sl-divider>
|
||||
}
|
||||
|
||||
templ NameInput() {
|
||||
<sl-input id="name" name="name" pattern="[A-Za-z]+" label="Name" placeholder="Satoshi Nakamoto" required>
|
||||
<sl-icon name="person-circle" slot="prefix"></sl-icon>
|
||||
</sl-input>
|
||||
}
|
||||
|
||||
templ UsernameInput() {
|
||||
<sl-input id="handle" name="handle" pattern="[A-Za-z]+" label="Username" placeholder="really_satoshi" required>
|
||||
<sl-icon class="text-xl" name="at" slot="prefix"></sl-icon>
|
||||
</sl-input>
|
||||
}
|
||||
|
||||
templ EmailInput(required bool) {
|
||||
<sl-input id="email" name="email" type="email" label="Email" placeholder="satoshi@gmx.com" required?={ required }></sl-input>
|
||||
}
|
||||
|
||||
templ PrimaryButton(title string, href string) {
|
||||
<sl-button href={ href } size="medium" variant="primary" pill>
|
||||
{ title }
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ SecondaryButton(title string, href string) {
|
||||
<sl-button href={ href } size="medium" pill>
|
||||
{ title }
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ PasskeyButton(formId string) {
|
||||
<input type="hidden" id="credentialData" name="credentialData"/>
|
||||
<sl-button variant="primary" onClick={ createCredential(formId) }>
|
||||
<div slot="prefix" class="text-xl">
|
||||
<svg class="icon Passkey"><use xlink:href="#Passkey"></use></svg>
|
||||
</div>
|
||||
Create Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
script createCredential(formId string) {
|
||||
// Base64 encoding and decoding functions
|
||||
function arrayBufferToBase64(buffer) {
|
||||
return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=/g, "");
|
||||
}
|
||||
|
||||
function base64ToArrayBuffer(base64) {
|
||||
const binary = atob(base64.replace(/-/g, "+").replace(/_/g, "/"));
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
// Check if the form is valid
|
||||
const form = document.getElementById(formId);
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get user information from the form
|
||||
const name = document.getElementById('name').value;
|
||||
const handle = document.getElementById('handle').value;
|
||||
|
||||
let credential = navigator.credentials.create({
|
||||
publicKey: {
|
||||
challenge: new Uint8Array([117, 61, 252, 231, 191, 241]),
|
||||
rp: { name: "ACME Corporation" },
|
||||
user: {
|
||||
id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]),
|
||||
name: handle,
|
||||
displayName: name
|
||||
},
|
||||
pubKeyCredParams: [{ type: "public-key", alg: -7 }]
|
||||
}
|
||||
}).then(credential => {
|
||||
// Prepare the credential data
|
||||
let credentialData = {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
rawId: arrayBufferToBase64(credential.rawId),
|
||||
response: {
|
||||
clientDataJSON: arrayBufferToBase64(credential.response.clientDataJSON),
|
||||
attestationObject: arrayBufferToBase64(credential.response.attestationObject)
|
||||
},
|
||||
clientExtensionResults: credential.getClientExtensionResults()
|
||||
};
|
||||
|
||||
// Set the serialized credential data as the form value
|
||||
document.getElementById('credentialData').value = JSON.stringify(credentialData);
|
||||
|
||||
// Submit the form
|
||||
form.submit();
|
||||
}).catch(error => {
|
||||
console.error('Error creating credential:', error);
|
||||
// Handle the error (e.g., show an error message to the user)
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.731
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Header(title, description 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
|
||||
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 flex-col gap-2\"><h1 class=\"text-3xl font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/ui.templ`, Line: 5, Col: 40}
|
||||
}
|
||||
_, 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("</h1><p class=\"text-gray-600\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(description)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/ui.templ`, Line: 6, Col: 40}
|
||||
}
|
||||
_, 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("</p></div><sl-divider></sl-divider>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
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("<sl-input id=\"name\" name=\"name\" pattern=\"[A-Za-z]+\" label=\"Name\" placeholder=\"Satoshi Nakamoto\" required><sl-icon name=\"person-circle\" slot=\"prefix\"></sl-icon></sl-input>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func UsernameInput() 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
|
||||
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("<sl-input id=\"handle\" name=\"handle\" pattern=\"[A-Za-z]+\" label=\"Username\" placeholder=\"really_satoshi\" required><sl-icon class=\"text-xl\" name=\"at\" slot=\"prefix\"></sl-icon></sl-input>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func EmailInput(required 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
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-input id=\"email\" name=\"email\" type=\"email\" label=\"Email\" placeholder=\"satoshi@gmx.com\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if required {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" required")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("></sl-input>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func PrimaryButton(title string, href 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
|
||||
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-button href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(href)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/ui.templ`, Line: 28, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" size=\"medium\" variant=\"primary\" pill>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/ui.templ`, Line: 29, Col: 9}
|
||||
}
|
||||
_, 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("</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func SecondaryButton(title string, href 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
|
||||
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_Err = templ_7745c5c3_Buffer.WriteString("<sl-button href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(href)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/ui.templ`, Line: 34, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" size=\"medium\" pill>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/vault/components/ui.templ`, Line: 35, Col: 9}
|
||||
}
|
||||
_, 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("</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func PasskeyButton(formId 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
|
||||
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("<input type=\"hidden\" id=\"credentialData\" name=\"credentialData\"> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, createCredential(formId))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-button variant=\"primary\" onClick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var14 templ.ComponentScript = createCredential(formId)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><div slot=\"prefix\" class=\"text-xl\"><svg class=\"icon Passkey\"><use xlink:href=\"#Passkey\"></use></svg></div>Create Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func createCredential(formId string) templ.ComponentScript {
|
||||
return templ.ComponentScript{
|
||||
Name: `__templ_createCredential_190e`,
|
||||
Function: `function __templ_createCredential_190e(formId){// Base64 encoding and decoding functions
|
||||
function arrayBufferToBase64(buffer) {
|
||||
return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=/g, "");
|
||||
}
|
||||
|
||||
function base64ToArrayBuffer(base64) {
|
||||
const binary = atob(base64.replace(/-/g, "+").replace(/_/g, "/"));
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
// Check if the form is valid
|
||||
const form = document.getElementById(formId);
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get user information from the form
|
||||
const name = document.getElementById('name').value;
|
||||
const handle = document.getElementById('handle').value;
|
||||
|
||||
let credential = navigator.credentials.create({
|
||||
publicKey: {
|
||||
challenge: new Uint8Array([117, 61, 252, 231, 191, 241]),
|
||||
rp: { name: "ACME Corporation" },
|
||||
user: {
|
||||
id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]),
|
||||
name: handle,
|
||||
displayName: name
|
||||
},
|
||||
pubKeyCredParams: [{ type: "public-key", alg: -7 }]
|
||||
}
|
||||
}).then(credential => {
|
||||
// Prepare the credential data
|
||||
let credentialData = {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
rawId: arrayBufferToBase64(credential.rawId),
|
||||
response: {
|
||||
clientDataJSON: arrayBufferToBase64(credential.response.clientDataJSON),
|
||||
attestationObject: arrayBufferToBase64(credential.response.attestationObject)
|
||||
},
|
||||
clientExtensionResults: credential.getClientExtensionResults()
|
||||
};
|
||||
|
||||
// Set the serialized credential data as the form value
|
||||
document.getElementById('credentialData').value = JSON.stringify(credentialData);
|
||||
|
||||
// Submit the form
|
||||
form.submit();
|
||||
}).catch(error => {
|
||||
console.error('Error creating credential:', error);
|
||||
// Handle the error (e.g., show an error message to the user)
|
||||
});
|
||||
}`,
|
||||
Call: templ.SafeScript(`__templ_createCredential_190e`, formId),
|
||||
CallInline: templ.SafeScriptInline(`__templ_createCredential_190e`, formId),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
pages "github.com/onsonr/hway/pkg/vault/components"
|
||||
"github.com/onsonr/hway/pkg/vault/middleware"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
var Login = loginHandler{}
|
||||
|
||||
type loginHandler struct{}
|
||||
|
||||
func (h loginHandler) Page(e echo.Context) error {
|
||||
return middleware.Render(e, pages.Login(middleware.SessionID(e)))
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
var OIDC = oidcHandler{}
|
||||
|
||||
type oidcHandler struct{}
|
||||
|
||||
func (p oidcHandler) HandleAuthorize(e echo.Context) error {
|
||||
// Implement authorization endpoint using passkey authentication
|
||||
// Store session data in cache
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p oidcHandler) HandleToken(e echo.Context) error {
|
||||
// Implement token endpoint
|
||||
// Use cached session data for validation
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p oidcHandler) HandleUserInfo(e echo.Context) error {
|
||||
// Implement userinfo endpoint
|
||||
// Use cached session data for validation
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p oidcHandler) HandleDiscovery(e echo.Context) error {
|
||||
baseURL := "https://" + e.Request().Host // Ensure this is the correct base URL for your service
|
||||
|
||||
discoveryDoc := DiscoveryDocument{
|
||||
Issuer: baseURL,
|
||||
AuthorizationEndpoint: baseURL + "/authorize",
|
||||
TokenEndpoint: baseURL + "/token",
|
||||
UserinfoEndpoint: baseURL + "/userinfo",
|
||||
JwksURI: baseURL + "/jwks", // You'll need to implement this endpoint
|
||||
RegistrationEndpoint: baseURL + "/register",
|
||||
ScopesSupported: []string{"openid", "profile", "email"},
|
||||
ResponseTypesSupported: []string{"code"},
|
||||
SubjectTypesSupported: []string{"public"},
|
||||
IDTokenSigningAlgValuesSupported: []string{"RS256"},
|
||||
ClaimsSupported: []string{"sub", "iss", "name", "email"},
|
||||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||||
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic", "client_secret_post"},
|
||||
}
|
||||
return e.JSON(200, discoveryDoc)
|
||||
}
|
||||
|
||||
type DiscoveryDocument struct {
|
||||
Issuer string `json:"issuer"`
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||||
TokenEndpoint string `json:"token_endpoint"`
|
||||
UserinfoEndpoint string `json:"userinfo_endpoint"`
|
||||
JwksURI string `json:"jwks_uri"`
|
||||
RegistrationEndpoint string `json:"registration_endpoint"`
|
||||
ScopesSupported []string `json:"scopes_supported"`
|
||||
ResponseTypesSupported []string `json:"response_types_supported"`
|
||||
SubjectTypesSupported []string `json:"subject_types_supported"`
|
||||
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
|
||||
ClaimsSupported []string `json:"claims_supported"`
|
||||
GrantTypesSupported []string `json:"grant_types_supported"`
|
||||
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/onsonr/hway/pkg/vault/components"
|
||||
"github.com/onsonr/hway/pkg/vault/middleware"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
var Session = sessionHandler{}
|
||||
|
||||
type sessionHandler struct{}
|
||||
|
||||
func (h sessionHandler) Page(e echo.Context) error {
|
||||
return middleware.Render(e, components.Home(middleware.SessionID(e)))
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/hway/internal/orm"
|
||||
pages "github.com/onsonr/hway/pkg/vault/components"
|
||||
"github.com/onsonr/hway/pkg/vault/middleware"
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
var Register = registerHandler{}
|
||||
|
||||
type registerHandler struct{}
|
||||
|
||||
func (h registerHandler) Start(e echo.Context) error {
|
||||
return e.JSON(0, nil)
|
||||
}
|
||||
|
||||
func (h registerHandler) Finish(e echo.Context) error {
|
||||
// Get the serialized credential data from the form
|
||||
credentialDataJSON := e.FormValue("credentialData")
|
||||
|
||||
// Deserialize the JSON into a temporary struct
|
||||
var ccr protocol.CredentialCreationResponse
|
||||
err := json.Unmarshal([]byte(credentialDataJSON), &ccr)
|
||||
if err != nil {
|
||||
return e.JSON(500, err.Error())
|
||||
}
|
||||
|
||||
// Parse the CredentialCreationResponse
|
||||
parsedData, err := ccr.Parse()
|
||||
if err != nil {
|
||||
return e.JSON(500, err.Error())
|
||||
}
|
||||
|
||||
// Create the Credential
|
||||
credential := orm.MakeNewCredential(parsedData)
|
||||
|
||||
// Set additional fields
|
||||
credential.DisplayName = ccr.ID // You might want to set this to a more meaningful value
|
||||
credential.Origin = e.Request().Host // Set the origin to the current host
|
||||
credential.Controller = "" // Set this to the appropriate controller value
|
||||
return e.JSON(200, fmt.Sprintf("REGISTER: %s", string(credential.ID)))
|
||||
}
|
||||
|
||||
// FormPage returns the page for registering a new user
|
||||
func (h registerHandler) FormPage(e echo.Context) error {
|
||||
return middleware.Render(e, pages.Register(middleware.SessionID(e), string(middleware.Cache.GetChallenge(e))))
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
var ccref *cacheStore
|
||||
|
||||
func CacheStores(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if ccref == nil {
|
||||
initCacheStore()
|
||||
}
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
|
||||
type cacheStore struct {
|
||||
Challenges *cache.Cache
|
||||
Paths *cache.Cache
|
||||
CIDs *cache.Cache
|
||||
}
|
||||
|
||||
func initCacheStore() {
|
||||
ccref = &cacheStore{
|
||||
Challenges: cache.New(5*time.Minute, 10*time.Minute),
|
||||
Paths: cache.New(30*time.Minute, 1*time.Hour),
|
||||
CIDs: cache.New(30*time.Minute, 1*time.Hour),
|
||||
}
|
||||
}
|
||||
|
||||
func cacheKey(e echo.Context, key string) string {
|
||||
return fmt.Sprintf(SessionID(e), ".", key)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/segmentio/ksuid"
|
||||
)
|
||||
|
||||
func SessionCookies(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if val := readCookie(c, "session"); val == "" {
|
||||
writeCookie(c, "session", ksuid.New().String())
|
||||
}
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
|
||||
func readCookie(c echo.Context, key string) string {
|
||||
cookie, err := c.Cookie(key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if cookie == nil {
|
||||
return ""
|
||||
}
|
||||
return cookie.Value
|
||||
}
|
||||
|
||||
func writeCookie(c echo.Context, key string, value string) {
|
||||
cookie := new(http.Cookie)
|
||||
cookie.Name = key
|
||||
cookie.Value = value
|
||||
cookie.Expires = time.Now().Add(24 * time.Hour)
|
||||
c.SetCookie(cookie)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
// TODO: Replace session authentication with macroons.
|
||||
func GenerateSessionMacaroon(userId string, audience string) (*macaroon.Macaroon, error) {
|
||||
m, err := macaroon.New([]byte("secret-key"), []byte(userId), "sonr-oidc", macaroon.LatestVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = m.AddFirstPartyCaveat([]byte("exp=" + time.Now().Add(1*time.Hour).Format(time.RFC3339)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = m.AddFirstPartyCaveat([]byte("aud=" + audience))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func ValidateSessionMacaroon(m *macaroon.Macaroon) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Render renders a templ.Component
|
||||
func Render(c echo.Context, cmp templ.Component) error {
|
||||
c.Response().Writer.WriteHeader(http.StatusOK)
|
||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML)
|
||||
return cmp.Render(c.Request().Context(), c.Response())
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
func SessionID(c echo.Context) string {
|
||||
return readCookie(c, "session")
|
||||
}
|
||||
|
||||
var Cache = cacheHandler{}
|
||||
|
||||
type cacheHandler struct{}
|
||||
|
||||
func (c cacheHandler) GetChallenge(e echo.Context) protocol.URLEncodedBase64 {
|
||||
key := cacheKey(e, "challenge")
|
||||
if x, found := ccref.Challenges.Get(key); found {
|
||||
chalbz := x.([]byte)
|
||||
chal := protocol.URLEncodedBase64{}
|
||||
err := chal.UnmarshalJSON(chalbz)
|
||||
if err != nil {
|
||||
return chal
|
||||
}
|
||||
return chal
|
||||
}
|
||||
chal, _ := protocol.CreateChallenge()
|
||||
// Save challenge
|
||||
str, err := chal.MarshalJSON()
|
||||
ccref.Challenges.Set(key, str, cache.DefaultExpiration)
|
||||
if err != nil {
|
||||
return chal
|
||||
}
|
||||
return chal
|
||||
}
|
||||
|
||||
func (c cacheHandler) GetLocalPath(e echo.Context) string {
|
||||
key := cacheKey(e, "localPath")
|
||||
if x, found := ccref.Paths.Get(key); found {
|
||||
return x.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c cacheHandler) GetRemoteCID(e echo.Context) path.Path {
|
||||
key := cacheKey(e, "remoteCID")
|
||||
if x, found := ccref.CIDs.Get(key); found {
|
||||
return x.(path.Path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c cacheHandler) SetLocalPath(e echo.Context, path string) {
|
||||
key := cacheKey(e, "localPath")
|
||||
ccref.Paths.Set(key, path, cache.DefaultExpiration)
|
||||
}
|
||||
|
||||
func (c cacheHandler) SetRemoteCID(e echo.Context, path path.Path) {
|
||||
key := cacheKey(e, "remoteCID")
|
||||
ccref.CIDs.Set(key, path, cache.DefaultExpiration)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"github.com/onsonr/hway/pkg/vault/handlers"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func RegisterAPI(e *echo.Echo) {
|
||||
e.GET("/api/register/{handle}/start", handlers.Register.Start)
|
||||
e.POST("/api/register/finish", handlers.Register.Finish)
|
||||
}
|
||||
|
||||
func RegisterOpenIDProvider(e *echo.Echo) {
|
||||
}
|
||||
|
||||
func RegisterPages(e *echo.Echo) {
|
||||
e.GET("/", handlers.Session.Page)
|
||||
e.GET("/login", handlers.Login.Page)
|
||||
e.GET("/register", handlers.Register.FormPage)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/onsonr/hway/pkg/vault/middleware"
|
||||
"github.com/onsonr/hway/pkg/vault/routes"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func Serve(ctx context.Context) {
|
||||
// Configure the server
|
||||
e := echo.New()
|
||||
|
||||
// Use Middlewares
|
||||
e.Use(middleware.SessionCookies)
|
||||
e.Use(middleware.CacheStores)
|
||||
|
||||
// Setup routes
|
||||
routes.RegisterPages(e)
|
||||
routes.RegisterAPI(e)
|
||||
|
||||
// Run the server
|
||||
ctx, stop := signal.NotifyContext(ctx, os.Interrupt)
|
||||
defer stop()
|
||||
// Start server
|
||||
go func() {
|
||||
if err := e.Start(":1323"); err != nil && err != http.ErrServerClosed {
|
||||
e.Logger.Fatal("shutting down the server")
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for interrupt signal to gracefully shutdown the server with a timeout of 10 seconds.
|
||||
<-ctx.Done()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := e.Shutdown(ctx); err != nil {
|
||||
e.Logger.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
)
|
||||
|
||||
// File represents a file in the filesystem
|
||||
type File string
|
||||
|
||||
// NewFile creates a new File instance
|
||||
func NewFile(path string) File {
|
||||
return File(path)
|
||||
}
|
||||
|
||||
// Name returns the name of the file
|
||||
func (f File) Name() string {
|
||||
return filepath.Base(string(f))
|
||||
}
|
||||
|
||||
// Path returns the path of the file
|
||||
func (f File) Path() string {
|
||||
return string(f)
|
||||
}
|
||||
|
||||
// Read reads the contents of the file
|
||||
func (f File) Read() ([]byte, error) {
|
||||
return os.ReadFile(string(f))
|
||||
}
|
||||
|
||||
// Write writes data to the file, but throws an error if the file already exists
|
||||
func (f File) Write(data []byte) error {
|
||||
if f.Exists() {
|
||||
return fmt.Errorf("file already exists: %s", f)
|
||||
}
|
||||
return os.WriteFile(string(f), data, 0644)
|
||||
}
|
||||
|
||||
// Append appends data to the file
|
||||
func (f File) Append(data []byte) error {
|
||||
file, err := os.OpenFile(string(f), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = file.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Overwrite deletes all data for the file at path if it exists and writes the new data
|
||||
func (f File) Overwrite(data []byte) error {
|
||||
// If the file exists, remove it first
|
||||
if f.Exists() {
|
||||
if err := f.Remove(); err != nil {
|
||||
return fmt.Errorf("failed to remove existing file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Write the new data
|
||||
return os.WriteFile(string(f), data, 0644)
|
||||
}
|
||||
|
||||
// Exists checks if the file exists
|
||||
func (f File) Exists() bool {
|
||||
_, err := os.Stat(string(f))
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
// Remove removes the file
|
||||
func (f File) Remove() error {
|
||||
return os.Remove(string(f))
|
||||
}
|
||||
|
||||
// Stat returns the FileInfo for the file
|
||||
func (f File) Stat() (os.FileInfo, error) {
|
||||
return os.Stat(string(f))
|
||||
}
|
||||
|
||||
// Open opens the file and returns an fs.File
|
||||
func (f File) Open() (fs.File, error) {
|
||||
return os.Open(string(f))
|
||||
}
|
||||
|
||||
// Node returns a files.Node representation of the file
|
||||
func (f File) Node() (files.Node, error) {
|
||||
file, err := os.Open(string(f))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files.NewReaderFile(file), nil
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
)
|
||||
|
||||
// Folder represents a folder in the filesystem
|
||||
type Folder string
|
||||
|
||||
// NewFolder creates a new Folder instance
|
||||
func NewFolder(path string) Folder {
|
||||
return Folder(path)
|
||||
}
|
||||
|
||||
// Name returns the name of the folder
|
||||
func (f Folder) Name() string {
|
||||
return filepath.Base(string(f))
|
||||
}
|
||||
|
||||
// Path returns the path of the folder
|
||||
func (f Folder) Path() string {
|
||||
return string(f)
|
||||
}
|
||||
|
||||
// Create creates the folder if it doesn't exist
|
||||
func (f Folder) Create() error {
|
||||
return os.MkdirAll(string(f), os.ModePerm)
|
||||
}
|
||||
|
||||
// Exists checks if the folder exists
|
||||
func (f Folder) Exists() bool {
|
||||
info, err := os.Stat(string(f))
|
||||
return err == nil && info.IsDir()
|
||||
}
|
||||
|
||||
// Ls lists the contents of the folder
|
||||
func (f Folder) Ls() ([]fs.DirEntry, error) {
|
||||
return os.ReadDir(string(f))
|
||||
}
|
||||
|
||||
// WriteFile writes data to a file in the folder
|
||||
func (f Folder) WriteFile(name string, data []byte, perm os.FileMode) (File, error) {
|
||||
err := os.WriteFile(filepath.Join(string(f), name), data, perm)
|
||||
return File(filepath.Join(string(f), name)), err
|
||||
}
|
||||
|
||||
// ReadFile reads the contents of a file in the folder
|
||||
func (f Folder) ReadFile(name string) ([]byte, error) {
|
||||
return os.ReadFile(filepath.Join(string(f), name))
|
||||
}
|
||||
|
||||
// DeleteFile deletes a file from the folder
|
||||
func (f Folder) DeleteFile(name string) error {
|
||||
return os.Remove(filepath.Join(string(f), name))
|
||||
}
|
||||
|
||||
// Remove removes the folder and its contents
|
||||
func (f Folder) Remove() error {
|
||||
return os.RemoveAll(string(f))
|
||||
}
|
||||
|
||||
// Join joins the folder path with the given elements
|
||||
func (f Folder) Join(elem ...string) Folder {
|
||||
return Folder(filepath.Join(append([]string{string(f)}, elem...)...))
|
||||
}
|
||||
|
||||
// IsDir checks if the folder is a directory
|
||||
func (f Folder) IsDir() bool {
|
||||
info, err := os.Stat(string(f))
|
||||
return err == nil && info.IsDir()
|
||||
}
|
||||
|
||||
// Touch creates an empty file if it doesn't exist, or updates its access and modification times if it does
|
||||
func (f Folder) Touch(name string) (File, error) {
|
||||
var err error
|
||||
filePath := filepath.Join(string(f), name)
|
||||
_, err = os.Stat(filePath)
|
||||
if os.IsNotExist(err) {
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return File(filePath), err
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return File(filePath), err
|
||||
}
|
||||
return File(filePath), nil
|
||||
}
|
||||
return File(filePath), err
|
||||
}
|
||||
|
||||
// Node returns a files.Node representation of the folder
|
||||
func (f Folder) Node() (files.Node, error) {
|
||||
entries, err := f.Ls()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dirEntries := make([]files.DirEntry, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
subFolder := f.Join(entry.Name())
|
||||
subNode, err := subFolder.Node()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dirEntries = append(dirEntries, files.FileEntry(entry.Name(), subNode))
|
||||
} else {
|
||||
file := File(filepath.Join(string(f), entry.Name()))
|
||||
fileNode, err := file.Node()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dirEntries = append(dirEntries, files.FileEntry(entry.Name(), fileNode))
|
||||
}
|
||||
}
|
||||
return files.NewSliceDirectory(dirEntries), nil
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/onsonr/hway/internal/env"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/ipfs/kubo/core/coreiface/options"
|
||||
)
|
||||
|
||||
// Constant for the name of the folder where the vaults are stored
|
||||
const kVaultsFolderName = ".sonr-vaults"
|
||||
|
||||
// enclaveRoot is the folder where the vaults are stored
|
||||
var enclaveRoot Folder
|
||||
|
||||
// Package initializes the VaultsFolder
|
||||
func init() {
|
||||
// Initialize VaultsFolder
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create the folder if it does not exist
|
||||
enclaveRoot = NewFolder(filepath.Join(homeDir, kVaultsFolderName))
|
||||
if !enclaveRoot.Exists() {
|
||||
if err := enclaveRoot.Create(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewVaultFolder creates a new folder under the VaultsFolder directory
|
||||
func NewVaultFolder(name string) (Folder, error) {
|
||||
vaultFolder := enclaveRoot.Join(name)
|
||||
err := vaultFolder.Create()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return vaultFolder, nil
|
||||
}
|
||||
|
||||
// SaveToIPFS saves the Folder to IPFS and returns the IPFS path
|
||||
func SyncFolderToIPFS(ctx context.Context, f Folder) (path.Path, error) {
|
||||
node, err := f.Node()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := env.GetIPFSClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path, err := c.Unixfs().Add(ctx, node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return path, nil
|
||||
}
|
||||
|
||||
// PublishToIPNS publishes the Folder to IPNS
|
||||
func PublishToIPNS(ctx context.Context, ipfsPath path.Path, f Folder) error {
|
||||
c, err := env.GetIPFSClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = c.Name().Publish(ctx, ipfsPath, options.Name.Key(f.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadFromIPFS loads a Folder from IPFS
|
||||
func LoadFromIPFS(ctx context.Context, path string) (Folder, error) {
|
||||
c, err := env.GetIPFSClient()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cid, err := ParsePath(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
node, err := c.Unixfs().Get(ctx, cid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return LoadNodeInFolder(path, node)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/boxo/path"
|
||||
)
|
||||
|
||||
// Helper function to parse IPFS path
|
||||
func ParsePath(p string) (path.Path, error) {
|
||||
return path.NewPath(p)
|
||||
}
|
||||
|
||||
// FetchVaultPath returns the path to the vault with the given name
|
||||
func FetchVaultPath(name string) string {
|
||||
return enclaveRoot.Join(name).Path()
|
||||
}
|
||||
|
||||
// LoadNodeInFolder loads an IPFS node into a Folder
|
||||
func LoadNodeInFolder(path string, node files.Node) (Folder, error) {
|
||||
folder := NewFolder(path)
|
||||
if err := folder.Create(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch n := node.(type) {
|
||||
case files.File:
|
||||
f, err := os.Create(folder.Path())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := io.Copy(f, n); err != nil {
|
||||
return "", err
|
||||
}
|
||||
case files.Directory:
|
||||
entries := n.Entries()
|
||||
for entries.Next() {
|
||||
name := entries.Name()
|
||||
childNode := entries.Node()
|
||||
childPath := filepath.Join(folder.Path(), name)
|
||||
if _, err := LoadNodeInFolder(childPath, childNode); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if entries.Err() != nil {
|
||||
return "", entries.Err()
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported node type: %T", n)
|
||||
}
|
||||
|
||||
return folder, nil
|
||||
}
|
||||
Reference in New Issue
Block a user