summaryrefslogtreecommitdiff
path: root/system/db
diff options
context:
space:
mode:
Diffstat (limited to 'system/db')
-rw-r--r--system/db/config.go4
-rw-r--r--system/db/content.go73
-rw-r--r--system/db/init.go8
-rw-r--r--system/db/user.go25
4 files changed, 75 insertions, 35 deletions
diff --git a/system/db/config.go b/system/db/config.go
index 6855081..ab1c720 100644
--- a/system/db/config.go
+++ b/system/db/config.go
@@ -24,7 +24,7 @@ func init() {
// SetConfig sets key:value pairs in the db for configuration settings
func SetConfig(data url.Values) error {
err := store.Update(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("_config"))
+ b := tx.Bucket([]byte("__config"))
// check for any multi-value fields (ex. checkbox fields)
// and correctly format for db storage. Essentially, we need
@@ -108,7 +108,7 @@ func Config(key string) ([]byte, error) {
func ConfigAll() ([]byte, error) {
val := &bytes.Buffer{}
err := store.View(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("_config"))
+ b := tx.Bucket([]byte("__config"))
val.Write(b.Get([]byte("settings")))
return nil
diff --git a/system/db/content.go b/system/db/content.go
index 0cfadf4..74a77ec 100644
--- a/system/db/content.go
+++ b/system/db/content.go
@@ -39,11 +39,11 @@ func SetContent(target string, data url.Values) (int, error) {
}
func update(ns, id string, data url.Values) (int, error) {
- var specifier string // i.e. _pending, _sorted, etc.
- if strings.Contains(ns, "_") {
- spec := strings.Split(ns, "_")
+ var specifier string // i.e. __pending, __sorted, etc.
+ if strings.Contains(ns, "__") {
+ spec := strings.Split(ns, "__")
ns = spec[0]
- specifier = "_" + spec[1]
+ specifier = "__" + spec[1]
}
cid, err := strconv.Atoi(id)
@@ -82,11 +82,11 @@ func update(ns, id string, data url.Values) (int, error) {
func insert(ns string, data url.Values) (int, error) {
var effectedID int
- var specifier string // i.e. _pending, _sorted, etc.
- if strings.Contains(ns, "_") {
- spec := strings.Split(ns, "_")
+ var specifier string // i.e. __pending, __sorted, etc.
+ if strings.Contains(ns, "__") {
+ spec := strings.Split(ns, "__")
ns = spec[0]
- specifier = "_" + spec[1]
+ specifier = "__" + spec[1]
}
err := store.Update(func(tx *bolt.Tx) error {
@@ -215,8 +215,21 @@ type QueryOptions struct {
}
// Query retrieves a set of content from the db based on options
-func Query(namespace string, opts QueryOptions) [][]byte {
+// and returns the total number of content in the namespace and the content
+func Query(namespace string, opts QueryOptions) (int, [][]byte) {
var posts [][]byte
+ var total int
+
+ // correct bad input rather than return nil or error
+ // similar to default case for opts.Order switch below
+ if opts.Count < 0 {
+ opts.Count = 0
+ }
+
+ if opts.Offset < 0 {
+ opts.Offset = 0
+ }
+
store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(namespace))
if b == nil {
@@ -225,6 +238,12 @@ func Query(namespace string, opts QueryOptions) [][]byte {
c := b.Cursor()
n := b.Stats().KeyN
+ total = n
+
+ // return nil if no content
+ if n == 0 {
+ return nil
+ }
var start, end int
switch opts.Count {
@@ -279,12 +298,29 @@ func Query(namespace string, opts QueryOptions) [][]byte {
i++
cur++
}
+
+ default:
+ // results for DESC order
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ if cur < start {
+ cur++
+ continue
+ }
+
+ if cur >= end {
+ break
+ }
+
+ posts = append(posts, v)
+ i++
+ cur++
+ }
}
return nil
})
- return posts
+ return total, posts
}
// SortContent sorts all content of the type supplied as the namespace by time,
@@ -292,13 +328,13 @@ func Query(namespace string, opts QueryOptions) [][]byte {
// Should be called from a goroutine after SetContent is successful
func SortContent(namespace string) {
// only sort main content types i.e. Post
- if strings.Contains(namespace, "_") {
+ if strings.Contains(namespace, "__") {
return
}
all := ContentAll(namespace)
- var posts sortablePosts
+ var posts sortableContent
// decode each (json) into type to then sort
for i := range all {
j := all[i]
@@ -318,7 +354,7 @@ func SortContent(namespace string) {
// store in <namespace>_sorted bucket, first delete existing
err := store.Update(func(tx *bolt.Tx) error {
- bname := []byte(namespace + "_sorted")
+ bname := []byte(namespace + "__sorted")
err := tx.DeleteBucket(bname)
if err != nil {
return err
@@ -351,23 +387,22 @@ func SortContent(namespace string) {
}
-type sortablePosts []editor.Sortable
+type sortableContent []editor.Sortable
-func (s sortablePosts) Len() int {
+func (s sortableContent) Len() int {
return len(s)
}
-func (s sortablePosts) Less(i, j int) bool {
+func (s sortableContent) Less(i, j int) bool {
return s[i].Time() > s[j].Time()
}
-func (s sortablePosts) Swap(i, j int) {
+func (s sortableContent) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func postToJSON(ns string, data url.Values) ([]byte, error) {
// find the content type and decode values into it
- ns = strings.TrimSuffix(ns, "_external")
t, ok := content.Types[ns]
if !ok {
return nil, fmt.Errorf(content.ErrTypeNotRegistered, ns)
@@ -382,7 +417,7 @@ func postToJSON(ns string, data url.Values) ([]byte, error) {
return nil, err
}
- slug, err := manager.Slug(post.(editor.Editable))
+ slug, err := manager.Slug(post.(content.Identifiable))
if err != nil {
return nil, err
}
diff --git a/system/db/init.go b/system/db/init.go
index 63804e1..967eed1 100644
--- a/system/db/init.go
+++ b/system/db/init.go
@@ -38,14 +38,14 @@ func Init() {
return err
}
- _, err = tx.CreateBucketIfNotExists([]byte(t + "_sorted"))
+ _, err = tx.CreateBucketIfNotExists([]byte(t + "__sorted"))
if err != nil {
return err
}
}
// init db with other buckets as needed
- buckets := []string{"_config", "_users"}
+ buckets := []string{"__config", "__users"}
for _, name := range buckets {
_, err := tx.CreateBucketIfNotExists([]byte(name))
if err != nil {
@@ -54,7 +54,7 @@ func Init() {
}
// seed db with configs structure if not present
- b := tx.Bucket([]byte("_config"))
+ b := tx.Bucket([]byte("__config"))
if b.Get([]byte("settings")) == nil {
j, err := json.Marshal(&config.Config{})
if err != nil {
@@ -93,7 +93,7 @@ func SystemInitComplete() bool {
complete := false
err := store.View(func(tx *bolt.Tx) error {
- users := tx.Bucket([]byte("_users"))
+ users := tx.Bucket([]byte("__users"))
err := users.ForEach(func(k, v []byte) error {
complete = true
diff --git a/system/db/user.go b/system/db/user.go
index 3386dc2..b92a62a 100644
--- a/system/db/user.go
+++ b/system/db/user.go
@@ -24,7 +24,7 @@ var ErrNoUserExists = errors.New("Error. No user exists.")
func SetUser(usr *user.User) (int, error) {
err := store.Update(func(tx *bolt.Tx) error {
email := []byte(usr.Email)
- users := tx.Bucket([]byte("_users"))
+ users := tx.Bucket([]byte("__users"))
// check if user is found by email, fail if nil
exists := users.Get(email)
@@ -61,8 +61,13 @@ func SetUser(usr *user.User) (int, error) {
// UpdateUser sets key:value pairs in the db for existing user settings
func UpdateUser(usr, updatedUsr *user.User) error {
+ // ensure user ID remains the same
+ if updatedUsr.ID != usr.ID {
+ updatedUsr.ID = usr.ID
+ }
+
err := store.Update(func(tx *bolt.Tx) error {
- users := tx.Bucket([]byte("_users"))
+ users := tx.Bucket([]byte("__users"))
// check if user is found by email, fail if nil
exists := users.Get([]byte(usr.Email))
@@ -103,7 +108,7 @@ func UpdateUser(usr, updatedUsr *user.User) error {
// DeleteUser deletes a user from the db by email
func DeleteUser(email string) error {
err := store.Update(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("_users"))
+ b := tx.Bucket([]byte("__users"))
err := b.Delete([]byte(email))
if err != nil {
return err
@@ -122,7 +127,7 @@ func DeleteUser(email string) error {
func User(email string) ([]byte, error) {
val := &bytes.Buffer{}
err := store.View(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("_users"))
+ b := tx.Bucket([]byte("__users"))
usr := b.Get([]byte(email))
_, err := val.Write(usr)
@@ -147,7 +152,7 @@ func User(email string) ([]byte, error) {
func UserAll() ([][]byte, error) {
var users [][]byte
err := store.View(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("_users"))
+ b := tx.Bucket([]byte("__users"))
err := b.ForEach(func(k, v []byte) error {
users = append(users, v)
return nil
@@ -196,7 +201,7 @@ func SetRecoveryKey(email string) (string, error) {
key := fmt.Sprintf("%d", rand.Int63())
err := store.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucketIfNotExists([]byte("_recoveryKeys"))
+ b, err := tx.CreateBucketIfNotExists([]byte("__recoveryKeys"))
if err != nil {
return err
}
@@ -215,18 +220,18 @@ func SetRecoveryKey(email string) (string, error) {
return key, nil
}
-// RecoveryKey generates and saves a random secret key to verify an email
-// address submitted in order to recover/reset an account password
+// RecoveryKey gets a previously set recovery key to verify an email address
+// submitted in order to recover/reset an account password
func RecoveryKey(email string) (string, error) {
key := &bytes.Buffer{}
err := store.View(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("_recoveryKeys"))
+ b := tx.Bucket([]byte("__recoveryKeys"))
if b == nil {
return errors.New("No database found for checking keys.")
}
- _, err := key.Write(b.Get([]byte("email")))
+ _, err := key.Write(b.Get([]byte(email)))
if err != nil {
return err
}