From 1a31bb6b307be4a676d56a98fd7df2e8e1eabc6e Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Jun 2020 16:02:46 -0400 Subject: [PATCH] Add bump with ip --- main.go | 189 +++++++++++++++++++++++++++----------------------------- 1 file changed, 92 insertions(+), 97 deletions(-) diff --git a/main.go b/main.go index ca23b37..a78d0a8 100644 --- a/main.go +++ b/main.go @@ -2,19 +2,19 @@ package scsusers import ( "bytes" + "crypto/rand" "database/sql" + "encoding/base32" + "encoding/json" "fmt" - "github.com/jmoiron/sqlx" - "golang.org/x/crypto/bcrypt" "html/template" "log" - "crypto/rand" - "encoding/json" - "encoding/base32" "net/smtp" "strings" -) + "github.com/jmoiron/sqlx" + "golang.org/x/crypto/bcrypt" +) type templates struct { Registration *template.Template @@ -26,14 +26,14 @@ type config struct { SiteName string FromEmail string Templates templates - SMTPServer string + SMTPServer string db *sqlx.DB TablePrefix string } type UserData struct { - Username string `json:"username"` - UserPerms map[string]string `json:"perms"` + Username string `json:"username"` + UserPerms map[string]string `json:"perms"` UserSettings map[string]string `json:"settings"` } @@ -44,7 +44,7 @@ func Init(dbin *sqlx.DB, tp, sitename, fromaddr, smtpserver string) { c.TablePrefix = tp c.SiteName = sitename c.FromEmail = fromaddr - c.SMTPServer=smtpserver + c.SMTPServer = smtpserver SetRegistrationTemplate("") SetAlertTemplate("") @@ -52,7 +52,7 @@ func Init(dbin *sqlx.DB, tp, sitename, fromaddr, smtpserver string) { } func UsernameAvailable(username string) bool { - if len(username)==0 { + if len(username) == 0 { return false } var u string @@ -91,8 +91,8 @@ func Register(username, email, ip string) bool { 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 ILIKE $1 AND password=$2", c.TablePrefix) - _,err = c.db.Exec(q, username, string(crypt)) + q = fmt.Sprintf("delete from %s_auth where username ILIKE $1 AND password=$2", 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()) } @@ -100,9 +100,9 @@ func Register(username, email, ip string) bool { } func Login(username, password string) bool { - q:=fmt.Sprintf("select password from %s_auth where username ILIKE $1 AND status='active'",c.TablePrefix) + q := fmt.Sprintf("select password from %s_auth where username ILIKE $1 AND status='active'", c.TablePrefix) var crypt string - err:=c.db.Get(&crypt, q, username) + err := c.db.Get(&crypt, q, username) if err != nil { log.Printf("scsusers.Login: Failed login attempt for unknown username: %s\n", username) return false @@ -117,33 +117,33 @@ func Login(username, password string) bool { } func ChangePassword(username, oldpass, newpass string) bool { - q:=fmt.Sprintf("select password from %s_auth where username ILIKE $1 AND status='active'",c.TablePrefix) + q := fmt.Sprintf("select password from %s_auth where username ILIKE $1 AND status='active'", c.TablePrefix) var crypt string - err:=c.db.Get(&crypt, q, username) + err := c.db.Get(&crypt, q, username) if err != nil { log.Println("scsusers.ChangePassword: Failed change attempt for unknown username: " + username) return false } if bcrypt.CompareHashAndPassword([]byte(crypt), []byte(oldpass)) != nil { - log.Printf("scsusers.ChangePassword: Failed password for %s\n", username) + log.Printf("scsusers.ChangePassword: Failed password for %s\n", username) return false } newcrypt, err := bcrypt.GenerateFromPassword([]byte(newpass), 10) - q=fmt.Sprintf("update %s_auth set password=$2 where username ILIKE $1", c.TablePrefix) - _,err=c.db.Exec(q, username, newcrypt) - if err!= nil { + q = fmt.Sprintf("update %s_auth set password=$2 where username ILIKE $1", c.TablePrefix) + _, err = c.db.Exec(q, username, newcrypt) + if err != nil { log.Printf("scsusers.ChangePassword: update failed for %s: %s\n", username, err.Error()) return false } Bump(username) return true - + } func GetUserid(username string) int64 { var i int64 - q:=fmt.Sprintf("select userid from %s_auth where username ILIKE $1", c.TablePrefix) - err:=c.db.Get(&i, q, username) + q := fmt.Sprintf("select userid from %s_auth where username ILIKE $1", 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 @@ -152,118 +152,117 @@ func GetUserid(username string) int64 { } func LoadUser(username string) (UserData, error) { var u UserData - q:=fmt.Sprintf("select data from %s_userdata where username ILIKE $1", c.TablePrefix) + q := fmt.Sprintf("select data from %s_userdata where username ILIKE $1", c.TablePrefix) var d string - err:=c.db.Get(d, q, username) + err := c.db.Get(d, q, username) if err != nil { log.Printf("scsusers.LoadUser: Error loading user: %s : %s\n", username, err.Error()) return u, err } - err=json.Unmarshal([]byte(d), &u) + err = json.Unmarshal([]byte(d), &u) if err != nil { log.Printf("scsusers.LoadUser: Error decoding json on user %s. Unmarshal returned %s\n", username, err.Error()) } - return u,err + return u, err } func SaveUser(username string, d UserData) bool { - q:=fmt.Sprintf("update %s_userdata set data=$1 where username ILIKE $2") - j, err:=json.Marshal(d) + q := fmt.Sprintf("update %s_userdata set data=$1 where username ILIKE $2") + j, err := json.Marshal(d) if err != nil { log.Printf("scsusers.SaveUser: json.Marshal failed for username %s : %s\n", username, err.Error()) return false } - _, err=c.db.Exec(q, username, j) + _, err = c.db.Exec(q, username, j) if err != nil { log.Printf("scsusers.SaveUser: db.Exec failed for username %s : %s\n", username, err.Error()) return false } return true - + } -func Bump(username string) { - q:=fmt.Sprintf("update %s_auth set lastseen=CURRENT_TIMESTAMP where username ILIKE $1", c.TablePrefix) - _, err :=c.db.Exec(q, username) +func Bump(username string, ip string) { + q := fmt.Sprintf("update %s_auth set lastseen=CURRENT_TIMESTAMP, set lastseenip=$2 where username ILIKE $1", c.TablePrefix) + _, err := c.db.Exec(q, username, ip) if err != nil { - log.Printf("scsusers.Bump: Error on user bump: %s : %s\n", username, err.Error()) + log.Printf("scsusers.Bump: Error on user bump: %s : %s\n", username, err.Error()) } } type Metadata struct { - MetaKey string `db:meta_key` + MetaKey string `db:meta_key` MetaValue string `db:meta_value` } -func GetAllMeta(username string) (map[string]string) { - meta:=make(map[string]string) - q:=fmt.Sprintf(`select meta_key, meta_value +func GetAllMeta(username string) map[string]string { + meta := make(map[string]string) + q := fmt.Sprintf(`select meta_key, meta_value from %s_user_metadata where user_id=(select userid from %s_auth where username ILIKE $1)`, - c.TablePrefix, c.TablePrefix) - rows,err:=c.db.Queryx(q, username) - if err != nil && err!=sql.ErrNoRows { + c.TablePrefix, c.TablePrefix) + rows, err := c.db.Queryx(q, username) + if err != nil && err != sql.ErrNoRows { log.Printf("scsusers.GetAllMeta: %s: %s\n", username, err.Error()) return meta } - var m Metadata + var m Metadata for rows.Next() { - err=rows.StructScan(&m) + err = rows.StructScan(&m) if err != nil { log.Printf("scsusers.GetAllMeta: StructScan: %s\n", username, err.Error()) return meta } - meta[m.MetaKey]=m.MetaValue + meta[m.MetaKey] = m.MetaValue } return meta } func GetMeta(username string, metakey string) string { var v string - q:=fmt.Sprintf(`select meta_value from %s_user_metadata where + q := fmt.Sprintf(`select meta_value from %s_user_metadata where user_id=(select userid from %s_auth where username ILIKE $1) AND meta_key=$2`, c.TablePrefix, c.TablePrefix) - err:=c.db.Get(&v, q, username, metakey) - if err != nil && err!=sql.ErrNoRows { + err := c.db.Get(&v, q, username, metakey) + if err != nil && err != sql.ErrNoRows { log.Printf("scsusers.GetMeta: %s - %s - %s\n", username, metakey, err.Error()) } - if v=="" { - // get default user - err:=c.db.Get(&v, q, "//default//", metakey) - if err != nil && err!=sql.ErrNoRows { + if v == "" { + // get default user + err := c.db.Get(&v, q, "//default//", metakey) + if err != nil && err != sql.ErrNoRows { log.Printf("scsusers.GetMeta: %s - %s - %s\n", username, metakey, err.Error()) } - + } return v } func SetMeta(username string, metakey string, metavalue string) { var err error - if metavalue=="" { - q:=fmt.Sprintf(`delete from %s_user_metadata where user_id=(select userid from %s_auth where username ILIKE $1) AND meta_key=$2`, + if metavalue == "" { + q := fmt.Sprintf(`delete from %s_user_metadata where user_id=(select userid from %s_auth where username ILIKE $1) AND meta_key=$2`, c.TablePrefix, c.TablePrefix) - _, err=c.db.Exec(q, username, metakey) + _, err = c.db.Exec(q, username, metakey) } else { - q:=fmt.Sprintf(`insert into %s_user_metadata (user_id, meta_key, meta_value) VALUES + q := fmt.Sprintf(`insert into %s_user_metadata (user_id, meta_key, meta_value) VALUES ((select userid from %s_auth where username ILIKE $1), $2, $3)`, c.TablePrefix, c.TablePrefix) - _,err=c.db.Exec(q, username, metakey, metavalue) + _, err = c.db.Exec(q, username, metakey, metavalue) } if err != nil { log.Printf("scsusers.SetMeta: %s %s %s %s\n", username, metakey, metavalue, err.Error()) } } - func RecoverByUsername(u string) { var username, email string - q:=fmt.Sprintf("select username, email from %s_auth where username ILIKE $1", c.TablePrefix) - row:=c.db.QueryRow(q, u) - err:=row.Scan(&username, &email) - if err!=sql.ErrNoRows { - recoverycode:=randBytes(16) - qq:=fmt.Sprintf("update %s_auth set recoverycode=$1, recoverytime=NOW() where username ILIKE $2", c.TablePrefix) - _,err:=c.db.Exec(qq, recoverycode, username) - if err==nil { + q := fmt.Sprintf("select username, email from %s_auth where username ILIKE $1", c.TablePrefix) + row := c.db.QueryRow(q, u) + err := row.Scan(&username, &email) + if err != sql.ErrNoRows { + recoverycode := randBytes(16) + qq := fmt.Sprintf("update %s_auth set recoverycode=$1, recoverytime=NOW() where username ILIKE $2", c.TablePrefix) + _, err := c.db.Exec(qq, recoverycode, username) + if err == nil { sendRecoveryEmail(email, username, string(recoverycode)) } } @@ -271,27 +270,26 @@ func RecoverByUsername(u string) { func RecoverByEmail(e string) { var username, email string - q:=fmt.Sprintf("select username, email from %s_auth where email=$1", c.TablePrefix) - row:=c.db.QueryRow(q, e) - err:=row.Scan(&username, &email) - if err!=sql.ErrNoRows { - recoverycode:=randBytes(16) - qq:=fmt.Sprintf("update %s_auth set recoverycode=$1, recoverytime=NOW() where username ILIKE $2", c.TablePrefix) - _,err:=c.db.Exec(qq, recoverycode, username) - if err==nil { + q := fmt.Sprintf("select username, email from %s_auth where email=$1", c.TablePrefix) + row := c.db.QueryRow(q, e) + err := row.Scan(&username, &email) + if err != sql.ErrNoRows { + recoverycode := randBytes(16) + qq := fmt.Sprintf("update %s_auth set recoverycode=$1, recoverytime=NOW() where username ILIKE $2", c.TablePrefix) + _, err := c.db.Exec(qq, recoverycode, username) + if err == nil { sendRecoveryEmail(email, username, string(recoverycode)) } } } - func randBytes(n int) []byte { - randomBytes := make([]byte, 32) - _, err := rand.Read(randomBytes) - if err != nil { - panic(err) - } - return []byte(base32.StdEncoding.EncodeToString(randomBytes)[:n]) + randomBytes := make([]byte, 32) + _, err := rand.Read(randomBytes) + if err != nil { + panic(err) + } + return []byte(base32.StdEncoding.EncodeToString(randomBytes)[:n]) } func sendRegistrationEmail(recipient, username, password string) bool { @@ -321,13 +319,12 @@ func sendRegistrationEmail(recipient, username, password string) bool { return true } - func sendAlertEmail(username, recipient, message string) bool { data := struct { SiteName string FromEmail string UserName string - Activity string + Activity string }{ SiteName: c.SiteName, FromEmail: c.FromEmail, @@ -340,9 +337,9 @@ func sendAlertEmail(username, recipient, message string) bool { log.Printf("scsusers.sendAlertEmail: Alert template failed to execute: %v returned %s\n", data, err.Error()) return false } - + subject := fmt.Sprintf("New activity on %s", c.SiteName) - err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient) + err = SendMail(c.SMTPServer, c.FromEmail, subject, body.String(), recipient) if err != nil { log.Printf("scsusers.sendAlertEmail: Error sending mail to %s: %s\n", recipient, err.Error()) return false @@ -352,15 +349,15 @@ func sendAlertEmail(username, recipient, message string) bool { func sendRecoveryEmail(recipient, username, code string) bool { data := struct { - SiteName string - FromEmail string - UserName string - RecoveryCode string + SiteName string + FromEmail string + UserName string + RecoveryCode string }{ - SiteName: c.SiteName, - FromEmail: c.FromEmail, - UserName: username, - RecoveryCode: code, + SiteName: c.SiteName, + FromEmail: c.FromEmail, + UserName: username, + RecoveryCode: code, } var body bytes.Buffer err := c.Templates.Registration.Execute(&body, data) @@ -377,7 +374,6 @@ func sendRecoveryEmail(recipient, username, code string) bool { return true } - func SetRegistrationTemplate(t string) bool { if len(t) != 0 { r, err := template.New("reg").Parse(t) @@ -414,7 +410,6 @@ func SetAlertTemplate(t string) bool { return false } - func SetRecoveryTemplate(t string) bool { if len(t) != 0 { r, err := template.New("recovery").Parse(t)