mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
223 lines
5.0 KiB
Go
223 lines
5.0 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package plugin
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// KVSetJSON implements Helpers.KVSetJSON.
|
|
func (p *HelpersImpl) KVSetJSON(key string, value interface{}) error {
|
|
err := p.ensureServerVersion("5.2.0")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := json.Marshal(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
appErr := p.API.KVSet(key, data)
|
|
if appErr != nil {
|
|
return appErr
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// KVCompareAndSetJSON implements Helpers.KVCompareAndSetJSON.
|
|
func (p *HelpersImpl) KVCompareAndSetJSON(key string, oldValue interface{}, newValue interface{}) (bool, error) {
|
|
var err error
|
|
|
|
err = p.ensureServerVersion("5.12.0")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
var oldData, newData []byte
|
|
|
|
if oldValue != nil {
|
|
oldData, err = json.Marshal(oldValue)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "unable to marshal old value")
|
|
}
|
|
}
|
|
|
|
if newValue != nil {
|
|
newData, err = json.Marshal(newValue)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "unable to marshal new value")
|
|
}
|
|
}
|
|
|
|
set, appErr := p.API.KVCompareAndSet(key, oldData, newData)
|
|
if appErr != nil {
|
|
return set, appErr
|
|
}
|
|
|
|
return set, nil
|
|
}
|
|
|
|
// KVCompareAndDeleteJSON implements Helpers.KVCompareAndDeleteJSON.
|
|
func (p *HelpersImpl) KVCompareAndDeleteJSON(key string, oldValue interface{}) (bool, error) {
|
|
var err error
|
|
|
|
err = p.ensureServerVersion("5.16.0")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
var oldData []byte
|
|
|
|
if oldValue != nil {
|
|
oldData, err = json.Marshal(oldValue)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "unable to marshal old value")
|
|
}
|
|
}
|
|
|
|
deleted, appErr := p.API.KVCompareAndDelete(key, oldData)
|
|
if appErr != nil {
|
|
return deleted, appErr
|
|
}
|
|
|
|
return deleted, nil
|
|
}
|
|
|
|
// KVGetJSON implements Helpers.KVGetJSON.
|
|
func (p *HelpersImpl) KVGetJSON(key string, value interface{}) (bool, error) {
|
|
err := p.ensureServerVersion("5.2.0")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
data, appErr := p.API.KVGet(key)
|
|
if appErr != nil {
|
|
return false, appErr
|
|
}
|
|
if data == nil {
|
|
return false, nil
|
|
}
|
|
|
|
err = json.Unmarshal(data, value)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// KVSetWithExpiryJSON is a wrapper around KVSetWithExpiry to simplify atomically writing a JSON object with expiry to the key value store.
|
|
func (p *HelpersImpl) KVSetWithExpiryJSON(key string, value interface{}, expireInSeconds int64) error {
|
|
err := p.ensureServerVersion("5.6.0")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := json.Marshal(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
appErr := p.API.KVSetWithExpiry(key, data, expireInSeconds)
|
|
if appErr != nil {
|
|
return appErr
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type kvListOptions struct {
|
|
checkers []func(key string) (keep bool, err error)
|
|
}
|
|
|
|
func (o *kvListOptions) checkAll(key string) (keep bool, err error) {
|
|
for _, check := range o.checkers {
|
|
keep, err := check(key)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !keep {
|
|
return false, nil
|
|
}
|
|
}
|
|
|
|
// key made it through all checkers
|
|
return true, nil
|
|
}
|
|
|
|
// KVListOption represents a single input option for KVListWithOptions
|
|
type KVListOption func(*kvListOptions)
|
|
|
|
// WithPrefix only return keys that start with the given string.
|
|
func WithPrefix(prefix string) KVListOption {
|
|
return WithChecker(func(key string) (keep bool, err error) {
|
|
return strings.HasPrefix(key, prefix), nil
|
|
})
|
|
}
|
|
|
|
// WithChecker allows for a custom filter function to determine which keys to return.
|
|
// Returning true will keep the key and false will filter it out. Returning an error
|
|
// will halt KVListWithOptions immediately and pass the error up (with no other results).
|
|
func WithChecker(f func(key string) (keep bool, err error)) KVListOption {
|
|
return func(args *kvListOptions) {
|
|
args.checkers = append(args.checkers, f)
|
|
}
|
|
}
|
|
|
|
// kvListPerPage is the number of keys KVListWithOptions gets per request
|
|
const kvListPerPage = 100
|
|
|
|
// KVListWithOptions implements Helpers.KVListWithOptions.
|
|
func (p *HelpersImpl) KVListWithOptions(options ...KVListOption) ([]string, error) {
|
|
err := p.ensureServerVersion("5.6.0")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// convert functional options into args struct
|
|
args := &kvListOptions{}
|
|
for _, opt := range options {
|
|
opt(args)
|
|
}
|
|
ret := make([]string, 0)
|
|
|
|
// get our keys a batch at a time, filter out the ones we don't want based on our args
|
|
// any errors will hault the whole process and return the error raw
|
|
for i := 0; ; i++ {
|
|
keys, appErr := p.API.KVList(i, kvListPerPage)
|
|
if appErr != nil {
|
|
return nil, appErr
|
|
}
|
|
|
|
if len(args.checkers) == 0 {
|
|
// no checkers, just append the whole block at once
|
|
ret = append(ret, keys...)
|
|
} else {
|
|
// we have a filter, so check each key, all checkers must say key
|
|
// for us to keep a key
|
|
for _, key := range keys {
|
|
keep, err := args.checkAll(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !keep {
|
|
continue
|
|
}
|
|
|
|
// didn't get filtered out, add to our return
|
|
ret = append(ret, key)
|
|
}
|
|
}
|
|
|
|
if len(keys) < kvListPerPage {
|
|
break
|
|
}
|
|
}
|
|
|
|
return ret, nil
|
|
}
|