Restructure config on compose module

This commit is contained in:
Denis Arh
2022-07-30 15:11:13 +02:00
parent 7d91b4eaaf
commit a58eb1e052
24 changed files with 367 additions and 472 deletions
+7 -7
View File
@@ -101,8 +101,8 @@ func WalkIterator(ctx context.Context, iter dal.Iterator, mod *types.Module, f f
func prepFilter(filter types.RecordFilter, mod *types.Module) (dalFilter filter.Filter) {
dalFilter = filter.ToFilter()
if mod.ModelConfig.Partitioned {
dalFilter = filter.ToConstraintedFilter(mod.ModelConfig.Constraints)
if mod.Config.DAL.Partitioned {
dalFilter = filter.ToConstraintedFilter(mod.Config.DAL.Constraints)
}
return
@@ -253,15 +253,15 @@ func recToGetters(rr ...*types.Record) (out []dal.ValueGetter) {
}
func recCreateCapabilities(m *types.Module) (out capabilities.Set) {
return capabilities.CreateCapabilities(m.ModelConfig.Capabilities...)
return capabilities.CreateCapabilities(m.Config.DAL.Capabilities...)
}
func recUpdateCapabilities(m *types.Module) (out capabilities.Set) {
return capabilities.UpdateCapabilities(m.ModelConfig.Capabilities...)
return capabilities.UpdateCapabilities(m.Config.DAL.Capabilities...)
}
func recDeleteCapabilities(m *types.Module) (out capabilities.Set) {
return capabilities.DeleteCapabilities(m.ModelConfig.Capabilities...)
return capabilities.DeleteCapabilities(m.Config.DAL.Capabilities...)
}
func recFilterCapabilities(f types.RecordFilter) (out capabilities.Set) {
@@ -285,10 +285,10 @@ func recFilterCapabilities(f types.RecordFilter) (out capabilities.Set) {
}
func recSearchCapabilities(m *types.Module, f types.RecordFilter) (out capabilities.Set) {
return capabilities.SearchCapabilities(m.ModelConfig.Capabilities...).
return capabilities.SearchCapabilities(m.Config.DAL.Capabilities...).
Union(recFilterCapabilities(f))
}
func recLookupCapabilities(m *types.Module) (out capabilities.Set) {
return capabilities.LookupCapabilities(m.ModelConfig.Capabilities...)
return capabilities.LookupCapabilities(m.Config.DAL.Capabilities...)
}
+1 -1
View File
@@ -20,7 +20,7 @@ moduleField: schema.#Resource & {
label: {sortable: true}
options: { goType: "types.ModuleFieldOptions" }
encoding_strategy: { goType: "types.EncodingStrategy" }
privacy: { goType: "types.DataPrivacyConfig" }
privacy: { goType: "types.ModuleFieldConfigDataPrivacy" }
private: { goType: "bool", storeIdent: "is_private" }
required: { goType: "bool", storeIdent: "is_required" }
visible: { goType: "bool", storeIdent: "is_visible" }
+1 -2
View File
@@ -14,8 +14,7 @@ module: schema.#Resource & {
id: schema.IdField
handle: schema.HandleField
meta: { goType: "rawJson" }
model_config: { goType: "types.ModelConfig" }
privacy: { goType: "types.DataPrivacyConfig" }
config: { goType: "types.ModuleConfig" }
fields: { goType: "types.ModuleFieldSet", store: false }
namespace_id: { ident: "namespaceID", goType: "uint64", storeIdent: "rel_namespace" }
name: {sortable: true}
+13 -64
View File
@@ -548,36 +548,12 @@ endpoints:
path: "/"
parameters:
post:
- type: string
name: name
required: true
title: Module Name
- type: string
name: handle
required: false
title: Module handle
- type: types.ModelConfig
name: modelConfig
required: false
title: modelConfig
parser: types.ParseModelConfig
- type: types.DataPrivacyConfig
name: privacy
required: false
title: Data privacy config
parser: types.ParseDataPrivacyConfig
- type: types.ModuleFieldSet
name: fields
required: true
title: Fields JSON
- type: sqlxTypes.JSONText
name: meta
required: true
title: Module meta data
- type: map[string]string
name: labels
title: Module labels
parser: label.ParseStrings
- { type: "string", name: name, title: Name, required: true }
- { type: "string", name: handle, title: Handle }
- { type: "types.ModuleConfig", name: config, title: Configuration, parser: types.ParseModuleConfig }
- { type: "sqlxTypes.JSONText", name: meta, title: Meta data, required: true }
- { type: "types.ModuleFieldSet", name: fields, title: Fields, required: true }
- { type: "map[string]string", name: labels, title: Labels, parser: label.ParseStrings }
- name: read
method: GET
title: Read module
@@ -599,40 +575,13 @@ endpoints:
required: true
title: Module ID
post:
- type: string
name: name
required: true
title: Module Name
- type: string
name: handle
required: false
title: Module Handle
- type: types.ModelConfig
name: modelConfig
required: false
title: modelConfig
parser: types.ParseModelConfig
- type: types.DataPrivacyConfig
name: privacy
required: false
title: Data privacy config
parser: types.ParseDataPrivacyConfig
- type: types.ModuleFieldSet
name: fields
required: true
title: Fields JSON
- type: sqlxTypes.JSONText
name: meta
required: true
title: Module meta data
- type: "*time.Time"
name: updatedAt
required: false
title: Last update (or creation) date
- type: map[string]string
name: labels
title: Module labels
parser: label.ParseStrings
- { type: "string", name: name, title: Name, required: true }
- { type: "string", name: handle, title: Handle }
- { type: "types.ModuleConfig", name: config, title: Configuration, parser: types.ParseModuleConfig }
- { type: "sqlxTypes.JSONText", name: meta, title: Meta data, required: true }
- { type: "types.ModuleFieldSet", name: fields, title: Fields, required: true }
- { type: "map[string]string", name: labels, title: Labels, parser: label.ParseStrings }
- { type: "*time.Time", name: updatedAt, title: Last update (or creation) date }
- name: delete
method: DELETE
title: Delete module
+1 -1
View File
@@ -75,7 +75,7 @@ func (ctrl *DataPrivacy) RecordList(ctx context.Context, r *request.DataPrivacyR
for _, s := range ss {
// Skip the ones we don't want
if hasReqConns && !reqConns[s.Module.ModelConfig.ConnectionID] {
if hasReqConns && !reqConns[s.Module.Config.DAL.ConnectionID] {
continue
}
+2 -4
View File
@@ -109,8 +109,7 @@ func (ctrl *Module) Create(ctx context.Context, r *request.ModuleCreate) (interf
err error
mod = &types.Module{
NamespaceID: r.NamespaceID,
ModelConfig: r.ModelConfig,
Privacy: r.Privacy,
Config: r.Config,
Name: r.Name,
Handle: r.Handle,
Fields: r.Fields,
@@ -129,8 +128,7 @@ func (ctrl *Module) Update(ctx context.Context, r *request.ModuleUpdate) (interf
mod = &types.Module{
ID: r.ModuleID,
NamespaceID: r.NamespaceID,
ModelConfig: r.ModelConfig,
Privacy: r.Privacy,
Config: r.Config,
Name: r.Name,
Handle: r.Handle,
Fields: r.Fields,
+83 -153
View File
@@ -88,37 +88,32 @@ type (
// Name POST parameter
//
// Module Name
// Name
Name string
// Handle POST parameter
//
// Module handle
// Handle
Handle string
// ModelConfig POST parameter
// Config POST parameter
//
// modelConfig
ModelConfig types.ModelConfig
// Privacy POST parameter
//
// Data privacy config
Privacy types.DataPrivacyConfig
// Fields POST parameter
//
// Fields JSON
Fields types.ModuleFieldSet
// Configuration
Config types.ModuleConfig
// Meta POST parameter
//
// Module meta data
// Meta data
Meta sqlxTypes.JSONText
// Fields POST parameter
//
// Fields
Fields types.ModuleFieldSet
// Labels POST parameter
//
// Module labels
// Labels
Labels map[string]string
}
@@ -147,43 +142,38 @@ type (
// Name POST parameter
//
// Module Name
// Name
Name string
// Handle POST parameter
//
// Module Handle
// Handle
Handle string
// ModelConfig POST parameter
// Config POST parameter
//
// modelConfig
ModelConfig types.ModelConfig
// Privacy POST parameter
//
// Data privacy config
Privacy types.DataPrivacyConfig
// Fields POST parameter
//
// Fields JSON
Fields types.ModuleFieldSet
// Configuration
Config types.ModuleConfig
// Meta POST parameter
//
// Module meta data
// Meta data
Meta sqlxTypes.JSONText
// Fields POST parameter
//
// Fields
Fields types.ModuleFieldSet
// Labels POST parameter
//
// Labels
Labels map[string]string
// UpdatedAt POST parameter
//
// Last update (or creation) date
UpdatedAt *time.Time
// Labels POST parameter
//
// Module labels
Labels map[string]string
}
ModuleDelete struct {
@@ -391,10 +381,9 @@ func (r ModuleCreate) Auditable() map[string]interface{} {
"namespaceID": r.NamespaceID,
"name": r.Name,
"handle": r.Handle,
"modelConfig": r.ModelConfig,
"privacy": r.Privacy,
"fields": r.Fields,
"config": r.Config,
"meta": r.Meta,
"fields": r.Fields,
"labels": r.Labels,
}
}
@@ -415,18 +404,8 @@ func (r ModuleCreate) GetHandle() string {
}
// Auditable returns all auditable/loggable parameters
func (r ModuleCreate) GetModelConfig() types.ModelConfig {
return r.ModelConfig
}
// Auditable returns all auditable/loggable parameters
func (r ModuleCreate) GetPrivacy() types.DataPrivacyConfig {
return r.Privacy
}
// Auditable returns all auditable/loggable parameters
func (r ModuleCreate) GetFields() types.ModuleFieldSet {
return r.Fields
func (r ModuleCreate) GetConfig() types.ModuleConfig {
return r.Config
}
// Auditable returns all auditable/loggable parameters
@@ -434,6 +413,11 @@ func (r ModuleCreate) GetMeta() sqlxTypes.JSONText {
return r.Meta
}
// Auditable returns all auditable/loggable parameters
func (r ModuleCreate) GetFields() types.ModuleFieldSet {
return r.Fields
}
// Auditable returns all auditable/loggable parameters
func (r ModuleCreate) GetLabels() map[string]string {
return r.Labels
@@ -474,25 +458,13 @@ func (r *ModuleCreate) Fill(req *http.Request) (err error) {
}
}
if val, ok := req.MultipartForm.Value["modelConfig[]"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
if val, ok := req.MultipartForm.Value["config[]"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["modelConfig"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
if err != nil {
return err
}
}
if val, ok := req.MultipartForm.Value["privacy[]"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["privacy"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
} else if val, ok := req.MultipartForm.Value["config"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
@@ -540,25 +512,20 @@ func (r *ModuleCreate) Fill(req *http.Request) (err error) {
}
}
if val, ok := req.Form["modelConfig[]"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
if val, ok := req.Form["config[]"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
} else if val, ok := req.Form["modelConfig"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
} else if val, ok := req.Form["config"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
}
if val, ok := req.Form["privacy[]"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
if err != nil {
return err
}
} else if val, ok := req.Form["privacy"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
if val, ok := req.Form["meta"]; ok && len(val) > 0 {
r.Meta, err = payload.ParseJSONTextWithErr(val[0])
if err != nil {
return err
}
@@ -571,13 +538,6 @@ func (r *ModuleCreate) Fill(req *http.Request) (err error) {
// }
//}
if val, ok := req.Form["meta"]; ok && len(val) > 0 {
r.Meta, err = payload.ParseJSONTextWithErr(val[0])
if err != nil {
return err
}
}
if val, ok := req.Form["labels[]"]; ok {
r.Labels, err = label.ParseStrings(val)
if err != nil {
@@ -665,12 +625,11 @@ func (r ModuleUpdate) Auditable() map[string]interface{} {
"moduleID": r.ModuleID,
"name": r.Name,
"handle": r.Handle,
"modelConfig": r.ModelConfig,
"privacy": r.Privacy,
"fields": r.Fields,
"config": r.Config,
"meta": r.Meta,
"updatedAt": r.UpdatedAt,
"fields": r.Fields,
"labels": r.Labels,
"updatedAt": r.UpdatedAt,
}
}
@@ -695,18 +654,8 @@ func (r ModuleUpdate) GetHandle() string {
}
// Auditable returns all auditable/loggable parameters
func (r ModuleUpdate) GetModelConfig() types.ModelConfig {
return r.ModelConfig
}
// Auditable returns all auditable/loggable parameters
func (r ModuleUpdate) GetPrivacy() types.DataPrivacyConfig {
return r.Privacy
}
// Auditable returns all auditable/loggable parameters
func (r ModuleUpdate) GetFields() types.ModuleFieldSet {
return r.Fields
func (r ModuleUpdate) GetConfig() types.ModuleConfig {
return r.Config
}
// Auditable returns all auditable/loggable parameters
@@ -715,8 +664,8 @@ func (r ModuleUpdate) GetMeta() sqlxTypes.JSONText {
}
// Auditable returns all auditable/loggable parameters
func (r ModuleUpdate) GetUpdatedAt() *time.Time {
return r.UpdatedAt
func (r ModuleUpdate) GetFields() types.ModuleFieldSet {
return r.Fields
}
// Auditable returns all auditable/loggable parameters
@@ -724,6 +673,11 @@ func (r ModuleUpdate) GetLabels() map[string]string {
return r.Labels
}
// Auditable returns all auditable/loggable parameters
func (r ModuleUpdate) GetUpdatedAt() *time.Time {
return r.UpdatedAt
}
// Fill processes request and fills internal variables
func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
@@ -759,25 +713,13 @@ func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
}
}
if val, ok := req.MultipartForm.Value["modelConfig[]"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
if val, ok := req.MultipartForm.Value["config[]"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["modelConfig"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
if err != nil {
return err
}
}
if val, ok := req.MultipartForm.Value["privacy[]"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["privacy"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
} else if val, ok := req.MultipartForm.Value["config"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
@@ -790,13 +732,6 @@ func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
}
}
if val, ok := req.MultipartForm.Value["updatedAt"]; ok && len(val) > 0 {
r.UpdatedAt, err = payload.ParseISODatePtrWithErr(val[0])
if err != nil {
return err
}
}
if val, ok := req.MultipartForm.Value["labels[]"]; ok {
r.Labels, err = label.ParseStrings(val)
if err != nil {
@@ -808,6 +743,13 @@ func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := req.MultipartForm.Value["updatedAt"]; ok && len(val) > 0 {
r.UpdatedAt, err = payload.ParseISODatePtrWithErr(val[0])
if err != nil {
return err
}
}
}
}
@@ -832,25 +774,20 @@ func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
}
}
if val, ok := req.Form["modelConfig[]"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
if val, ok := req.Form["config[]"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
} else if val, ok := req.Form["modelConfig"]; ok {
r.ModelConfig, err = types.ParseModelConfig(val)
} else if val, ok := req.Form["config"]; ok {
r.Config, err = types.ParseModuleConfig(val)
if err != nil {
return err
}
}
if val, ok := req.Form["privacy[]"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
if err != nil {
return err
}
} else if val, ok := req.Form["privacy"]; ok {
r.Privacy, err = types.ParseDataPrivacyConfig(val)
if val, ok := req.Form["meta"]; ok && len(val) > 0 {
r.Meta, err = payload.ParseJSONTextWithErr(val[0])
if err != nil {
return err
}
@@ -863,20 +800,6 @@ func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
// }
//}
if val, ok := req.Form["meta"]; ok && len(val) > 0 {
r.Meta, err = payload.ParseJSONTextWithErr(val[0])
if err != nil {
return err
}
}
if val, ok := req.Form["updatedAt"]; ok && len(val) > 0 {
r.UpdatedAt, err = payload.ParseISODatePtrWithErr(val[0])
if err != nil {
return err
}
}
if val, ok := req.Form["labels[]"]; ok {
r.Labels, err = label.ParseStrings(val)
if err != nil {
@@ -888,6 +811,13 @@ func (r *ModuleUpdate) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := req.Form["updatedAt"]; ok && len(val) > 0 {
r.UpdatedAt, err = payload.ParseISODatePtrWithErr(val[0])
if err != nil {
return err
}
}
}
{
+35 -23
View File
@@ -295,15 +295,15 @@ func (svc module) procDal(m *types.Module) {
return
}
ii := svc.dal.SearchModelIssues(m.ModelConfig.ConnectionID, m.ID)
ii := svc.dal.SearchModelIssues(m.Config.DAL.ConnectionID, m.ID)
if len(ii) == 0 {
m.ModelConfig.Issues = nil
m.Config.DAL.Issues = nil
return
}
m.ModelConfig.Issues = make([]string, len(ii))
m.Config.DAL.Issues = make([]string, len(ii))
for i, err := range ii {
m.ModelConfig.Issues[i] = err.Error()
m.Config.DAL.Issues[i] = err.Error()
}
}
@@ -453,7 +453,7 @@ func (svc module) FindSensitive(ctx context.Context, filter types.PrivacyModuleF
}
for _, m := range mm {
cMeta, err := svc.dal.GetConnectionMeta(ctx, m.ModelConfig.ConnectionID)
cMeta, err := svc.dal.GetConnectionMeta(ctx, m.Config.DAL.ConnectionID)
if err != nil {
return err
}
@@ -534,7 +534,24 @@ func (svc module) updater(ctx context.Context, namespaceID, moduleID uint64, act
}
if changes&moduleChanged > 0 {
if old.ModelConfig.ConnectionID != m.ModelConfig.ConnectionID {
{
// properly resolve connection ID 0 to the actual ID of the default connection
var defConn dal.ConnectionMeta
defConn, err = svc.dal.GetConnectionMeta(ctx, 0)
if err != nil {
return err
}
if old.Config.DAL.ConnectionID == 0 {
old.Config.DAL.ConnectionID = defConn.ConnectionID
}
if m.Config.DAL.ConnectionID == 0 {
m.Config.DAL.ConnectionID = defConn.ConnectionID
}
}
if old.Config.DAL.ConnectionID != m.Config.DAL.ConnectionID {
return fmt.Errorf("unable to switch connection for existing models: run data migration")
}
@@ -551,7 +568,7 @@ func (svc module) updater(ctx context.Context, namespaceID, moduleID uint64, act
// @todo rethink how model issues and attempted module update with records should interact.
// this is a temporary solution but should be re-thinked.
modelIssues := svc.dal.SearchModelIssues(m.ModelConfig.ConnectionID, m.ID)
modelIssues := svc.dal.SearchModelIssues(m.Config.DAL.ConnectionID, m.ID)
if len(modelIssues) == 0 {
if set, _, err = dalutils.ComposeRecordsList(ctx, svc.dal, m, types.RecordFilter{Paging: filter.Paging{Limit: 1}, Check: func(r *types.Record) (bool, error) { return true, nil }}); err != nil {
return err
@@ -718,14 +735,9 @@ func (svc module) handleUpdate(ctx context.Context, upd *types.Module) moduleUpd
}
if !reflect.DeepEqual(res.ModelConfig, upd.ModelConfig) {
if !reflect.DeepEqual(res.Config, upd.Config) {
changes |= moduleChanged
res.ModelConfig = upd.ModelConfig
}
if !reflect.DeepEqual(res.Privacy, upd.Privacy) {
changes |= moduleChanged
res.Privacy = upd.Privacy
res.Config = upd.Config
}
// @todo make field-change detection more optimal
@@ -1148,7 +1160,7 @@ func dalAttributeReplace(ctx context.Context, dmm dalModelManager, ns *types.Nam
// Removes a connection from DAL service
func DalModelRemove(ctx context.Context, dmm dalModelManager, mm ...*types.Module) (err error) {
for _, m := range mm {
if err = dmm.RemoveModel(ctx, m.ModelConfig.ConnectionID, m.ID); err != nil {
if err = dmm.RemoveModel(ctx, m.Config.DAL.ConnectionID, m.ID); err != nil {
return err
}
}
@@ -1188,14 +1200,14 @@ func moduleToModel(ctx context.Context, dmm dalModelManager, ns *types.Namespace
Resource: mod.RbacResource(),
ResourceID: mod.ID,
ResourceType: types.ModuleResourceType,
SensitivityLevel: mod.Privacy.SensitivityLevel,
Capabilities: mod.ModelConfig.Capabilities,
SensitivityLevel: mod.Config.Privacy.SensitivityLevel,
Capabilities: mod.Config.DAL.Capabilities,
}
// - make the model ident
ident := cm.DefaultModelIdent
if mod.ModelConfig.Partitioned {
tpl := mod.ModelConfig.PartitionFormat
if mod.Config.DAL.Partitioned {
tpl := mod.Config.DAL.PartitionFormat
if tpl == "" {
tpl = cm.DefaultPartitionFormat
}
@@ -1249,7 +1261,7 @@ func moduleFieldsToAttributes(ctx context.Context, cm dal.ConnectionMeta, ns *ty
// moduleSystemFieldsToAttributes converts all system-defined module fields to attributes
func moduleSystemFieldsToAttributes(ctx context.Context, cm dal.ConnectionMeta, ns *types.Namespace, mod *types.Module) (out dal.AttributeSet, err error) {
if mod.ModelConfig.Partitioned {
if mod.Config.DAL.Partitioned {
return partitionedModuleSystemFieldsToAttributes(cm, mod), nil
}
return defaultModuleSystemFieldsToAttributes(), nil
@@ -1258,7 +1270,7 @@ func moduleSystemFieldsToAttributes(ctx context.Context, cm dal.ConnectionMeta,
// partitionedModuleSystemFieldsToAttributes converts all system-defined module fields to attributes
// keeping user-defined codec in mind
func partitionedModuleSystemFieldsToAttributes(cm dal.ConnectionMeta, mod *types.Module) (out dal.AttributeSet) {
sysEnc := mod.ModelConfig.SystemFieldEncoding
sysEnc := mod.Config.DAL.SystemFieldEncoding
if sysEnc.ID != nil {
out = append(out, dal.PrimaryAttribute(sysID, modelFieldCodec(cm, mod, &types.ModuleField{Name: sysID, EncodingStrategy: *sysEnc.ID})))
@@ -1410,7 +1422,7 @@ func moduleFieldToAttribute(ctx context.Context, cm dal.ConnectionMeta, mod *typ
func modulesByConnection(modules ...*types.Module) map[uint64]types.ModuleSet {
out := make(map[uint64]types.ModuleSet)
for _, mod := range modules {
out[mod.ModelConfig.ConnectionID] = append(out[mod.ModelConfig.ConnectionID], mod)
out[mod.Config.DAL.ConnectionID] = append(out[mod.Config.DAL.ConnectionID], mod)
}
return out
@@ -1452,7 +1464,7 @@ func modelFieldCodec(cm dal.ConnectionMeta, mod *types.Module, f *types.ModuleFi
// baseModelFieldCodec returns the DAL codec the given module field should use by default
func baseModelFieldCodec(cm dal.ConnectionMeta, mod *types.Module, f *types.ModuleField) dal.Codec {
if mod.ModelConfig.Partitioned {
if mod.Config.DAL.Partitioned {
return &dal.CodecPlain{}
}
+53 -95
View File
@@ -3,44 +3,31 @@ package types
import (
"database/sql/driver"
"encoding/json"
discovery "github.com/cortezaproject/corteza-server/discovery/types"
"github.com/cortezaproject/corteza-server/pkg/sql"
"github.com/jmoiron/sqlx/types"
"time"
discovery "github.com/cortezaproject/corteza-server/discovery/types"
"github.com/cortezaproject/corteza-server/pkg/dal"
"github.com/cortezaproject/corteza-server/pkg/dal/capabilities"
"github.com/cortezaproject/corteza-server/pkg/filter"
"github.com/cortezaproject/corteza-server/pkg/locale"
"github.com/jmoiron/sqlx/types"
"github.com/pkg/errors"
)
type (
ModelConfig struct {
ConnectionID uint64 `json:"connectionID,string"`
Capabilities capabilities.Set `json:"capabilities"`
Issues []string `json:"issues,omitempty"`
Constraints map[string][]any `json:"constraints"`
Partitioned bool `json:"partitioned"`
PartitionFormat string `json:"partitionFormat"`
SystemFieldEncoding SystemFieldEncoding `json:"systemFieldEncoding"`
}
DataPrivacyConfig struct {
SensitivityLevel uint64 `json:"sensitivityLevel,string,omitempty"`
UsageDisclosure string `json:"usageDisclosure"`
}
Module struct {
ID uint64 `json:"moduleID,string"`
Handle string `json:"handle"`
Meta types.JSONText `json:"meta"`
ID uint64 `json:"moduleID,string"`
Handle string `json:"handle"`
ModelConfig ModelConfig `json:"modelConfig"`
Privacy DataPrivacyConfig `json:"privacy"`
// collection of configurations for various subsystems that
// use this module and how it affects their behaviour
Config ModuleConfig `json:"config"`
// @todo should be removed and placed into a separate subsystem
// mostly because we want to allow client apps to store
// application configs away from the module config
// using separate access-control
Meta types.JSONText `json:"meta"`
Fields ModuleFieldSet `json:"fields"`
@@ -76,10 +63,41 @@ type (
DeletedBy *EncodingStrategy `json:"deletedBy"`
}
ModuleMeta struct {
ModuleConfig struct {
// How and where the records of this module are stored in the database
DAL ModuleConfigDAL `json:"dal"`
// Record data privacy settings
Privacy ModuleConfigDataPrivacy `json:"privacy"`
// @todo we need to transfer this from meta!!
Discovery discovery.ModuleMeta `json:"discovery"`
}
ModuleConfigDAL struct {
ConnectionID uint64 `json:"connectionID,string"`
Capabilities capabilities.Set `json:"capabilities"`
Issues []string `json:"issues,omitempty"`
Constraints map[string][]any `json:"constraints"`
Partitioned bool `json:"partitioned"`
PartitionFormat string `json:"partitionFormat"`
SystemFieldEncoding SystemFieldEncoding `json:"systemFieldEncoding"`
}
ModuleConfigDataPrivacy struct {
// Define the highest sensitivity level which
// can be configured on the module fields
SensitivityLevel uint64 `json:"sensitivityLevel,string,omitempty"`
UsageDisclosure string `json:"usageDisclosure"`
}
ModelMeta map[string]any
ModuleFilter struct {
ModuleID []uint64 `json:"moduleID"`
NamespaceID uint64 `json:"namespaceID,string"`
@@ -111,7 +129,7 @@ func (m Module) Clone() *Module {
}
func (m Module) HasIssues() bool {
return len(m.ModelConfig.Issues) > 0
return len(m.Config.DAL.Issues) > 0
}
// We won't worry about fields at this point
@@ -126,7 +144,7 @@ func (m *Module) encodeTranslations() (out locale.ResourceTranslationSet) {
func (m *Module) ModelRef() dal.ModelRef {
return dal.ModelRef{
ConnectionID: m.ModelConfig.ConnectionID,
ConnectionID: m.Config.DAL.ConnectionID,
ResourceID: m.ID,
@@ -147,45 +165,13 @@ func (set ModuleSet) FindByHandle(handle string) *Module {
return nil
}
func (nm *ModuleMeta) Scan(value interface{}) error {
//lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8
switch value.(type) {
case nil:
*nm = ModuleMeta{}
case []uint8:
b := value.([]byte)
if err := json.Unmarshal(b, nm); err != nil {
return errors.Wrapf(err, "cannot scan '%v' into ModuleMeta", string(b))
}
}
func (c *ModuleConfig) Scan(src any) error { return sql.ParseJSON(src, c) }
func (c ModuleConfig) Value() (driver.Value, error) { return json.Marshal(c) }
return nil
}
func (m *ModelMeta) Scan(src any) error { return sql.ParseJSON(src, m) }
func (m ModelMeta) Value() (driver.Value, error) { return json.Marshal(m) }
func (nm ModuleMeta) Value() (driver.Value, error) {
return json.Marshal(nm)
}
func (nm *ModelConfig) Scan(value interface{}) error {
//lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8
switch value.(type) {
case nil:
*nm = ModelConfig{}
case []uint8:
b := value.([]byte)
if err := json.Unmarshal(b, nm); err != nil {
return errors.Wrapf(err, "cannot scan '%v' into ModelConfig", string(b))
}
}
return nil
}
func (nm ModelConfig) Value() (driver.Value, error) {
return json.Marshal(nm)
}
func ParseModelConfig(ss []string) (m ModelConfig, err error) {
func ParseModuleConfig(ss []string) (m ModuleConfig, err error) {
if len(ss) == 0 {
return
}
@@ -193,31 +179,3 @@ func ParseModelConfig(ss []string) (m ModelConfig, err error) {
err = json.Unmarshal([]byte(ss[0]), &m)
return
}
func (nm *DataPrivacyConfig) Scan(value interface{}) error {
//lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8
switch value.(type) {
case nil:
*nm = DataPrivacyConfig{}
case []uint8:
b := value.([]byte)
if err := json.Unmarshal(b, nm); err != nil {
return errors.Wrapf(err, "cannot scan '%v' into DataPrivacyConfig", string(b))
}
}
return nil
}
func (nm DataPrivacyConfig) Value() (driver.Value, error) {
return json.Marshal(nm)
}
func ParseDataPrivacyConfig(ss []string) (dpc DataPrivacyConfig, err error) {
if len(ss) == 0 {
return
}
err = json.Unmarshal([]byte(ss[0]), &dpc)
return
}
+13 -1
View File
@@ -3,6 +3,7 @@ package types
import (
"database/sql/driver"
"encoding/json"
"github.com/cortezaproject/corteza-server/pkg/sql"
"sort"
"strconv"
"strings"
@@ -28,7 +29,7 @@ type (
EncodingStrategy EncodingStrategy `json:"encodingStrategy"`
Privacy DataPrivacyConfig `json:"privacy"`
Privacy ModuleFieldConfigDataPrivacy `json:"privacy"`
Private bool `json:"isPrivate"`
Required bool `json:"isRequired"`
@@ -50,6 +51,14 @@ type (
Label string `json:"label"`
}
ModuleFieldConfigDataPrivacy struct {
// Define the highest sensitivity level which
// can be configured on the module fields
SensitivityLevel uint64 `json:"sensitivityLevel,string,omitempty"`
UsageDisclosure string `json:"usageDisclosure"`
}
EncodingStrategy struct {
*EncodingStrategyAlias `json:"alias,omitempty"`
*EncodingStrategyJSON `json:"json,omitempty"`
@@ -520,3 +529,6 @@ func (f ModuleField) IsRef() bool {
func (f ModuleField) IsSensitive() bool {
return f.Privacy.SensitivityLevel > 0
}
func (p *ModuleFieldConfigDataPrivacy) Scan(src any) error { return sql.ParseJSON(src, p) }
func (p ModuleFieldConfigDataPrivacy) Value() (driver.Value, error) { return json.Marshal(p) }
+26
View File
@@ -0,0 +1,26 @@
package sql
import (
"encoding/json"
"fmt"
)
func ParseJSON(raw any, dest any) (error) {
var (
data []byte
)
if b, ok := raw.([]byte); ok {
data = b
} else if s, ok := raw.(string); ok {
data = []byte(s)
} else if raw == nil {
return nil
}
if err := json.Unmarshal(data, dest); err != nil {
return fmt.Errorf("can not scan JSON into %T: %w", dest, err)
}
return nil
}
+30 -34
View File
@@ -244,38 +244,37 @@ type (
// auxComposeModule is an auxiliary structure used for transporting to/from RDBMS store
auxComposeModule struct {
ID uint64 `db:"id"`
Handle string `db:"handle"`
Meta rawJson `db:"meta"`
ModelConfig composeType.ModelConfig `db:"model_config"`
Privacy composeType.DataPrivacyConfig `db:"privacy"`
NamespaceID uint64 `db:"namespace_id"`
Name string `db:"name"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
DeletedAt *time.Time `db:"deleted_at"`
ID uint64 `db:"id"`
Handle string `db:"handle"`
Meta rawJson `db:"meta"`
Config composeType.ModuleConfig `db:"config"`
NamespaceID uint64 `db:"namespace_id"`
Name string `db:"name"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
DeletedAt *time.Time `db:"deleted_at"`
}
// auxComposeModuleField is an auxiliary structure used for transporting to/from RDBMS store
auxComposeModuleField struct {
ID uint64 `db:"id"`
ModuleID uint64 `db:"module_id"`
Place int `db:"place"`
Kind string `db:"kind"`
Name string `db:"name"`
Label string `db:"label"`
Options composeType.ModuleFieldOptions `db:"options"`
EncodingStrategy composeType.EncodingStrategy `db:"encoding_strategy"`
Privacy composeType.DataPrivacyConfig `db:"privacy"`
Private bool `db:"private"`
Required bool `db:"required"`
Visible bool `db:"visible"`
Multi bool `db:"multi"`
DefaultValue composeType.RecordValueSet `db:"default_value"`
Expressions composeType.ModuleFieldExpr `db:"expressions"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
DeletedAt *time.Time `db:"deleted_at"`
ID uint64 `db:"id"`
ModuleID uint64 `db:"module_id"`
Place int `db:"place"`
Kind string `db:"kind"`
Name string `db:"name"`
Label string `db:"label"`
Options composeType.ModuleFieldOptions `db:"options"`
EncodingStrategy composeType.EncodingStrategy `db:"encoding_strategy"`
Privacy composeType.ModuleFieldConfigDataPrivacy `db:"privacy"`
Private bool `db:"private"`
Required bool `db:"required"`
Visible bool `db:"visible"`
Multi bool `db:"multi"`
DefaultValue composeType.RecordValueSet `db:"default_value"`
Expressions composeType.ModuleFieldExpr `db:"expressions"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
DeletedAt *time.Time `db:"deleted_at"`
}
// auxComposeNamespace is an auxiliary structure used for transporting to/from RDBMS store
@@ -1442,8 +1441,7 @@ func (aux *auxComposeModule) encode(res *composeType.Module) (_ error) {
aux.ID = res.ID
aux.Handle = res.Handle
aux.Meta = res.Meta
aux.ModelConfig = res.ModelConfig
aux.Privacy = res.Privacy
aux.Config = res.Config
aux.NamespaceID = res.NamespaceID
aux.Name = res.Name
aux.CreatedAt = res.CreatedAt
@@ -1460,8 +1458,7 @@ func (aux auxComposeModule) decode() (res *composeType.Module, _ error) {
res.ID = aux.ID
res.Handle = aux.Handle
res.Meta = aux.Meta
res.ModelConfig = aux.ModelConfig
res.Privacy = aux.Privacy
res.Config = aux.Config
res.NamespaceID = aux.NamespaceID
res.Name = aux.Name
res.CreatedAt = aux.CreatedAt
@@ -1478,8 +1475,7 @@ func (aux *auxComposeModule) scan(row scanner) error {
&aux.ID,
&aux.Handle,
&aux.Meta,
&aux.ModelConfig,
&aux.Privacy,
&aux.Config,
&aux.NamespaceID,
&aux.Name,
&aux.CreatedAt,
+4 -8
View File
@@ -1636,8 +1636,7 @@ var (
"id",
"handle",
"meta",
"model_config",
"privacy",
"config",
"rel_namespace",
"name",
"created_at",
@@ -1655,8 +1654,7 @@ var (
"id": res.ID,
"handle": res.Handle,
"meta": res.Meta,
"model_config": res.ModelConfig,
"privacy": res.Privacy,
"config": res.Config,
"rel_namespace": res.NamespaceID,
"name": res.Name,
"created_at": res.CreatedAt,
@@ -1677,8 +1675,7 @@ var (
goqu.Record{
"handle": res.Handle,
"meta": res.Meta,
"model_config": res.ModelConfig,
"privacy": res.Privacy,
"config": res.Config,
"rel_namespace": res.NamespaceID,
"name": res.Name,
"created_at": res.CreatedAt,
@@ -1697,8 +1694,7 @@ var (
Set(goqu.Record{
"handle": res.Handle,
"meta": res.Meta,
"model_config": res.ModelConfig,
"privacy": res.Privacy,
"config": res.Config,
"rel_namespace": res.NamespaceID,
"name": res.Name,
"created_at": res.CreatedAt,
+2 -3
View File
@@ -6,12 +6,11 @@ import (
)
func fix202209_extendComposeModuleForPrivacyAndDAL(ctx context.Context, s *Store) (err error) {
s.log(ctx).Info("extending compose_module table with privacy and model_config columns")
s.log(ctx).Info("extending compose_module table with config column")
return s.SchemaAPI.AddColumn(
ctx, s.DB,
&Table{Name: "compose_module"},
&Column{Type: ColumnType{Type: ColumnTypeJson}, DefaultValue: "'{}'", Name: "privacy"},
&Column{Type: ColumnType{Type: ColumnTypeJson}, DefaultValue: "'{}'", Name: "model_config"},
&Column{Type: ColumnType{Type: ColumnTypeJson}, DefaultValue: "'{}'", Name: "config"},
)
}
+1 -2
View File
@@ -448,8 +448,7 @@ func tableComposeModule() *Table {
ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)),
ColumnDef("name", ColumnTypeText),
ColumnDef("meta", ColumnTypeJson),
ColumnDef("privacy", ColumnTypeJson),
ColumnDef("model_config", ColumnTypeJson),
ColumnDef("config", ColumnTypeJson),
CUDTimestamps,
AddIndex("namespace", IColumn("rel_namespace")),
+15 -9
View File
@@ -22,9 +22,11 @@ func Test_dal_crud_compose_record_create(t *testing.T) {
helpers.AllowMeRecordCRUD(h)
ns := h.createNamespace("test")
module := createModuleFromGenerics(ctx, t, "ok_module.json", ns.ID, &types.ModelConfig{
ConnectionID: 0,
Capabilities: capabilities.FullCapabilities(),
module := createModuleFromGenerics(ctx, t, "ok_module.json", ns.ID, &types.ModuleConfig{
DAL: types.ModuleConfigDAL{
ConnectionID: 0,
Capabilities: capabilities.FullCapabilities(),
},
})
// create
@@ -81,9 +83,11 @@ func Test_dal_crud_compose_record_update(t *testing.T) {
helpers.AllowMeRecordCRUD(h)
ns := h.createNamespace("test")
module := createModuleFromGenerics(ctx, t, "ok_module.json", ns.ID, &types.ModelConfig{
ConnectionID: 0,
Capabilities: capabilities.FullCapabilities(),
module := createModuleFromGenerics(ctx, t, "ok_module.json", ns.ID, &types.ModuleConfig{
DAL: types.ModuleConfigDAL{
ConnectionID: 0,
Capabilities: capabilities.FullCapabilities(),
},
})
record := createRecordFromGenerics(ctx, t, "ok_record.json", ns.ID, module.ID)
@@ -140,9 +144,11 @@ func Test_dal_crud_compose_record_delete(t *testing.T) {
helpers.AllowMeRecordCRUD(h)
ns := h.createNamespace("test")
module := createModuleFromGenerics(ctx, t, "ok_module.json", ns.ID, &types.ModelConfig{
ConnectionID: 0,
Capabilities: capabilities.FullCapabilities(),
module := createModuleFromGenerics(ctx, t, "ok_module.json", ns.ID, &types.ModuleConfig{
DAL: types.ModuleConfigDAL{
ConnectionID: 0,
Capabilities: capabilities.FullCapabilities(),
},
})
record := createRecordFromGenerics(ctx, t, "ok_record.json", ns.ID, module.ID)
@@ -27,7 +27,7 @@ func Test_dal_crud_issues_compose_module_missing_sensitivity(t *testing.T) {
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.Len("$.response.modelConfig.issues", 1)).
Assert(jsonpath.Len("$.response.config.dal.issues", 1)).
End()
dd := json.NewDecoder(rsp.Response.Body)
@@ -42,7 +42,7 @@ func Test_dal_crud_issues_compose_module_missing_sensitivity(t *testing.T) {
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.NotPresent("$.response.modelConfig.issues")).
Assert(jsonpath.NotPresent("$.response.config.dal.issues")).
End()
rsp = h.apiInit().
@@ -54,7 +54,7 @@ func Test_dal_crud_issues_compose_module_missing_sensitivity(t *testing.T) {
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.Len("$.response.modelConfig.issues", 1)).
Assert(jsonpath.Len("$.response.config.dal.issues", 1)).
End()
rsp = h.apiInit().
@@ -84,7 +84,7 @@ func Test_dal_crud_issues_compose_module_field_missing_sensitivity(t *testing.T)
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.Len("$.response.modelConfig.issues", 1)).
Assert(jsonpath.Len("$.response.config.dal.issues", 1)).
End()
dd := json.NewDecoder(rsp.Response.Body)
@@ -98,7 +98,7 @@ func Test_dal_crud_issues_compose_module_field_missing_sensitivity(t *testing.T)
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.NotPresent("$.response.modelConfig.issues")).
Assert(jsonpath.NotPresent("$.response.config.dal.issues")).
End()
rsp = h.apiInit().
@@ -110,7 +110,7 @@ func Test_dal_crud_issues_compose_module_field_missing_sensitivity(t *testing.T)
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.Len("$.response.modelConfig.issues", 1)).
Assert(jsonpath.Len("$.response.config.dal.issues", 1)).
End()
rsp = h.apiInit().
@@ -143,7 +143,7 @@ func Test_dal_crud_issues_compose_module_nok_connection(t *testing.T) {
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.Len("$.response.modelConfig.issues", 1)).
Assert(jsonpath.Len("$.response.config.dal.issues", 1)).
End()
dd := json.NewDecoder(rsp.Response.Body)
@@ -170,7 +170,7 @@ func Test_dal_crud_issues_compose_module_nok_connection(t *testing.T) {
Status(http.StatusOK).
Assert(helpers.AssertNoErrors).
Assert(jsonpath.Present("$.response.moduleID")).
Assert(jsonpath.NotPresent("$.response.modelConfig.issues")).
Assert(jsonpath.NotPresent("$.response.config.dal.issues")).
End()
rsp = h.apiInit().
@@ -21,9 +21,11 @@ func Test_dal_crud_issues_compose_record_nok_connection(t *testing.T) {
ns := h.createNamespace("test")
connection := createConnectionFromGenerics(h.secCtx(), t, "nok_connection_connectivity.json")
module := createModuleFromGenerics(h.secCtx(), t, "ok_module.json", ns.ID, &types.ModelConfig{
ConnectionID: connection.ID,
Capabilities: capabilities.FullCapabilities(),
module := createModuleFromGenerics(h.secCtx(), t, "ok_module.json", ns.ID, &types.ModuleConfig{
DAL: types.ModuleConfigDAL{
ConnectionID: connection.ID,
Capabilities: capabilities.FullCapabilities(),
},
})
h.apiInit().
@@ -48,9 +50,11 @@ func Test_dal_crud_issues_compose_record_nok_model(t *testing.T) {
ns := h.createNamespace("test")
connection := createConnectionFromGenerics(h.secCtx(), t, "ok_connection.json")
module := createModuleFromGenerics(h.secCtx(), t, "nok_module_sensitivity_level.json", ns.ID, &types.ModelConfig{
ConnectionID: connection.ID,
Capabilities: capabilities.FullCapabilities(),
module := createModuleFromGenerics(h.secCtx(), t, "nok_module_sensitivity_level.json", ns.ID, &types.ModuleConfig{
DAL: types.ModuleConfigDAL{
ConnectionID: connection.ID,
Capabilities: capabilities.FullCapabilities(),
},
})
h.apiInit().
@@ -75,9 +79,11 @@ func Test_dal_crud_issues_compose_record_ok(t *testing.T) {
ns := h.createNamespace("test")
connection := createConnectionFromGenerics(h.secCtx(), t, "ok_connection.json")
module := createModuleFromGenerics(h.secCtx(), t, "ok_module.json", ns.ID, &types.ModelConfig{
ConnectionID: connection.ID,
Capabilities: capabilities.FullCapabilities(),
module := createModuleFromGenerics(h.secCtx(), t, "ok_module.json", ns.ID, &types.ModuleConfig{
DAL: types.ModuleConfigDAL{
ConnectionID: connection.ID,
Capabilities: capabilities.FullCapabilities(),
},
})
h.apiInit().
+6 -5
View File
@@ -129,7 +129,7 @@ func loadRequestFromScenarioWithConnection(t *testing.T, req string, connectionI
aux := &composeTypes.Module{}
require.NoError(t, json.Unmarshal([]byte(out), &aux))
aux.ModelConfig.ConnectionID = connectionID
aux.Config.DAL.ConnectionID = connectionID
a, err := json.Marshal(aux)
require.NoError(t, err)
@@ -158,13 +158,13 @@ func createRecordFrom(ctx context.Context, t *testing.T, suite, name string, nam
return record
}
func createModuleFromCase(ctx context.Context, t *testing.T, name string, namespaceID uint64, config *composeTypes.ModelConfig) (module *composeTypes.Module) {
func createModuleFromCase(ctx context.Context, t *testing.T, name string, namespaceID uint64, config *composeTypes.ModuleConfig) (module *composeTypes.Module) {
return createModuleFrom(ctx, t, suiteFromT(t), name, namespaceID, config)
}
func createModuleFromGenerics(ctx context.Context, t *testing.T, name string, namespaceID uint64, config *composeTypes.ModelConfig) (module *composeTypes.Module) {
func createModuleFromGenerics(ctx context.Context, t *testing.T, name string, namespaceID uint64, config *composeTypes.ModuleConfig) (module *composeTypes.Module) {
return createModuleFrom(ctx, t, "generic", name, namespaceID, config)
}
func createModuleFrom(ctx context.Context, t *testing.T, suite, name string, namespaceID uint64, config *composeTypes.ModelConfig) (module *composeTypes.Module) {
func createModuleFrom(ctx context.Context, t *testing.T, suite, name string, namespaceID uint64, config *composeTypes.ModuleConfig) (module *composeTypes.Module) {
raw := loadRequestFrom(t, suite, name)
module = &composeTypes.Module{}
@@ -173,7 +173,8 @@ func createModuleFrom(ctx context.Context, t *testing.T, suite, name string, nam
module.NamespaceID = namespaceID
if config != nil {
module.ModelConfig = *config
// let's be careful not to override whole config
module.Config.DAL = config.DAL
}
module, err := composeService.DefaultModule.Create(ctx, module)
@@ -2,16 +2,19 @@
"name": "internal_non_partitioned",
"handle": "internal_non_partitioned",
"modelConfig": {
"connectionID": "42",
"capabilities": [],
"partitioned": false
"config": {
"dal": {
"connectionID": "42",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "0",
"usageDisclosure": "A"
}
},
"privacy": {
"sensitivityLevel": "0",
"usageDisclosure": "A"
},
"fields": [
{
@@ -2,15 +2,16 @@
"name": "internal_non_partitioned",
"handle": "internal_non_partitioned",
"modelConfig": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "0",
"usageDisclosure": "A"
"config": {
"dal": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "0",
"usageDisclosure": "A"
}
},
"fields": [
@@ -2,15 +2,16 @@
"name": "internal_non_partitioned",
"handle": "internal_non_partitioned",
"modelConfig": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "42",
"usageDisclosure": "A"
"config": {
"dal": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "42",
"usageDisclosure": "A"
}
},
"fields": [
@@ -2,15 +2,17 @@
"name": "internal_non_partitioned",
"handle": "internal_non_partitioned",
"modelConfig": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"config": {
"dal": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "42",
"usageDisclosure": "A"
"privacy": {
"sensitivityLevel": "42",
"usageDisclosure": "A"
}
},
"fields": [
+10 -9
View File
@@ -2,15 +2,16 @@
"name": "internal_non_partitioned",
"handle": "internal_non_partitioned",
"modelConfig": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "0",
"usageDisclosure": "A"
"config": {
"dal": {
"connectionID": "0",
"capabilities": [],
"partitioned": false
},
"privacy": {
"sensitivityLevel": "0",
"usageDisclosure": "A"
}
},
"fields": [