go-sample-webpage/pkg/user/userclient.go

155 lines
3.9 KiB
Go
Raw Normal View History

2021-11-04 02:04:05 +00:00
package user
import (
2021-11-23 19:21:43 +00:00
"encoding/base64"
2021-11-04 02:04:05 +00:00
"errors"
"fmt"
2021-11-23 20:32:55 +00:00
"golang.org/x/crypto/bcrypt"
"log"
2021-11-22 22:11:37 +00:00
"math/rand"
2021-11-23 20:32:55 +00:00
"github.com/jmoiron/sqlx"
2021-11-04 02:04:05 +00:00
)
type UserClient interface {
2021-11-09 18:23:19 +00:00
register(username, password, email string) (bool, error)
2021-11-22 22:11:37 +00:00
login(username, password string, requiredMailValidation bool) (bool, error)
2021-11-23 20:32:55 +00:00
getMailValidationToken(email string, forceRecreate bool) (string, error)
2021-11-04 02:04:05 +00:00
}
type UserClientMemory struct {
users map[string]string
}
2021-11-22 22:46:01 +00:00
func GetUserMemmoryClient() *UserClientMemory {
2021-11-23 20:32:55 +00:00
uc := UserClientMemory{}
uc.users = make(map[string]string)
uc.users["admin"]="password"
return &uc
2021-11-04 02:04:05 +00:00
}
2021-11-09 18:23:19 +00:00
func (uc *UserClientMemory) register(username, password, email string) (bool, error) {
2021-11-04 02:04:05 +00:00
if _, ok := uc.users[username]; ok {
return false, errors.New("Username already used")
}
uc.users[username] = password
return true, nil
}
2021-11-22 22:11:37 +00:00
func (uc UserClientMemory) login(username, password string, requiredMailValidation bool) (bool, error) {
if requiredMailValidation == true {
return false, errors.New("In memmory User Client cant validate email addresses")
}
2021-11-04 02:04:05 +00:00
if val, ok := uc.users[username]; ok {
fmt.Println("Login for valide user")
if val == password {
return true, nil
}
} else {
fmt.Printf("User %v not found", username)
}
return false, nil
2021-11-22 22:11:37 +00:00
}
2021-11-23 19:21:43 +00:00
func (uc UserClientMemory) getMailValidationToken(email string, forceRecreate bool) (string, error) {
token := randomString(35)
token = fmt.Sprintf("%v/%v", base64.StdEncoding.EncodeToString([]byte(email)), token)
2021-11-22 22:11:37 +00:00
return token, nil
}
2021-11-23 20:32:55 +00:00
type UserClientSql struct {
db *sqlx.DB
}
type User struct {
Id int `db:"id"`
Mail string `db:"mail"`
MailValidationCode *string `db:"mailValidationCode"`
MailValidate bool `db:"mailValidate"`
Username string `db:"username"`
Password string `db:"password"`
}
func NewUserClientSql(DB *sqlx.DB) *UserClientSql {
uc := UserClientSql{}
uc.db = DB
return &uc
}
func (uc *UserClientSql) register(username, password, email string) (bool, error) {
_, err := uc.db.NamedExec("INSERT INTO `user` (`mail`, `username`, `password`) VALUE (:mail, :username, :password)", map[string]interface{}{
"mail": email,
"username": username,
"password": uc.hashAndSalt([]byte(password)),
})
if err != nil {
return false, err
}
return true, nil
}
func (uc UserClientSql) login(username, password string, requiredMailValidation bool) (bool, error) {
user := User{}
err := uc.db.Get(&user, "SELECT * FROM `user` WHERE `username` = ?", username)
if err != nil {
return false, err
}
if uc.comparePasswords(user.Password, []byte(password)) == false {
return false, errors.New("Wrong password")
}
if requiredMailValidation && user.MailValidate == false {
return false, errors.New("Mail not validated")
}
return true, nil
}
func (uc UserClientSql) getMailValidationToken(email string, forceRecreate bool) (string, error) {
token := randomString(35)
token = fmt.Sprintf("%v/%v", base64.StdEncoding.EncodeToString([]byte(email)), token)
return token, nil
}
func (uc UserClientSql)hashAndSalt(pwd []byte) string {
// Use GenerateFromPassword to hash & salt pwd.
// MinCost is just an integer constant provided by the bcrypt
// package along with DefaultCost & MaxCost.
// The cost can be any value you want provided it isn't lower
// than the MinCost (4)
hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)
if err != nil {
log.Println(err)
} // GenerateFromPassword returns a byte slice so we need to
// convert the bytes to a string and return it
return string(hash)
}
func (uc UserClientSql)comparePasswords(hashedPwd string, plainPwd []byte) bool {
byteHash := []byte(hashedPwd)
err := bcrypt.CompareHashAndPassword(byteHash, plainPwd)
if err != nil {
log.Println(err)
return false
}
return true
}
2021-11-22 22:11:37 +00:00
func randomString(n int) string {
var letters = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
b := make([]byte, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
2021-11-04 02:04:05 +00:00
}