From d5aff6fc8364a3257d8e88b9c4906a6e3efcd666 Mon Sep 17 00:00:00 2001 From: vilmibm Date: Sun, 26 Feb 2023 23:02:51 +0000 Subject: [PATCH] generate invites on acceptance --- cmd/review/main.go | 26 ++++++++++--------- invites/invites.go | 62 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/cmd/review/main.go b/cmd/review/main.go index f89667b..14fe877 100644 --- a/cmd/review/main.go +++ b/cmd/review/main.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "git.tilde.town/tildetown/town/invites" "git.tilde.town/tildetown/town/models" "git.tilde.town/tildetown/town/signup" tuser "git.tilde.town/tildetown/town/user" @@ -88,13 +89,10 @@ func renderNotes(s models.TownSignup) string { } func _main() error { - /* - TODO will use this for invites - userDB, err := review.ConnectDB() - if err != nil { - return fmt.Errorf("could not connect to user database: %w", err) - } - */ + inviteDB, err := invites.ConnectDB() + if err != nil { + return fmt.Errorf("could not connect to invites database: %w", err) + } signupDB, err := signup.ConnectDB() if err != nil { @@ -145,11 +143,10 @@ func _main() error { count := tview.NewTextView() count.SetDynamicColors(true) updateCount := func() { - plural := "s" - if len(signups) == 1 { - plural = "" + count.SetText(fmt.Sprintf("[-:-:b]%d of %d[-:-:-]", signupIx+1, len(signups))) + if len(signups) == 0 { + count.SetText("") } - count.SetText(fmt.Sprintf("[-:-:b]%d of %d %s[-:-:-]", signupIx+1, len(signups), plural)) } updateCount() @@ -266,7 +263,12 @@ func _main() error { updateCount() render() if decision == models.SignupAccepted { - // TODO generate invite token + err = invites.InsertInvite(inviteDB, currSignup.CleanEmail) + if err != nil { + errorModal.SetText(fmt.Sprintf("error! failed to create invite: %s", err.Error())) + pages.SwitchToPage("error") + } + // TODO send invite email } pages.SwitchToPage("main") diff --git a/invites/invites.go b/invites/invites.go index 1011c91..ad144c7 100644 --- a/invites/invites.go +++ b/invites/invites.go @@ -2,10 +2,18 @@ package invites import ( "database/sql" + "encoding/base64" + "math/rand" + "strings" + "time" + _ "github.com/mattn/go-sqlite3" ) -const dsn = "/town/var/invites/invites.db?mode=rw" +const ( + dsn = "/town/var/invites/invites.db?mode=rw" + codeLen = 32 +) func ConnectDB() (*sql.DB, error) { db, err := sql.Open("sqlite3", dsn) @@ -15,3 +23,55 @@ func ConnectDB() (*sql.DB, error) { return db, nil } + +func generateCode(email string) string { + rand.Seed(time.Now().Unix()) + + charset := "abcdefghijklmnopqrztuvwxyz" + charset += strings.ToUpper(charset) + charset += "0123456789" + charset += "`~!@#$%^&*()-=_+[]{}|;:,./<>?" + + code := []byte{} + + for len(code) < codeLen { + code = append(code, charset[rand.Intn(len(charset))]) + } + + code = append(code, ' ') + + eb := []byte(email) + for x := 0; x < len(eb); x++ { + code = append(code, eb[x]) + } + + return base64.StdEncoding.EncodeToString(code) +} + +func Decode(code string) ([]string, error) { + decoded, err := base64.StdEncoding.DecodeString(code) + if err != nil { + return nil, err + } + + return strings.Split(string(decoded), " "), nil +} + +func InsertInvite(db *sql.DB, email string) error { + stmt, err := db.Prepare(` + INSERT INTO invites (code, email) VALUES (?, ?) + `) + if err != nil { + return err + } + + _, err = stmt.Exec(generateCode(email), email) + if err != nil { + return err + } + defer stmt.Close() + + return nil +} + +// TODO decide on rest of API (eg Validate, Use, Get, etc)