github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/password_reset.go (about) 1 package common 2 3 import ( 4 "crypto/subtle" 5 "database/sql" 6 "errors" 7 8 qgen "github.com/Azareal/Gosora/query_gen" 9 ) 10 11 var PasswordResetter *DefaultPasswordResetter 12 var ErrBadResetToken = errors.New("This reset token has expired.") 13 14 type DefaultPasswordResetter struct { 15 getTokens *sql.Stmt 16 create *sql.Stmt 17 delete *sql.Stmt 18 } 19 20 /* 21 type PasswordReset struct { 22 Email string `q:"email"` 23 Uid int `q:"uid"` 24 Validated bool `q:"validated"` 25 Token string `q:"token"` 26 CreatedAt time.Time `q:"createdAt"` 27 } 28 */ 29 30 func NewDefaultPasswordResetter(acc *qgen.Accumulator) (*DefaultPasswordResetter, error) { 31 pr := "password_resets" 32 return &DefaultPasswordResetter{ 33 getTokens: acc.Select(pr).Columns("token").Where("uid=?").Prepare(), 34 create: acc.Insert(pr).Columns("email,uid,validated,token,createdAt").Fields("?,?,0,?,UTC_TIMESTAMP()").Prepare(), 35 //create: acc.Insert(pr).Cols("email,uid,validated=0,token,createdAt=UTC_TIMESTAMP()").Prep(), 36 delete: acc.Delete(pr).Where("uid=?").Prepare(), 37 //model: acc.Model(w).Cols("email,uid,validated=0,token").Key("uid").CreatedAt("createdAt").Prep(), 38 }, acc.FirstError() 39 } 40 41 func (r *DefaultPasswordResetter) Create(email string, uid int, token string) error { 42 _, err := r.create.Exec(email, uid, token) 43 return err 44 } 45 46 func (r *DefaultPasswordResetter) FlushTokens(uid int) error { 47 _, err := r.delete.Exec(uid) 48 return err 49 } 50 51 func (r *DefaultPasswordResetter) ValidateToken(uid int, token string) error { 52 rows, err := r.getTokens.Query(uid) 53 if err != nil { 54 return err 55 } 56 defer rows.Close() 57 58 success := false 59 for rows.Next() { 60 var rtoken string 61 if err := rows.Scan(&rtoken); err != nil { 62 return err 63 } 64 if subtle.ConstantTimeCompare([]byte(token), []byte(rtoken)) == 1 { 65 success = true 66 } 67 } 68 if err = rows.Err(); err != nil { 69 return err 70 } 71 72 if !success { 73 return ErrBadResetToken 74 } 75 return nil 76 }