scsusers/main.go

188 lines
4.7 KiB
Go
Raw Permalink Normal View History

2018-12-25 19:22:13 +00:00
package scsusers
import (
"database/sql"
"fmt"
"html/template"
"log"
"strings"
2020-12-19 01:41:28 +00:00
"github.com/jmoiron/sqlx"
"golang.org/x/crypto/bcrypt"
2020-06-04 20:02:46 +00:00
)
2018-12-27 21:49:59 +00:00
2018-12-25 19:22:13 +00:00
type templates struct {
Registration *template.Template
Alert *template.Template
Recovery *template.Template
2023-09-26 20:45:19 +00:00
TwoFA *template.Template
2018-12-25 19:22:13 +00:00
}
type config struct {
SiteName string
FromEmail string
Templates templates
2020-06-04 20:02:46 +00:00
SMTPServer string
2018-12-25 19:22:13 +00:00
db *sqlx.DB
2024-01-02 15:13:52 +00:00
Testing bool
2018-12-25 19:22:13 +00:00
TablePrefix string
}
2018-12-28 19:33:36 +00:00
type UserData struct {
2023-09-19 22:01:41 +00:00
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"`
2018-12-28 19:33:36 +00:00
}
2018-12-25 19:22:13 +00:00
var c config
2024-01-02 15:15:57 +00:00
func Init(dbin *sqlx.DB, tp, sitename, fromaddr, smtpserver string, testing bool) {
2018-12-25 19:22:13 +00:00
c.db = dbin
c.TablePrefix = tp
c.SiteName = sitename
c.FromEmail = fromaddr
2020-06-04 20:02:46 +00:00
c.SMTPServer = smtpserver
2024-01-11 17:02:16 +00:00
c.Testing = testing
2018-12-25 19:22:13 +00:00
SetRegistrationTemplate("")
SetAlertTemplate("")
SetRecoveryTemplate("")
Set2faTemplate("")
2018-12-25 19:22:13 +00:00
}
func UsernameAvailable(username string) bool {
2020-06-04 20:02:46 +00:00
if len(username) == 0 {
2018-12-28 19:33:36 +00:00
return false
}
2020-07-18 11:55:19 +00:00
var tmp string
2020-07-18 12:03:31 +00:00
username = strings.ToLower(username)
2020-07-18 11:55:19 +00:00
2023-10-09 15:42:29 +00:00
q := fmt.Sprintf("select username from %s_users where username = ?", c.TablePrefix)
2020-07-18 12:03:31 +00:00
err := c.db.Get(&tmp, q, username)
2018-12-25 19:22:13 +00:00
if err == sql.ErrNoRows {
return true
}
2018-12-27 22:09:23 +00:00
if err != nil {
log.Printf("UsernameAvailable returned error: " + err.Error() + " Query was " + q)
return false
}
2018-12-25 19:22:13 +00:00
return false
}
/* Check for username availability, add to database, send email */
2024-03-01 15:37:41 +00:00
func Register(username, email, ip string) error {
2018-12-25 19:22:13 +00:00
if !UsernameAvailable(username) {
2024-03-01 15:37:41 +00:00
return fmt.Errorf("Username %s is not available", username)
2018-12-25 19:22:13 +00:00
}
2020-07-18 12:03:31 +00:00
username = strings.ToLower(username)
2020-07-18 11:55:19 +00:00
2023-10-07 13:22:30 +00:00
pass := generatePassword(16)
2018-12-27 22:09:23 +00:00
crypt, err := bcrypt.GenerateFromPassword(pass, 10)
2018-12-25 19:22:13 +00:00
if err != nil {
log.Printf("scsusers.Register: Bcrypt GenerateFromPassword failed? Pass is %s and error is %s\n", pass, err.Error())
2024-03-01 15:37:41 +00:00
return fmt.Errorf("Failed to generate password")
2018-12-25 19:22:13 +00:00
}
2023-10-09 15:42:29 +00:00
_, err = c.db.Query(fmt.Sprintf("insert into %s_users (username, password) VALUES (?,?)", c.TablePrefix), username, crypt)
2018-12-25 19:22:13 +00:00
if err != nil {
log.Printf("scsusers.Register: insert failed: %s\n", err.Error())
2024-03-01 15:40:12 +00:00
return fmt.Errorf("failed to insert user")
2018-12-25 19:22:13 +00:00
}
2024-01-10 19:35:09 +00:00
2020-07-23 22:12:44 +00:00
if SendRegistrationEmail(email, username, string(pass)) {
log.Printf("scsusers.Register: New user registration: %s from %s\n", username, ip)
2024-03-01 15:37:41 +00:00
return nil
2018-12-27 22:09:23 +00:00
}
log.Printf("scsusers.Register: Failed to send registration email, deleting user %s\n", username)
2023-10-09 15:42:29 +00:00
q := fmt.Sprintf("delete from %s_users where username = ? AND password=?", c.TablePrefix)
2020-07-18 12:03:31 +00:00
_, err = c.db.Exec(q, username, string(crypt))
2018-12-27 22:09:23 +00:00
if err != nil {
log.Printf("scsusers.Register: Failed to delete new user %s: %s\n", username, err.Error())
2018-12-27 22:09:23 +00:00
}
2024-03-01 15:40:12 +00:00
return fmt.Errorf("failed to send registration email")
2018-12-25 19:22:13 +00:00
}
2023-09-19 22:01:41 +00:00
func NewUser() *UserData {
var u UserData
u.Meta = make(map[string]metadata)
return &u
}
func Get(username string) (*UserData, bool) {
u := NewUser()
2023-10-09 15:42:29 +00:00
q := fmt.Sprintf("select username, password, id from %s_users where username=?", c.TablePrefix)
2023-09-19 22:12:55 +00:00
err := c.db.Get(u, q, username)
2018-12-27 21:49:59 +00:00
if err != nil {
2023-09-19 22:01:41 +00:00
if err == sql.ErrNoRows {
return nil, false
}
log.Printf("scsusers.Get: %s", err.Error())
return nil, false
}
2023-10-09 15:36:43 +00:00
ok := u.LoadMeta()
return u, ok
2023-09-19 22:01:41 +00:00
}
2023-11-29 23:06:29 +00:00
func GetById(id int64) (*UserData, bool) {
u := NewUser()
q := fmt.Sprintf("select username, password, id from %s_users where id=?", c.TablePrefix)
err := c.db.Get(u, q, id)
if err != nil {
if err == sql.ErrNoRows {
return nil, false
}
2023-12-13 20:46:02 +00:00
log.Printf("scsusers.GetById: %s", err.Error())
2023-11-29 23:06:29 +00:00
return nil, false
}
ok := u.LoadMeta()
return u, ok
}
func GetUsersByMeta(key string, value string) []string {
var u []string
var userids []int64
q := fmt.Sprintf("select user from %s_meta where meta_key=? AND meta_value=?", c.TablePrefix)
err := c.db.Select(&userids, q, key, value)
if err != nil && err != sql.ErrNoRows {
log.Printf("scsusers.getusersByMeta: %s", err)
return nil
}
if len(userids) == 0 {
return nil
}
q = fmt.Sprintf("select username from %s_users where id IN (?)", c.TablePrefix)
query, args, err := sqlx.In(q, userids)
if err != nil {
log.Printf("scsusers.getusersbymeta: %s", err.Error())
return nil
}
query = c.db.Rebind(query)
err = c.db.Select(&u, query, args...)
if err != nil {
log.Printf("scsusers.getusersbymeta: %s", err.Error())
return nil
}
return u
}
2019-01-11 21:39:47 +00:00
func GetUserid(username string) int64 {
var i int64
2020-07-18 12:03:31 +00:00
username = strings.ToLower(username)
2020-07-18 11:55:19 +00:00
2023-10-09 15:42:29 +00:00
q := fmt.Sprintf("select userid from %s_users where username = ?", c.TablePrefix)
2020-07-18 12:03:31 +00:00
err := c.db.Get(&i, q, username)
2019-01-11 21:39:47 +00:00
if err != nil {
log.Printf("scsusers.getUserId: Error loading user: %s : %s\n", username, err.Error())
return 0
}
return i
}