~evanj/cms

ref: 37b75b6fd4e482657f38cb98668b78df49c66971 cms/internal/s/db/user.go -rw-r--r-- 2.8 KiB
37b75b6fEvan M Jones TEST(cache): Attempting to cache at controller level. 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
package db

import (
	"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
}