github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/plugin_key_value_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"crypto/sha256"
     8  	"encoding/base64"
     9  	"net/http"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/mlog"
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  )
    14  
    15  func getKeyHash(key string) string {
    16  	hash := sha256.New()
    17  	hash.Write([]byte(key))
    18  	return base64.StdEncoding.EncodeToString(hash.Sum(nil))
    19  }
    20  
    21  func (a *App) SetPluginKey(pluginId string, key string, value []byte) *model.AppError {
    22  	return a.SetPluginKeyWithExpiry(pluginId, key, value, 0)
    23  }
    24  
    25  func (a *App) SetPluginKeyWithExpiry(pluginId string, key string, value []byte, expireInSeconds int64) *model.AppError {
    26  	options := model.PluginKVSetOptions{
    27  		ExpireInSeconds: expireInSeconds,
    28  	}
    29  	_, err := a.SetPluginKeyWithOptions(pluginId, key, value, options)
    30  	return err
    31  }
    32  
    33  func (a *App) CompareAndSetPluginKey(pluginId string, key string, oldValue, newValue []byte) (bool, *model.AppError) {
    34  	options := model.PluginKVSetOptions{
    35  		Atomic:   true,
    36  		OldValue: oldValue,
    37  	}
    38  	return a.SetPluginKeyWithOptions(pluginId, key, newValue, options)
    39  }
    40  
    41  func (a *App) SetPluginKeyWithOptions(pluginId string, key string, value []byte, options model.PluginKVSetOptions) (bool, *model.AppError) {
    42  	if err := options.IsValid(); err != nil {
    43  		mlog.Error("Failed to set plugin key value with options", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    44  		return false, err
    45  	}
    46  
    47  	updated, err := a.Srv().Store.Plugin().SetWithOptions(pluginId, key, value, options)
    48  	if err != nil {
    49  		mlog.Error("Failed to set plugin key value with options", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    50  		return updated, err
    51  	}
    52  
    53  	// Clean up a previous entry using the hashed key, if it exists.
    54  	if err := a.Srv().Store.Plugin().Delete(pluginId, getKeyHash(key)); err != nil {
    55  		mlog.Error("Failed to clean up previously hashed plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    56  	}
    57  
    58  	return updated, nil
    59  }
    60  
    61  func (a *App) CompareAndDeletePluginKey(pluginId string, key string, oldValue []byte) (bool, *model.AppError) {
    62  	kv := &model.PluginKeyValue{
    63  		PluginId: pluginId,
    64  		Key:      key,
    65  	}
    66  
    67  	deleted, err := a.Srv().Store.Plugin().CompareAndDelete(kv, oldValue)
    68  	if err != nil {
    69  		mlog.Error("Failed to compare and delete plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    70  		return deleted, err
    71  	}
    72  
    73  	// Clean up a previous entry using the hashed key, if it exists.
    74  	if err := a.Srv().Store.Plugin().Delete(pluginId, getKeyHash(key)); err != nil {
    75  		mlog.Error("Failed to clean up previously hashed plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    76  	}
    77  
    78  	return deleted, nil
    79  }
    80  
    81  func (a *App) GetPluginKey(pluginId string, key string) ([]byte, *model.AppError) {
    82  	if kv, err := a.Srv().Store.Plugin().Get(pluginId, key); err == nil {
    83  		return kv.Value, nil
    84  	} else if err.StatusCode != http.StatusNotFound {
    85  		mlog.Error("Failed to query plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    86  		return nil, err
    87  	}
    88  
    89  	// Lookup using the hashed version of the key for keys written prior to v5.6.
    90  	if kv, err := a.Srv().Store.Plugin().Get(pluginId, getKeyHash(key)); err == nil {
    91  		return kv.Value, nil
    92  	} else if err.StatusCode != http.StatusNotFound {
    93  		mlog.Error("Failed to query plugin key value using hashed key", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
    94  		return nil, err
    95  	}
    96  
    97  	return nil, nil
    98  }
    99  
   100  func (a *App) DeletePluginKey(pluginId string, key string) *model.AppError {
   101  	if err := a.Srv().Store.Plugin().Delete(pluginId, getKeyHash(key)); err != nil {
   102  		mlog.Error("Failed to delete plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
   103  		return err
   104  	}
   105  
   106  	// Also delete the key without hashing
   107  	if err := a.Srv().Store.Plugin().Delete(pluginId, key); err != nil {
   108  		mlog.Error("Failed to delete plugin key value using hashed key", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
   109  		return err
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  func (a *App) DeleteAllKeysForPlugin(pluginId string) *model.AppError {
   116  	if err := a.Srv().Store.Plugin().DeleteAllForPlugin(pluginId); err != nil {
   117  		mlog.Error("Failed to delete all plugin key values", mlog.String("plugin_id", pluginId), mlog.Err(err))
   118  		return err
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  func (a *App) DeleteAllExpiredPluginKeys() *model.AppError {
   125  	if a.Srv() == nil {
   126  		return nil
   127  	}
   128  
   129  	if err := a.Srv().Store.Plugin().DeleteAllExpired(); err != nil {
   130  		mlog.Error("Failed to delete all expired plugin key values", mlog.Err(err))
   131  		return err
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func (a *App) ListPluginKeys(pluginId string, page, perPage int) ([]string, *model.AppError) {
   138  	data, err := a.Srv().Store.Plugin().List(pluginId, page*perPage, perPage)
   139  
   140  	if err != nil {
   141  		mlog.Error("Failed to list plugin key values", mlog.Int("page", page), mlog.Int("perPage", perPage), mlog.Err(err))
   142  		return nil, err
   143  	}
   144  
   145  	return data, nil
   146  }