Add improve settings for messaging

This commit is contained in:
Denis Arh
2019-10-30 18:00:40 +01:00
parent 93c10fbf24
commit 1aebc456b0
7 changed files with 204 additions and 37 deletions
+32 -18
View File
@@ -37,15 +37,23 @@ func (imp *Importer) Cast(in interface{}) (err error) {
return deinterfacer.Each(in, func(index int, key string, val interface{}) (err error) {
switch key {
case "channels":
return imp.channels.CastSet(val)
if imp.channels != nil {
return imp.channels.CastSet(val)
}
case "channel":
return imp.channels.CastSet([]interface{}{val})
if imp.channels != nil {
return imp.channels.CastSet([]interface{}{val})
}
case "settings":
return imp.settings.CastSet(val)
if imp.settings != nil {
return imp.settings.CastSet(val)
}
case "allow", "deny":
return imp.permissions.CastResourcesSet(key, val)
if imp.permissions != nil {
return imp.permissions.CastResourcesSet(key, val)
}
default:
err = fmt.Errorf("unexpected key %q", key)
@@ -56,25 +64,31 @@ func (imp *Importer) Cast(in interface{}) (err error) {
}
func (imp *Importer) Store(ctx context.Context, rk channelKeeper, pk permissions.ImportKeeper, sk settings.ImportKeeper, roles sysTypes.RoleSet) (err error) {
err = imp.channels.Store(ctx, rk)
if err != nil {
return
if imp.channels != nil {
err = imp.channels.Store(ctx, rk)
if err != nil {
return
}
}
// Make sure we properly replace channel handles with IDs
roles.Walk(func(r *sysTypes.Role) error {
imp.permissions.UpdateRoles(r.Handle, r.ID)
return nil
})
if imp.permissions != nil {
// Make sure we properly replace channel handles with IDs
roles.Walk(func(r *sysTypes.Role) error {
imp.permissions.UpdateRoles(r.Handle, r.ID)
return nil
})
err = imp.permissions.Store(ctx, pk)
if err != nil {
return
err = imp.permissions.Store(ctx, pk)
if err != nil {
return
}
}
err = imp.settings.Store(ctx, sk)
if err != nil {
return
if imp.settings != nil {
err = imp.settings.Store(ctx, sk)
if err != nil {
return
}
}
return nil
+61 -3
View File
@@ -2,9 +2,11 @@ package messaging
import (
"context"
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"github.com/cortezaproject/corteza-server/messaging/importer"
"github.com/cortezaproject/corteza-server/messaging/service"
@@ -12,21 +14,23 @@ import (
"github.com/cortezaproject/corteza-server/pkg/auth"
"github.com/cortezaproject/corteza-server/pkg/cli"
impAux "github.com/cortezaproject/corteza-server/pkg/importer"
"github.com/cortezaproject/corteza-server/pkg/settings"
provision "github.com/cortezaproject/corteza-server/provision/messaging"
)
func provisionConfig(ctx context.Context, cmd *cobra.Command, c *cli.Config) error {
func provisionConfig(ctx context.Context, cmd *cobra.Command, c *cli.Config) (err error) {
c.Log.Debug("running configuration provision")
c.InitServices(ctx, c)
var provisioned bool
// Make sure we have all full access for provisioning
ctx = auth.SetSuperUserContext(ctx)
if provisioned, err := isProvisioned(ctx); err != nil {
if provisioned, err = isProvisioned(ctx); err != nil {
return err
} else if provisioned {
c.Log.Debug("configuration already provisioned")
return nil
}
readers, err := impAux.ReadStatic(provision.Asset)
@@ -34,6 +38,10 @@ func provisionConfig(ctx context.Context, cmd *cobra.Command, c *cli.Config) err
return err
}
if provisioned {
return partialImportSettings(ctx, service.DefaultSettings, readers...)
}
return errors.Wrap(
importer.Import(ctx, readers...),
"could not provision configuration for messaging service",
@@ -45,3 +53,53 @@ func isProvisioned(ctx context.Context) (bool, error) {
cc, _, err := service.DefaultChannel.With(ctx).Find(types.ChannelFilter{IncludeDeleted: true})
return len(cc) > 0, err
}
// Partial import of settings from provision files
func partialImportSettings(ctx context.Context, ss service.SettingsService, ff ...io.Reader) (err error) {
var (
// decoded content from YAML files
aux interface{}
si = settings.NewImporter()
// importer w/o permissions & roles
// we need only settings
imp = importer.NewImporter(nil, si, nil)
// current value
current settings.ValueSet
// unexisting values
unex settings.ValueSet
)
for _, f := range ff {
if err = yaml.NewDecoder(f).Decode(&aux); err != nil {
return
}
err = imp.Cast(aux)
if err != nil {
return
}
}
ss = ss.With(ctx)
// Get all "current" settings storage
current, err = ss.FindByPrefix("")
if err != nil {
return
}
// Compare current settings with imported, get all that do not exist yet
if unex = si.GetValues(); len(unex) > 0 {
// Store non existing
err = ss.BulkSet(current.New(unex))
if err != nil {
return
}
}
return nil
}
+5 -1
View File
@@ -7,6 +7,7 @@ import (
"go.uber.org/zap"
"github.com/cortezaproject/corteza-server/messaging/repository"
"github.com/cortezaproject/corteza-server/messaging/types"
"github.com/cortezaproject/corteza-server/pkg/cli/options"
"github.com/cortezaproject/corteza-server/pkg/http"
"github.com/cortezaproject/corteza-server/pkg/permissions"
@@ -41,6 +42,9 @@ var (
DefaultSettings SettingsService
DefaultAccessControl *accessControl
// CurrentSettings represents current messaging settings
CurrentSettings = &types.Settings{}
DefaultAttachment AttachmentService
DefaultChannel ChannelService
DefaultMessage MessageService
@@ -101,7 +105,7 @@ func Init(ctx context.Context, log *zap.Logger, c Config) (err error) {
}
DefaultAccessControl = AccessControl(DefaultPermissions)
DefaultSettings = Settings(ctx, DefaultInternalSettings)
DefaultSettings = Settings(ctx, DefaultInternalSettings, CurrentSettings)
DefaultEvent = Event(ctx)
DefaultChannel = Channel(ctx)
+53 -5
View File
@@ -9,6 +9,7 @@ import (
"go.uber.org/zap/zapcore"
"github.com/cortezaproject/corteza-server/messaging/repository"
"github.com/cortezaproject/corteza-server/messaging/types"
"github.com/cortezaproject/corteza-server/pkg/logger"
internalSettings "github.com/cortezaproject/corteza-server/pkg/settings"
)
@@ -22,6 +23,7 @@ type (
ac settingsAccessController
internalSettings internalSettings.Service
current *types.Settings
}
settingsAccessController interface {
@@ -30,7 +32,7 @@ type (
}
SettingsService interface {
With(ctx context.Context) SettingsService
With(ctx context.Context) *settings
FindByPrefix(prefix string) (vv internalSettings.ValueSet, err error)
Set(v *internalSettings.Value) (err error)
BulkSet(vv internalSettings.ValueSet) (err error)
@@ -38,15 +40,16 @@ type (
}
)
func Settings(ctx context.Context, intSet internalSettings.Service) SettingsService {
func Settings(ctx context.Context, intSet internalSettings.Service, current *types.Settings) *settings {
return (&settings{
internalSettings: intSet,
ac: DefaultAccessControl,
logger: DefaultLogger.Named("settings"),
current: current,
}).With(ctx)
}
func (svc settings) With(ctx context.Context) SettingsService {
func (svc settings) With(ctx context.Context) *settings {
db := repository.DB(ctx)
return &settings{
@@ -56,6 +59,8 @@ func (svc settings) With(ctx context.Context) SettingsService {
logger: svc.logger,
internalSettings: svc.internalSettings.With(ctx),
current: svc.current,
}
}
@@ -71,12 +76,28 @@ func (svc settings) FindByPrefix(prefix string) (vv internalSettings.ValueSet, e
return svc.internalSettings.FindByPrefix(prefix)
}
// UpdateCurrent loads settings values from storage and updates current settings variable
//
// It accesses internal settings directly because
// we do not want any security checks for this
func (svc settings) UpdateCurrent() error {
if vv, err := svc.internalSettings.FindByPrefix(""); err != nil {
return err
} else {
return svc.updateCurrent(vv.KV())
}
}
func (svc settings) Set(v *internalSettings.Value) (err error) {
if !svc.ac.CanManageSettings(svc.ctx) {
return errors.New("not allowed to manage settings")
}
return svc.internalSettings.Set(v)
if err = svc.internalSettings.Set(v); err != nil {
return
}
return svc.updateCurrent(internalSettings.KV{v.Name: v.Value})
}
func (svc settings) BulkSet(vv internalSettings.ValueSet) (err error) {
@@ -84,7 +105,34 @@ func (svc settings) BulkSet(vv internalSettings.ValueSet) (err error) {
return errors.New("not allowed to manage settings")
}
return svc.internalSettings.BulkSet(vv)
var old internalSettings.ValueSet
if old, err = svc.internalSettings.FindByPrefix(""); err != nil {
return
} else {
vv = old.Changed(vv)
}
if err = svc.internalSettings.BulkSet(vv); err != nil {
return
}
for _, v := range vv {
svc.log(svc.ctx,
zap.String("name", v.Name),
zap.Stringer("value", v.Value)).Info("settings changed")
}
return svc.updateCurrent(vv.KV())
}
func (svc settings) updateCurrent(kv internalSettings.KV) (err error) {
// update current settings with new values
if err = kv.Decode(svc.current); err != nil {
return
}
svc.log(svc.ctx).Info("current settings updated")
return
}
func (svc settings) Get(name string, ownedBy uint64) (out *internalSettings.Value, err error) {
+43
View File
@@ -0,0 +1,43 @@
package types
type (
Settings struct {
// UI related settings
UI struct {
// Emoji
// @todo implementation
Emoji struct {
Enabled bool
}
// In-browser notifications
// @todo implementation
BrowserNotifications struct {
Enabled bool
Header string
MessageTrim uint `kv:"message-trim"`
} `kv:"browser-notifications"`
} `kv:"ui"`
// Message related settings
Message struct {
// @todo implementation
Attachments struct {
// Completely disable attachments
Enabled bool
// What is max size (in MB, so: MaxSize x 2^20)
MaxSize uint `kv:"max-size"`
// List of mime-types we support,
Mimetypes []string
// Enable/disable individual attachment sources (mobile)
Source struct {
Gallery struct{ Enabled bool }
Camera struct{ Enabled bool }
}
}
}
}
)
+9 -9
View File
@@ -1,10 +1,10 @@
settings:
emoji.enabled: true
message.attachment.enabled: true
message.attachment.source.gallery.enabled: true
message.attachment.source.camera.enabled: true
message.attachment.max-size: 10
message.attachment.type.whitelist: []
notification.enabled: true
notification.header.template: ${user} in ${channel} | Corteza
notification.message.max-length: 200
ui.emoji.enabled: true
ui.browser-notifications.enabled: true
ui.browser-notifications.header: ${user} in ${channel}
ui.browser-notifications.message-trim: 200
message.attachments.enabled: true
message.attachments.max-size: 10
message.attachments.mimetypes: []
message.attachments.source.gallery.enabled: true
message.attachments.source.camera.enabled: true
+1 -1
View File
@@ -3,4 +3,4 @@
// Package contains static assets.
package messaging
var Asset = "PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00 \x000000_access_control.yamlUT\x05\x00\x01\x80Cm8allow:\n everyone:\n messaging:\n - access\n\n admins:\n messaging:\n - access\n - grant\n - settings.read\n - settings.manage\n - channel.public.create\n - channel.private.create\n - channel.group.create\n\n messaging:channel:\n - update\n - leave\n - read\n - join\n - delete\n - undelete\n - archive\n - unarchive\n - members.manage\n - attachments.manage\n - message.attach\n - message.update.all\n - message.update.own\n - message.delete.all\n - message.delete.own\n - message.embed\n - message.send\n - message.reply\n - message.react\n\nPK\x07\x08\xae\x83\x83d\x8e\x02\x00\x00\x8e\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x000100_settings.yamlUT\x05\x00\x01\x80Cm8settings:\n emoji.enabled: true\n message.attachment.enabled: true\n message.attachment.source.gallery.enabled: true\n message.attachment.source.camera.enabled: true\n message.attachment.max-size: 10\n message.attachment.type.whitelist: []\n notification.enabled: true\n notification.header.template: ${user} in ${channel} | Corteza\n notification.message.max-length: 200\nPK\x07\x08\xc2\x0c\xfdkt\x01\x00\x00t\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x001000_channels.yamlUT\x05\x00\x01\x80Cm8channels:\n - name: General\n type: public\n - name: Random\n type: public\nPK\x07\x08\xe8\x83F\xf8O\x00\x00\x00O\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xae\x83\x83d\x8e\x02\x00\x00\x8e\x02\x00\x00\x18\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x000000_access_control.yamlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xc2\x0c\xfdkt\x01\x00\x00t\x01\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdd\x02\x00\x000100_settings.yamlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xe8\x83F\xf8O\x00\x00\x00O\x00\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x9a\x04\x00\x001000_channels.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x03\x00\x03\x00\xe1\x00\x00\x002\x05\x00\x00\x00\x00"
var Asset = "PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00 \x000000_access_control.yamlUT\x05\x00\x01\x80Cm8allow:\n everyone:\n messaging:\n - access\n\n admins:\n messaging:\n - access\n - grant\n - settings.read\n - settings.manage\n - channel.public.create\n - channel.private.create\n - channel.group.create\n\n messaging:channel:\n - update\n - leave\n - read\n - join\n - delete\n - undelete\n - archive\n - unarchive\n - members.manage\n - attachments.manage\n - message.attach\n - message.update.all\n - message.update.own\n - message.delete.all\n - message.delete.own\n - message.embed\n - message.send\n - message.reply\n - message.react\n\nPK\x07\x08\xae\x83\x83d\x8e\x02\x00\x00\x8e\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x000100_settings.yamlUT\x05\x00\x01\x80Cm8settings:\n ui.emoji.enabled: true\n ui.browser-notifications.enabled: true\n ui.browser-notifications.header: ${user} in ${channel}\n ui.browser-notifications.message-trim: 200\n message.attachments.enabled: true\n message.attachments.max-size: 10\n message.attachments.mimetypes: []\n message.attachments.source.gallery.enabled: true\n message.attachments.source.camera.enabled: true\nPK\x07\x08Cy\xf0y\x82\x01\x00\x00\x82\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x00\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x001000_channels.yamlUT\x05\x00\x01\x80Cm8channels:\n - name: General\n type: public\n - name: Random\n type: public\nPK\x07\x08\xe8\x83F\xf8O\x00\x00\x00O\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xae\x83\x83d\x8e\x02\x00\x00\x8e\x02\x00\x00\x18\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x000000_access_control.yamlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(Cy\xf0y\x82\x01\x00\x00\x82\x01\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdd\x02\x00\x000100_settings.yamlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x00\x00\x00\x00!(\xe8\x83F\xf8O\x00\x00\x00O\x00\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa8\x04\x00\x001000_channels.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x03\x00\x03\x00\xe1\x00\x00\x00@\x05\x00\x00\x00\x00"