1
1
package models
2
2
3
3
import (
4
+ "fmt"
4
5
"errors"
5
6
"github.com/go-redis/redis"
6
7
"golang.org/x/crypto/bcrypt"
@@ -11,18 +12,65 @@ var (
11
12
ErrInvalidLogin = errors .New ("invalid login" )
12
13
)
13
14
14
- func AuthenticateUser (username , password string ) error {
15
- hash , err := client .Get ("user:" + username ).Bytes ()
16
- if err == redis .Nil {
17
- return ErrUserNotFound
18
- } else if err != nil {
15
+ type User struct {
16
+ key string
17
+ }
18
+
19
+ func NewUser (username string , hash []byte ) (* User , error ) {
20
+ id , err := client .Incr ("user:next-id" ).Result ()
21
+ if err != nil {
22
+ return nil , err
23
+ }
24
+ key := fmt .Sprintf ("user:%d" , id )
25
+ pipe := client .Pipeline ()
26
+ pipe .HSet (key , "id" , id )
27
+ pipe .HSet (key , "username" , username )
28
+ pipe .HSet (key , "hash" , hash )
29
+ pipe .HSet ("user:by-username" , username , id )
30
+ _ , err = pipe .Exec ()
31
+ if err != nil {
32
+ return nil , err
33
+ }
34
+ return & User {key }, nil
35
+ }
36
+
37
+ func (user * User ) GetUsername () (string , error ) {
38
+ return client .HGet (user .key , "username" ).Result ()
39
+ }
40
+
41
+ func (user * User ) GetHash () ([]byte , error ) {
42
+ return client .HGet (user .key , "hash" ).Bytes ()
43
+ }
44
+
45
+ func (user * User ) Authenticate (password string ) error {
46
+ hash , err := user .GetHash ()
47
+ if err != nil {
19
48
return err
20
49
}
21
50
err = bcrypt .CompareHashAndPassword (hash , []byte (password ))
22
- if err != nil {
51
+ if err == bcrypt . ErrMismatchedHashAndPassword {
23
52
return ErrInvalidLogin
24
53
}
25
- return nil
54
+ return err
55
+ }
56
+
57
+ func GetUserByUsername (username string ) (* User , error ) {
58
+ id , err := client .HGet ("user:by-username" , username ).Int64 ()
59
+ if err == redis .Nil {
60
+ return nil , ErrUserNotFound
61
+ } else if err != nil {
62
+ return nil , err
63
+ }
64
+ key := fmt .Sprintf ("user:%d" , id )
65
+ return & User {key }, nil
66
+ }
67
+
68
+ func AuthenticateUser (username , password string ) error {
69
+ user , err := GetUserByUsername (username )
70
+ if err != nil {
71
+ return err
72
+ }
73
+ return user .Authenticate (password )
26
74
}
27
75
28
76
func RegisterUser (username , password string ) error {
@@ -31,5 +79,6 @@ func RegisterUser(username, password string) error {
31
79
if err != nil {
32
80
return err
33
81
}
34
- return client .Set ("user:" + username , hash , 0 ).Err ()
82
+ _ , err = NewUser (username , hash )
83
+ return err
35
84
}
0 commit comments