~evanj/cms

ref: 4aa45cc85249c542c4d80aed47e25c86145bcc3c cms/internal/s/db/user.go -rw-r--r-- 3.0 KiB
4aa45cc8Evan M Jones Feat(mysql): Moving to mysql. Getting ready for alpha release (just for 8 months ago
                                                                                
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package db

import (
	"encoding/json"
	"fmt"

	"git.sr.ht/~evanj/cms/internal/m/user"
	"git.sr.ht/~evanj/security"
)

type User struct {
	id   string
	name string
	hash string

	token string
}

// SQL QUERIES

var (
	queryCreateNewUser  = `INSERT INTO cms_user (NAME, HASH) VALUES (?, ?);`
	queryFindUserByID   = `SELECT ID, NAME, HASH FROM cms_user WHERE ID = ?;`
	queryFindUserByName = `SELECT ID, NAME, HASH FROM cms_user WHERE NAME = ?;`
)

func (db *DB) UserNew(username, password, verifyPassword string) (user.User, error) {
	if password != verifyPassword {
		return nil, fmt.Errorf("passwords do not match")
	}

	hash, err := db.sec.HashCreate(username, password)
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to create password hash")
	}

	res, err := db.Exec(queryCreateNewUser, username, hash)
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("user '%s' already exists", username)
	}

	id, err := res.LastInsertId()
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to create user")
	}

	var user User
	if err := db.QueryRow(queryFindUserByID, id).Scan(&user.id, &user.name, &user.hash); err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find user created")
	}

	tok, err := db.sec.TokenCreate(security.TokenMap{"ID": user.id})
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to create token for user")
	}

	user.token = tok
	return &user, nil
}

func (db *DB) UserGet(username, password string) (user.User, error) {
	var user User
	if err := db.QueryRow(queryFindUserByName, username).Scan(&user.id, &user.name, &user.hash); err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find user '%s'", username)
	}

	if err := db.sec.HashCompare(username, password, user.hash); err != nil {
		return nil, fmt.Errorf("incorrect password")
	}

	tok, err := db.sec.TokenCreate(security.TokenMap{"ID": user.id})
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to create token for user")
	}

	user.token = tok
	return &user, nil
}

func (db *DB) UserGetFromToken(token string) (user.User, error) {
	tmap, err := db.sec.TokenFrom(token)
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to decode user token")
	}

	id, ok := tmap["ID"]
	if !ok {
		db.log.Println(err)
		return nil, fmt.Errorf("corrupted user token")
	}

	var user User
	if err := db.QueryRow(queryFindUserByID, id).Scan(&user.id, &user.name, &user.hash); err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find user")
	}

	tok, err := db.sec.TokenCreate(security.TokenMap{"ID": user.id})
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to create token for user")
	}

	user.token = tok
	return &user, nil
}

func (u *User) ID() string {
	return u.id
}

func (u *User) Name() string {
	return u.name
}

func (u *User) Token() string {
	return u.token
}

func (u *User) MarshalJSON() ([]byte, error) {
	values := make(map[string]string)
	values["id"] = u.ID()
	values["name"] = u.Name()
	return json.Marshal(values)
}