scsusers/main.go

158 lines
3.7 KiB
Go

package scsusers
import (
"database/sql"
"fmt"
"html/template"
"log"
"strings"
"github.com/jmoiron/sqlx"
"golang.org/x/crypto/bcrypt"
)
type templates struct {
Registration *template.Template
Alert *template.Template
Recovery *template.Template
TwoFA *template.Template
}
type config struct {
SiteName string
FromEmail string
Templates templates
SMTPServer string
db *sqlx.DB
testing bool
TablePrefix string
}
type UserData struct {
UserID int64 `db:"id"`
Username string `db:"username"`
Password string `db:"password"`
Meta map[string]metadata
}
type metadata struct {
Key string `db:"meta_key"`
Value string `db:"meta_value"`
ID int64 `db:"id"`
}
var c config
func Init(dbin *sqlx.DB, tp, sitename, fromaddr, smtpserver string) {
c.db = dbin
c.TablePrefix = tp
c.SiteName = sitename
c.FromEmail = fromaddr
c.SMTPServer = smtpserver
SetRegistrationTemplate("")
SetAlertTemplate("")
SetRecoveryTemplate("")
Set2faTemplate("")
}
func UsernameAvailable(username string) bool {
if len(username) == 0 {
return false
}
var tmp string
username = strings.ToLower(username)
q := fmt.Sprintf("select username from %s_auth where username = ?", c.TablePrefix)
err := c.db.Get(&tmp, q, username)
if err == sql.ErrNoRows {
return true
}
if err != nil {
log.Printf("UsernameAvailable returned error: " + err.Error() + " Query was " + q)
return false
}
return false
}
/* Check for username availability, add to database, send email */
func Register(username, email, ip string) bool {
if !UsernameAvailable(username) {
return false
}
username = strings.ToLower(username)
pass := randBytes(16)
crypt, err := bcrypt.GenerateFromPassword(pass, 10)
if err != nil {
log.Printf("scsusers.Register: Bcrypt GenerateFromPassword failed? Pass is %s and error is %s\n", pass, err.Error())
return false
}
_, err = c.db.Query(fmt.Sprintf("insert into %s_auth (username, password) VALUES (?,?)", c.TablePrefix), username, crypt)
if err != nil {
log.Printf("scsusers.Register: insert failed: %s\n", err.Error())
return false
}
if c.testing {
return true
}
if SendRegistrationEmail(email, username, string(pass)) {
log.Printf("scsusers.Register: New user registration: %s from %s\n", username, ip)
return true
}
log.Printf("scsusers.Register: Failed to send registration email, deleting user %s\n", username)
q := fmt.Sprintf("delete from %s_auth where username = ? AND password=?", c.TablePrefix)
_, err = c.db.Exec(q, username, string(crypt))
if err != nil {
log.Printf("scsusers.Register: Failed to delete new user %s: %s\n", username, err.Error())
}
return false
}
func NewUser() *UserData {
var u UserData
u.Meta = make(map[string]metadata)
return &u
}
func Get(username string) (*UserData, bool) {
u := NewUser()
q := fmt.Sprintf("select username, password, id from %s_auth where username=?", c.TablePrefix)
err := c.db.Get(u, q, username)
if err != nil {
if err == sql.ErrNoRows {
return nil, false
}
log.Printf("scsusers.Get: %s", err.Error())
return nil, false
}
q = fmt.Sprintf("select meta_key, meta_value, id from %s_meta where user=?", c.TablePrefix)
rows, err := c.db.Query(q, u.UserID)
if err != nil && err != sql.ErrNoRows {
log.Printf("scsuser.Get: select: %s", err.Error())
return u, false
}
for rows.Next() {
var m metadata
rows.Scan(m.Key, m.Value, m.ID)
u.Meta[m.Key] = m
}
return u, true
}
func GetUserid(username string) int64 {
var i int64
username = strings.ToLower(username)
q := fmt.Sprintf("select userid from %s_auth where username = ?", c.TablePrefix)
err := c.db.Get(&i, q, username)
if err != nil {
log.Printf("scsusers.getUserId: Error loading user: %s : %s\n", username, err.Error())
return 0
}
return i
}