welcome working end to end

pull/1/head
vilmibm 2023-03-06 20:34:29 +00:00
parent 92807f9b6b
commit 57115b1c11
6 changed files with 57 additions and 50 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ cmd/signup/signup
cmd/review/review cmd/review/review
cmd/welcome/welcome cmd/welcome/welcome
cmd/createkeyfile/createkeyfile cmd/createkeyfile/createkeyfile
cmd/registeruser/registeruser

View File

@ -26,36 +26,36 @@ import (
const keyfileName = "authorized_keys2" const keyfileName = "authorized_keys2"
func quit(msg string) { func quit(msg string, code int) {
fmt.Println(msg) fmt.Println(msg)
os.Exit(1) os.Exit(code)
} }
func main() { func main() {
username := os.Args[1] username := os.Args[1]
if username == "" { if username == "" {
quit("expected username as argument") quit("expected username as argument", 1)
} }
u, err := user.Current() u, err := user.Current()
if err != nil { if err != nil {
quit(err.Error()) quit(err.Error(), 2)
} }
if u.Username != username { if u.Username != username {
quit("that's my purse; I don't know you") quit("that's my purse; I don't know you", 3)
} }
sshPath := path.Join("/home", u.Username, ".ssh") sshPath := path.Join("/home", u.Username, ".ssh")
keyfilePath := path.Join(sshPath, keyfileName) keyfilePath := path.Join(sshPath, keyfileName)
if err = os.Mkdir(sshPath, os.FileMode(0700)); err != nil { if err = os.Mkdir(sshPath, os.FileMode(0700)); err != nil {
quit(err.Error()) quit(err.Error(), 4)
} }
f, err := os.OpenFile(keyfilePath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600) f, err := os.OpenFile(keyfilePath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600)
if err != nil { if err != nil {
quit(fmt.Sprintf("failed to open %s: %s", keyfilePath, err.Error())) quit(fmt.Sprintf("failed to open %s: %s", keyfilePath, err.Error()), 5)
} }
defer f.Close() defer f.Close()
@ -64,23 +64,23 @@ func main() {
n, err := os.Stdin.Read(stdin) n, err := os.Stdin.Read(stdin)
if err != nil { if err != nil {
quit(err.Error()) quit(err.Error(), 6)
} else if n == 0 { } else if n == 0 {
quit("nothing passed on STDIN") quit("nothing passed on STDIN", 7)
} }
stdin = stdin[0:n] stdin = stdin[0:n]
if !strings.HasPrefix(string(stdin), "########## GREETINGS! ##########") { if !strings.HasPrefix(string(stdin), "########## GREETINGS! ##########") {
// TODO further validation? // TODO further validation?
quit(fmt.Sprintf("file contents look wrong: %s", string(stdin))) quit(fmt.Sprintf("file contents look wrong: %s", string(stdin)), 8)
} }
n, err = f.Write(stdin) n, err = f.Write(stdin)
if err != nil { if err != nil {
quit(err.Error()) quit(err.Error(), 9)
} else if n == 0 { } else if n == 0 {
quit("wrote nothing to keyfile") quit("wrote nothing to keyfile", 10)
} }
} }

View File

@ -1,13 +1,12 @@
package main package main
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"os" "os"
_ "github.com/mattn/go-sqlite3" // _ "github.com/mattn/go-sqlite3"
"git.tilde.town/tildetown/town/towndb" "git.tilde.town/tildetown/town/towndb"
) )
@ -15,7 +14,31 @@ import (
// this command adds a new user to /town/var/town.db. it's meant to be invoked // this command adds a new user to /town/var/town.db. it's meant to be invoked
// by the welcome binary upon successfully creating a new user account // by the welcome binary upon successfully creating a new user account
func _main(tdb *sql.DB, userData towndb.TownUser) error { func main() {
tdb, err := towndb.ConnectDB()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
userData, err := parseInput(os.Stdin)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(2)
}
if err = validateInput(userData); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(3)
}
if err = userData.Insert(tdb); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(4)
}
}
func validateInput(userData towndb.TownUser) error {
if userData.Username == "" { if userData.Username == "" {
return errors.New("no username") return errors.New("no username")
} }
@ -38,7 +61,7 @@ func _main(tdb *sql.DB, userData towndb.TownUser) error {
return errors.New("bad state") return errors.New("bad state")
} }
return userData.Insert(tdb) return nil
} }
func parseInput(stdin *os.File) (u towndb.TownUser, err error) { func parseInput(stdin *os.File) (u towndb.TownUser, err error) {
@ -54,22 +77,3 @@ func parseInput(stdin *os.File) (u towndb.TownUser, err error) {
err = json.Unmarshal(input[0:n], &u) err = json.Unmarshal(input[0:n], &u)
return return
} }
func main() {
tdb, err := towndb.ConnectDB()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
userData, err := parseInput(os.Stdin)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
if err = _main(tdb, userData); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(3)
}
}

View File

@ -153,8 +153,10 @@ func createUser(data newUserData) (err error) {
cmd = exec.Command("sudo", "--user", data.Username, "/town/bin/createkeyfile", data.Username) cmd = exec.Command("sudo", "--user", data.Username, "/town/bin/createkeyfile", data.Username)
cmd.Stdin = bytes.NewBufferString(keyfileText(data)) cmd.Stdin = bytes.NewBufferString(keyfileText(data))
stdoutBuff := bytes.NewBuffer([]byte{})
cmd.Stdout = stdoutBuff
if err = cmd.Run(); err != nil { if err = cmd.Run(); err != nil {
return fmt.Errorf("createkeyfile failed: %w", err) return fmt.Errorf("createkeyfile failed with '%s': %w", string(stdoutBuff.Bytes()), err)
} }
cmd = exec.Command("sudo", "/town/bin/generate_welcome_present.sh", data.Username) cmd = exec.Command("sudo", "/town/bin/generate_welcome_present.sh", data.Username)
@ -162,7 +164,6 @@ func createUser(data newUserData) (err error) {
// TODO log this. no reason to bail out. // TODO log this. no reason to bail out.
} }
cmd = exec.Command("sudo", "/town/bin/registeruser")
tu := towndb.TownUser{ tu := towndb.TownUser{
Username: data.Username, Username: data.Username,
Emails: []string{ Emails: []string{
@ -174,9 +175,12 @@ func createUser(data newUserData) (err error) {
if out, err = json.Marshal(tu); err != nil { if out, err = json.Marshal(tu); err != nil {
return fmt.Errorf("could not serialize user data: %w", err) return fmt.Errorf("could not serialize user data: %w", err)
} }
cmd = exec.Command("sudo", "/town/bin/registeruser")
stderrBuff := bytes.NewBuffer([]byte{})
cmd.Stderr = stderrBuff
cmd.Stdin = bytes.NewBuffer(out) cmd.Stdin = bytes.NewBuffer(out)
if err = cmd.Run(); err != nil { if err = cmd.Run(); err != nil {
return fmt.Errorf("register user failed: %w", err) return fmt.Errorf("register user failed with '%s': %w", string(stderrBuff.Bytes()), err)
} }
return nil return nil

View File

@ -2,11 +2,8 @@ CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
created TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M', 'now', 'localtime')), created TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M', 'now', 'localtime')),
username TEXT UNIQUE, username TEXT UNIQUE,
signupid INTEGER,
state TEXT, state TEXT,
admin INTEGER DEFAULT FALSE, admin INTEGER DEFAULT 0
FOREIGN KEY (signupid) REFERENCES signups(signupid)
); );
-- TODO address /should/ be unique but leaving it duplicable for now since i can think of some cases where there might be >1 account for the same human -- TODO address /should/ be unique but leaving it duplicable for now since i can think of some cases where there might be >1 account for the same human
@ -33,5 +30,5 @@ CREATE TABLE IF NOT EXISTS notes (
content TEXT, content TEXT,
created TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M', 'now', 'localtime')), created TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M', 'now', 'localtime')),
FOREIGN KEY (adminid) REFERENCES users(adminid) FOREIGN KEY (author) REFERENCES users(author)
); );

View File

@ -83,18 +83,21 @@ func (u *TownUser) Insert(db *sql.DB) (err error) {
} }
}() }()
// TODO this does not set the admin flag intentionally as rn this code is
// just meant to be called by the welcome binary; other stuff for now is just
// expected to be done via sql
u.Created = time.Now() u.Created = time.Now()
if stmt, err = tx.Prepare(` if stmt, err = tx.Prepare(`
INSERT INTO notes (created, username, state, admin) INSERT INTO users (created, username, state)
VALUES ( ?, ?, ?, ?)`); err != nil { VALUES (?, ?, ?)`); err != nil {
return err return err
} }
if result, err = stmt.Exec( if result, err = stmt.Exec(
u.Created.Unix(), u.Created.Unix(),
u.Username, u.Username,
u.State, u.State); err != nil {
u.IsAdmin); err != nil {
return err return err
} }
@ -117,9 +120,7 @@ func (u *TownUser) Insert(db *sql.DB) (err error) {
} }
} }
tx.Commit() return tx.Commit()
return nil
} }
func ConnectDB() (*sql.DB, error) { func ConnectDB() (*sql.DB, error) {