-
Notifications
You must be signed in to change notification settings - Fork 0
/
users.go
107 lines (90 loc) · 2.38 KB
/
users.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
import (
"database/sql"
"log"
"strings"
"unicode"
"github.com/sethvargo/go-password/password"
"golang.org/x/text/unicode/norm"
)
const (
USERNAME_MIN_LENGTH = 1
USERNAME_MAX_LENGTH = 32
PASSWORD_LENGTH = 60
)
type User struct {
Id int `json:"id"`
SuperUser bool `json:"superuser"`
Name string `json:"name"`
NameNormal string `json:"nameNormal"`
}
func createPassword() []byte {
// todo: handle error
p, _ := password.Generate(PASSWORD_LENGTH, 12, 12, true, true)
return []byte(p)
}
func normalizeUsername(username string) string {
return norm.NFKD.String(strings.ToLower(norm.NFKD.String(username)))
}
func ValidatePassword(password string) error {
length := len([]rune(password))
if length != PASSWORD_LENGTH {
return ErrorPasswordTooShort
}
return nil
}
func ValidateUsername(username string) error {
length := len([]rune(username))
if length <= 0 {
return ErrorUsernameTooShort
}
if length > USERNAME_MAX_LENGTH {
return ErrorUsernameTooLong
}
for _, ch := range username {
if unicode.IsSpace(ch) {
return ErrorUsernameInvalidChars
}
}
return nil
}
func CreateUser(username string) (User, string, error) {
user := User{NameNormal: normalizeUsername(username)}
password := createPassword()
var id int
err := DB.QueryRow(`INSERT INTO players(name, name_normal, password) VALUES ($1, $2, $3)
RETURNING id`, username, user.NameNormal, password).Scan(&id)
if err != nil {
log.Printf("SQL Error: %v", err)
return user, "", err
}
log.Printf("User created, ID: %d", id)
user.Name = username
return user, string(password), nil
}
func AuthenticateUser(password string) (User, error) {
user := User{}
err := DB.QueryRow(`SELECT id, name, name_normal, superuser FROM players
WHERE password = $1`, password).Scan(&user.Id, &user.Name, &user.NameNormal, &user.SuperUser)
if err != nil {
log.Printf("SQL Error: %v", err)
if err == sql.ErrNoRows {
return user, ErrorInvalidLogin
}
return user, err
}
return user, nil
}
func LoadUser(username string) (User, error) {
user := User{NameNormal: username}
err := DB.QueryRow(`SELECT id, name, superuser FROM players
WHERE name_normal = $1`, username).Scan(&user.Id, &user.Name, &user.SuperUser)
if err != nil {
log.Printf("SQL Error: %v", err)
if err == sql.ErrNoRows {
return user, ErrorUserMissing
}
return user, err
}
return user, nil
}