generated from templates/go-generic
checkpoint: setup database; create user in database
This commit is contained in:
parent
8bc4f94c20
commit
a31ca5d127
5 changed files with 159 additions and 3 deletions
4
go.mod
4
go.mod
|
@ -1,3 +1,7 @@
|
||||||
module codeflow.dananglin.me.uk/apollo/indieauth-server
|
module codeflow.dananglin.me.uk/apollo/indieauth-server
|
||||||
|
|
||||||
go 1.23.2
|
go 1.23.2
|
||||||
|
|
||||||
|
require go.etcd.io/bbolt v1.3.11
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.4.0 // indirect
|
||||||
|
|
14
go.sum
Normal file
14
go.sum
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||||
|
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||||
|
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||||
|
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||||
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -11,6 +11,11 @@ type Config struct {
|
||||||
BindAddress string `json:"bindAddress"`
|
BindAddress string `json:"bindAddress"`
|
||||||
Port int32 `json:"port"`
|
Port int32 `json:"port"`
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
|
Database Database `json:"database"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
Path string `json:"path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig(path string) (Config, error) {
|
func NewConfig(path string) (Config, error) {
|
||||||
|
|
72
internal/database/database.go
Normal file
72
internal/database/database.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
usersBucket string = "users"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(path string) (*bolt.DB, error) {
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
|
||||||
|
if err := os.MkdirAll(dir, 0o700); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to create directory %q: %w", dir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := bolt.Options{
|
||||||
|
Timeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
boltdb, err := bolt.Open(path, 0o600, &opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"unable to open the database at %q: %w",
|
||||||
|
path,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ensureBuckets(boltdb); err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"unable to ensure that the required buckets are present in the database: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return boltdb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureBuckets(boltdb *bolt.DB) error {
|
||||||
|
err := boltdb.Update(func(tx *bolt.Tx) error {
|
||||||
|
for _, bucket := range getBuckets() {
|
||||||
|
if _, err := tx.CreateBucketIfNotExists(bucket); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unable to ensure the existence of the %q bucket: %w",
|
||||||
|
string(bucket),
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"error ensuring the existence of the buckets in the database: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBuckets() [][]byte {
|
||||||
|
return [][]byte{[]byte(usersBucket)}
|
||||||
|
}
|
61
internal/database/users.go
Normal file
61
internal/database/users.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
HashedPassword string
|
||||||
|
Profile Profile
|
||||||
|
}
|
||||||
|
|
||||||
|
type Profile struct {
|
||||||
|
Name string
|
||||||
|
URL string
|
||||||
|
Photo string
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateUser(boltdb *bolt.DB, identifier string, user User) error {
|
||||||
|
bucketName := []byte(usersBucket)
|
||||||
|
|
||||||
|
err := boltdb.Update(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket(bucketName)
|
||||||
|
|
||||||
|
if bucket == nil {
|
||||||
|
return fmt.Errorf("the %s bucket does not exist", string(bucketName))
|
||||||
|
}
|
||||||
|
|
||||||
|
key := []byte(identifier)
|
||||||
|
|
||||||
|
buffer := new(bytes.Buffer)
|
||||||
|
if err := gob.NewEncoder(buffer).Encode(user); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unable to encode the user data: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bucket.Put(key, buffer.Bytes()); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unable to update the user in the %s bucket: %w",
|
||||||
|
string(bucketName),
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating the user in the database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue