-
Notifications
You must be signed in to change notification settings - Fork 7k
/
plugin_key_value_store.go
146 lines (117 loc) · 4.98 KB
/
plugin_key_value_store.go
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"crypto/sha256"
"encoding/base64"
"net/http"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
)
func getKeyHash(key string) string {
hash := sha256.New()
hash.Write([]byte(key))
return base64.StdEncoding.EncodeToString(hash.Sum(nil))
}
func (a *App) SetPluginKey(pluginId string, key string, value []byte) *model.AppError {
return a.SetPluginKeyWithExpiry(pluginId, key, value, 0)
}
func (a *App) SetPluginKeyWithExpiry(pluginId string, key string, value []byte, expireInSeconds int64) *model.AppError {
options := model.PluginKVSetOptions{
ExpireInSeconds: expireInSeconds,
}
_, err := a.SetPluginKeyWithOptions(pluginId, key, value, options)
return err
}
func (a *App) CompareAndSetPluginKey(pluginId string, key string, oldValue, newValue []byte) (bool, *model.AppError) {
options := model.PluginKVSetOptions{
Atomic: true,
OldValue: oldValue,
}
return a.SetPluginKeyWithOptions(pluginId, key, newValue, options)
}
func (a *App) SetPluginKeyWithOptions(pluginId string, key string, value []byte, options model.PluginKVSetOptions) (bool, *model.AppError) {
if err := options.IsValid(); err != nil {
mlog.Error("Failed to set plugin key value with options", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return false, err
}
updated, err := a.Srv.Store.Plugin().SetWithOptions(pluginId, key, value, options)
if err != nil {
mlog.Error("Failed to set plugin key value with options", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return updated, err
}
// Clean up a previous entry using the hashed key, if it exists.
if err := a.Srv.Store.Plugin().Delete(pluginId, getKeyHash(key)); err != nil {
mlog.Error("Failed to clean up previously hashed plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
}
return updated, nil
}
func (a *App) CompareAndDeletePluginKey(pluginId string, key string, oldValue []byte) (bool, *model.AppError) {
kv := &model.PluginKeyValue{
PluginId: pluginId,
Key: key,
}
deleted, err := a.Srv.Store.Plugin().CompareAndDelete(kv, oldValue)
if err != nil {
mlog.Error("Failed to compare and delete plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return deleted, err
}
// Clean up a previous entry using the hashed key, if it exists.
if err := a.Srv.Store.Plugin().Delete(pluginId, getKeyHash(key)); err != nil {
mlog.Error("Failed to clean up previously hashed plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
}
return deleted, nil
}
func (a *App) GetPluginKey(pluginId string, key string) ([]byte, *model.AppError) {
if kv, err := a.Srv.Store.Plugin().Get(pluginId, key); err == nil {
return kv.Value, nil
} else if err.StatusCode != http.StatusNotFound {
mlog.Error("Failed to query plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return nil, err
}
// Lookup using the hashed version of the key for keys written prior to v5.6.
if kv, err := a.Srv.Store.Plugin().Get(pluginId, getKeyHash(key)); err == nil {
return kv.Value, nil
} else if err.StatusCode != http.StatusNotFound {
mlog.Error("Failed to query plugin key value using hashed key", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return nil, err
}
return nil, nil
}
func (a *App) DeletePluginKey(pluginId string, key string) *model.AppError {
if err := a.Srv.Store.Plugin().Delete(pluginId, getKeyHash(key)); err != nil {
mlog.Error("Failed to delete plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return err
}
// Also delete the key without hashing
if err := a.Srv.Store.Plugin().Delete(pluginId, key); err != nil {
mlog.Error("Failed to delete plugin key value using hashed key", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return err
}
return nil
}
func (a *App) DeleteAllKeysForPlugin(pluginId string) *model.AppError {
if err := a.Srv.Store.Plugin().DeleteAllForPlugin(pluginId); err != nil {
mlog.Error("Failed to delete all plugin key values", mlog.String("plugin_id", pluginId), mlog.Err(err))
return err
}
return nil
}
func (a *App) DeleteAllExpiredPluginKeys() *model.AppError {
if a.Srv == nil {
return nil
}
if err := a.Srv.Store.Plugin().DeleteAllExpired(); err != nil {
mlog.Error("Failed to delete all expired plugin key values", mlog.Err(err))
return err
}
return nil
}
func (a *App) ListPluginKeys(pluginId string, page, perPage int) ([]string, *model.AppError) {
data, err := a.Srv.Store.Plugin().List(pluginId, page*perPage, perPage)
if err != nil {
mlog.Error("Failed to list plugin key values", mlog.Int("page", page), mlog.Int("perPage", perPage), mlog.Err(err))
return nil, err
}
return data, nil
}