package towndb import ( "database/sql" "time" _ "github.com/mattn/go-sqlite3" ) const dsn = "/town/var/town.db?mode=rw" type UserState string const ( StateActive = "active" StateTempBan = "temp_banned" StateBan = "banned" StateDeleted = "deleted" // some users request deletion ) type AdminNote struct { ID int64 Created time.Time AuthorID int64 Content string UserID int64 } func (n *AdminNote) Insert(db *sql.DB) error { n.Created = time.Now() stmt, err := db.Prepare(` INSERT INTO notes (created, authorid, content, userid) VALUES ( ?, ?, ?, ? )`) if err != nil { return err } result, err := stmt.Exec( n.Created.Unix(), n.AuthorID, n.Content, n.UserID) if err != nil { return err } defer stmt.Close() liid, err := result.LastInsertId() if err != nil { return err } n.ID = liid return nil } type TownUser struct { ID int64 Created time.Time Emails []string Username string Notes []AdminNote State UserState IsAdmin bool } func (u *TownUser) Insert(db *sql.DB) (err error) { var tx *sql.Tx var stmt *sql.Stmt var result sql.Result var liid int64 if tx, err = db.Begin(); err != nil { return err } defer func() { if err != nil { tx.Rollback() } }() // 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() if stmt, err = tx.Prepare(` INSERT INTO users (created, username, state) VALUES (?, ?, ?)`); err != nil { return err } if result, err = stmt.Exec( u.Created.Unix(), u.Username, u.State); err != nil { return err } if liid, err = result.LastInsertId(); err != nil { return err } u.ID = liid if len(u.Emails) > 0 { for _, e := range u.Emails { if stmt, err = tx.Prepare(` INSERT INTO emails (address, userid) VALUES (?, ?)`); err != nil { return err } if result, err = stmt.Exec(e, u.ID); err != nil { return err } } } return tx.Commit() } func ConnectDB() (*sql.DB, error) { db, err := sql.Open("sqlite3", dsn) if err != nil { return nil, err } return db, nil }