mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
store WebAddress config in datastore (#421)
moves web address config to datastore so that it can be configured by a user in the Web UI. rename OrgInfo struct to AppConfig. For #363 For #378
This commit is contained in:
parent
9be166b834
commit
def24499b5
13 changed files with 166 additions and 93 deletions
11
cli/serve.go
11
cli/serve.go
|
|
@ -94,7 +94,7 @@ the way that the kolide server works.
|
|||
createDevHosts(ds, config)
|
||||
createDevQueries(ds, config)
|
||||
createDevLabels(ds, config)
|
||||
createDevOrgInfo(svc, config)
|
||||
createDevOrgInfo(ds, config)
|
||||
}
|
||||
|
||||
fieldKeys := []string{"method", "error"}
|
||||
|
|
@ -265,15 +265,12 @@ func createDevHosts(ds kolide.Datastore, config config.KolideConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func createDevOrgInfo(svc kolide.Service, config config.KolideConfig) {
|
||||
devOrgInfo := &kolide.OrgInfo{
|
||||
func createDevOrgInfo(ds kolide.Datastore, config config.KolideConfig) {
|
||||
devOrgInfo := &kolide.AppConfig{
|
||||
OrgName: "Kolide",
|
||||
OrgLogoURL: fmt.Sprintf("%s/logo.png", config.Server.Address),
|
||||
}
|
||||
_, err := svc.NewOrgInfo(context.Background(), kolide.OrgInfoPayload{
|
||||
OrgName: &devOrgInfo.OrgName,
|
||||
OrgLogoURL: &devOrgInfo.OrgLogoURL,
|
||||
})
|
||||
_, err := ds.NewAppConfig(devOrgInfo)
|
||||
if err != nil {
|
||||
initFatal(err, "creating fake org info")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ type AuthConfig struct {
|
|||
|
||||
// AppConfig defines configs related to HTTP
|
||||
type AppConfig struct {
|
||||
WebAddress string
|
||||
TokenKeySize int
|
||||
TokenKey string
|
||||
InviteTokenValidityPeriod time.Duration
|
||||
|
|
@ -161,7 +160,6 @@ func (man Manager) LoadConfig() KolideConfig {
|
|||
SaltKeySize: man.getConfigInt("auth.salt_key_size"),
|
||||
},
|
||||
App: AppConfig{
|
||||
WebAddress: man.getConfigString("app.web_address"),
|
||||
TokenKeySize: man.getConfigInt("app.token_key_size"),
|
||||
TokenKey: man.getConfigString("app.token_key"),
|
||||
InviteTokenValidityPeriod: man.getConfigDuration("app.invite_token_validity_period"),
|
||||
|
|
|
|||
|
|
@ -8,27 +8,27 @@ import (
|
|||
)
|
||||
|
||||
func testOrgInfo(t *testing.T, ds kolide.Datastore) {
|
||||
info := &kolide.OrgInfo{
|
||||
info := &kolide.AppConfig{
|
||||
OrgName: "Kolide",
|
||||
OrgLogoURL: "localhost:8080/logo.png",
|
||||
}
|
||||
|
||||
info, err := ds.NewOrgInfo(info)
|
||||
info, err := ds.NewAppConfig(info)
|
||||
assert.Nil(t, err)
|
||||
|
||||
info2, err := ds.OrgInfo()
|
||||
info2, err := ds.AppConfig()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, info2.OrgName, info.OrgName)
|
||||
|
||||
info2.OrgName = "koolide"
|
||||
err = ds.SaveOrgInfo(info2)
|
||||
err = ds.SaveAppConfig(info2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
info3, err := ds.OrgInfo()
|
||||
info3, err := ds.AppConfig()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, info3.OrgName, info2.OrgName)
|
||||
|
||||
info4, err := ds.NewOrgInfo(info3)
|
||||
info4, err := ds.NewAppConfig(info3)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, info4.OrgName, info3.OrgName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ var tables = [...]interface{}{
|
|||
&kolide.DistributedQueryCampaignTarget{},
|
||||
&kolide.Query{},
|
||||
&kolide.DistributedQueryExecution{},
|
||||
&kolide.OrgInfo{},
|
||||
&kolide.AppConfig{},
|
||||
&kolide.Invite{},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
)
|
||||
|
||||
func (orm gormDB) NewOrgInfo(info *kolide.OrgInfo) (*kolide.OrgInfo, error) {
|
||||
func (orm gormDB) NewAppConfig(info *kolide.AppConfig) (*kolide.AppConfig, error) {
|
||||
err := orm.DB.First(info).Error
|
||||
switch err {
|
||||
case gorm.ErrRecordNotFound:
|
||||
|
|
@ -15,14 +15,14 @@ func (orm gormDB) NewOrgInfo(info *kolide.OrgInfo) (*kolide.OrgInfo, error) {
|
|||
}
|
||||
return info, nil
|
||||
case nil:
|
||||
return info, orm.SaveOrgInfo(info)
|
||||
return info, orm.SaveAppConfig(info)
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (orm gormDB) OrgInfo() (*kolide.OrgInfo, error) {
|
||||
info := &kolide.OrgInfo{}
|
||||
func (orm gormDB) AppConfig() (*kolide.AppConfig, error) {
|
||||
info := &kolide.AppConfig{}
|
||||
err := orm.DB.First(info).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -30,6 +30,6 @@ func (orm gormDB) OrgInfo() (*kolide.OrgInfo, error) {
|
|||
return info, nil
|
||||
}
|
||||
|
||||
func (orm gormDB) SaveOrgInfo(info *kolide.OrgInfo) error {
|
||||
func (orm gormDB) SaveAppConfig(info *kolide.AppConfig) error {
|
||||
return orm.DB.Save(info).Error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ type inmem struct {
|
|||
packQueries map[uint]*kolide.PackQuery
|
||||
packTargets map[uint]*kolide.PackTarget
|
||||
|
||||
orginfo *kolide.OrgInfo
|
||||
orginfo *kolide.AppConfig
|
||||
}
|
||||
|
||||
func (orm *inmem) Name() string {
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@ package datastore
|
|||
|
||||
import "github.com/kolide/kolide-ose/server/kolide"
|
||||
|
||||
func (orm *inmem) NewOrgInfo(info *kolide.OrgInfo) (*kolide.OrgInfo, error) {
|
||||
func (orm *inmem) NewAppConfig(info *kolide.AppConfig) (*kolide.AppConfig, error) {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
info.ID = 1
|
||||
orm.orginfo = info
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (orm *inmem) OrgInfo() (*kolide.OrgInfo, error) {
|
||||
func (orm *inmem) AppConfig() (*kolide.AppConfig, error) {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ func (orm *inmem) OrgInfo() (*kolide.OrgInfo, error) {
|
|||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
func (orm *inmem) SaveOrgInfo(info *kolide.OrgInfo) error {
|
||||
func (orm *inmem) SaveAppConfig(info *kolide.AppConfig) error {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,32 +5,44 @@ import "golang.org/x/net/context"
|
|||
// AppConfigStore contains method for saving and retrieving
|
||||
// application configuration
|
||||
type AppConfigStore interface {
|
||||
NewOrgInfo(info *OrgInfo) (*OrgInfo, error)
|
||||
OrgInfo() (*OrgInfo, error)
|
||||
SaveOrgInfo(info *OrgInfo) error
|
||||
NewAppConfig(info *AppConfig) (*AppConfig, error)
|
||||
AppConfig() (*AppConfig, error)
|
||||
SaveAppConfig(info *AppConfig) error
|
||||
}
|
||||
|
||||
// AppConfigService provides methods for configuring
|
||||
// the Kolide application
|
||||
type AppConfigService interface {
|
||||
NewOrgInfo(ctx context.Context, p OrgInfoPayload) (info *OrgInfo, err error)
|
||||
OrgInfo(ctx context.Context) (info *OrgInfo, err error)
|
||||
ModifyOrgInfo(ctx context.Context, p OrgInfoPayload) (info *OrgInfo, err error)
|
||||
NewAppConfig(ctx context.Context, p AppConfigPayload) (info *AppConfig, err error)
|
||||
AppConfig(ctx context.Context) (info *AppConfig, err error)
|
||||
ModifyAppConfig(ctx context.Context, p AppConfigPayload) (info *AppConfig, err error)
|
||||
}
|
||||
|
||||
// OrgInfo holds information about the current
|
||||
// organization using Kolide
|
||||
// AppConfig holds configuration about the Kolide application.
|
||||
// AppConfig data can be managed by a Kolide API user.
|
||||
type AppConfig struct {
|
||||
ID uint `gorm:"primary_key"`
|
||||
OrgName string
|
||||
OrgLogoURL string
|
||||
KolideServerURL string
|
||||
}
|
||||
|
||||
// AppConfigPayload contains request and response format of
|
||||
// the AppConfig struct.
|
||||
type AppConfigPayload struct {
|
||||
OrgInfo *OrgInfo `json:"org_info,omitempty"`
|
||||
ServerSettings *ServerSettings `json:"server_settings,omitempty"`
|
||||
}
|
||||
|
||||
// OrgInfo contains general info about the organization using Kolide.
|
||||
type OrgInfo struct {
|
||||
ID uint `gorm:"primary_key"`
|
||||
OrgName string
|
||||
OrgLogoURL string
|
||||
OrgName *string `json:"org_name,omitempty"`
|
||||
OrgLogoURL *string `json:"org_logo_url,omitempty"`
|
||||
}
|
||||
|
||||
// OrgInfoPayload is used to accept
|
||||
// OrgInfo modifications by a client
|
||||
type OrgInfoPayload struct {
|
||||
OrgName *string `json:"org_name"`
|
||||
OrgLogoURL *string `json:"org_logo_url"`
|
||||
// ServerSettings contains general settings about the kolide App.
|
||||
type ServerSettings struct {
|
||||
KolideServerURL *string `json:"web_address_url,omitempty"`
|
||||
}
|
||||
|
||||
type OrderDirection int
|
||||
|
|
|
|||
|
|
@ -14,41 +14,62 @@ type getAppConfigResponse struct {
|
|||
|
||||
func (r getAppConfigResponse) error() error { return r.Err }
|
||||
|
||||
type appConfig map[string]map[string]string
|
||||
|
||||
func makeGetAppConfigEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
info, err := svc.OrgInfo(ctx)
|
||||
config, err := svc.AppConfig(ctx)
|
||||
if err != nil {
|
||||
return getAppConfigResponse{Err: err}, nil
|
||||
}
|
||||
config := appConfig{
|
||||
"org_info": map[string]string{
|
||||
"org_name": info.OrgName,
|
||||
"org_logo_url": info.OrgLogoURL,
|
||||
},
|
||||
}
|
||||
return config, nil
|
||||
response := appConfigPayload(*config)
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
|
||||
type modifyAppConfigRequest struct {
|
||||
OrgPayload kolide.OrgInfoPayload `json:"org_info"`
|
||||
ConfigPayload kolide.AppConfigPayload
|
||||
}
|
||||
|
||||
func makeModifyAppConfigRequest(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(modifyAppConfigRequest)
|
||||
info, err := svc.ModifyOrgInfo(ctx, req.OrgPayload)
|
||||
config, err := svc.ModifyAppConfig(ctx, req.ConfigPayload)
|
||||
if err != nil {
|
||||
return getAppConfigResponse{Err: err}, nil
|
||||
}
|
||||
config := appConfig{
|
||||
"org_info": map[string]string{
|
||||
"org_name": info.OrgName,
|
||||
"org_logo_url": info.OrgLogoURL,
|
||||
},
|
||||
}
|
||||
return config, nil
|
||||
response := appConfigPayload(*config)
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
|
||||
func appConfigPayload(config kolide.AppConfig) kolide.AppConfigPayload {
|
||||
orgInfo := func() *kolide.OrgInfo {
|
||||
if config.OrgName == "" && config.OrgLogoURL == "" {
|
||||
return nil
|
||||
}
|
||||
return &kolide.OrgInfo{
|
||||
OrgName: nilString(config.OrgName),
|
||||
OrgLogoURL: nilString(config.OrgLogoURL),
|
||||
}
|
||||
}
|
||||
|
||||
serverSettings := func() *kolide.ServerSettings {
|
||||
if config.KolideServerURL == "" {
|
||||
return nil
|
||||
}
|
||||
return &kolide.ServerSettings{
|
||||
KolideServerURL: nilString(config.KolideServerURL),
|
||||
}
|
||||
}
|
||||
|
||||
return kolide.AppConfigPayload{
|
||||
OrgInfo: orgInfo(),
|
||||
ServerSettings: serverSettings(),
|
||||
}
|
||||
}
|
||||
|
||||
func nilString(s string) *string {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (mw metricsMiddleware) NewOrgInfo(ctx context.Context, p kolide.OrgInfoPayload) (*kolide.OrgInfo, error) {
|
||||
func (mw metricsMiddleware) NewAppConfig(ctx context.Context, p kolide.AppConfigPayload) (*kolide.AppConfig, error) {
|
||||
var (
|
||||
info *kolide.OrgInfo
|
||||
info *kolide.AppConfig
|
||||
err error
|
||||
)
|
||||
defer func(begin time.Time) {
|
||||
|
|
@ -18,13 +18,13 @@ func (mw metricsMiddleware) NewOrgInfo(ctx context.Context, p kolide.OrgInfoPayl
|
|||
mw.requestCount.With(lvs...).Add(1)
|
||||
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
info, err = mw.Service.NewOrgInfo(ctx, p)
|
||||
info, err = mw.Service.NewAppConfig(ctx, p)
|
||||
return info, err
|
||||
}
|
||||
|
||||
func (mw metricsMiddleware) OrgInfo(ctx context.Context) (*kolide.OrgInfo, error) {
|
||||
func (mw metricsMiddleware) AppConfig(ctx context.Context) (*kolide.AppConfig, error) {
|
||||
var (
|
||||
info *kolide.OrgInfo
|
||||
info *kolide.AppConfig
|
||||
err error
|
||||
)
|
||||
defer func(begin time.Time) {
|
||||
|
|
@ -32,13 +32,13 @@ func (mw metricsMiddleware) OrgInfo(ctx context.Context) (*kolide.OrgInfo, error
|
|||
mw.requestCount.With(lvs...).Add(1)
|
||||
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
info, err = mw.Service.OrgInfo(ctx)
|
||||
info, err = mw.Service.AppConfig(ctx)
|
||||
return info, err
|
||||
}
|
||||
|
||||
func (mw metricsMiddleware) ModifyOrgInfo(ctx context.Context, p kolide.OrgInfoPayload) (*kolide.OrgInfo, error) {
|
||||
func (mw metricsMiddleware) ModifyAppConfig(ctx context.Context, p kolide.AppConfigPayload) (*kolide.AppConfig, error) {
|
||||
var (
|
||||
info *kolide.OrgInfo
|
||||
info *kolide.AppConfig
|
||||
err error
|
||||
)
|
||||
defer func(begin time.Time) {
|
||||
|
|
@ -46,6 +46,6 @@ func (mw metricsMiddleware) ModifyOrgInfo(ctx context.Context, p kolide.OrgInfoP
|
|||
mw.requestCount.With(lvs...).Add(1)
|
||||
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
info, err = mw.Service.ModifyOrgInfo(ctx, p)
|
||||
info, err = mw.Service.ModifyAppConfig(ctx, p)
|
||||
return info, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,41 +5,41 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (svc service) NewOrgInfo(ctx context.Context, p kolide.OrgInfoPayload) (*kolide.OrgInfo, error) {
|
||||
info := &kolide.OrgInfo{}
|
||||
if p.OrgName != nil {
|
||||
info.OrgName = *p.OrgName
|
||||
}
|
||||
if p.OrgLogoURL != nil {
|
||||
info.OrgLogoURL = *p.OrgLogoURL
|
||||
}
|
||||
info, err := svc.ds.NewOrgInfo(info)
|
||||
func (svc service) NewAppConfig(ctx context.Context, p kolide.AppConfigPayload) (*kolide.AppConfig, error) {
|
||||
newConfig, err := svc.ds.NewAppConfig(fromPayload(p, kolide.AppConfig{}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return info, nil
|
||||
return newConfig, nil
|
||||
}
|
||||
|
||||
func (svc service) OrgInfo(ctx context.Context) (*kolide.OrgInfo, error) {
|
||||
return svc.ds.OrgInfo()
|
||||
func (svc service) AppConfig(ctx context.Context) (*kolide.AppConfig, error) {
|
||||
return svc.ds.AppConfig()
|
||||
}
|
||||
|
||||
func (svc service) ModifyOrgInfo(ctx context.Context, p kolide.OrgInfoPayload) (*kolide.OrgInfo, error) {
|
||||
info, err := svc.ds.OrgInfo()
|
||||
func (svc service) ModifyAppConfig(ctx context.Context, p kolide.AppConfigPayload) (*kolide.AppConfig, error) {
|
||||
config, err := svc.ds.AppConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if p.OrgName != nil {
|
||||
info.OrgName = *p.OrgName
|
||||
}
|
||||
if p.OrgLogoURL != nil {
|
||||
info.OrgLogoURL = *p.OrgLogoURL
|
||||
}
|
||||
updated := fromPayload(p, *config)
|
||||
|
||||
err = svc.ds.SaveOrgInfo(info)
|
||||
if err != nil {
|
||||
if err := svc.ds.SaveAppConfig(updated); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return info, nil
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func fromPayload(p kolide.AppConfigPayload, config kolide.AppConfig) *kolide.AppConfig {
|
||||
if p.OrgInfo != nil && p.OrgInfo.OrgLogoURL != nil {
|
||||
config.OrgLogoURL = *p.OrgInfo.OrgLogoURL
|
||||
}
|
||||
if p.OrgInfo != nil && p.OrgInfo.OrgName != nil {
|
||||
config.OrgName = *p.OrgInfo.OrgName
|
||||
}
|
||||
if p.ServerSettings != nil && p.ServerSettings.KolideServerURL != nil {
|
||||
config.KolideServerURL = *p.ServerSettings.KolideServerURL
|
||||
}
|
||||
return &config
|
||||
}
|
||||
|
|
|
|||
44
server/service/service_appconfig_test.go
Normal file
44
server/service/service_appconfig_test.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kolide/kolide-ose/server/datastore"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestCreateOrgInfo(t *testing.T) {
|
||||
ds, err := datastore.New("inmem", "")
|
||||
require.Nil(t, err)
|
||||
svc, err := newTestService(ds)
|
||||
require.Nil(t, err)
|
||||
var orgInfoTests = []struct {
|
||||
infoPayload kolide.AppConfigPayload
|
||||
}{
|
||||
{
|
||||
infoPayload: kolide.AppConfigPayload{
|
||||
OrgInfo: &kolide.OrgInfo{
|
||||
OrgLogoURL: stringPtr("acme.co/images/logo.png"),
|
||||
OrgName: stringPtr("Acme"),
|
||||
},
|
||||
ServerSettings: &kolide.ServerSettings{
|
||||
KolideServerURL: stringPtr("https://acme.co:8080/"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range orgInfoTests {
|
||||
result, err := svc.NewAppConfig(context.Background(), tt.infoPayload)
|
||||
require.Nil(t, err)
|
||||
|
||||
payload := tt.infoPayload
|
||||
assert.NotEmpty(t, result.ID)
|
||||
assert.Equal(t, *payload.OrgInfo.OrgLogoURL, result.OrgLogoURL)
|
||||
assert.Equal(t, *payload.OrgInfo.OrgName, result.OrgName)
|
||||
assert.Equal(t, *payload.ServerSettings.KolideServerURL, result.KolideServerURL)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
func decodeModifyAppConfigRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req modifyAppConfigRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
if err := json.NewDecoder(r.Body).Decode(&req.ConfigPayload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue