Initial commit
This commit is contained in:
commit
dc8a638814
4 changed files with 209 additions and 0 deletions
31
db.go
Normal file
31
db.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// External
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
// Standard
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
db *sqlx.DB
|
||||
)
|
||||
|
||||
func initDB(host string, port int, dbName, username, password string) (err error) { // {{{
|
||||
dbConn := fmt.Sprintf(
|
||||
"host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
dbName,
|
||||
)
|
||||
|
||||
if db, err = sqlx.Connect("postgres", dbConn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
} // }}}
|
||||
9
go.mod
Normal file
9
go.mod
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
module nodebb_invite_link
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/lib/pq v1.10.9
|
||||
)
|
||||
12
go.sum
Normal file
12
go.sum
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
157
main.go
Normal file
157
main.go
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// External
|
||||
"github.com/google/uuid"
|
||||
|
||||
// Standard
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const VERSION = "v1"
|
||||
|
||||
var (
|
||||
flagVersion bool
|
||||
flagHost string
|
||||
flagPort int
|
||||
flagUsername string
|
||||
flagPassword string
|
||||
flagDatabase string
|
||||
flagListenPort int
|
||||
flagSequenceFilename string
|
||||
flagDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&flagVersion, "version", false, "Display version and exit")
|
||||
flag.StringVar(&flagHost, "host", "", "Database host")
|
||||
flag.StringVar(&flagUsername, "username", "", "Database username")
|
||||
flag.StringVar(&flagPassword, "password", "", "Database password")
|
||||
flag.StringVar(&flagDatabase, "database", "", "Database name")
|
||||
flag.IntVar(&flagPort, "port", 5432, "Database port")
|
||||
flag.IntVar(&flagListenPort, "listen", 9876, "Web server listen port")
|
||||
flag.StringVar(&flagSequenceFilename, "seq", "sequence", "Sequence filename")
|
||||
flag.StringVar(&flagDomain, "domain", "", "Domain FQDN")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := initDB(flagHost, flagPort, flagDatabase, flagUsername, flagPassword)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
listenOn := fmt.Sprintf("[::]:%d", flagListenPort)
|
||||
http.HandleFunc("/invite", createInvite)
|
||||
fmt.Printf("Listen on %s\n", listenOn)
|
||||
err = http.ListenAndServe(listenOn, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func sequenceNext() (seq int, err error) {
|
||||
var contents []byte
|
||||
var oldSequence int
|
||||
contents, err = os.ReadFile(flagSequenceFilename)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
oldSequence = 0
|
||||
} else {
|
||||
fixedContents := strings.TrimSpace(string(contents))
|
||||
oldSequence, err = strconv.Atoi(fixedContents)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
seq = oldSequence + 1
|
||||
err = os.WriteFile(flagSequenceFilename, []byte(strconv.Itoa(seq)), 0644)
|
||||
return
|
||||
}
|
||||
|
||||
func createInvite(w http.ResponseWriter, r *http.Request) {
|
||||
seq, err := sequenceNext()
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
newUUID := uuid.NewString()
|
||||
email := fmt.Sprintf("%08d@example.com", seq)
|
||||
expire := time.Now().Add(time.Hour * 24 * 7)
|
||||
|
||||
// legacy_object
|
||||
key := fmt.Sprintf("invitation:uid:2:invited:%s", email)
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_object(_key, "type", "expireAt") VALUES($1, 'string', null)`, key)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
key = fmt.Sprintf("invitation:invited:%s", email)
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_object(_key, "type", "expireAt") VALUES($1, 'set', null)`, key)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
key = fmt.Sprintf("invitation:token:%s", newUUID)
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_object(_key, "type", "expireAt") VALUES($1, 'hash', $2)`, key, expire)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// legacy_hash
|
||||
key = fmt.Sprintf("invitation:token:%s", newUUID)
|
||||
data := fmt.Sprintf(`{"email": "%s", "token": "%s", "inviter": 2, "groupsToJoin": "[]"}`, email, newUUID)
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_hash(_key, "data", "type") VALUES($1, $2, 'hash')`, key, data)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// legacy_set
|
||||
key = fmt.Sprintf("invitation:uid:2")
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_set(_key, "member", "type") VALUES($1, $2, 'set')`, key, email)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
key = fmt.Sprintf("invitation:invited:%s", email)
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_set(_key, "member", "type") VALUES($1, $2, 'set')`, key, newUUID)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
key = fmt.Sprintf("invitation:uid:2:invited:%s", email)
|
||||
_, err = db.Exec(` INSERT INTO public.legacy_string(_key, "data", "type") VALUES($1, $2, 'string')`, key, newUUID)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
j, _ := json.Marshal(struct {
|
||||
Link string
|
||||
}{
|
||||
fmt.Sprintf("https://%s/register?token=%s", flagDomain, newUUID),
|
||||
})
|
||||
w.Write(j)
|
||||
|
||||
return
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue