single db with prefixes, dump/restore, blacklisting on user deletion

This commit is contained in:
ston1th 2018-09-23 23:56:12 +02:00
commit d4971cda89
20 changed files with 264 additions and 163 deletions

View file

@ -2,7 +2,11 @@
package store
import "github.com/boltdb/bolt"
import (
"encoding/json"
"github.com/boltdb/bolt"
"io"
)
const defaultBoltBucket = "default"
@ -15,15 +19,13 @@ func NewBoltStore(file string, m Marshaler) (bs *BoltStore, err error) {
if m == nil {
m = NewGOB()
}
db, err := bolt.Open(file, 0666, nil)
db, err := bolt.Open(file, 0640, nil)
if err != nil {
return
}
if err = db.Update(func(tx *bolt.Tx) error {
if _, err := tx.CreateBucketIfNotExists([]byte(defaultBoltBucket)); err != nil {
return err
}
return nil
if err = db.Update(func(tx *bolt.Tx) (err error) {
_, err = tx.CreateBucketIfNotExists([]byte(defaultBoltBucket))
return
}); err != nil {
return
}
@ -31,6 +33,53 @@ func NewBoltStore(file string, m Marshaler) (bs *BoltStore, err error) {
return
}
type dump struct {
k string `json:"k"`
v []byte `json:"v"`
}
func (bs *BoltStore) Dump(w io.Writer) (err error) {
if w == nil {
return ErrWriterIsNil
}
var d []dump
err = bs.ForEach(func(k string, v []byte) error {
d = append(d, dump{k, v})
return nil
})
if err != nil {
return
}
return json.NewEncoder(w).Encode(d)
}
func (bs *BoltStore) Restore(r io.Reader) (err error) {
if r == nil {
return ErrReaderIsNil
}
var d []dump
err = json.NewDecoder(r).Decode(&d)
if err != nil {
return
}
if err = bs.db.Update(func(tx *bolt.Tx) (err error) {
if err = tx.DeleteBucket([]byte(defaultBoltBucket)); err != nil {
return
}
_, err = tx.CreateBucket([]byte(defaultBoltBucket))
return
}); err != nil {
return
}
return bs.db.Update(func(tx *bolt.Tx) (err error) {
b := tx.Bucket([]byte(defaultBoltBucket))
for _, v := range d {
b.Put([]byte(v.k), v.v)
}
return nil
})
}
func (bs *BoltStore) Get(key string, v interface{}) (err error) {
err = bs.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(defaultBoltBucket)).Get([]byte(key))
@ -46,10 +95,13 @@ func (bs *BoltStore) Get(key string, v interface{}) (err error) {
}
func (bs *BoltStore) Set(key string, v interface{}) error {
return bs.db.Update(func(tx *bolt.Tx) error {
b, err := bs.Marshal(v)
if err != nil {
return err
return bs.db.Update(func(tx *bolt.Tx) (err error) {
var b []byte
if v != nil {
b, err = bs.Marshal(v)
if err != nil {
return
}
}
return tx.Bucket([]byte(defaultBoltBucket)).Put([]byte(key), b)
})

View file

@ -2,12 +2,7 @@
package store
/*import (
"encoding/json"
"fmt"
"io"
"os"
)
import "io"
type Dumper interface {
Dump(io.Writer) error
@ -16,85 +11,3 @@ type Dumper interface {
type Restorer interface {
Restore(io.Reader) error
}
type DBDump struct {
Pages []DumpPage `json:"pages"`
Snippets []Snippet `json:"snippets"`
Users []User `json:"users"`
}
type DumpPage struct {
Title string `json:"title"`
LinkTitle string `json:"link_title"`
MD string `json:"md"`
Created string `json:"created"`
Updated string `json:"updated"`
Public bool `json:"public"`
}
func verboseLog(prefix, title string, v bool) {
if v {
fmt.Fprintln(os.Stderr, prefix, title)
}
}
func Dump(path string, v bool) (err error) {
bs, err := NewBoltStore()
if err != nil {
return
}
var dump DBDump
//TODO bs.GetAllPages
var pages []*core.Page
for _, p := range pages {
if err != nil {
return
}
verboseLog("dump:", p.Title, v)
dump.Pages = append(dump.Pages, DumpPage{
Title: p.Title,
LinkTitle: p.LinkTitle,
MD: p.MD,
Created: p.Created,
Updated: p.Updated,
Public: p.Public,
})
}
//TODO snippets
//verboseLog("dump:", "snippets", v)
verboseLog("dump:", "users", v)
dump.Users, err = bs.DumpUsers()
if err != nil {
return
}
return json.NewEncoder(os.Stdout).Encode(dump)
}
func Restore(path string, v bool) (err error) {
i, err := NewIndex(path)
if err != nil {
return
}
defer i.Close()
bs, err := NewBoltStore()
if err != nil {
return
}
var dump DBDump
err = json.NewDecoder(os.Stdin).Decode(&dump)
if err != nil {
return
}
for _, art := range dump.Articles {
verboseLog("restore:", art.Title, v)
err = i.Restore(&art)
if err != nil {
return
}
}
//TODO snippets
//verboseLog("restore:", "snippets", v)
verboseLog("restore:", "users", v)
err = bs.RestoreUsers(dump.Users)
return
}*/

View file

@ -8,10 +8,16 @@ func storeErr(i interface{}) error {
return fmt.Errorf("store: %s", i)
}
var ErrKeyNotFound = storeErr("key not found")
var (
ErrKeyNotFound = storeErr("key not found")
ErrWriterIsNil = storeErr("writer is nil")
ErrReaderIsNil = storeErr("reader is nil")
)
type Store interface {
Marshaler
Dumper
Restorer
Get(string, interface{}) error
Set(string, interface{}) error
ForEach(func(string, []byte) error) error