mirror of
https://github.com/aljazceru/satdress.git
synced 2025-12-17 05:24:20 +01:00
support changing usernames with pins.
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
|||||||
satdress: $(shell find . -name "*.go")
|
satdress: $(shell find . -name "*.go") index.html go.mod
|
||||||
CC=$$(which musl-gcc) go build -ldflags='-s -w -linkmode external -extldflags "-static"' -o ./satdress
|
CC=$$(which musl-gcc) go build -ldflags='-s -w -linkmode external -extldflags "-static"' -o ./satdress
|
||||||
|
|
||||||
deploy: satdress
|
deploy: satdress
|
||||||
|
|||||||
53
db.go
53
db.go
@@ -1,5 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cockroachdb/pebble"
|
||||||
|
)
|
||||||
|
|
||||||
type Params struct {
|
type Params struct {
|
||||||
Name string
|
Name string
|
||||||
Kind string
|
Kind string
|
||||||
@@ -8,3 +19,45 @@ type Params struct {
|
|||||||
Pak string
|
Pak string
|
||||||
Waki string
|
Waki string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SaveName(name string, params *Params, providedPin string) (pin string, err error) {
|
||||||
|
key := []byte(name + "@" + s.Domain)
|
||||||
|
|
||||||
|
mac := hmac.New(sha256.New, []byte(s.Secret))
|
||||||
|
mac.Write(key)
|
||||||
|
pin = hex.EncodeToString(mac.Sum(nil))
|
||||||
|
|
||||||
|
if _, closer, err := db.Get(key); err == nil {
|
||||||
|
defer closer.Close()
|
||||||
|
if pin != providedPin {
|
||||||
|
return "", errors.New("name already exists! must provide pin.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the given data works
|
||||||
|
if _, err := makeInvoice(params, 1000); err != nil {
|
||||||
|
return "", fmt.Errorf("couldn't make an invoice with the given data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// save it
|
||||||
|
data, _ := json.Marshal(params)
|
||||||
|
if err := db.Set(key, data, pebble.Sync); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pin, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetName(name string) (params *Params, err error) {
|
||||||
|
val, closer, err := db.Get([]byte(name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer closer.Close()
|
||||||
|
if err := json.Unmarshal(val, params); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Name = name
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -7,6 +7,7 @@ require (
|
|||||||
github.com/fiatjaf/go-lnurl v1.4.0
|
github.com/fiatjaf/go-lnurl v1.4.0
|
||||||
github.com/fiatjaf/makeinvoice v1.2.3
|
github.com/fiatjaf/makeinvoice v1.2.3
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
|
github.com/joho/godotenv v1.3.0 // indirect
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/lib/pq v1.10.2
|
github.com/lib/pq v1.10.2
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -203,6 +203,8 @@ github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH04
|
|||||||
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
|
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
|
||||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
|||||||
110
index.html
110
index.html
@@ -103,7 +103,17 @@
|
|||||||
background-color: rgba(86, 46, 249, 0.85);
|
background-color: rgba(86, 46, 249, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -147,11 +157,6 @@
|
|||||||
background-color: #f3f3f3;
|
background-color: #f3f3f3;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resources {
|
.resources {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -233,67 +238,79 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="description">Use the form below to connect your own node to a <b>Lightning Address</b>.</div>
|
<div class="description">Use the form below to connect your own node to a <b>Lightning Address</b>.</div>
|
||||||
<form action="/grab" method="post">
|
<form action="/grab" method="post">
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<div class="row" style="justify-content: space-between">
|
||||||
Desired Username
|
<label for="name">
|
||||||
</p>
|
Desired Username
|
||||||
|
</label>
|
||||||
|
<label style="float: right">
|
||||||
|
Is New?
|
||||||
|
<input type="checkbox" v-model="isNew">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div style="position: relative;">
|
<div style="position: relative;">
|
||||||
<input class="input" name="name">
|
<input class="input" name="name" id="name">
|
||||||
<span class="suffix" style="position: absolute;">@{{ domain }}</span>
|
<span class="suffix" style="position: absolute;">@{{ domain }}</span>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</div>
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="kind">
|
||||||
Node Backend Type
|
Node Backend Type
|
||||||
</p>
|
</label>
|
||||||
<select name="kind" v-model="kind">
|
<select name="kind" id="kind" id="kind" v-model="kind">
|
||||||
<option value="lnd">LND</option>
|
<option value="lnd">LND</option>
|
||||||
<option value="sparko">Sparko</option>
|
<option value="sparko">Sparko</option>
|
||||||
<option value="lnpay">LNPay</option>
|
<option value="lnpay">LNPay</option>
|
||||||
<option value="lnbits">LNbits</option>
|
<option value="lnbits">LNbits</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</div>
|
||||||
<div v-if="kind == 'lnd'">
|
<div v-if="kind == 'lnd'">
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="host">
|
||||||
Host (IP or Domain + Port)
|
Host (IP or Domain + Port)
|
||||||
</p>
|
</label>
|
||||||
<input class="input" name="host">
|
<input class="input" name="host" id="host">
|
||||||
</label>
|
</div>
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="key">
|
||||||
Invoice Macaroon
|
Invoice Macaroon
|
||||||
</p>
|
</label>
|
||||||
<input class="input" name="key">
|
<input class="input" name="key" id="key">
|
||||||
</label>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="kind == 'sparko' || kind == 'lnbits'">
|
<div v-if="kind == 'sparko' || kind == 'lnbits'">
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="host">
|
||||||
Host (IP or Domain + Port)
|
Host (IP or Domain + Port)
|
||||||
</p>
|
</label>
|
||||||
<input class="input" name="host">
|
<input class="input" name="host" id="host">
|
||||||
</label>
|
</div>
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="key">
|
||||||
Key
|
Key
|
||||||
</p>
|
</label>
|
||||||
<input class="input" name="key">
|
<input class="input" name="key" id="key">
|
||||||
</label>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="kind == 'lnpay'">
|
<div v-if="kind == 'lnpay'">
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="pak">
|
||||||
Public Access Key (pak)
|
Public Access Key (pak)
|
||||||
</p>
|
</label>
|
||||||
<input class="input" name="pak">
|
<input class="input" name="pak" id="pak">
|
||||||
</label>
|
</div>
|
||||||
<label>
|
<div class="field">
|
||||||
<p class="label">
|
<label for="waki">
|
||||||
Wallet Invoice Key (waki)
|
Wallet Invoice Key (waki)
|
||||||
</p>
|
</label>
|
||||||
<input class="input" name="waki">
|
<input class="input" name="waki" id="waki">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field" v-if="!isNew">
|
||||||
|
<label for="pin">
|
||||||
|
Pin
|
||||||
</label>
|
</label>
|
||||||
|
<input class="input" name="pin" id="pin">
|
||||||
</div>
|
</div>
|
||||||
<button class="submit">Submit</button>
|
<button class="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -323,6 +340,7 @@
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
kind: 'lnd',
|
kind: 'lnd',
|
||||||
|
isNew: true,
|
||||||
...initial,
|
...initial,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
lnurl.go
22
lnurl.go
@@ -6,7 +6,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/cockroachdb/pebble"
|
|
||||||
"github.com/fiatjaf/go-lnurl"
|
"github.com/fiatjaf/go-lnurl"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
@@ -14,25 +13,14 @@ import (
|
|||||||
func handleLNURL(w http.ResponseWriter, r *http.Request) {
|
func handleLNURL(w http.ResponseWriter, r *http.Request) {
|
||||||
username := mux.Vars(r)["username"]
|
username := mux.Vars(r)["username"]
|
||||||
|
|
||||||
log.Info().Str("username", username).Msg("got lnurl request")
|
params, err := GetName(username)
|
||||||
|
|
||||||
var params Params
|
|
||||||
val, closer, err := db.Get([]byte(username))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != pebble.ErrNotFound {
|
log.Error().Err(err).Str("name", username).Msg("failed to get name")
|
||||||
log.Error().Err(err).Str("name", username).
|
json.NewEncoder(w).Encode(lnurl.ErrorResponse(fmt.Sprintf(
|
||||||
Msg("error getting data")
|
"failed to get name %s", username)))
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer closer.Close()
|
|
||||||
if err := json.Unmarshal(val, ¶ms); err != nil {
|
|
||||||
log.Error().Err(err).Str("name", username).Str("data", string(val)).
|
|
||||||
Msg("got broken json from db")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
params.Name = username
|
log.Info().Str("username", username).Msg("got lnurl request")
|
||||||
|
|
||||||
if amount := r.URL.Query().Get("amount"); amount == "" {
|
if amount := r.URL.Query().Get("amount"); amount == "" {
|
||||||
// check if the receiver accepts comments
|
// check if the receiver accepts comments
|
||||||
|
|||||||
36
main.go
36
main.go
@@ -1,10 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha256"
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -78,41 +75,16 @@ func main() {
|
|||||||
|
|
||||||
router.Path("/grab").HandlerFunc(
|
router.Path("/grab").HandlerFunc(
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
name := []byte(r.FormValue("name") + "@" + s.Domain)
|
pin, err := SaveName(r.FormValue("name"), &Params{
|
||||||
|
|
||||||
mac := hmac.New(sha256.New, []byte(s.Secret))
|
|
||||||
mac.Write(name)
|
|
||||||
pin := hex.EncodeToString(mac.Sum(nil))
|
|
||||||
|
|
||||||
if _, closer, err := db.Get(name); err == nil {
|
|
||||||
w.WriteHeader(401)
|
|
||||||
fmt.Fprint(w,
|
|
||||||
"name already exists! must provide pin (contact support).")
|
|
||||||
return
|
|
||||||
} else if err == nil {
|
|
||||||
closer.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
params := Params{
|
|
||||||
Kind: r.FormValue("kind"),
|
Kind: r.FormValue("kind"),
|
||||||
Host: r.FormValue("host"),
|
Host: r.FormValue("host"),
|
||||||
Key: r.FormValue("key"),
|
Key: r.FormValue("key"),
|
||||||
Pak: r.FormValue("pak"),
|
Pak: r.FormValue("pak"),
|
||||||
Waki: r.FormValue("waki"),
|
Waki: r.FormValue("waki"),
|
||||||
}
|
}, r.FormValue("pin"))
|
||||||
|
if err != nil {
|
||||||
// check if the given data works
|
|
||||||
if _, err := makeInvoice(params, 1000); err != nil {
|
|
||||||
w.WriteHeader(400)
|
|
||||||
fmt.Fprint(w, "couldn't make an invoice with the given data: "+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// save it
|
|
||||||
data, _ := json.Marshal(params)
|
|
||||||
if err := db.Set(name, data, pebble.Sync); err != nil {
|
|
||||||
w.WriteHeader(500)
|
w.WriteHeader(500)
|
||||||
fmt.Fprint(w, "error! "+err.Error())
|
fmt.Fprint(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeMetadata(params Params) string {
|
func makeMetadata(params *Params) string {
|
||||||
metadata, _ := sjson.Set("[]", "0.0", "text/identifier")
|
metadata, _ := sjson.Set("[]", "0.0", "text/identifier")
|
||||||
metadata, _ = sjson.Set(metadata, "0.1", params.Name+"@"+s.Domain)
|
metadata, _ = sjson.Set(metadata, "0.1", params.Name+"@"+s.Domain)
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ func makeMetadata(params Params) string {
|
|||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeInvoice(params Params, msat int) (bolt11 string, err error) {
|
func makeInvoice(params *Params, msat int) (bolt11 string, err error) {
|
||||||
// description_hash
|
// description_hash
|
||||||
h := sha256.Sum256([]byte(makeMetadata(params)))
|
h := sha256.Sum256([]byte(makeMetadata(params)))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user