You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
memos/store/instance_setting.go

246 lines
9.2 KiB
Go

package store
import (
"context"
"github.com/pkg/errors"
"google.golang.org/protobuf/encoding/protojson"
storepb "github.com/usememos/memos/proto/gen/store"
)
type InstanceSetting struct {
Name string
Value string
Description string
}
type FindInstanceSetting struct {
Name string
}
type DeleteInstanceSetting struct {
Name string
}
func (s *Store) UpsertInstanceSetting(ctx context.Context, upsert *storepb.InstanceSetting) (*storepb.InstanceSetting, error) {
instanceSettingRaw := &InstanceSetting{
Name: upsert.Key.String(),
}
var valueBytes []byte
var err error
if upsert.Key == storepb.InstanceSettingKey_BASIC {
valueBytes, err = protojson.Marshal(upsert.GetBasicSetting())
} else if upsert.Key == storepb.InstanceSettingKey_GENERAL {
valueBytes, err = protojson.Marshal(upsert.GetGeneralSetting())
} else if upsert.Key == storepb.InstanceSettingKey_STORAGE {
valueBytes, err = protojson.Marshal(upsert.GetStorageSetting())
} else if upsert.Key == storepb.InstanceSettingKey_MEMO_RELATED {
valueBytes, err = protojson.Marshal(upsert.GetMemoRelatedSetting())
} else {
return nil, errors.Errorf("unsupported instance setting key: %v", upsert.Key)
}
if err != nil {
return nil, errors.Wrap(err, "failed to marshal instance setting value")
}
valueString := string(valueBytes)
instanceSettingRaw.Value = valueString
instanceSettingRaw, err = s.driver.UpsertInstanceSetting(ctx, instanceSettingRaw)
if err != nil {
return nil, errors.Wrap(err, "Failed to upsert instance setting")
}
instanceSetting, err := convertInstanceSettingFromRaw(instanceSettingRaw)
if err != nil {
return nil, errors.Wrap(err, "Failed to convert instance setting")
}
s.instanceSettingCache.Set(ctx, instanceSetting.Key.String(), instanceSetting)
return instanceSetting, nil
}
func (s *Store) ListInstanceSettings(ctx context.Context, find *FindInstanceSetting) ([]*storepb.InstanceSetting, error) {
list, err := s.driver.ListInstanceSettings(ctx, find)
if err != nil {
return nil, err
}
instanceSettings := []*storepb.InstanceSetting{}
for _, instanceSettingRaw := range list {
instanceSetting, err := convertInstanceSettingFromRaw(instanceSettingRaw)
if err != nil {
return nil, errors.Wrap(err, "Failed to convert instance setting")
}
if instanceSetting == nil {
continue
}
s.instanceSettingCache.Set(ctx, instanceSetting.Key.String(), instanceSetting)
instanceSettings = append(instanceSettings, instanceSetting)
}
return instanceSettings, nil
}
func (s *Store) GetInstanceSetting(ctx context.Context, find *FindInstanceSetting) (*storepb.InstanceSetting, error) {
if cache, ok := s.instanceSettingCache.Get(ctx, find.Name); ok {
instanceSetting, ok := cache.(*storepb.InstanceSetting)
if ok {
return instanceSetting, nil
}
}
list, err := s.ListInstanceSettings(ctx, find)
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, nil
}
if len(list) > 1 {
return nil, errors.Errorf("found multiple instance settings with key %s", find.Name)
}
return list[0], nil
}
func (s *Store) GetInstanceBasicSetting(ctx context.Context) (*storepb.InstanceBasicSetting, error) {
instanceSetting, err := s.GetInstanceSetting(ctx, &FindInstanceSetting{
Name: storepb.InstanceSettingKey_BASIC.String(),
})
if err != nil {
return nil, errors.Wrap(err, "failed to get instance basic setting")
}
instanceBasicSetting := &storepb.InstanceBasicSetting{}
if instanceSetting != nil {
instanceBasicSetting = instanceSetting.GetBasicSetting()
}
s.instanceSettingCache.Set(ctx, storepb.InstanceSettingKey_BASIC.String(), &storepb.InstanceSetting{
Key: storepb.InstanceSettingKey_BASIC,
Value: &storepb.InstanceSetting_BasicSetting{BasicSetting: instanceBasicSetting},
})
return instanceBasicSetting, nil
}
func (s *Store) GetInstanceGeneralSetting(ctx context.Context) (*storepb.InstanceGeneralSetting, error) {
instanceSetting, err := s.GetInstanceSetting(ctx, &FindInstanceSetting{
Name: storepb.InstanceSettingKey_GENERAL.String(),
})
if err != nil {
return nil, errors.Wrap(err, "failed to get instance general setting")
}
instanceGeneralSetting := &storepb.InstanceGeneralSetting{}
if instanceSetting != nil {
instanceGeneralSetting = instanceSetting.GetGeneralSetting()
}
s.instanceSettingCache.Set(ctx, storepb.InstanceSettingKey_GENERAL.String(), &storepb.InstanceSetting{
Key: storepb.InstanceSettingKey_GENERAL,
Value: &storepb.InstanceSetting_GeneralSetting{GeneralSetting: instanceGeneralSetting},
})
return instanceGeneralSetting, nil
}
// DefaultContentLengthLimit is the default limit of content length in bytes. 8KB.
const DefaultContentLengthLimit = 8 * 1024
// DefaultReactions is the default reactions for memo related setting.
var DefaultReactions = []string{"👍", "👎", "❤️", "🎉", "😄", "😕", "😢", "😡"}
// DefaultNsfwTags is the default tags that mark content as NSFW for blurring.
var DefaultNsfwTags = []string{"nsfw"}
func (s *Store) GetInstanceMemoRelatedSetting(ctx context.Context) (*storepb.InstanceMemoRelatedSetting, error) {
instanceSetting, err := s.GetInstanceSetting(ctx, &FindInstanceSetting{
Name: storepb.InstanceSettingKey_MEMO_RELATED.String(),
})
if err != nil {
return nil, errors.Wrap(err, "failed to get instance general setting")
}
instanceMemoRelatedSetting := &storepb.InstanceMemoRelatedSetting{}
if instanceSetting != nil {
instanceMemoRelatedSetting = instanceSetting.GetMemoRelatedSetting()
}
if instanceMemoRelatedSetting.ContentLengthLimit < DefaultContentLengthLimit {
instanceMemoRelatedSetting.ContentLengthLimit = DefaultContentLengthLimit
}
if len(instanceMemoRelatedSetting.Reactions) == 0 {
instanceMemoRelatedSetting.Reactions = append(instanceMemoRelatedSetting.Reactions, DefaultReactions...)
}
if len(instanceMemoRelatedSetting.NsfwTags) == 0 {
instanceMemoRelatedSetting.NsfwTags = append(instanceMemoRelatedSetting.NsfwTags, DefaultNsfwTags...)
}
s.instanceSettingCache.Set(ctx, storepb.InstanceSettingKey_MEMO_RELATED.String(), &storepb.InstanceSetting{
Key: storepb.InstanceSettingKey_MEMO_RELATED,
Value: &storepb.InstanceSetting_MemoRelatedSetting{MemoRelatedSetting: instanceMemoRelatedSetting},
})
return instanceMemoRelatedSetting, nil
}
const (
defaultInstanceStorageType = storepb.InstanceStorageSetting_DATABASE
defaultInstanceUploadSizeLimitMb = 30
defaultInstanceFilepathTemplate = "assets/{timestamp}_{filename}"
)
func (s *Store) GetInstanceStorageSetting(ctx context.Context) (*storepb.InstanceStorageSetting, error) {
instanceSetting, err := s.GetInstanceSetting(ctx, &FindInstanceSetting{
Name: storepb.InstanceSettingKey_STORAGE.String(),
})
if err != nil {
return nil, errors.Wrap(err, "failed to get instance storage setting")
}
instanceStorageSetting := &storepb.InstanceStorageSetting{}
if instanceSetting != nil {
instanceStorageSetting = instanceSetting.GetStorageSetting()
}
if instanceStorageSetting.StorageType == storepb.InstanceStorageSetting_STORAGE_TYPE_UNSPECIFIED {
instanceStorageSetting.StorageType = defaultInstanceStorageType
}
if instanceStorageSetting.UploadSizeLimitMb == 0 {
instanceStorageSetting.UploadSizeLimitMb = defaultInstanceUploadSizeLimitMb
}
if instanceStorageSetting.FilepathTemplate == "" {
instanceStorageSetting.FilepathTemplate = defaultInstanceFilepathTemplate
}
s.instanceSettingCache.Set(ctx, storepb.InstanceSettingKey_STORAGE.String(), &storepb.InstanceSetting{
Key: storepb.InstanceSettingKey_STORAGE,
Value: &storepb.InstanceSetting_StorageSetting{StorageSetting: instanceStorageSetting},
})
return instanceStorageSetting, nil
}
func convertInstanceSettingFromRaw(instanceSettingRaw *InstanceSetting) (*storepb.InstanceSetting, error) {
instanceSetting := &storepb.InstanceSetting{
Key: storepb.InstanceSettingKey(storepb.InstanceSettingKey_value[instanceSettingRaw.Name]),
}
switch instanceSettingRaw.Name {
case storepb.InstanceSettingKey_BASIC.String():
basicSetting := &storepb.InstanceBasicSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(instanceSettingRaw.Value), basicSetting); err != nil {
return nil, err
}
instanceSetting.Value = &storepb.InstanceSetting_BasicSetting{BasicSetting: basicSetting}
case storepb.InstanceSettingKey_GENERAL.String():
generalSetting := &storepb.InstanceGeneralSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(instanceSettingRaw.Value), generalSetting); err != nil {
return nil, err
}
instanceSetting.Value = &storepb.InstanceSetting_GeneralSetting{GeneralSetting: generalSetting}
case storepb.InstanceSettingKey_STORAGE.String():
storageSetting := &storepb.InstanceStorageSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(instanceSettingRaw.Value), storageSetting); err != nil {
return nil, err
}
instanceSetting.Value = &storepb.InstanceSetting_StorageSetting{StorageSetting: storageSetting}
case storepb.InstanceSettingKey_MEMO_RELATED.String():
memoRelatedSetting := &storepb.InstanceMemoRelatedSetting{}
if err := protojsonUnmarshaler.Unmarshal([]byte(instanceSettingRaw.Value), memoRelatedSetting); err != nil {
return nil, err
}
instanceSetting.Value = &storepb.InstanceSetting_MemoRelatedSetting{MemoRelatedSetting: memoRelatedSetting}
default:
// Skip unsupported instance setting key.
return nil, nil
}
return instanceSetting, nil
}